diff --git a/.github/workflows/_reusable-tests.yml b/.github/workflows/_reusable-tests.yml
index 47678d7303c..059c223f76d 100644
--- a/.github/workflows/_reusable-tests.yml
+++ b/.github/workflows/_reusable-tests.yml
@@ -95,13 +95,13 @@ jobs:
COV_FLAG="-DWITH_CODE_COV=ON"
fi
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ${COV_FLAG}
- cmake --build build
+ cmake --build build -j $(nproc)
- name: Configure and compile MNE-CPP (MacOS)
if: matrix.os == 'macos-26'
run: |
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON
- cmake --build build
+ cmake --build build -j $(sysctl -n hw.logicalcpu)
- name: Configure and compile MNE-CPP (Windows)
if: matrix.os == 'windows-2025'
@@ -109,13 +109,13 @@ jobs:
cmd.exe /c "call `"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat`" && set > %temp%\vcvars.txt"
Get-Content "$env:temp\vcvars.txt" | Foreach-Object { if ($_ -match "^(.*?)=(.*)$") { Set-Content "env:\$($matches[1])" $matches[2] } }
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON
- cmake --build build --config Release
+ cmake --build build --config Release --parallel
# ── Run tests ──────────────────────────────────────────────────────────
- name: Run tests (Linux)
if: matrix.os == 'ubuntu-24.04'
env:
- QTEST_FUNCTION_TIMEOUT: 900000
+ QTEST_FUNCTION_TIMEOUT: ${{ inputs.with_code_coverage && 1800000 || 900000 }}
QT_QPA_PLATFORM: offscreen
MNE_DATA: ~/mne_data
run: |
@@ -150,26 +150,33 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
# ── Coverage: threshold & regression check (staging branch) ────────────
- - name: Install lcov
+ - name: Install fastcov
if: matrix.os == 'ubuntu-24.04' && inputs.with_code_coverage && !inputs.upload_codecov
- run: sudo apt-get install -y -qq lcov
+ run: pip install fastcov
- - name: Generate lcov report
+ - name: Generate coverage report (fastcov)
id: lcov
if: matrix.os == 'ubuntu-24.04' && inputs.with_code_coverage && !inputs.upload_codecov
run: |
- lcov --capture --directory build \
- --output-file coverage.info \
- --ignore-errors mismatch 2>/dev/null || true
- # Remove external/test code from the report
- lcov --remove coverage.info \
- '*/src/external/*' '*/src/examples/*' '*/src/testframes/*' \
- '/usr/*' '*/Qt/*' \
- --output-file coverage_filtered.info \
- --ignore-errors unused 2>/dev/null || true
- # Extract total line coverage percentage
- COVERAGE=$(lcov --summary coverage_filtered.info 2>&1 \
- | grep -oP 'lines\.*:\s*\K[0-9]+(\.[0-9]+)?' || echo "0")
+ echo "=== Coverage diagnostics ==="
+ echo "gcno files: $(find build -name '*.gcno' 2>/dev/null | wc -l)"
+ echo "gcda files: $(find build -name '*.gcda' 2>/dev/null | wc -l)"
+ # Collect coverage data with fastcov (10-100x faster than lcov)
+ fastcov -d build -o coverage.json
+ # Full report in lcov format
+ fastcov -C coverage.json --lcov -o coverage.info
+ # Filtered report: only MNE-CPP libraries (no apps, tests, examples, external, Qt, Eigen)
+ fastcov -C coverage.json --lcov -o coverage_filtered.info \
+ --include src/libraries/ \
+ --exclude /usr Qt eigen
+ # Extract total line coverage percentage from lcov format
+ TOTAL_LINES=$(grep -c "^DA:" coverage_filtered.info 2>/dev/null || echo "0")
+ HIT_LINES=$(grep "^DA:" coverage_filtered.info | awk -F, '$2 > 0' | wc -l 2>/dev/null || echo "0")
+ if [ "$TOTAL_LINES" -gt 0 ]; then
+ COVERAGE=$(awk "BEGIN {printf \"%.2f\", $HIT_LINES * 100.0 / $TOTAL_LINES}")
+ else
+ COVERAGE="0"
+ fi
echo "Total line coverage: ${COVERAGE}%"
echo "coverage=${COVERAGE}" >> "$GITHUB_OUTPUT"
@@ -206,16 +213,23 @@ jobs:
fi
fi
- # --- Regression check ---
+ # --- Regression check (allow up to 2% drop) ---
if [ "$CHECK_REGRESSION" = "true" ] && [ -f .coverage-baseline ]; then
PREVIOUS=$(cat .coverage-baseline)
echo " Previous coverage: ${PREVIOUS}%"
- if (( $(echo "${CURRENT} < ${PREVIOUS}" | bc -l) )); then
+ ALLOWED_DROP="2.0"
+ LIMIT=$(echo "${PREVIOUS} - ${ALLOWED_DROP}" | bc -l)
+ if (( $(echo "${CURRENT} < ${LIMIT}" | bc -l) )); then
DELTA=$(echo "${PREVIOUS} - ${CURRENT}" | bc -l)
- echo " ❌ FAIL: Coverage dropped by ${DELTA}% (${PREVIOUS}% → ${CURRENT}%)"
+ echo " ❌ FAIL: Coverage dropped by ${DELTA}% (${PREVIOUS}% → ${CURRENT}%), exceeds ${ALLOWED_DROP}% tolerance"
FAILED=true
else
- echo " ✅ PASS: Coverage did not regress"
+ if (( $(echo "${CURRENT} < ${PREVIOUS}" | bc -l) )); then
+ DELTA=$(echo "${PREVIOUS} - ${CURRENT}" | bc -l)
+ echo " ⚠️ WARN: Coverage dropped by ${DELTA}% (within ${ALLOWED_DROP}% tolerance)"
+ else
+ echo " ✅ PASS: Coverage did not regress"
+ fi
fi
fi
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1171f1b81fa..4c59f7f1fb3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -22,7 +22,7 @@
#
# Branch model: Feature → Staging → Main
# ═══════════════════════════════════════════════════════════════════════════
-name: Main
+name: Release
on:
push:
@@ -84,13 +84,11 @@ jobs:
- name: Deploy qch to GitHub Release
if: startsWith(github.ref, 'refs/tags/')
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: doc/doxygen/qt-creator_doc/mne-cpp.qch
- asset_name: mne-cpp-${{ github.ref_name }}-doc-qtcreator.qch
- tag: ${{ github.ref }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp doc/doxygen/qt-creator_doc/mne-cpp.qch "mne-cpp-${{ github.ref_name }}-doc-qtcreator.qch"
+ gh release upload "${{ github.ref_name }}" "mne-cpp-${{ github.ref_name }}-doc-qtcreator.qch" --clobber
- name: Deploy Doxygen to GitHub Pages (production)
env:
@@ -294,13 +292,11 @@ jobs:
tar cfz mne-cpp-wasm.tar.gz -C out/wasm .
- name: Upload WASM to GitHub Release
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-wasm.tar.gz
- asset_name: mne-cpp-${{ github.ref_name }}-wasm.tar.gz
- tag: ${{ github.ref }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-wasm.tar.gz "mne-cpp-${{ github.ref_name }}-wasm.tar.gz"
+ gh release upload "${{ github.ref_name }}" "mne-cpp-${{ github.ref_name }}-wasm.tar.gz" --clobber
- name: Deploy WASM to mne-cpp/wasm repository
env:
diff --git a/.github/workflows/release-installer.yml b/.github/workflows/release-installer.yml
index 822d471811b..fafa295eee7 100644
--- a/.github/workflows/release-installer.yml
+++ b/.github/workflows/release-installer.yml
@@ -205,14 +205,11 @@ jobs:
ls -lh MNE-CPP-*.run
- name: Upload installer
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: MNE-CPP-*-Linux.run
- file_glob: true
- asset_name: ${{ steps.tag.outputs.asset_prefix }}-linux-installer-x86_64.run
- tag: ${{ steps.tag.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp MNE-CPP-*-Linux.run "${{ steps.tag.outputs.asset_prefix }}-linux-installer-x86_64.run"
+ gh release upload "${{ steps.tag.outputs.tag }}" "${{ steps.tag.outputs.asset_prefix }}-linux-installer-x86_64.run" --clobber
# =========================================================================
# macOS Installer (.dmg)
@@ -540,14 +537,11 @@ jobs:
security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true
- name: Upload installer
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: MNE-CPP-*-Darwin.dmg
- file_glob: true
- asset_name: ${{ steps.tag.outputs.asset_prefix }}-macos-installer-arm64.dmg
- tag: ${{ steps.tag.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp MNE-CPP-*-Darwin.dmg "${{ steps.tag.outputs.asset_prefix }}-macos-installer-arm64.dmg"
+ gh release upload "${{ steps.tag.outputs.tag }}" "${{ steps.tag.outputs.asset_prefix }}-macos-installer-arm64.dmg" --clobber
# =========================================================================
# Windows Installer (.exe)
@@ -734,11 +728,9 @@ jobs:
Get-ChildItem MNE-CPP-*-win64.exe
- name: Upload installer
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: MNE-CPP-*-win64.exe
- file_glob: true
- asset_name: ${{ steps.tag.outputs.asset_prefix }}-windows-installer-x86_64.exe
- tag: ${{ steps.tag.outputs.tag }}
- overwrite: true
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp MNE-CPP-*-win64.exe "${{ steps.tag.outputs.asset_prefix }}-windows-installer-x86_64.exe"
+ gh release upload "${{ steps.tag.outputs.tag }}" "${{ steps.tag.outputs.asset_prefix }}-windows-installer-x86_64.exe" --clobber
diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml
index ef06b0385a0..e30d7f4417b 100644
--- a/.github/workflows/release-linux.yml
+++ b/.github/workflows/release-linux.yml
@@ -58,13 +58,11 @@ jobs:
./tools/deploy.bat dynamic pack
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-linux-dynamic-x86_64.tar.gz
- asset_name: ${{ steps.release-info.outputs.prefix }}-linux-dynamic-x86_64.tar.gz
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-linux-dynamic-x86_64.tar.gz "${{ steps.release-info.outputs.prefix }}-linux-dynamic-x86_64.tar.gz"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-linux-dynamic-x86_64.tar.gz" --clobber
LinuxStatic:
@@ -141,10 +139,8 @@ jobs:
./tools/deploy.bat static pack
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-linux-static-x86_64.tar.gz
- asset_name: ${{ steps.release-info.outputs.prefix }}-linux-static-x86_64.tar.gz
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-linux-static-x86_64.tar.gz "${{ steps.release-info.outputs.prefix }}-linux-static-x86_64.tar.gz"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-linux-static-x86_64.tar.gz" --clobber
diff --git a/.github/workflows/release-macos.yml b/.github/workflows/release-macos.yml
index 41c1312b6a3..fe2672b8cee 100644
--- a/.github/workflows/release-macos.yml
+++ b/.github/workflows/release-macos.yml
@@ -77,13 +77,11 @@ jobs:
fi
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-macos-dynamic-arm64.tar.gz
- asset_name: ${{ steps.release-info.outputs.prefix }}-macos-dynamic-arm64.tar.gz
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-macos-dynamic-arm64.tar.gz "${{ steps.release-info.outputs.prefix }}-macos-dynamic-arm64.tar.gz"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-macos-dynamic-arm64.tar.gz" --clobber
MacOSStatic:
@@ -159,10 +157,8 @@ jobs:
./tools/deploy.bat static pack
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-macos-static-arm64.tar.gz
- asset_name: ${{ steps.release-info.outputs.prefix }}-macos-static-arm64.tar.gz
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-macos-static-arm64.tar.gz "${{ steps.release-info.outputs.prefix }}-macos-static-arm64.tar.gz"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-macos-static-arm64.tar.gz" --clobber
diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml
index 0460a82659c..2ba71d96b01 100644
--- a/.github/workflows/release-windows.yml
+++ b/.github/workflows/release-windows.yml
@@ -72,13 +72,12 @@ jobs:
}
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-windows-dynamic-x86_64.zip
- asset_name: ${{ steps.release-info.outputs.prefix }}-windows-dynamic-x86_64.zip
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-windows-dynamic-x86_64.zip "${{ steps.release-info.outputs.prefix }}-windows-dynamic-x86_64.zip"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-windows-dynamic-x86_64.zip" --clobber
WinStatic:
@@ -156,10 +155,9 @@ jobs:
./tools/deploy.bat static pack
- name: Upload release binaries
if: steps.release-info.outputs.should_upload == 'true'
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-windows-static-x86_64.zip
- asset_name: ${{ steps.release-info.outputs.prefix }}-windows-static-x86_64.zip
- tag: ${{ steps.release-info.outputs.tag }}
- overwrite: true
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-windows-static-x86_64.zip "${{ steps.release-info.outputs.prefix }}-windows-static-x86_64.zip"
+ gh release upload "${{ steps.release-info.outputs.tag }}" "${{ steps.release-info.outputs.prefix }}-windows-static-x86_64.zip" --clobber
diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml
index 5a4b6e51f5e..c38f17c840e 100644
--- a/.github/workflows/staging.yml
+++ b/.github/workflows/staging.yml
@@ -33,9 +33,9 @@ concurrency:
cancel-in-progress: true
env:
- # Minimum acceptable line coverage percentage.
+ # Minimum acceptable line coverage percentage (libraries only).
# The pipeline will FAIL if coverage drops below this.
- COVERAGE_THRESHOLD: 50
+ COVERAGE_THRESHOLD: 35
jobs:
@@ -100,13 +100,15 @@ jobs:
qt_version: '6.10.2'
# ── Tests with coverage threshold & regression checks ────────────────────
+ # Add [skip-coverage] to your commit message to skip coverage analysis.
+ # Coverage is only collected on Ubuntu; macOS/Windows always run without it.
Tests:
uses: ./.github/workflows/_reusable-tests.yml
with:
- with_code_coverage: true
+ with_code_coverage: ${{ !contains(github.event.head_commit.message, '[skip-coverage]') }}
upload_codecov: false
- coverage_threshold: 50
- fail_on_coverage_regression: true
+ coverage_threshold: ${{ contains(github.event.head_commit.message, '[skip-coverage]') && 0 || 35 }}
+ fail_on_coverage_regression: ${{ !contains(github.event.head_commit.message, '[skip-coverage]') }}
# ── Doxygen API documentation (dev) ──────────────────────────────────────
Doxygen:
@@ -131,13 +133,11 @@ jobs:
doxygen mne-cpp_doxyfile
- name: Deploy qch to dev_build release
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: doc/doxygen/qt-creator_doc/mne-cpp.qch
- asset_name: mne-cpp-dev-doc-qtcreator.qch
- tag: dev_build
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp doc/doxygen/qt-creator_doc/mne-cpp.qch mne-cpp-dev-doc-qtcreator.qch
+ gh release upload dev_build mne-cpp-dev-doc-qtcreator.qch --clobber
- name: Deploy Doxygen to GitHub Pages (dev subdirectory)
env:
@@ -262,10 +262,8 @@ jobs:
tar cfz mne-cpp-wasm.tar.gz -C out/wasm .
- name: Upload WASM to dev_build release
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- file: mne-cpp-wasm.tar.gz
- asset_name: mne-cpp-dev-wasm.tar.gz
- tag: dev_build
- overwrite: true
+ env:
+ GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
+ run: |
+ cp mne-cpp-wasm.tar.gz mne-cpp-dev-wasm.tar.gz
+ gh release upload dev_build mne-cpp-dev-wasm.tar.gz --clobber
diff --git a/README.md b/README.md
index 6b673113234..bb3e0ba4bc6 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
diff --git a/codecov.yml b/codecov.yml
index f288100145a..b76c64f3f62 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -34,3 +34,4 @@ ignore:
- "src/external/**" # third-party libraries (e.g. Eigen)
- "src/examples/**" # example code is not part of coverage
- "src/testframes/**" # test harnesses themselves
+ - "src/applications/**" # applications are not part of library coverage
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cf376bcbbd7..24142e2637e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -63,7 +63,7 @@ if(USE_FFTW)
endif()
if(WITH_CODE_COV)
- add_compile_options("--coverage")
+ add_compile_options("--coverage" "-O1" "-g")
add_link_options("--coverage")
endif()
diff --git a/src/applications/mne_analyze/libs/anShared/Model/dipolefitmodel.h b/src/applications/mne_analyze/libs/anShared/Model/dipolefitmodel.h
index 9ef0121cb64..362ddf8562a 100644
--- a/src/applications/mne_analyze/libs/anShared/Model/dipolefitmodel.h
+++ b/src/applications/mne_analyze/libs/anShared/Model/dipolefitmodel.h
@@ -43,7 +43,7 @@
#include "../Utils/types.h"
#include "abstractmodel.h"
-#include
+#include
//=============================================================================================================
// QT INCLUDES
diff --git a/src/applications/mne_analyze/libs/anShared/Utils/metatypes.h b/src/applications/mne_analyze/libs/anShared/Utils/metatypes.h
index be8c84470ab..78aa60f0e1e 100644
--- a/src/applications/mne_analyze/libs/anShared/Utils/metatypes.h
+++ b/src/applications/mne_analyze/libs/anShared/Utils/metatypes.h
@@ -37,7 +37,7 @@
#ifndef METATYPES_H
#define METATYPES_H
-#include
+#include
#include
#include "../Management/event.h"
#include "../Model/fiffrawviewmodel.h"
diff --git a/src/applications/mne_analyze/libs/anShared/Utils/types.h b/src/applications/mne_analyze/libs/anShared/Utils/types.h
index ea9124889f6..a938e2320c9 100644
--- a/src/applications/mne_analyze/libs/anShared/Utils/types.h
+++ b/src/applications/mne_analyze/libs/anShared/Utils/types.h
@@ -40,7 +40,7 @@
// INCLUDES
//=============================================================================================================
-#include
+#include
#include
//=============================================================================================================
diff --git a/src/applications/mne_analyze/plugins/dipolefit/dipolefit.cpp b/src/applications/mne_analyze/plugins/dipolefit/dipolefit.cpp
index 2f7db8827ea..e50f2bcc668 100644
--- a/src/applications/mne_analyze/plugins/dipolefit/dipolefit.cpp
+++ b/src/applications/mne_analyze/plugins/dipolefit/dipolefit.cpp
@@ -53,9 +53,9 @@
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
diff --git a/src/applications/mne_analyze/plugins/dipolefit/dipolefit.h b/src/applications/mne_analyze/plugins/dipolefit/dipolefit.h
index 163d28d37dc..19719a3eaa7 100644
--- a/src/applications/mne_analyze/plugins/dipolefit/dipolefit.h
+++ b/src/applications/mne_analyze/plugins/dipolefit/dipolefit.h
@@ -42,7 +42,7 @@
#include "dipolefit_global.h"
#include
-#include
+#include
//=============================================================================================================
// QT INCLUDES
diff --git a/src/applications/mne_browse/Models/averagemodel.h b/src/applications/mne_browse/Models/averagemodel.h
index 77dc469f501..b15d7c4ebdf 100644
--- a/src/applications/mne_browse/Models/averagemodel.h
+++ b/src/applications/mne_browse/Models/averagemodel.h
@@ -51,6 +51,7 @@
//=============================================================================================================
#include
+#include
//*************************************************************************************************************
diff --git a/src/applications/mne_browse/Models/eventmodel.h b/src/applications/mne_browse/Models/eventmodel.h
index 9b24fbec614..6a8989a3272 100644
--- a/src/applications/mne_browse/Models/eventmodel.h
+++ b/src/applications/mne_browse/Models/eventmodel.h
@@ -51,6 +51,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/src/applications/mne_compute_mne/main.cpp b/src/applications/mne_compute_mne/main.cpp
index 3ba9ae7c9f4..27b8094e42b 100644
--- a/src/applications/mne_compute_mne/main.cpp
+++ b/src/applications/mne_compute_mne/main.cpp
@@ -52,14 +52,14 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
-#include
+#include
-#include
+#include
#include
@@ -90,6 +90,7 @@
using namespace Eigen;
using namespace FIFFLIB;
using namespace MNELIB;
+using namespace FWDLIB;
using namespace INVERSELIB;
using namespace FSLIB;
using namespace UTILSLIB;
@@ -431,7 +432,7 @@ static bool writeDipFile(const QString &fileName,
* @return true on success.
*/
static bool writePredictedData(const QString &fileName,
- const MNEForwardSolution &forward,
+ const FwdForwardSolution &forward,
const MatrixXd &stcData,
const VectorXd ×Vec)
{
@@ -857,7 +858,7 @@ int main(int argc, char *argv[])
printf(" Source amplitude: %.1f nAm\n", fwdAmp * 1e9);
QFile fwdFile(fwdName);
- MNEForwardSolution fwd(fwdFile);
+ FwdForwardSolution fwd(fwdFile);
if (!fwd.sol || fwd.sol->data.rows() == 0) {
qCritical() << "Error: Could not read forward solution from" << fwdName;
@@ -1264,13 +1265,13 @@ int main(int argc, char *argv[])
printf("\nComputing predicted sensor data...\n");
// Read forward solution for prediction
- MNEForwardSolution predFwd;
+ FwdForwardSolution predFwd;
if (parser.isSet(predfwdOpt)) {
QFile fwdFile(parser.value(predfwdOpt));
- predFwd = MNEForwardSolution(fwdFile, false, true);
+ predFwd = FwdForwardSolution(fwdFile, false, true);
} else if (useFwdAsData) {
QFile fwdFile(parser.value(fwdOpt));
- predFwd = MNEForwardSolution(fwdFile, false, true);
+ predFwd = FwdForwardSolution(fwdFile, false, true);
} else {
printf(" NOTE: --pred requires a forward solution.\n");
printf(" Use --predfwd to specify one, or use --fwd mode.\n");
diff --git a/src/applications/mne_compute_raw_inverse/main.cpp b/src/applications/mne_compute_raw_inverse/main.cpp
index 026657bd00c..0df82a3cb62 100644
--- a/src/applications/mne_compute_raw_inverse/main.cpp
+++ b/src/applications/mne_compute_raw_inverse/main.cpp
@@ -50,13 +50,13 @@
#include
#include
-#include
-#include
+#include
+#include
#include
-#include
+#include
-#include
+#include
#include
diff --git a/src/applications/mne_dipole_fit/main.cpp b/src/applications/mne_dipole_fit/main.cpp
index efa64e9c75a..fa95bf773ab 100644
--- a/src/applications/mne_dipole_fit/main.cpp
+++ b/src/applications/mne_dipole_fit/main.cpp
@@ -37,8 +37,8 @@
// INCLUDES
//=============================================================================================================
-#include
-#include
+#include
+#include
#include
@@ -50,9 +50,9 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
diff --git a/src/applications/mne_flash_bem/flashbem.cpp b/src/applications/mne_flash_bem/flashbem.cpp
index 1263849fad0..ec627b52e52 100644
--- a/src/applications/mne_flash_bem/flashbem.cpp
+++ b/src/applications/mne_flash_bem/flashbem.cpp
@@ -44,7 +44,7 @@
#include "flashbem.h"
#include "mne_flash_bem_settings.h"
-#include
+#include
#include
#include
diff --git a/src/applications/mne_forward_solution/main.cpp b/src/applications/mne_forward_solution/main.cpp
index 7022158355e..77baa303cc7 100644
--- a/src/applications/mne_forward_solution/main.cpp
+++ b/src/applications/mne_forward_solution/main.cpp
@@ -28,7 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*
- * @brief Implements the mne_dipole_fit application.
+ * @brief Implements the mne_forward_solution application.
*
*/
@@ -36,10 +36,9 @@
// INCLUDES
//=============================================================================================================
-#include
-#include
-
-#include
+#include
+#include
+#include
#include
@@ -48,6 +47,8 @@
//=============================================================================================================
#include
+#include
+#include
//=============================================================================================================
// USED NAMESPACES
@@ -72,11 +73,177 @@ int main(int argc, char *argv[])
{
qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);
QApplication app(argc, argv);
+ app.setApplicationVersion("2.10");
+
+ //=========================================================================================================
+ // Command line parser
+ //=========================================================================================================
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription(
+ "Compute the MEG/EEG forward solution.\n"
+ "Port of the original MNE-C mne_forward_solution by Matti Hamalainen."
+ );
+ parser.addHelpOption();
+ parser.addVersionOption();
+
+ // Source & sensor options
+ QCommandLineOption srcOpt("src", "Source space file.", "file");
+ QCommandLineOption measOpt("meas", "MEG/EEG measurement file (sensor & electrode locations).", "file");
+ QCommandLineOption fwdOpt("fwd", "Output forward solution file.", "file");
+
+ // Transform options
+ QCommandLineOption mriOpt("mri", "MRI description file for head/MRI transform.", "file");
+ QCommandLineOption transOpt("trans", "Text file for head/MRI transform.", "file");
+ QCommandLineOption notransOpt("notrans", "Head and MRI coordinate systems are identical.");
+
+ // BEM & sphere model options
+ QCommandLineOption bemOpt("bem", "BEM model file.", "file");
+ QCommandLineOption originOpt("origin", "Sphere model origin in head coordinates (x:y:z in mm).", "x:y:z");
+ QCommandLineOption eegscalpOpt("eegscalp", "Scale electrode locations to the scalp surface (sphere model).");
+ QCommandLineOption eegmodelsOpt("eegmodels", "File of EEG sphere model specifications.", "file");
+ QCommandLineOption eegmodelOpt("eegmodel", "Name of the EEG sphere model to use (default: Default).", "name");
+ QCommandLineOption eegradOpt("eegrad", "Scalp radius for EEG sphere model in mm (default: 90.0).", "radius");
+
+ // Modality flags
+ QCommandLineOption megOpt("meg", "Compute the MEG forward solution.");
+ QCommandLineOption eegOpt("eeg", "Compute the EEG forward solution.");
+ QCommandLineOption gradOpt("grad", "Compute the gradient of the field with respect to dipole coordinates.");
+ QCommandLineOption fixedOpt("fixed", "Calculate only for the source orientation given by surface normals.");
+ QCommandLineOption accurateOpt("accurate", "Use accurate coil definitions in MEG forward computation.");
+ QCommandLineOption mricoordOpt("mricoord", "Do calculations in MRI coordinates instead of head coordinates.");
+ QCommandLineOption allOpt("all", "Calculate forward solution in all nodes instead of selected ones only.");
+
+ // Source space filtering
+ QCommandLineOption labelOpt("label", "Label file to select sources (can be specified multiple times).", "file");
+ QCommandLineOption mindistOpt("mindist", "Minimum distance of sources from the inner skull surface (mm).", "dist");
+ QCommandLineOption mindistoutOpt("mindistout", "Output file for omitted source space points.", "file");
+ QCommandLineOption includeallOpt("includeall", "Omit all source space checks.");
+
+ parser.addOptions({srcOpt, measOpt, fwdOpt,
+ mriOpt, transOpt, notransOpt,
+ bemOpt, originOpt, eegscalpOpt, eegmodelsOpt, eegmodelOpt, eegradOpt,
+ megOpt, eegOpt, gradOpt, fixedOpt, accurateOpt, mricoordOpt, allOpt,
+ labelOpt, mindistOpt, mindistoutOpt, includeallOpt});
+
+ parser.process(app);
+
+ //=========================================================================================================
+ // Populate settings from parsed arguments
+ //=========================================================================================================
+
+ ComputeFwdSettings::SPtr settings = ComputeFwdSettings::SPtr(new ComputeFwdSettings());
+
+ // Build the command string for FIFF stamping
+ settings->command = QCoreApplication::arguments().join(" ");
+
+ // Source & sensor files
+ if (parser.isSet(srcOpt))
+ settings->srcname = parser.value(srcOpt);
+ if (parser.isSet(measOpt))
+ settings->measname = parser.value(measOpt);
+ if (parser.isSet(fwdOpt))
+ settings->solname = parser.value(fwdOpt);
+
+ // Transform options (--mri and --trans are mutually exclusive with --notrans)
+ if (parser.isSet(notransOpt)) {
+ settings->mri_head_ident = true;
+ settings->mriname.clear();
+ settings->transname.clear();
+ } else if (parser.isSet(mriOpt)) {
+ settings->mri_head_ident = false;
+ settings->mriname = parser.value(mriOpt);
+ settings->transname.clear();
+ } else if (parser.isSet(transOpt)) {
+ settings->mri_head_ident = false;
+ settings->transname = parser.value(transOpt);
+ settings->mriname.clear();
+ }
+
+ // BEM model
+ if (parser.isSet(bemOpt))
+ settings->bemname = parser.value(bemOpt);
+
+ // Sphere model origin (x:y:z in mm, converted to meters)
+ if (parser.isSet(originOpt)) {
+ QStringList parts = parser.value(originOpt).split(':');
+ if (parts.size() != 3) {
+ qCritical("Could not interpret the origin.");
+ return 1;
+ }
+ bool ok1, ok2, ok3;
+ settings->r0[0] = parts[0].toFloat(&ok1) / 1000.0f;
+ settings->r0[1] = parts[1].toFloat(&ok2) / 1000.0f;
+ settings->r0[2] = parts[2].toFloat(&ok3) / 1000.0f;
+ if (!ok1 || !ok2 || !ok3) {
+ qCritical("Could not interpret the origin.");
+ return 1;
+ }
+ }
+
+ // EEG sphere model options
+ if (parser.isSet(eegscalpOpt))
+ settings->scale_eeg_pos = true;
+ if (parser.isSet(eegmodelsOpt))
+ settings->eeg_model_file = parser.value(eegmodelsOpt);
+ if (parser.isSet(eegmodelOpt))
+ settings->eeg_model_name = parser.value(eegmodelOpt);
+ if (parser.isSet(eegradOpt)) {
+ bool ok;
+ float rad = parser.value(eegradOpt).toFloat(&ok);
+ if (!ok || rad <= 0) {
+ qCritical("Radius must be a positive number.");
+ return 1;
+ }
+ settings->eeg_sphere_rad = rad / 1000.0f;
+ }
+
+ // Modality flags
+ if (parser.isSet(megOpt))
+ settings->include_meg = true;
+ if (parser.isSet(eegOpt))
+ settings->include_eeg = true;
+ if (parser.isSet(gradOpt))
+ settings->compute_grad = true;
+ if (parser.isSet(fixedOpt))
+ settings->fixed_ori = true;
+ if (parser.isSet(accurateOpt))
+ settings->accurate = true;
+ if (parser.isSet(mricoordOpt))
+ settings->coord_frame = FIFFV_COORD_MRI;
+ if (parser.isSet(allOpt))
+ settings->do_all = true;
+
+ // Source space filtering
+ if (parser.isSet(labelOpt)) {
+ settings->labels = parser.values(labelOpt);
+ settings->nlabel = settings->labels.size();
+ }
+ if (parser.isSet(mindistOpt)) {
+ bool ok;
+ float dist = parser.value(mindistOpt).toFloat(&ok);
+ if (!ok) {
+ qCritical("Could not interpret the distance.");
+ return 1;
+ }
+ settings->mindist = (dist <= 0.0f) ? 0.0f : dist / 1000.0f;
+ }
+ if (parser.isSet(mindistoutOpt))
+ settings->mindistoutname = parser.value(mindistoutOpt);
+ if (parser.isSet(includeallOpt))
+ settings->filter_spaces = false;
+
+ //=========================================================================================================
+ // Run forward computation
+ //=========================================================================================================
+
+ settings->checkIntegrity();
+
+ ComputeFwd computer(settings);
+ auto fwdSolution = computer.calculateFwd();
- ComputeFwdSettings::SPtr settings = ComputeFwdSettings::SPtr(new ComputeFwdSettings(&argc,argv));
- ComputeFwd cmpFwd(settings);
- cmpFwd.calculateFwd();
- cmpFwd.storeFwd();
+ QFile fwdFile(settings->solname);
+ fwdSolution->write(fwdFile);
return app.exec();
}
diff --git a/src/applications/mne_inspect/app/mainwindow.cpp b/src/applications/mne_inspect/app/mainwindow.cpp
index 7d2ec4f1f79..bf0b56ca8fd 100644
--- a/src/applications/mne_inspect/app/mainwindow.cpp
+++ b/src/applications/mne_inspect/app/mainwindow.cpp
@@ -41,9 +41,9 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
#include
#include
diff --git a/src/applications/mne_inverse_operator/main.cpp b/src/applications/mne_inverse_operator/main.cpp
index 2760132446d..750a876065d 100644
--- a/src/applications/mne_inverse_operator/main.cpp
+++ b/src/applications/mne_inverse_operator/main.cpp
@@ -57,8 +57,8 @@
#include
#include
-#include
-#include
+#include
+#include
#include
@@ -87,6 +87,8 @@
using namespace Eigen;
using namespace FIFFLIB;
using namespace MNELIB;
+using namespace FWDLIB;
+using namespace INVERSELIB;
using namespace UTILSLIB;
//=============================================================================================================
@@ -105,7 +107,7 @@ using namespace UTILSLIB;
* and populates SSP projectors from the noise covariance and/or --proj files.
* This mirrors the original MNE-C approach where no measurement file is needed.
*/
-static FiffInfo buildInfoFromForward(const MNEForwardSolution &forward,
+static FiffInfo buildInfoFromForward(const FwdForwardSolution &forward,
const FiffCov &noiseCov,
const QList &extraProjs)
{
@@ -427,7 +429,7 @@ int main(int argc, char *argv[])
printf("Reading forward solution from %s...\n", fwdName.toUtf8().constData());
QFile fwdFile(fwdName);
- MNEForwardSolution forward(fwdFile, false, true);
+ FwdForwardSolution forward(fwdFile, false, true);
if (forward.isEmpty()) {
qCritical() << "Error: Could not read forward solution from" << fwdName;
diff --git a/src/applications/mne_make_source_space/main.cpp b/src/applications/mne_make_source_space/main.cpp
index 696d10d7a94..a92bdc82784 100644
--- a/src/applications/mne_make_source_space/main.cpp
+++ b/src/applications/mne_make_source_space/main.cpp
@@ -49,8 +49,8 @@
#include
#include
-#include
-#include
+#include
+#include
#include
diff --git a/src/applications/mne_scan/libs/scDisp/realtime3dwidget.cpp b/src/applications/mne_scan/libs/scDisp/realtime3dwidget.cpp
index 0d704b11c77..86cfb6aa570 100644
--- a/src/applications/mne_scan/libs/scDisp/realtime3dwidget.cpp
+++ b/src/applications/mne_scan/libs/scDisp/realtime3dwidget.cpp
@@ -65,6 +65,8 @@
#include
+#include
+
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================
diff --git a/src/applications/mne_scan/libs/scDisp/realtime3dwidget.h b/src/applications/mne_scan/libs/scDisp/realtime3dwidget.h
index 2b621036a52..09e5b915757 100644
--- a/src/applications/mne_scan/libs/scDisp/realtime3dwidget.h
+++ b/src/applications/mne_scan/libs/scDisp/realtime3dwidget.h
@@ -46,8 +46,8 @@
#include
-#include
-#include
+#include
+#include
//=============================================================================================================
// QT INCLUDES
diff --git a/src/applications/mne_scan/libs/scMeas/CMakeLists.txt b/src/applications/mne_scan/libs/scMeas/CMakeLists.txt
index a6b0ef85fc9..5b379aba93c 100644
--- a/src/applications/mne_scan/libs/scMeas/CMakeLists.txt
+++ b/src/applications/mne_scan/libs/scMeas/CMakeLists.txt
@@ -74,7 +74,9 @@ set(MNE_LIBS_REQUIRED
mne_utils
mne_fiff
mne_fs
+ mne_fwd
mne_mne
+ mne_inverse
mne_connectivity
)
diff --git a/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.cpp b/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.cpp
index a7fdfb5344c..bc2a0208624 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.cpp
+++ b/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.cpp
@@ -40,10 +40,10 @@
#include
-#include
+#include
-#include
-#include
+#include
+#include
#include
@@ -58,6 +58,7 @@
using namespace SCMEASLIB;
using namespace CONNECTIVITYLIB;
using namespace MNELIB;
+using namespace FWDLIB;
using namespace FSLIB;
//=============================================================================================================
@@ -68,7 +69,7 @@ RealTimeConnectivityEstimate::RealTimeConnectivityEstimate(QObject *parent)
: Measurement(QMetaType::fromName("RealTimeConnectivityEstimate::SPtr").id(), parent)
, m_pAnnotSet(AnnotationSet::SPtr(new AnnotationSet))
, m_pSurfSet(SurfaceSet::SPtr(new SurfaceSet))
-, m_pFwdSolution(MNEForwardSolution::SPtr(new MNEForwardSolution))
+, m_pFwdSolution(FwdForwardSolution::SPtr(new FwdForwardSolution))
, m_pNetwork(Network::SPtr(new Network))
, m_bInitialized(false)
{
diff --git a/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.h b/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.h
index f3fc1f3841b..60cf6cb7234 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.h
+++ b/src/applications/mne_scan/libs/scMeas/realtimeconnectivityestimate.h
@@ -62,8 +62,11 @@ namespace FIFFLIB {
class FiffInfo;
}
+namespace FWDLIB {
+ class FwdForwardSolution;
+}
+
namespace MNELIB {
- class MNEForwardSolution;
class MNEBem;
}
@@ -159,7 +162,7 @@ class SCMEASSHARED_EXPORT RealTimeConnectivityEstimate : public Measurement
*
* @param[in] fwdSolution the forward solution to set.
*/
- inline void setFwdSolution(const QSharedPointer& fwdSolution);
+ inline void setFwdSolution(const QSharedPointer& fwdSolution);
//=========================================================================================================
/**
@@ -167,7 +170,7 @@ class SCMEASSHARED_EXPORT RealTimeConnectivityEstimate : public Measurement
*
* @return the forward solution.
*/
- inline QSharedPointer& getFwdSolution();
+ inline QSharedPointer& getFwdSolution();
//=========================================================================================================
/**
@@ -218,7 +221,7 @@ class SCMEASSHARED_EXPORT RealTimeConnectivityEstimate : public Measurement
QSharedPointer m_pAnnotSet; /**< Annotation set. Needed for visualization. */
QSharedPointer m_pSurfSet; /**< Surface set. Needed for visualization. */
- QSharedPointer m_pFwdSolution; /**< Forward solution. Needed for visualization. */
+ QSharedPointer m_pFwdSolution; /**< Forward solution. Needed for visualization. */
QSharedPointer m_pSensorSurface; /**< The sensor surface. Needed for visualization. */
QSharedPointer m_pNetwork; /**< The network/connectivity estimate. */
@@ -277,7 +280,7 @@ inline QSharedPointer& RealTimeConnectivityEstimate::getSurfS
//=============================================================================================================
-inline void RealTimeConnectivityEstimate::setFwdSolution(const QSharedPointer& fwdSolution)
+inline void RealTimeConnectivityEstimate::setFwdSolution(const QSharedPointer& fwdSolution)
{
QMutexLocker locker(&m_qMutex);
m_pFwdSolution = fwdSolution;
@@ -285,7 +288,7 @@ inline void RealTimeConnectivityEstimate::setFwdSolution(const QSharedPointer& RealTimeConnectivityEstimate::getFwdSolution()
+inline QSharedPointer& RealTimeConnectivityEstimate::getFwdSolution()
{
QMutexLocker locker(&m_qMutex);
return m_pFwdSolution;
diff --git a/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.cpp b/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.cpp
index 4065e786d9f..b59c218338b 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.cpp
+++ b/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.cpp
@@ -37,7 +37,7 @@
//=============================================================================================================
#include "realtimefwdsolution.h"
-#include
+#include
#include
//=============================================================================================================
@@ -51,6 +51,7 @@
using namespace SCMEASLIB;
using namespace FIFFLIB;
using namespace MNELIB;
+using namespace FWDLIB;
//=============================================================================================================
// DEFINE MEMBER METHODS
@@ -60,7 +61,7 @@ RealTimeFwdSolution::RealTimeFwdSolution(QObject *parent)
: Measurement(QMetaType::fromName("RealTimeFwdSolution::SPtr").id(), parent)
, m_bInitialized(false)
, m_bClustered(false)
-, m_pFwdSolution(QSharedPointer(new MNEForwardSolution))
+, m_pFwdSolution(QSharedPointer(new FwdForwardSolution))
{
}
@@ -86,7 +87,7 @@ QSharedPointer RealTimeFwdSolution::getFiffInfo()
//=============================================================================================================
-QSharedPointer RealTimeFwdSolution::getValue()
+QSharedPointer RealTimeFwdSolution::getValue()
{
QMutexLocker locker(&m_qMutex);
return m_pFwdSolution;
@@ -94,7 +95,7 @@ QSharedPointer RealTimeFwdSolution::getValue()
//=============================================================================================================
-void RealTimeFwdSolution::setValue(const MNEForwardSolution::SPtr pFwdSolution)
+void RealTimeFwdSolution::setValue(const FwdForwardSolution::SPtr pFwdSolution)
{
m_qMutex.lock();
m_pFwdSolution = pFwdSolution;
diff --git a/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.h b/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.h
index 3446deb9f40..386235e7fc4 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.h
+++ b/src/applications/mne_scan/libs/scMeas/realtimefwdsolution.h
@@ -42,7 +42,7 @@
#include "scmeas_global.h"
#include "measurement.h"
-#include
+#include
//=============================================================================================================
// QT INCLUDES
@@ -63,8 +63,8 @@ namespace FIFFLIB{
class FiffInfo;
}
-namespace MNELIB{
- class MNEForwardSolution;
+namespace FWDLIB{
+ class FwdForwardSolution;
}
//=============================================================================================================
@@ -122,7 +122,7 @@ class SCMEASSHARED_EXPORT RealTimeFwdSolution : public Measurement
*
* @param[in] fwdSolution The forward solution which should be distributed.
*/
- virtual void setValue(const MNELIB::MNEForwardSolution::SPtr pFwdSolution);
+ virtual void setValue(const FWDLIB::FwdForwardSolution::SPtr pFwdSolution);
//=========================================================================================================
/**
@@ -131,7 +131,7 @@ class SCMEASSHARED_EXPORT RealTimeFwdSolution : public Measurement
*
* @return The last attached value.
*/
- virtual QSharedPointer getValue();
+ virtual QSharedPointer getValue();
//=========================================================================================================
/**
@@ -186,7 +186,7 @@ class SCMEASSHARED_EXPORT RealTimeFwdSolution : public Measurement
bool m_bInitialized; /**< If values are stored.*/
bool m_bClustered; /**< If fwd is clustered.*/
- QSharedPointer m_pFwdSolution; /**< The Mne Forward Solution. */
+ QSharedPointer m_pFwdSolution; /**< The Mne Forward Solution. */
QSharedPointer m_pFiffInfo; /**< The Fiff Info. */
QSharedDataPointer m_pNamedMatSol; /**< The solution matrix (LF). */
diff --git a/src/applications/mne_scan/libs/scMeas/realtimehpiresult.h b/src/applications/mne_scan/libs/scMeas/realtimehpiresult.h
index 50fc5775639..897faa23955 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimehpiresult.h
+++ b/src/applications/mne_scan/libs/scMeas/realtimehpiresult.h
@@ -42,7 +42,7 @@
#include "scmeas_global.h"
#include "measurement.h"
-#include
+#include
//=============================================================================================================
// QT INCLUDES
diff --git a/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.cpp b/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.cpp
index adb8d5d0374..97e4db47414 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.cpp
+++ b/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.cpp
@@ -49,6 +49,8 @@
using namespace SCMEASLIB;
using namespace MNELIB;
+using namespace FWDLIB;
+using namespace INVERSELIB;
using namespace FSLIB;
//=============================================================================================================
@@ -59,7 +61,7 @@ RealTimeSourceEstimate::RealTimeSourceEstimate(QObject *parent)
: Measurement(QMetaType::fromName("RealTimeSourceEstimate::SPtr").id(), parent)
, m_pAnnotSet(AnnotationSet::SPtr(new AnnotationSet))
, m_pSurfSet(SurfaceSet::SPtr(new SurfaceSet))
-, m_pFwdSolution(MNEForwardSolution::SPtr(new MNEForwardSolution))
+, m_pFwdSolution(FwdForwardSolution::SPtr(new FwdForwardSolution))
, m_iSourceEstimateSize(1)
, m_bInitialized(false)
{
diff --git a/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.h b/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.h
index a87321176e9..39d2d491c30 100644
--- a/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.h
+++ b/src/applications/mne_scan/libs/scMeas/realtimesourceestimate.h
@@ -43,16 +43,16 @@
#include "scmeas_global.h"
#include "measurement.h"
-#include
-#include
-#include
+#include
+#include
+#include
#include
#include
#include
-#include
-#include
+#include
+#include
//=============================================================================================================
// QT INCLUDES
@@ -151,7 +151,7 @@ class SCMEASSHARED_EXPORT RealTimeSourceEstimate : public Measurement
*
* @param[in] fwdSolution the forward solution to set.
*/
- inline void setFwdSolution(MNELIB::MNEForwardSolution::SPtr& fwdSolution);
+ inline void setFwdSolution(FWDLIB::FwdForwardSolution::SPtr& fwdSolution);
//=========================================================================================================
/**
@@ -159,7 +159,7 @@ class SCMEASSHARED_EXPORT RealTimeSourceEstimate : public Measurement
*
* @return the forward solution.
*/
- inline MNELIB::MNEForwardSolution::SPtr& getFwdSolution();
+ inline FWDLIB::FwdForwardSolution::SPtr& getFwdSolution();
//=========================================================================================================
/**
@@ -168,7 +168,7 @@ class SCMEASSHARED_EXPORT RealTimeSourceEstimate : public Measurement
*
* @param[in] v the value which is attached to the sample array vector.
*/
- virtual void setValue(MNELIB::MNESourceEstimate &v);
+ virtual void setValue(INVERSELIB::MNESourceEstimate &v);
//=========================================================================================================
/**
@@ -177,7 +177,7 @@ class SCMEASSHARED_EXPORT RealTimeSourceEstimate : public Measurement
*
* @return the last attached value.
*/
- virtual QList& getValue();
+ virtual QList& getValue();
//=========================================================================================================
/**
@@ -227,11 +227,11 @@ class SCMEASSHARED_EXPORT RealTimeSourceEstimate : public Measurement
FSLIB::AnnotationSet::SPtr m_pAnnotSet; /**< Annotation set. */
FSLIB::SurfaceSet::SPtr m_pSurfSet; /**< Surface set. */
- MNELIB::MNEForwardSolution::SPtr m_pFwdSolution; /**< Forward solution. */
+ FWDLIB::FwdForwardSolution::SPtr m_pFwdSolution; /**< Forward solution. */
qint32 m_iSourceEstimateSize; /**< Sample size of the multi sample array.*/
- QList m_pMNEStc; /**< The source estimates. */
+ QList m_pMNEStc; /**< The source estimates. */
bool m_bInitialized; /**< Is initialized. */
};
@@ -286,7 +286,7 @@ inline FIFFLIB::FiffCoordTrans& RealTimeSourceEstimate::getMriHeadTrans()
}
//=============================================================================================================
-inline void RealTimeSourceEstimate::setFwdSolution(MNELIB::MNEForwardSolution::SPtr& fwdSolution)
+inline void RealTimeSourceEstimate::setFwdSolution(FWDLIB::FwdForwardSolution::SPtr& fwdSolution)
{
QMutexLocker locker(&m_qMutex);
m_pFwdSolution = fwdSolution;
@@ -294,7 +294,7 @@ inline void RealTimeSourceEstimate::setFwdSolution(MNELIB::MNEForwardSolution::S
//=============================================================================================================
-inline MNELIB::MNEForwardSolution::SPtr& RealTimeSourceEstimate::getFwdSolution()
+inline FWDLIB::FwdForwardSolution::SPtr& RealTimeSourceEstimate::getFwdSolution()
{
QMutexLocker locker(&m_qMutex);
return m_pFwdSolution;
diff --git a/src/applications/mne_scan/plugins/hpi/hpi.cpp b/src/applications/mne_scan/plugins/hpi/hpi.cpp
index c281c008d0c..47f6fbfaf1b 100644
--- a/src/applications/mne_scan/plugins/hpi/hpi.cpp
+++ b/src/applications/mne_scan/plugins/hpi/hpi.cpp
@@ -46,8 +46,8 @@
#include
#include
#include
-#include
-#include
+#include
+#include
#include
#include
diff --git a/src/applications/mne_scan/plugins/rtcmne/FormFiles/rtcmnesetupwidget.cpp b/src/applications/mne_scan/plugins/rtcmne/FormFiles/rtcmnesetupwidget.cpp
index fb87df4d708..240ac356be1 100644
--- a/src/applications/mne_scan/plugins/rtcmne/FormFiles/rtcmnesetupwidget.cpp
+++ b/src/applications/mne_scan/plugins/rtcmne/FormFiles/rtcmnesetupwidget.cpp
@@ -41,11 +41,11 @@
#include "../rtcmne.h"
-#include
-#include
+#include
+#include
#include
-#include
+#include
#include
diff --git a/src/applications/mne_scan/plugins/rtcmne/rtcmne.cpp b/src/applications/mne_scan/plugins/rtcmne/rtcmne.cpp
index 3801d465f82..eb413bdc42d 100644
--- a/src/applications/mne_scan/plugins/rtcmne/rtcmne.cpp
+++ b/src/applications/mne_scan/plugins/rtcmne/rtcmne.cpp
@@ -43,16 +43,16 @@
#include
-#include
-#include
+#include
+#include
#include
-#include
-#include
+#include
+#include
#include
-#include
+#include
#include
diff --git a/src/applications/mne_scan/plugins/rtcmne/rtcmne.h b/src/applications/mne_scan/plugins/rtcmne/rtcmne.h
index 83c36037120..a81a1f8d3a5 100644
--- a/src/applications/mne_scan/plugins/rtcmne/rtcmne.h
+++ b/src/applications/mne_scan/plugins/rtcmne/rtcmne.h
@@ -48,12 +48,13 @@
#include
-#include
+#include
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================
+#include
#include
#include
#include
@@ -66,9 +67,8 @@ namespace DISPLIB {
class MinimumNormSettingsView;
}
-namespace MNELIB {
- class MNEForwardSolution;
- class MNEInverseOperator;
+namespace FWDLIB {
+ class FwdForwardSolution;
}
namespace FIFFLIB {
@@ -77,6 +77,7 @@ namespace FIFFLIB {
}
namespace INVERSELIB {
+ class MNEInverseOperator;
class MinimumNorm;
}
@@ -189,7 +190,7 @@ class RTCMNESHARED_EXPORT RtcMne : public SCSHAREDLIB::AbstractAlgorithm
*
* @param[in] invOp The inverse operator to update.
*/
- void updateInvOp(const MNELIB::MNEInverseOperator& invOp);
+ void updateInvOp(const INVERSELIB::MNEInverseOperator& invOp);
//=========================================================================================================
/**
@@ -232,7 +233,7 @@ class RTCMNESHARED_EXPORT RtcMne : public SCSHAREDLIB::AbstractAlgorithm
QSharedPointer m_pCircularMatrixBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/
QSharedPointer > m_pCircularEvokedBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/
QSharedPointer m_pRtInvOp; /**< Real-time inverse operator. */
- QSharedPointer m_pFwd; /**< Forward solution. */
+ QSharedPointer m_pFwd; /**< Forward solution. */
QSharedPointer m_pNoiseCov; /**< Noise Covariance Matrix. */
QSharedPointer m_pAnnotationSet; /**< Annotation set. */
QSharedPointer m_pSurfaceSet; /**< Surface set. */
@@ -263,7 +264,7 @@ class RTCMNESHARED_EXPORT RtcMne : public SCSHAREDLIB::AbstractAlgorithm
QStringList m_qListCovChNames; /**< Covariance channel names. */
QStringList m_qListPickChannels; /**< Channels to pick. */
- MNELIB::MNEInverseOperator m_invOp; /**< The inverse operator. */
+ INVERSELIB::MNEInverseOperator m_invOp; /**< The inverse operator. */
signals:
void responsibleTriggerTypesChanged(const QStringList& lResponsibleTriggerTypes);
diff --git a/src/applications/mne_scan/plugins/rtfwd/FormFiles/rtfwdsetupwidget.cpp b/src/applications/mne_scan/plugins/rtfwd/FormFiles/rtfwdsetupwidget.cpp
index 8c884400d98..f307c161f10 100644
--- a/src/applications/mne_scan/plugins/rtfwd/FormFiles/rtfwdsetupwidget.cpp
+++ b/src/applications/mne_scan/plugins/rtfwd/FormFiles/rtfwdsetupwidget.cpp
@@ -40,7 +40,7 @@
#include
-#include
+#include
//=============================================================================================================
// QT INCLUDES
diff --git a/src/applications/mne_scan/plugins/rtfwd/rtfwd.cpp b/src/applications/mne_scan/plugins/rtfwd/rtfwd.cpp
index 1be8a4ce057..aab02243351 100644
--- a/src/applications/mne_scan/plugins/rtfwd/rtfwd.cpp
+++ b/src/applications/mne_scan/plugins/rtfwd/rtfwd.cpp
@@ -40,14 +40,14 @@
#include
-#include
-#include
+#include
+#include
-#include
+#include
-#include
+#include
-#include
+#include
#include
#include
@@ -59,6 +59,7 @@
#include
#include
+#include
//=============================================================================================================
// EIGEN INCLUDES
@@ -425,11 +426,10 @@ void RtFwd::run()
// initialize fwd solution
emit statusInformationChanged(0); // initializing
- ComputeFwd::SPtr pComputeFwd = ComputeFwd::SPtr(new ComputeFwd(m_pFwdSettings));
+ ComputeFwd::SPtr pFwdComputer = ComputeFwd::SPtr(new ComputeFwd(m_pFwdSettings));
- QFile t_fSolution(m_pFwdSettings->solname);
- MNEForwardSolution::SPtr pFwdSolution;
- MNEForwardSolution::SPtr pClusteredFwd;
+ FwdForwardSolution::SPtr pFwdSolution;
+ FwdForwardSolution::SPtr pClusteredFwd;
emit statusInformationChanged(4); // not computed
@@ -456,11 +456,10 @@ void RtFwd::run()
m_mutex.unlock();
// compute and store
- pComputeFwd->calculateFwd();
- pComputeFwd->storeFwd();
+ pFwdSolution.reset(pFwdComputer->calculateFwd().release());
- // get Mne Forward Solution (in future this is not necessary, ComputeForward will have this as member)
- pFwdSolution = MNEForwardSolution::SPtr(new MNEForwardSolution(t_fSolution, false, true));
+ QFile fwdFile(m_pFwdSettings->solname);
+ pFwdSolution->write(fwdFile);
// emit results to control widget
emit fwdSolutionAvailable(pFwdSolution->source_ori,
@@ -503,9 +502,7 @@ void RtFwd::run()
transMegHead = m_pHpiFitResult->devHeadTrans;
m_mutex.unlock();
- pComputeFwd->updateHeadPos(transMegHead);
- pFwdSolution->sol = pComputeFwd->sol;
- pFwdSolution->sol_grad = pComputeFwd->sol_grad;
+ pFwdComputer->updateHeadPos(transMegHead, *pFwdSolution);
m_mutex.lock();
m_bBusy = false;
@@ -528,7 +525,7 @@ void RtFwd::run()
if(bDoClustering && bFwdReady && bNClusterChanged) {
emit statusInformationChanged(3); // clustering
- pClusteredFwd = MNEForwardSolution::SPtr(new MNEForwardSolution(pFwdSolution->cluster_forward_solution(*m_pAnnotationSet.data(), m_pFwdSettings->ncluster)));
+ pClusteredFwd = FwdForwardSolution::SPtr(new FwdForwardSolution(pFwdSolution->cluster_forward_solution(*m_pAnnotationSet.data(), m_pFwdSettings->ncluster)));
emit clusteringAvailable(pClusteredFwd->nsource);
m_pRTFSOutput->measurementData()->setValue(pClusteredFwd);
diff --git a/src/applications/mne_scan/plugins/rtfwd/rtfwd.h b/src/applications/mne_scan/plugins/rtfwd/rtfwd.h
index f4872eb4344..676ab8243cf 100644
--- a/src/applications/mne_scan/plugins/rtfwd/rtfwd.h
+++ b/src/applications/mne_scan/plugins/rtfwd/rtfwd.h
@@ -75,8 +75,8 @@ namespace FWDLIB {
class ComputeFwd;
}
-namespace MNELIB{
- class MNEForwardSolution;
+namespace FWDLIB{
+ class FwdForwardSolution;
}
namespace FSLIB{
diff --git a/src/applications/mne_setup_forward_model/setupforwardmodel.cpp b/src/applications/mne_setup_forward_model/setupforwardmodel.cpp
index 3e24180e13e..0acf260d0db 100644
--- a/src/applications/mne_setup_forward_model/setupforwardmodel.cpp
+++ b/src/applications/mne_setup_forward_model/setupforwardmodel.cpp
@@ -54,7 +54,7 @@
#include "setupforwardmodel.h"
#include "mne_setup_forward_model_settings.h"
-#include
+#include
#include
#include
@@ -662,7 +662,7 @@ bool SetupForwardModel::prepareBemSolution(const QString& bemFile,
// 2. Compute the linear collocation solution
// 3. Save the BEM model with the solution to a new FIFF file
//
- FwdBemModel* bemModel = nullptr;
+ std::unique_ptr bemModel;
if (m_settings.homogeneous()) {
bemModel = FwdBemModel::fwd_bem_load_homog_surface(const_cast(bemFile));
@@ -677,10 +677,9 @@ bool SetupForwardModel::prepareBemSolution(const QString& bemFile,
printf("Computing the linear collocation solution...\n");
- int result = FwdBemModel::fwd_bem_compute_solution(bemModel, FWD_BEM_LINEAR_COLL);
+ int result = bemModel->fwd_bem_compute_solution(FWD_BEM_LINEAR_COLL);
if (result != 0) {
qCritical() << "BEM solution computation failed.";
- delete bemModel;
return false;
}
@@ -711,7 +710,7 @@ bool SetupForwardModel::prepareBemSolution(const QString& bemFile,
for (int k = 0; k < bemModel->nsurf; ++k) {
stream->start_block(FIFFB_BEM_SURF);
- MNESurface* s = bemModel->surfs[k];
+ MNESurface* s = bemModel->surfs[k].get();
// Surface ID
int surfId = s->id;
@@ -762,14 +761,8 @@ bool SetupForwardModel::prepareBemSolution(const QString& bemFile,
}
// Write the solution matrix
- if (bemModel->solution && bemModel->nsol > 0) {
- MatrixXf solMat(bemModel->nsol, bemModel->nsol);
- for (int i = 0; i < bemModel->nsol; ++i) {
- for (int j = 0; j < bemModel->nsol; ++j) {
- solMat(i, j) = bemModel->solution[i][j];
- }
- }
- stream->write_float_matrix(FIFF_BEM_POT_SOLUTION, solMat);
+ if (bemModel->solution.size() > 0 && bemModel->nsol > 0) {
+ stream->write_float_matrix(FIFF_BEM_POT_SOLUTION, bemModel->solution);
}
stream->end_block(FIFFB_BEM);
@@ -778,6 +771,6 @@ bool SetupForwardModel::prepareBemSolution(const QString& bemFile,
printf("Saved the result to %s\n", qPrintable(solFile));
- delete bemModel;
+
return true;
}
diff --git a/src/applications/mne_surf2bem/surf2bem.cpp b/src/applications/mne_surf2bem/surf2bem.cpp
index c5ec019ddb5..d94e5d8c128 100644
--- a/src/applications/mne_surf2bem/surf2bem.cpp
+++ b/src/applications/mne_surf2bem/surf2bem.cpp
@@ -45,7 +45,7 @@
#include "mne_surf2bem_settings.h"
#include "surfacechecks.h"
-#include
+#include
#include
#include
@@ -117,6 +117,7 @@ int Surf2Bem::run()
if (!m_settings.outputFile().isEmpty())
fprintf(stderr, "output file : %s\n", qPrintable(m_settings.outputFile()));
fprintf(stderr, "\n");
+ fflush(stderr);
//
// Step 1: Read all surfaces
@@ -136,12 +137,14 @@ int Surf2Bem::run()
}
if (!ok) {
- qCritical() << "Failed to read surface" << inputs[k].fileName;
+ fprintf(stderr, "Failed to read surface %s\n", qPrintable(inputs[k].fileName));
+ fflush(stderr);
return 1;
}
surfs[k].id = inputs[k].id;
fprintf(stderr, "%s read. id = %d\n\n", qPrintable(inputs[k].fileName), inputs[k].id);
+ fflush(stderr);
}
//
@@ -226,7 +229,8 @@ bool Surf2Bem::readFreeSurferSurface(const SurfaceInput& input, MNEBemSurface& b
//
QFile file(input.fileName);
if (!file.open(QIODevice::ReadOnly)) {
- qCritical() << "Could not open surface file:" << input.fileName;
+ fprintf(stderr, "Could not open surface file: %s\n", qPrintable(input.fileName));
+ fflush(stderr);
return false;
}
@@ -252,6 +256,7 @@ bool Surf2Bem::readFreeSurferSurface(const SurfaceInput& input, MNEBemSurface& b
fprintf(stderr, "%s: triangle file with %d vertices and %d triangles\n",
qPrintable(input.fileName), nvert, nface);
+ fflush(stderr);
// Read vertices (stored as 3 x nvert, column-major float32 big-endian)
verts.resize(3, nvert);
@@ -268,8 +273,9 @@ bool Surf2Bem::readFreeSurferSurface(const SurfaceInput& input, MNEBemSurface& b
}
}
} else {
- qCritical() << "Unsupported surface file format (magic =" << magic << ") in" << input.fileName;
- qCritical() << "Only FreeSurfer triangle format (0xFFFFFE) is supported for BEM surfaces.";
+ fprintf(stderr, "Unsupported surface file format (magic = %d) in %s\n", magic, qPrintable(input.fileName));
+ fprintf(stderr, "Only FreeSurfer triangle format (0xFFFFFE) is supported for BEM surfaces.\n");
+ fflush(stderr);
return false;
}
@@ -293,6 +299,7 @@ bool Surf2Bem::readFreeSurferSurface(const SurfaceInput& input, MNEBemSurface& b
fprintf(stderr, "Read FreeSurfer surface: %d vertices, %d triangles\n",
bemSurf.np, bemSurf.ntri);
+ fflush(stderr);
return true;
}
diff --git a/src/applications/mne_watershed_bem/watershedbem.cpp b/src/applications/mne_watershed_bem/watershedbem.cpp
index 6a9af90cdc8..10a1aab0ccc 100644
--- a/src/applications/mne_watershed_bem/watershedbem.cpp
+++ b/src/applications/mne_watershed_bem/watershedbem.cpp
@@ -51,7 +51,7 @@
#include "watershedbem.h"
#include "mne_watershed_bem_settings.h"
-#include
+#include
#include
#include
diff --git a/src/examples/ex_averaging/main.cpp b/src/examples/ex_averaging/main.cpp
index 0802b0f233e..3d67e33212c 100644
--- a/src/examples/ex_averaging/main.cpp
+++ b/src/examples/ex_averaging/main.cpp
@@ -55,6 +55,7 @@
#include