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
| Option | Description |
|---|---|
--file | The input file <in>. |
--endian | The file's endianness. 'little' or 'big' |
--pad | Adds -1 to end of stream to account for unfinished file (use for neuromag2ft) |
Key API
The documented classes this example uses most:
| Class | Library |
|---|---|
Fiff | FIFF I/O |
FiffDigitizerData | FIFF I/O |
FiffDirNode | FIFF I/O |
FiffIO | FIFF I/O |
FiffInfo | FIFF I/O |
FiffStream | FIFF I/O |
MNE | MNE 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;
}
Related examples
- Tour of the FIFF data structures — FIFF library: measurement info, channels, digitizer, transforms, projectors, covariance, events, annotations, evoked sets and the low-level file structure.
- Epochs, compensation and the FIFF file directory — FIFF library: fixed-length epochs, CTF compensation, the file directory and raw buffers, and handing recordings to another application.
- Copy a raw recording to a new FIFF file — Copy a raw FIFF recording buffer by buffer into a new file with FiffStream.