Skip to main content

Coding Conventions

Naming

Please make use of the following coding conventions when contributing to MNE-CPP:

ObjectRule
NamespaceMYNAMESPACE
ClassesMyClass
Member functionsmyFunction
Member variablesm_typeMeaningfulName
Local variablestypeMeaningfulName

Readability and Documentation

Use meaningful variable names and type indicators. Avoid complex as well as condensed expressions. For example:

int iNumChs = 306;
QString sChName = "MEG0000";
void loadTxtFile(const QString& sPath);

In general, try to make your code match the surrounding style — indentation, line breaks, etc. Use Doxygen-style comments to document your code (see example). When introducing new functions, include the @since tag with the current version. Always align function parameters in .h and .cpp files:

//=========================================================================================================
/**
* Constructs a FileLoader object.
*
* @param[in] iOpenMode The open mode. 0=ReadWrite, 1=WriteOnly, 1=ReadOnly
* @param[in] bSkipEmptyLines Whether to skip empty lines.
* @param[in] sCommentIdentifier String to identify comments. Default is empty which
* results in comments being read as normal lines.
* @since 0.1.1
*/
FileLoader(int iOpenMode,
bool bSkipEmptyLines,
const QString& sCommentIdentifier = "");

Documentation Scope: Public API vs. Application Code

MNE-CPP draws a deliberate line between the reusable library contract and the application/plugin code that consumes it:

  • Libraries (src/libraries/) are the public API. They are documented with full Doxygen comments and published to the website API reference. The public doc/Doxyfile extracts XML from these headers only.
  • Applications & plugins (src/applications/) are not part of the public API and are intentionally excluded from the published reference. They still deserve maintainer-level documentation: add a brief @brief file/class header describing the component's responsibility, plus inline comments for non-obvious logic. You do not need the full parameter-by-parameter @param/@return treatment expected of library API.

If a piece of documentation lives in a header that is scanned for the public API but is only relevant to maintainers, wrap it in an @internal / @endinternal block so it is stripped from the published reference:

/**
* @internal
* Implementation note: the spectral cache is rebuilt lazily on the first
* metric request to avoid paying for an FFT that may never be needed.
* @endinternal
*/

To browse the application/plugin internals locally, generate the separate maintainer doc set (HTML, never published):

./doc/build-internal-docs.sh # output: doc/internal_out/html/index.html

This uses doc/Doxyfile.internal, which adds src/applications to the input and enables INTERNAL_DOCS, keeping the published API surface limited to the libraries.

MNE-CPP Class Templates

MNE-CPP provides class templates under resources/wizards/mnecpp/ that follow the project's coding conventions. These templates can help you quickly scaffold new classes that are consistent with the existing codebase.

Using with QtCreator

If you use QtCreator as your IDE, you can install these templates as wizards:

  1. Copy the resources/wizards/mnecpp folder to your QtCreator wizard directory. The location varies by OS — see the Qt documentation for details.
  2. Restart QtCreator.
  3. The MNE-CPP category will appear in the new file/class wizard.

Command Line Outputs

Every output should start with [<ClassName::FunctionName>]. Please make use of qDebug() during development and qInfo() for general user information. qWarning() should be used to alert about unusual situations that do not lead to a termination of the application. qCritical() should only be used if an error was caught that will lead to the application being terminated. For example:

void FileLoader::loadTxtFile(const QString& sPath)
{
qInfo() << "[FileLoader::loadTxtFile] Working on file" << sPath;

if(!sPath.contains(".txt")) {
qWarning() << "[FileLoader::loadTxtFile] The file does not end with .txt."
}

QFile file(sPath);
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "[FileLoader::loadTxtFile] Unable to open file."
return;
}
// ...
}

| Please note: Eigen objects (MatrixXd, VectorXd, etc.) can only be plotted via std::cout.|

Commit Policy

A good commit should follow:

  • If you add new functions/classes, ensure everything is documented properly.
  • All code should follow the Coding Conventions & Style.
  • Write new unit tests for the bugs you fixed or functionality you added.
  • Commit often! In particular: Make atomic commits. This means that each commit should contain exactly one self-contained change - do not mix unrelated changes, and do not create inconsistent states. Never "hide" unrelated fixes in bigger commits.
  • Write descriptive commit messages. Make them self-contained, so people do not have to research the historical context to make sense of them.
  • And most importantly: use your brain :)

For better readability, we introduced conventions for PR naming and commit messages. This gives a first impression about the content of a commit and improves the commit history's readability. Please use the following identifiers:

ShortMeaning
FIXbug fix
ENHenhancement (new features, etc.)
MAINTmaintenance commit (refactoring, typos, style fixes, etc.)
DOCdocumentation

The following examples show how such commit messages could look like:

FIX: fix namespace error
ENH: add cHPI in Neuromag Plugin
MAINT: improved GitHubAction workflow for Linux deployment
DOC: add documentation for new amplifier in MNE Scan

MNE-CPP Documentation in QtCreator

You can integrate MNE-CPP's API documentation into QtCreator's Help mode (F1):

  • Download the mne-cpp-doc-qtcreator.qch file from the MNE-CPP releases page.
  • In QtCreator, go to Tools → Options → Help → Documentation → Add and select the .qch file.