Skip to main content

Parse a FIFF file from a memory buffer

Read a FIFF file from a memory buffer with a chosen byte order and summarise its contents.

Libraries: Connectivity, MNE Core, FIFF I/O

Results​

Console output
------------ Fiff Sniffer ------------
Input file : resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif
Num. raw dat sets: 1
Num. evoked sets: 0
---
Raw Set 0
Sample frequency: 600.615
LineFreq: -1 | Highpass: 0.1 | Lowpass: 172.176
First sample: 25800 | Last sample: 192599
Number of samples: 166799 | Time: 277.714 sec.
Number of digitizer points: 146
HPI Point 1 - 0.0329227, 0.0989798, 0.0798433
HPI Point 2 - -0.0699811, 0.0677165, 0.0688845
HPI Point 3 - -0.0726083, -0.0208683, 0.0971474
HPI Point 4 - 0.0499686, -0.00723305, 0.12289
---
--------------------------------------
Digitizer data found.
Number of digitizer points: 146
HPI Point 1 - 0.0329227, 0.0989798, 0.0798433
HPI Point 2 - -0.0699811, 0.0677165, 0.0688845
HPI Point 3 - -0.0726083, -0.0208683, 0.0971474
HPI Point 4 - 0.0499686, -0.00723305, 0.12289
Creating tag directory for TCPSocket...
Line frequency is not defined

Read a total of 3 projection items:

PCA-v1 (1 x 102) idle

PCA-v2 (1 x 102) idle

PCA-v3 (1 x 102) idle

Opening fiff data resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif...

Creating tag directory for resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif...
Line frequency is not defined

Read a total of 3 projection items:

PCA-v1 (1 x 102) idle

PCA-v2 (1 x 102) idle

PCA-v3 (1 x 102) idle

Opening raw data resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif...

Creating tag directory for resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif...
Line frequency is not defined

Read a total of 3 projection items:

PCA-v1 (1 x 102) idle

PCA-v2 (1 x 102) idle

PCA-v3 (1 x 102) idle

… 3 more lines

Build and run​

Needs the MNE sample dataset in resources/data/MNE-sample-data.

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

Options​

OptionDescription
--fileThe input file <in>.
--endianThe file's endianness. 'little' or 'big'
--padAdds -1 to end of stream to account for unfinished file (use for neuromag2ft)

Key API​

The documented classes this example uses most:

ClassLibrary
FiffFIFF I/O
FiffDigitizerDataFIFF I/O
FiffDirNodeFIFF I/O
FiffIOFIFF I/O
FiffInfoFIFF I/O
FiffStreamFIFF I/O
MNEMNE Core

Used in the API reference​

Source​

src/examples/ex_fiff_sniffer on GitHub.

src/examples/ex_fiff_sniffer/main.cpp
//=============================================================================================================
/**
* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2010-2026 MNE-CPP Authors
*
* @file main.cpp
* @author Gabriel Motta <gabrielbenmotta@gmail.com>;
* Christoph Dinh <christoph.dinh@mne-cpp.org>
* @brief Read a FIFF file from a memory buffer with a chosen byte order and summarise its contents
*/


//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <QCoreApplication>

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

#include <fiff/fiff_io.h>
#include <fiff/fiff_stream.h>
#include <fiff/fiff_digitizer_data.h>

////////////////////////

#include <connectivity/network/network.h>

#include <fiff/fiff_ch_info.h>
#include <fiff/fiff_digitizer_data.h>

#include <mne/mne_msh_display_surface_set.h>
#include <mne/mne_surface_or_volume.h>
//////////////////////

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

#include <QCommandLineParser>
#include <QBuffer>
#include <QtEndian>

//=============================================================================================================
// STL INCLUDES
//=============================================================================================================

#include <iostream>

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

using namespace CONNECTIVITYLIB;
using namespace MNELIB;
using namespace FIFFLIB;

int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);

QCommandLineParser parser;
parser.setApplicationDescription("Fiff Sniffer Example");
parser.addHelpOption();

QCommandLineOption inputOption({"file", "f"}, "The input file <in>.", "in", QCoreApplication::applicationDirPath() + "/../resources/data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif");
QCommandLineOption endianOption({"endian", "e", "en"}, "The file's endianness. 'little' or 'big'", "endian", "big");
QCommandLineOption padEndOption("pad", "Adds -1 to end of stream to account for unfinished file (use for neuromag2ft)");

