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.