Skip to main content

ex_compute_forward

This example shows how to compute the forward solution.

Libraries: Forward, MNE Core, FIFF I/O, Utilities

Options​

OptionDescription
--parameterThe first parameter description.

Build and run​

cmake --build build/developer-dynamic --target ex_compute_forward
./out/Release/examples/ex_compute_forward --help

The default inputs come from the MNE sample dataset.

Used in the API reference​

Source​

src/examples/ex_compute_forward/main.cpp
//=============================================================================================================
/**
* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2020-2026 MNE-CPP Authors
*
* @file main.cpp
* @author Gabriel Motta <gabrielbenmotta@gmail.com>;
* Christoph Dinh <christoph.dinh@mne-cpp.org>;
* Ruben Dörfel <ruben.deorfel@tu-ilmenau.de>
* @date April, 2020
* @version dev
* @brief This example shows how to compute the forward solution.
*/

//=============================================================================================================
// INCLUDES
//=============================================================================================================
#include <iostream>
#include <memory>

#include <utils/generics/mne_logger.h>

#include <fiff/fiff.h>
#include <fiff/fiff_info.h>

#include <fwd/compute_fwd/compute_fwd_settings.h>
#include <fwd/compute_fwd/compute_fwd.h>

#include <mne/mne_forward_solution.h>

#include <mne/mne.h>
//=============================================================================================================
// Eigen
//=============================================================================================================

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QApplication>
#include <QCommandLineParser>
#include <QFile>
#include <QElapsedTimer>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FWDLIB;
using namespace FIFFLIB;
using namespace MNELIB;
using namespace Eigen;

//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
* The function main marks the entry point of the program.
* By default, main has the storage class extern.
*
* @param[in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
* @param[in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
* @return the value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int main(int argc, char* argv[])
{
qInstallMessageHandler(UTILSLIB::MNELogger::customLogWriter);
QCoreApplication a(argc, argv);

QElapsedTimer timer0, timer1, timer2, timer3, timer4;
float fTime0, fTime1, fTime2, fTime3, fTime4;

// Command Line Parser
QCommandLineParser parser;
parser.setApplicationDescription("Example name");
parser.addHelpOption();

QCommandLineOption parameterOption("parameter", "The first parameter description.");
parser.addOption(parameterOption);

parser.process(a);

// specify necessary information for forward computation
std::shared_ptr<ComputeFwdSettings> pSettings = std::make_shared<ComputeFwdSettings>();

QFile t_fileBemName(QCoreApplication::applicationDirPath() + "/../resources/data/MNE-sample-data/subjects/sample/bem/sample-5120-5120-5120-bem.fif");
QFile t_fileSrcName(QCoreApplication::applicationDirPath() + "/../resources/data/MNE-sample-data/subjects/sample/bem/sample-oct-6-src.fif");

pSettings->include_meg = true;
pSettings->include_eeg = true;
pSettings->accurate = true;
pSettings->srcname = QCoreApplication::applicationDirPath() + "/../resources/data/MNE-sample-data/subjects/sample/bem/sample-oct-6-src.fif";
pSettings->measname = QCoreApplication::applicationDirPath() + "/../resources/data/mne-cpp-test-data/MEG/sample/sample_audvis_trunc_raw.fif";
pSettings->mriname = QCoreApplication::applicationDirPath() + "/../resources/data/mne-cpp-test-data/MEG/sample/all-trans.fif";
pSettings->transname.clear();
pSettings->bemname = QCoreApplication::applicationDirPath() + "/../resources/data/MNE-sample-data/subjects/sample/bem/sample-5120-5120-5120-bem.fif";
pSettings->mindist = 5.0f / 1000.0f;
pSettings->solname = QCoreApplication::applicationDirPath() + "/../resources/data/mne-cpp-test-data/Result/sample_audvis-meg-eeg-oct-6-fwd.fif";

// bring in dev_head transformation and FiffInfo
// Init data loading and writing
QFile t_fileIn(pSettings->measname);
FiffRawData raw(t_fileIn);
QSharedPointer<FiffInfo> pFiffInfo = QSharedPointer<FiffInfo>::create(raw.info);

FiffCoordTrans meg_head_t = pFiffInfo->dev_head_t;

pSettings->meg_head_t = meg_head_t;
pSettings->pFiffInfo = pFiffInfo;

pSettings->checkIntegrity();

timer0.start();
std::shared_ptr<ComputeFwd> pFwdComputer = std::make_shared<ComputeFwd>(pSettings);
fTime0 = timer0.elapsed();

// perform the actual computation
timer1.start();
auto pFwdSolution = pFwdComputer->calculateFwd();
fTime1 = timer1.elapsed();

// store calculated forward solution
timer2.start();
QFile fwdFile(pSettings->solname);
pFwdSolution->write(fwdFile);
fTime2 = timer2.elapsed();

// read back to verify round-trip
timer3.start();
QFile t_solution(pSettings->solname);
MNEForwardSolution::SPtr pFwdRead = MNEForwardSolution::SPtr(new MNEForwardSolution(t_solution));
fTime3 = timer3.elapsed();

// update head position and recompute
timer4.start();
pFwdComputer->updateHeadPos(meg_head_t, *pFwdSolution);
fTime4 = timer4.elapsed();

// Print timer results
qInfo() << "The initialization took: " << fTime0 << " ms.";
qInfo() << "The computation took: " << fTime1 << " ms.";
qInfo() << "Storing the fwd solution took: " << fTime2 << " ms.";
qInfo() << "Reading the fwd solution took: " << fTime3 << " ms.";
qInfo() << "The recomputation took: " << fTime4 << " ms.";
}