parser.addOption(inputOption);
parser.addOption(endianOption);
parser.addOption(padEndOption);

parser.process(a);

bool littleEndian = false;
if (parser.value(endianOption) == "little") {
littleEndian = true;
}

QFile t_fileRaw(parser.value(inputOption));

std::cout << "\n------------ Fiff Sniffer ------------\n";
std::cout << "Input file : " << t_fileRaw.fileName().toStdString() << "\n";

if (!t_fileRaw.exists()) {
std::cout << "File cannot be found.\n";
std::cout << "\nBye!\n";

} else { //file found
QBuffer buffer;
if (!buffer.open(QIODevice::ReadWrite)) {
std::cout << "Buffer can't be opened.\n";
return 1;
}
if (!t_fileRaw.open(QIODevice::ReadOnly)) {
std::cout << "Input file can't be opened.\n";
return 1;
}
buffer.write(t_fileRaw.readAll());

t_fileRaw.close();

qint32_le iIntToChar;
char cCharFromInt[sizeof(qint32)];

if (parser.isSet(padEndOption)) {
iIntToChar = -1;
memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
buffer.write(cCharFromInt);
iIntToChar = -1;
memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
buffer.write(cCharFromInt);
iIntToChar = -1;
memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
buffer.write(cCharFromInt);
iIntToChar = -1;
memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
buffer.write(cCharFromInt);
}

buffer.reset();

FIFFLIB::FiffStream stream(&buffer);
if (littleEndian) {
stream.setByteOrder(QDataStream::LittleEndian);
} else {
stream.setByteOrder(QDataStream::BigEndian);
}

if (stream.open()) {
FIFFLIB::FiffInfo FifInfo;
FIFFLIB::FiffDirNode::SPtr DirNode;

FIFFLIB::FiffDigitizerData digData;

if (stream.read_meas_info(stream.dirtree(), FifInfo, DirNode)) {
FIFFLIB::FiffIO p_fiffIO(t_fileRaw);

std::cout << "Num. raw dat sets: " << p_fiffIO.m_qlistRaw.size() << "\n";
std::cout << "Num. evoked sets: " << p_fiffIO.m_qlistEvoked.size() << "\n";

int count = 0;
for (auto& data : p_fiffIO.m_qlistRaw) {
std::cout << "--- \n";
std::cout << "Raw Set " << count << "\n";
std::cout << "Sample frequency: " << data->info.sfreq << "\n";
std::cout << "LineFreq: " << data->info.linefreq << " | Highpass: " << data->info.highpass << " | Lowpass: " << data->info.lowpass << "\n";
std::cout << "First sample: " << data->first_samp << " | Last sample: " << data->last_samp << "\n";
std::cout << "Number of samples: " << data->last_samp - data->first_samp << " | Time: " << (data->last_samp - data->first_samp) / data->info.sfreq << " sec. \n";
std::cout << "Number of digitizer points: " << data->info.dig.size() << "\n";
for (auto& point : data->info.dig) {
if (point.kind == FIFFV_POINT_HPI) {
std::cout << "HPI Point " << point.ident << " - " << point.r[0] << ", " << point.r[1] << ", " << point.r[2] << "\n";
}
}
}
count = 0;
for (auto& data : p_fiffIO.m_qlistEvoked) {
std::cout << "--- \n";
std::cout << "Evoked Set " << count << "\n";
std::cout << "Sample frequency: " << data->info.sfreq << "\n";
std::cout << "LineFreq: " << data->info.linefreq << " | Highpass: " << data->info.highpass << " | Lowpass: " << data->info.lowpass << "\n";
std::cout << "Num. averaged epochs: " << data->nave << "\n";
}
std::cout << "--- \n";
std::cout << "--------------------------------------\n";
}
if (stream.read_digitizer_data(stream.dirtree(), digData)) {
std::cout << "Digitizer data found.\n";
std::cout << "Number of digitizer points: " << digData.points.size() << "\n";
for (auto& point : digData.points) {
if (point.kind == FIFFV_POINT_HPI) {
std::cout << "HPI Point " << point.ident << " - " << point.r[0] << ", " << point.r[1] << ", " << point.r[2] << "\n";
}
}
}
}
}

return 0;
}