...
 
Commits (2)
......@@ -224,6 +224,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FIFFIO", "src\plugins\FIFIO
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EEGInto4D", "src\plugins\EEGInto4D\EEGInto4D.vcxproj", "{7A80BFFA-5097-495D-897A-A956654B2E71}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EEPIO", "src\plugins\EEPIO\EEPIO.vcxproj", "{C56501D8-7276-4207-B8FC-AAE4D647AABA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
......@@ -624,12 +626,18 @@ Global
{7A80BFFA-5097-495D-897A-A956654B2E71}.Release|Win32.Build.0 = Release|Win32
{7A80BFFA-5097-495D-897A-A956654B2E71}.Release|x64.ActiveCfg = Release|x64
{7A80BFFA-5097-495D-897A-A956654B2E71}.Release|x64.Build.0 = Release|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Debug|Win32.ActiveCfg = Debug|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Debug|x64.ActiveCfg = Debug|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Debug|x64.Build.0 = Debug|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Release|Win32.ActiveCfg = Release|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Release|x64.ActiveCfg = Release|x64
{C56501D8-7276-4207-B8FC-AAE4D647AABA}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Qt5Version = 5.10
SolutionGuid = {760C4A58-27A9-4401-83F8-D863D6C42B7E}
Qt5Version = 5.10
EndGlobalSection
EndGlobal
......@@ -88,7 +88,6 @@ public:
void lock() { m_mutex.lock(); }
void unlock() { m_mutex.unlock(); }
protected:
AwChannelList m_channels;
// markers will contain input markers for the process.
......
......@@ -217,10 +217,19 @@ void AnyWave::openFile(const QString &path)
AwDisplaySetupManager *ds = AwDisplaySetupManager::instance();
ds->setParent(this);
QString root = AwBIDSManager::detectBIDSFolderFromPath(filePath);
if (!root.isEmpty()) {
openBIDS(root);
AwBIDSManager::instance()->newFile(m_currentReader);
// if BIDS is already active, check if the file path is coming from an existing BIDS node:
bool BIDSCheck = false;
if (AwBIDSManager::isInstantiated()) {
auto BM = AwBIDSManager::instance();
if (BM->isBIDSActive() && BM->findSubject(filePath) != nullptr)
BIDSCheck = true;
}
if (!BIDSCheck) {
QString root = AwBIDSManager::detectBIDSFolderFromPath(filePath);
if (!root.isEmpty()) {
openBIDS(root);
AwBIDSManager::instance()->newFile(m_currentReader);
}
}
// read flt file before loading the montage.
......
......@@ -10,7 +10,7 @@
//
// --toBIDS : Convert a file or folder to BIDS by converting the data format if necessary and creating the .json files
// Options for --toBIDS:
// --bids_modality <modality> : MANDATORY. [ seeg or meg4DNI ]
// --bids_modality <modality> : MANDATORY. [ seeg meg eeg ]
// --bids_sub <subj> : MANDATORY. The BIDS subject
// --bids_task <task> : MANDATORY. The BIDS task
// --bids_ses <sessions> : OPTIONAL. The BIDS session.
......
......@@ -35,7 +35,7 @@ void AwBIDSManager::toBIDS(const AwArguments& args)
// check for modality
auto mod = args["bids_modality"].toString().trimmed().toLower();
if (mod == "ieeg") {
if (mod == "ieeg" || mod == "eeg") {
SEEGtoBIDS(args);
}
else if (mod == "meg") {
......@@ -317,9 +317,10 @@ int AwBIDSManager::MEGtoBIDS(const AwArguments& args)
int AwBIDSManager::SEEGtoBIDS(const AwArguments& args)
{
auto file = args["input_file"].toString();
auto mod = args["bids_modality"].toString().trimmed().toLower();
if (file.isEmpty()) {
emit log("AwBIDSManager::SEEGtoBIDS - No SEEG file specified.");
emit log(QString("AwBIDSManager::SEEGtoBIDS - No %1 file specified.").arg(mod));
return -1;
}
......@@ -410,7 +411,10 @@ int AwBIDSManager::SEEGtoBIDS(const AwArguments& args)
events_tsv = QString("%1_proc-%2").arg(events_tsv).arg(proc);
}
fileName = QString("%1_ieeg.%2").arg(fileName).arg(ext);
if (mod == "seeg")
fileName = QString("%1_ieeg.%2").arg(fileName).arg(ext);
else // Converting eeg file
fileName = QString("%1_eeg.%2").arg(fileName).arg(ext);
json = QString("%1_ieeg.json").arg(json);
channels_tsv = QString("%1_channels.tsv").arg(channels_tsv);
events_tsv = QString("%1_events.tsv").arg(events_tsv);
......@@ -443,7 +447,7 @@ int AwBIDSManager::SEEGtoBIDS(const AwArguments& args)
// to get the group from electrode
QRegularExpression re("\\d+$");
QRegularExpressionMatch match;
int countSEEG = 0, countECG = 0, countTRIG = 0;
int countSEEG = 0, countECG = 0, countTRIG = 0, countEEG = 0;
if (channel.open(QIODevice::WriteOnly | QIODevice::Text)) {
for (int i = 0; i < headers.size(); i++) {
stream << headers.at(i);
......@@ -463,10 +467,14 @@ int AwBIDSManager::SEEGtoBIDS(const AwArguments& args)
stream << "ECG" << "\t" << "microV" << "\t";
countECG++;
}
else if (c->type() == AwChannel::SEEG || c->type() == AwChannel::EEG) {
else if (c->type() == AwChannel::SEEG || (c->type() == AwChannel::EEG && mod == "seeg")) {
stream << "SEEG" << "\t" << "microV" << "\t";
countSEEG++;
}
else if (c->isEEG()) {
stream << "EEG" << "\t" << "microV" << "\t";
countEEG++;
}
else
stream << "OTHER" << "\t" << "n/a" << "\t";
......@@ -511,10 +519,17 @@ int AwBIDSManager::SEEGtoBIDS(const AwArguments& args)
jObject.insert("TaskName", QJsonValue::fromVariant(task));
jObject.insert("Manufacturer", QJsonValue::fromVariant(manufacturer));
jObject.insert("PowerLineFrequency", QJsonValue::fromVariant(50));
jObject.insert("SEEGChannelCount", QJsonValue::fromVariant(countSEEG));
if (mod == "seeg") {
jObject.insert("SEEGChannelCount", QJsonValue::fromVariant(countSEEG));
jObject["iEEGReference"] = QString("n/a");
}
else {
jObject["EEGReference"] = QString("n/a");
jObject.insert("EEGChannelCount", QJsonValue::fromVariant(countEEG));
}
jObject["SamplingFrequency"] = reader->infos.channels().first()->samplingRate();
jObject["SoftwareFilters"] = QString("n/a");
jObject["iEEGReference"] = QString("n/a");
if (countECG)
jObject.insert("ECGChannelCount", QJsonValue::fromVariant(countECG));
if (countTRIG)
......@@ -686,9 +701,8 @@ void AwBIDSManager::setRootDir(const QString& path)
AwBIDSParser parser;
parser.parse();
m_nodes = parser.nodes();
m_IDToSubject.clear();
for (auto n : m_nodes)
m_IDToSubject[n->ID()] = n;
m_hashNodes = parser.hash();
// instantiate UI if needed
if (m_ui == nullptr)
m_ui = new AwBIDSGUI;
......@@ -705,6 +719,8 @@ void AwBIDSManager::closeBIDS()
m_modifications.clear();
m_mustValidateModifications = false;
m_currentSubject = nullptr;
m_hashNodes.clear();
m_IDToSubject.clear();
emit BIDSClosed();
}
......@@ -950,16 +966,16 @@ AwBIDSNode *AwBIDSManager::findSubject(const QString& dataFilePath)
if (!isBIDSActive())
return nullptr;
QFileInfo fi(dataFilePath);
if (!fi.exists())
return nullptr;
auto fileName = fi.fileName();
for (auto s : m_nodes) {
auto files = s->gatherFiles();
if (files.contains(fileName)) {
m_currentSubject = s;
return s;
auto n = m_hashNodes[fi.fileName()];
if (n) {
auto parent = n->parent();
while (parent) {
n = parent;
parent = n->parent();
}
m_settings["BIDS_FilePath"] = dataFilePath;
}
m_currentSubject = n;
return m_currentSubject;
}
......
......@@ -39,10 +39,9 @@ class AwBIDSManager : public QObject
{
Q_OBJECT
public:
enum itemTypes { iEEG, MEG, EEG };
enum dataSources { raw = 0, source = 1, derivatives = 2 }; // indicates the type of data ordering (source data are place in a source_data folder).
enum Modifications { ChannelsTsv, EventsTsv };
enum supportedMEGFormats { Bti4DNI, Elekta, CTF };
enum Derivatives { ICA };
// destructor
~AwBIDSManager();
......@@ -63,6 +62,7 @@ public:
inline bool mustValidateMods() { return !m_modifications.isEmpty(); }
void closeBIDS();
AwBIDSNodes& subjects() { return m_nodes; }
QString buildPath(const QString& dataFilePath, int derivativesKind);
void toBIDS(const AwArguments& args);
int SEEGtoBIDS(const AwArguments& args);
......@@ -88,6 +88,8 @@ public:
AwBIDSNode *findSubject(const QString& dataFilePath);
/** Get the companion tsv file of a data file. Returns empty string if the file does not exist **/
QString getTSVFile(const QString& dataFilePath, int tsvType);
/** Get the BIDS path to the current open file **/
QString getCurrentBIDSPath() { return m_settings["BIDS_FilePath"].toString(); }
signals:
void log(const QString& message);
void BIDSClosed();
......@@ -97,6 +99,7 @@ protected:
static QStringList m_dataFileSuffixes; // list of suffix for known data file (_ieeg, _eeg, ...)
QHash<QString, QVariant> m_settings;
QHash<QString, AwBIDSNode *> m_hashNodes;
int convertFile(AwFileIO *reader, AwFileIOPlugin *plugin, const QString& file);
......
......@@ -31,6 +31,7 @@ AwBIDSNode::AwBIDSNode(const QString& parentDir, const QString& relativePath, in
m_type = type;
m_ID = ID;
m_fullPath = QString("%1/%2").arg(parentDir).arg(relativePath);
m_parent = nullptr;
}
AwBIDSNode::~AwBIDSNode()
......
......@@ -43,10 +43,11 @@ public:
inline QString& ID() { return m_ID; }
inline QList<AwBIDSNode *>& children() { return m_children; }
inline QStringList& files() { return m_files; }
inline AwBIDSNode *parent() { return m_parent; }
/** return all the files contained in the node and the child nodes. **/
QStringList gatherFiles();
AwBIDSNode * addChild(AwBIDSNode *node) { m_children.append(node); return node; }
AwBIDSNode * addChild(AwBIDSNode *node) { m_children.append(node); node->m_parent = this; return node; }
void addFiles(const QStringList& files) { m_files.append(files); }
/** Find child node which contains the file. **/
AwBIDSNode *findNode(const QString& fileName, AwBIDSNode *node);
......@@ -58,6 +59,7 @@ protected:
QStringList m_files;
// a node may contain child nodes
QList<AwBIDSNode *> m_children;
AwBIDSNode *m_parent;
int m_type;
};
......
......@@ -44,6 +44,7 @@
#include <AwVirtualChannel.h>
#include "AwProcessLogManager.h"
#include "Debug/AwDebugLog.h"
#include "IO/BIDS/AwBIDSManager.h"
AwProcessManager *AwProcessManager::m_instance = NULL;
AwProcessManager *AwProcessManager::instance()
......@@ -613,6 +614,13 @@ void AwProcessManager::runProcess(AwBaseProcess *process, const QStringList& arg
return;
}
if (AwBIDSManager::isInstantiated()) {
auto BM = AwBIDSManager::instance();
if (BM->isBIDSActive())
process->pdi.input.addArgument(QString("BIDS_FilePath"), BM->getCurrentBIDSPath());
}
AwProcessLogManager *plm = AwProcessLogManager::instance();
plm->setParent(this);
plm->connectProcess(process);
......
......@@ -35,7 +35,6 @@ static mxArray *parse_cfg(const mxArray *);
int filterFlags = 0; // 0 => AnyWave current filters, 1 => specified filters 2=> raw data
QHash<int, QVector<float>> filterSettings;
static QString montage, file;
//static float start = 0., duration = 0.;
float start = 0., duration = 0.;
QStringList labels, types;
int decimate = 0;
......@@ -120,32 +119,15 @@ mxArray *request_data()
int selected;
in >> name >> type >> ref >> samplingRate >> hpf >> lpf >> nSamples >> selected;
mxSetField(output, i, "name", mxCreateString(name.toStdString().c_str()));
mxSetField(output, i, "type", mxCreateString(type.toStdString().c_str()));
mxSetField(output, i, "ref", mxCreateString(ref.toStdString().c_str()));
mxSetField(output, i, "samplingRate", doubleToMat((double)samplingRate));
mxSetField(output, i, "hpf", doubleToMat((double)hpf));
mxSetField(output, i, "lpf", doubleToMat((double)lpf));
mxArray *f_name = mxCreateString(name.toStdString().c_str());
mxSetField(output, i, "name", f_name);
mxArray *f_type = mxCreateString(type.toStdString().c_str());
mxSetField(output, i, "type", f_type);
mxArray *f_ref = mxCreateString(ref.toStdString().c_str());
mxSetField(output, i, "ref", f_ref);
mxArray *f_sr = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
float *tmp = (float *)mxGetData(f_sr);
*tmp = samplingRate;
mxSetField(output, i, "samplingRate", f_sr);
mxArray *f_hpf = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
tmp = (float *)mxGetData(f_hpf);
*tmp = hpf;
mxSetField(output, i, "hpf", f_hpf);
mxArray *f_lpf = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
tmp = (float *)mxGetData(f_lpf);
*tmp = lpf;
mxSetField(output, i, "lpf", f_lpf);
mxArray *f_selected = mxCreateLogicalMatrix(1, 1);
mxArray *f_selected = mxCreateLogicalMatrix(1, 1);
*mxGetLogicals(f_selected) = selected;
mxSetField(output, i, "selected", f_selected);
......
......@@ -109,10 +109,10 @@ void parse_cfg(const mxArray *cfg, mxArray *plhs[], int nlhs)
mxSetField(output, i, "name", mxCreateString(name.toStdString().c_str()));
mxSetField(output, i, "ref", mxCreateString(ref.toStdString().c_str()));
mxSetField(output, i, "type", mxCreateString(type.toStdString().c_str()));
mxSetField(output, i, "samplingRate", floatToMat(samplingRate));
mxSetField(output, i, "hpf", floatToMat(hpf));
mxSetField(output, i, "lpf", floatToMat(lpf));
mxSetField(output, i, "notch", floatToMat(notch));
mxSetField(output, i, "samplingRate", doubleToMat((double)samplingRate));
mxSetField(output, i, "hpf", doubleToMat((double)hpf));
mxSetField(output, i, "lpf", doubleToMat((double)lpf));
mxSetField(output, i, "notch", doubleToMat((double)notch));
if (nSamples == 0) {
mxSetField(output, i, "data", mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL));
......
......@@ -110,32 +110,17 @@ mxArray* request_info()
mxSetField(output, 0, "refs", dummy);
// max_sr
mxArray *f_sr = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
float *v = (float *)mxGetData(f_sr);
v[0] = max_sr;
mxSetField(output, 0, "max_sr", f_sr);
mxSetField(output, 0, "max_sr", doubleToMat((double)max_sr));
// total_duration
mxArray *f_dur = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
v = (float *)mxGetData(f_dur);
v[0] = total_dur;
mxSetField(output, 0, "total_duration", f_dur);
mxSetField(output, 0, "total_duration", doubleToMat((double)total_dur));
// temp_dir
mxArray *f_temp = mxCreateString(temp_dir.toStdString().c_str());
mxSetField(output, 0, "temp_dir", f_temp);
mxSetField(output, 0, "temp_dir", mxCreateString(temp_dir.toStdString().c_str()));
// plugin_dir
mxArray *f_plugin = mxCreateString(plugin_dir.toStdString().c_str());
mxSetField(output, 0, "plugin_dir", f_plugin);
mxSetField(output, 0, "plugin_dir", mxCreateString(plugin_dir.toStdString().c_str()));
// file
mxArray *f_file = mxCreateString(file.toStdString().c_str());
mxSetField(output, 0, "file", f_file);
mxSetField(output, 0, "file", mxCreateString(file.toStdString().c_str()));
// ica_file
mxArray *f_ica_file = mxCreateString(ica_file.toStdString().c_str());
mxSetField(output, 0, "ica_file", f_ica_file);
mxSetField(output, 0, "ica_file", mxCreateString(ica_file.toStdString().c_str()));
return output;
}
......
......@@ -71,18 +71,18 @@ mxArray* request_info()
QStringList channels;
in >> label >> start >> duration >> value >> channels;
QVector<float> chunkVector = { start, duration };
QVector<double> chunkVector = { (double)start, (double)duration };
// label
mxSetField(markers, i, "label", mxCreateString(label.toStdString().c_str()));
// start
mxSetField(markers, i, "position", floatToMat(start));
mxSetField(markers, i, "position", doubleToMat((double)start));
// duration
mxSetField(markers, i, "duration", floatToMat(duration));
mxSetField(markers, i, "duration", doubleToMat((double)duration));
// value
mxSetField(markers, i, "value", floatToMat(value));
mxSetField(markers, i, "value", doubleToMat((double)value));
// chunk
mxSetField(markers, i, "chunk", floatVectorToMat(chunkVector));
mxSetField(markers, i, "chunk", doubleVectorToMat(chunkVector));
// channels
tmp = NULL;
if (!channels.isEmpty()) {
......@@ -143,9 +143,9 @@ mxArray* request_info()
mxSetField(output, 0, "types", tmp);
// max_sr
mxSetField(output, 0, "max_sr", floatToMat(max_sr));
mxSetField(output, 0, "max_sr", doubleToMat((double)max_sr));
// total_duration
mxSetField(output, 0, "total_duration", floatToMat(total_dur));
mxSetField(output, 0, "total_duration", doubleToMat((double)total_dur));
// temp_dir
mxSetField(output, 0, "temp_dir", mxCreateString(temp_dir.toStdString().c_str()));
// plugin_dir
......
......@@ -81,34 +81,19 @@ mxArray *request_markers(const QString& file, const QStringList& channels)
in >> label >> start >> duration >> value >> channels;
// label
mxArray *output_label = mxCreateString(label.toStdString().c_str());
mxSetField(output, i, "label", output_label);
mxSetField(output, i, "label", mxCreateString(label.toStdString().c_str()));
// start
mxArray *output_start = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
float *s = (float *)mxGetData(output_start);
s[0] = start;
mxSetField(output, i, "position", output_start);
mxSetField(output, i, "position", doubleToMat((double)start));
// duration
mxArray *output_duration = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
float *d = (float *)mxGetData(output_duration);
d[0] = duration;
mxSetField(output, i, "duration", output_duration);
mxSetField(output, i, "duration", doubleToMat((double)duration));
// value
mxArray *output_value = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
float *v = (float *)mxGetData(output_value);
v[0] = value;
mxSetField(output, i, "value", output_value);
mxSetField(output, i, "value", doubleToMat((double)value));
// channels
mxArray *output_channels = NULL;
if (!channels.isEmpty()) {
output_channels = mxCreateCellMatrix(1, channels.size());
for (mwSize j = 0; j < channels.size(); j++) {
mxArray *target = mxCreateString(channels.at(j).toLatin1().data());
mxSetCell(output_channels, j, target);
mxSetCell(output_channels, j, mxCreateString(channels.at(j).toStdString().c_str()));
}
}
else // create an empty cell array
......
......@@ -111,7 +111,7 @@ mxArray *doubleToMat(double value)
{
mxArray *tmp = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL);
double *s = (double *)mxGetData(tmp);
s[0] = value;
*s = value;
return tmp;
}
......
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C56501D8-7276-4207-B8FC-AAE4D647AABA}</ProjectGuid>
<Keyword>QtVS_v301</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')">
<QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(AWROOT)\bin\$(Platform)\$(Configuration)\Plugins\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(AWROOT)\bin\$(Platform)\$(Configuration)\Plugins\</OutDir>
</PropertyGroup>
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
</Target>
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
<Import Project="$(QtMsBuild)\qt_defaults.props" />
</ImportGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<QtInstall>5.10</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<QtInstall>5.10</QtInstall>
<QtModules>core</QtModules>
</PropertyGroup>
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')">
<Import Project="$(QtMsBuild)\qt.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>Disabled</Optimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;EEPIO_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(AWROOT)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(QTDIR)\lib;$(AWROOT)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>qtmaind.lib;Qt5Cored.lib;AwCorelibd.lib;AwReadWriteLibd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat />
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PreprocessorDefinitions>UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;EEPIO_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(AWROOT)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)\$(ProjectName).dll</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(QTDIR)\lib;$(AWROOT)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>qtmain.lib;Qt5Core.lib;AwCorelib.lib;AwReadWriteLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="EEProbeIO.cpp" />
<ClCompile Include="libcnt\cnt.cpp" />
<ClCompile Include="libcnt\cntutils.cpp" />
<ClCompile Include="libcnt\evt.cpp" />
<ClCompile Include="libcnt\raw3.cpp" />
<ClCompile Include="libcnt\rej.cpp" />
<ClCompile Include="libcnt\riff.cpp" />
<ClCompile Include="libcnt\riff64.cpp" />
<ClCompile Include="libcnt\seg.cpp" />
<ClCompile Include="libcnt\trg.cpp" />
<ClCompile Include="libeep\eepio.cpp" />
<ClCompile Include="libeep\eepmem.cpp" />
<ClCompile Include="libeep\eepmisc.cpp" />
<ClCompile Include="libeep\eepraw.cpp" />
<ClCompile Include="libeep\val.cpp" />
<ClCompile Include="libeep\var_string.cpp" />
<ClCompile Include="v4\eep.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="cnt\cnt.h" />
<ClInclude Include="cnt\cntutils.h" />
<ClInclude Include="cnt\cnt_private.h" />
<ClInclude Include="cnt\cnt_version.h" />
<ClInclude Include="cnt\evt.h" />
<ClInclude Include="cnt\raw3.h" />
<ClInclude Include="cnt\rej.h" />
<ClInclude Include="cnt\riff.h" />
<ClInclude Include="cnt\riff64.h" />
<ClInclude Include="cnt\seg.h" />
<ClInclude Include="cnt\trg.h" />
<QtMoc Include="EEProbeIO.h" />
<ClInclude Include="eep\eepio.h" />
<ClInclude Include="eep\eepmem.h" />
<ClInclude Include="eep\eepmisc.h" />
<ClInclude Include="eep\eepraw.h" />
<ClInclude Include="eep\inttypes.h" />
<ClInclude Include="eep\stdint.h" />
<ClInclude Include="eep\val.h" />
<ClInclude Include="eep\var_string.h" />
<ClInclude Include="eep\winsafe.h" />
<ClInclude Include="v4\eep.h" />
<ClInclude Include="eepio_global.h" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />
</ImportGroup>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" MocOptions="" />
</VisualStudio>
</ProjectExtensions>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
<Extensions>qrc;*</Extensions>
<ParseFiles>false</ParseFiles>
</Filter>
<Filter Include="eep">
<UniqueIdentifier>{a087f85b-0e9d-4125-85d4-ea1030675028}</UniqueIdentifier>
</Filter>
<Filter Include="cnt">
<UniqueIdentifier>{3b0d2dba-b182-4713-8f89-bb5b9702c657}</UniqueIdentifier>
</Filter>
<Filter Include="libcnt">
<UniqueIdentifier>{e84ff2d9-bc2c-44c2-90c4-9b4e8439cff9}</UniqueIdentifier>
</Filter>
<Filter Include="libeep">
<UniqueIdentifier>{6d0d9bc4-73e3-45d1-8cf2-c8ba08c1d2b4}</UniqueIdentifier>
</Filter>
<Filter Include="v4">
<UniqueIdentifier>{afa32cd6-cb0e-4cb3-8ce5-dba8ef8fc7a0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="v4\eep.cpp">
<Filter>v4</Filter>
</ClCompile>
<ClCompile Include="libeep\eepio.cpp">
<Filter>libeep</Filter>
</ClCompile>
<ClCompile Include="libeep\eepmem.cpp">
<Filter>libeep</Filter>
</ClCompile>
<ClCompile Include="libeep\eepmisc.cpp">
<Filter>libeep</Filter>
</ClCompile>
<ClCompile Include="libeep\eepraw.cpp">
<Filter>libeep</Filter>
</ClCompile>
<ClCompile Include="EEProbeIO.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libcnt\cnt.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\cntutils.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\evt.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\raw3.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\rej.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\riff.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\riff64.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\seg.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libcnt\trg.cpp">
<Filter>libcnt</Filter>
</ClCompile>
<ClCompile Include="libeep\val.cpp">
<Filter>libeep</Filter>
</ClCompile>
<ClCompile Include="libeep\var_string.cpp">
<Filter>libeep</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="eepio_global.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="eep\eepio.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\eepmem.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\eepmisc.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\eepraw.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\inttypes.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\stdint.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\val.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\var_string.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="eep\winsafe.h">
<Filter>eep</Filter>
</ClInclude>
<ClInclude Include="cnt\cnt.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\cnt_private.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\cnt_version.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\cntutils.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\evt.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\raw3.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\rej.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\riff.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\riff64.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\seg.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="cnt\trg.h">
<Filter>cnt</Filter>
</ClInclude>
<ClInclude Include="v4\eep.h">
<Filter>v4</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtMoc Include="EEProbeIO.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
</Project>
\ No newline at end of file
#include "EEProbeIO.h"
#include "cnt/cnt_private.h"
#include "eep/eepio.h"
EEPIO::EEPIO(const QString& fileName) : AwFileIO(fileName)
{
}
EEPIO::~EEPIO()
{
cleanUpAndClose();
}
EEPIOPlugin::EEPIOPlugin()
{
name = QString("EEProbe IO");
description = QString("Read .cnt files");
manufacturer = QString("ANT Neuro");
version = QString("3.3.177");
fileExtensions << "*.cnt";
m_flags = Aw::HasExtension | Aw::CanRead;
}
void EEPIO::cleanUpAndClose()
{
if (_libeep_cnt != nullptr)
free(_libeep_cnt);
m_scales.clear();
}
AwFileIO::FileStatus EEPIO::canRead(const QString &path)
{
auto file = eepio_fopen(path.toStdString().c_str(), "rb");
int status;
if (file) {
_libeep_cnt = eep_init_from_file(path.toStdString().c_str(), file, &status);
if (status != CNTERR_NONE) {
m_error = "invalid file format";
return AwFileIO::WrongFormat;
}
}
else
return AwFileIO::FileAccess;
return AwFileIO::NoError;
}
AwFileIO::FileStatus EEPIO::openFile(const QString &path)
{
cleanUpAndClose();
auto file = eepio_fopen(path.toStdString().c_str(), "rb");
int status;
if (file) {
_libeep_cnt = eep_init_from_file(path.toStdString().c_str(), file, &status);
if (status != CNTERR_NONE) {
m_error = "invalid file format";
return AwFileIO::WrongFormat;
}
}
auto block = infos.newBlock();
m_sampleRate = 1.0 / eep_get_period(_libeep_cnt);
block->setSamples(eep_get_samplec(_libeep_cnt));
block->setDuration(eep_get_samplec(_libeep_cnt) / m_sampleRate);
auto nChannels = eep_get_chanc(_libeep_cnt);
m_scales.reserve(nChannels);
for (int i = 0; i < nChannels; i++) {
AwChannel channel;
auto label = QString::fromLatin1(eep_get_chan_label(_libeep_cnt, i));
channel.setName(label);
channel.setSamplingRate(m_sampleRate);
auto unit = QString::fromLatin1(eep_get_chan_unit(_libeep_cnt, i));
// consider microV as the default unit
float gainFactor = 1.0;
// check if unit is V or mV
if (unit == "V" || unit == "v")
gainFactor = 1e6;
if (unit == "mV" || unit == "mv")
gainFactor = 1e3;
channel.setUnit(unit);
m_scales.append(eep_get_chan_scale(_libeep_cnt, i) * gainFactor);
infos.addChannel(&channel);
}
// triggers
uint64_t trg_offset;
char * trg_code;
auto trigger_table = eep_get_trg(_libeep_cnt);
for (int i = 0; i < trg_get_c(trigger_table); i++) {
AwMarker marker;
trg_code = trg_get(trigger_table, i, &trg_offset);
// convert offset in time
marker.setStart(trg_offset / m_sampleRate);
marker.setLabel(QString::fromLatin1(trg_code));
block->addMarker(&marker);
}
return AwFileIO::NoError;
}
qint64 EEPIO::readDataFromChannels(float start, float duration, QList<AwChannel *> &channelList)
{
if (channelList.isEmpty())
return 0;
// number of samples to read
quint64 nSamples = (quint64)floor(duration * m_sampleRate);
// starting sample in channel.
quint64 nStart = (quint64)floor(start * m_sampleRate);
// total number of channels in file.
quint32 nbChannels = infos.channelsCount();
// starting sample in file.
quint64 startSample = nStart * nbChannels;
if (nSamples <= 0)
return 0;
if (nStart > infos.totalSamples())
return 0;
if (nStart + nSamples > infos.totalSamples())
nSamples = infos.totalSamples() - nStart;
auto _libeep_muxbuf = (sraw_t*)(malloc(CNTBUF_SIZE(_libeep_cnt, nSamples)));
// seek to offset
auto status = eep_seek(_libeep_cnt, DATATYPE_EEG, nStart, 0);
if (status) {
free(_libeep_muxbuf);
return 0;
}
// read samples
status = eep_read_sraw(_libeep_cnt, DATATYPE_EEG, _libeep_muxbuf, nSamples);
if (status) {
free(_libeep_muxbuf);
return 0;
}
for (auto c : channelList) {
auto index = infos.indexOfChannel(c->name());
if (index == -1)
continue;
float *data = c->newData(nSamples);
quint64 count = 0;
while (count < nSamples) {
*data++ = (float)_libeep_muxbuf[index + count * nbChannels] * m_scales[index];
count++;
}
}
free(_libeep_muxbuf);
return nSamples;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// Universit dAix Marseille (AMU) -
// Institut National de la Sant et de la Recherche Mdicale (INSERM)
// Copyright 2013 AMU, INSERM
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
//
// Author: Bruno Colombet Laboratoire UMR INS INSERM 1106 - Bruno.Colombet@univ-amu.fr
//
//////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "eepio_global.h"
#include <AwFileIO.h>
#include "cnt/cnt.h"
class EEPIO_EXPORT EEPIO : public AwFileIO
{
Q_OBJECT
Q_INTERFACES(AwFileIO)
public:
EEPIO(const QString& fileName);
~EEPIO();
void cleanUpAndClose() override;
qint64 readDataFromChannels(float start, float duration, AwChannelList &channelList) override;
FileStatus openFile(const QString &path) override;
FileStatus canRead(const QString &path) override;
protected:
eeg_t *_libeep_cnt; // pointer to eeprobe data structure
float m_sampleRate;
QVector<double> m_scales;
};
class EEPIO_EXPORT EEPIOPlugin : public AwFileIOPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID AwFileIOInterfacePlugin_IID)
Q_INTERFACES(AwFileIOPlugin)
public:
EEPIOPlugin();
AW_INSTANTIATE_PLUGIN(EEPIO)
};
This diff is collapsed.
/********************************************************************************
* *
* this file is part of: *
* libeep, the project for reading and writing avr/cnt eeg and related files *
* *
********************************************************************************
* *
* LICENSE:Copyright (c) 2003-2009, *
* Advanced Neuro Technology (ANT) B.V., Enschede, The Netherlands *
* Max-Planck Institute for Human Cognitive & Brain Sciences, Leipzig, Germany *
* *
********************************************************************************
* *
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed WITHOUT ANY WARRANTY; even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
* *
*******************************************************************************/
#ifndef CNT_PRIVATE_H
#include <cnt/cnt.h>
#include <cnt/raw3.h>
#include <cnt/riff.h>
#include <cnt/riff64.h>
#include <eep/var_string.h>
#include <eep/val.h>
#define FOURCC_raw3 FOURCC('r', 'a', 'w', '3')
#define FOURCC_chan FOURCC('c', 'h', 'a', 'n')
#define FOURCC_data FOURCC('d', 'a', 't', 'a')
#define FOURCC_ep FOURCC('e', 'p', ' ', ' ')
#define FOURCC_eeph FOURCC('e', 'e', 'p', 'h')
#define FOURCC_evt FOURCC('e', 'v', 't', ' ')
#define FOURCC_refh FOURCC('r', 'e', 'f', 'h')
#define FOURCC_info FOURCC('i', 'n', 'f', 'o')
#define FOURCC_imp FOURCC('i', 'm', 'p', ' ')
#define FOURCC_stdd FOURCC('s', 't', 'd', 'd')
#define FOURCC_tfh FOURCC('t', 'f', 'h', ' ')
#define FOURCC_tfd FOURCC('t', 'f', 'd', ' ')
#define FOURCC_rawf FOURCC('r', 'a', 'w', 'f')
/* channel specific informations */
struct eegchan_s {
char lab[16]; /* electrode label */
double iscale; /* "internal" scaling gain * calibration */
double rscale; /* "real world" scaling (value of 1 bit if iscale = 1.0) */
char runit[16]; /* unit String (uV, fT...) */
char reflab[10]; /* reference label */
char status[10]; /* channel status */
char type[10]; /* sensor type (EEG, MEG ...)*/
};
/* time/frequency component specific informations */
struct tf_component_s {
float axis_value;
char description[40];
};
/* Epoch specific information */
typedef struct {
uint64_t epochc; /* number of epochs in file */
uint64_t epochl; /* epoch length in samples */
uint64_t * epochv; /* relative file position of epochs */
uint64_t epvbuf; /* file position buffer */
} cnt_epoch_t;
/* Time/frequency data-chunk information */
typedef struct {
uint64_t bufepoch; /* id number of the epoch in buffer */
char writeflag; /* access mode flag */
uint64_t writepos; /* working buffer write pointer */
uint64_t readpos; /* " read " */
/* Either buf_int or buf_float is used, the other should be NULL */
float * buf_float; /* working buffer (1 epoch), floats */
sraw_t * buf_int; /* working buffer (1 epoch), integers */
char * cbuf; /* buffer with data as in file (poss. compressed) */
} cnt_data_t;
/* Time Frequency Header contents */
typedef struct {
char tf_type[40]; /* Time/frequency type identifier */
tf_content_e content_datatype;/* TF content type spec. */
uint64_t componentc; /* Number of components */
tf_component_t *componentv; /* component info table */
char tf_unit[16]; /* Unit of measurement on time/freq axis */
uint64_t samplec; /* Number of TF samples */
double period; /* T/F time axis scaling */
/* RIFF hacking/trickery. See make_partial_output_consistent() */
/* Don't EVER touch this unless you know exactly what it does. */
uint64_t chunk_size;
} tf_header_t;
/* Standard EEP headers */
typedef struct {
double period; /* time axis scaling */
short chanc; /* number of electrodes */
eegchan_t * chanv; /* electrode info table */
uint64_t samplec; /* Number of samples */
int fileversion_major; /* CNT file versioning. See cnt_version.h */
int fileversion_minor; /* CNT file versioning. See cnt_version.h */
long total_trials;
long averaged_trials;
char conditionlabel[25]; /* condition label: used trigger value or condition description */
char conditioncolor[25]; /* condition color */
double pre_stimulus; /* pre-stimulus interval e.g. for baseline calc. */
/* RIFF hacking/trickery. See make_partial_output_consistent() */
/* Don't EVER touch this unless you know exactly what it does. */
uint64_t chunk_size;
} eep_header_t;
typedef struct {
int initialized; /* Can we read/write data of this type? */
fourcc_t fourcc; /* RIFF chunk identifier (four chars) */
chunk_t ch_toplevel; /* The toplevel chunk, e.g. raw3, tfd or avr */
chunk_t ch_chan; /* Channel sequence subchunk of toplevel chunk */
chunk_t ch_data; /* (Compressed) data subchunk of toplevel chunk */
chunk_t ch_ep; /* Epochs subchunk of toplevel chunk */
cnt_epoch_t epochs; /* Struct holding the epoch data for this TL chunk */
cnt_data_t data; /* Struct representing data from the 'data' chunk */
short *chanseq; /* Compressed channel seq, data from chan chunk */
/* RIFF hacking/trickery. See make_partial_output_consistent() */
/* Don't EVER touch this unless you know exactly what they're for. */
uint64_t data_size;
uint64_t ep_size;
/* memory mapped access. It maps the contents of the X.DATA chunk */
#ifdef CNT_MMAP
int data_mapped;
int map_offset; /* Offset because mmaps always start a page boundaries */
void *data_map;
#endif
} storage_t;
/* EEG informations; internal access control stuff */
struct eeg_dummy_t {
/* common members --------------------------------------- */
short mode; /* cnt type */
FILE *f; /* File pointer */
char *fname; /* File name */
val_t *values; /* Method to access extra information... */
/* Data structures */
eep_header_t eep_header; /* EEP header contents (EEPH chunk) */
var_string history; /* File history (EEPH chunk) */
tf_header_t tf_header; /* Time/freq. header contents (TFH chunk) */
storage_t store[NUM_DATATYPES];/* Data storage */
trg_t *trg; /* Trigger library (TRG chunk) */
record_info_t *recording_info; /* recording information (INFO chunk) */
/* Lowlevel structures for internal use */
raw3_t *r3; /* Raw3 compression data */
chunk_t cnt; /* The 'root' chunk of this file (parent of toplevel chunks) */
chunk_t eeph; /* EEP Header chunk */
chunk_t tfh; /* Time/frequency Header chunk */
chunk_t evt; /* Event-list chunk */
chunk_t info; /* Recording-information chunk */
/*chunk_mode_e active_chunk_mode;*/ /* type of data reading/writing */
eep_datatype_e current_datachunk; /* Chunk we're currently writing */
int finalized; /* When writing files, 0 = false, 1 = true */
/****************** Backwards compatibility ***********************/
/* NeuroScan ---------------------------------------------------- */
char ns_cnttype;
int ns_evtc;
int ns_evtpos;
char ns_evttype;
int ns_evtlen;
/* use members epochc, epochl, buf, bufepoch, readpos */
int keep_consistent;
};
#endif
/********************************************************************************
* *
* this file is part of: *
* libeep, the project for reading and writing avr/cnt eeg and related files *
* *
********************************************************************************
* *
* LICENSE:Copyright (c) 2003-2009, *
* Advanced Neuro Technology (ANT) B.V., Enschede, The Netherlands *
* Max-Planck Institute for Human Cognitive & Brain Sciences, Leipzig, Germany *
* *
********************************************************************************
* *
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed WITHOUT ANY WARRANTY; even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
* *
*******************************************************************************/
#ifndef CNT_VERSION_H
#define CNTVERSION_MAJOR 4
#define CNTVERSION_MINOR 1
/* Versioning information:
4.0 - introduction of file versioning. We start at 4.0 to avoid confusion
with existing (implicit) version numbers.
4.1 - 64-bit chunk sizes for large files
*/
#endif /* ifndef CNT_VERSION_H */
/********************************************************************************
* *
* this file is part of: *
* libeep, the project for reading and writing avr/cnt eeg and related files *
* *
********************************************************************************
* *
* LICENSE:Copyright (c) 2003-2009, *
* Advanced Neuro Technology (ANT) B.V., Enschede, The Netherlands *
* Max-Planck Institute for Human Cognitive & Brain Sciences, Leipzig, Germany *
* *
********************************************************************************
* *
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed WITHOUT ANY WARRANTY; even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
* *
*******************************************************************************/
#ifndef CNTUTILS_H
#define CNTUTILS_H
#include <cnt/cnt.h>
/*
Fill the buffer with data from one channel
@param cnt the cnt/avr file from which we want data.
@param type the datatype to get from the cnt/avr file.
@param name the name of the channel we want data from.
@param buffer the buffer in which to put data. Must be malloced before calling this.
@param start the first sample, from which we want data.
@param length the amonut of samples we want.
*/
int eep_read_float_channel(eeg_t *cnt, eep_datatype_e type, const char* name, float* buffer, slen_t start, int length);
int eep_read_sraw_channel(eeg_t *cnt, eep_datatype_e type, const char* name, sraw_t* buffer, slen_t start, int length);
/*
Set and get the sample0.
Mostly for use in old avr methods. Once there was a sample0 in the avr structure.
Sample0 is a negative number which identifies the first sample in the pre_stimulus part.
*/
slen_t eep_get_sample0(eeg_t* avr);
void eep_set_sample0(eeg_t* avr, slen_t sample0);
/*
This function is a replacement for avr_save.
It will put the data of v into the avrfile.
@param avr the avrfile.
@param type the datatype which will be written. There should be no such datatype in the avrfile.
@param v the data in a matrix of chanc * samplec.
@param samplec the number of samples.
*/
int eep_save_data_matrix_channels(eeg_t *avr, eep_datatype_e type, float **v, int samplec);
/*
* In many cases you want to use the settings of an old avr file for a new created one.
* This will set the trials/conditionlabel/conditioncolor/prestimulus_interval.
*/
void eep_copy_standard_avr_settings(eeg_t* dst, eeg_t* source);
#endif /* CNTUTILS_H */
#ifndef __libeep_cnt_evt_h__
#define __libeep_cnt_evt_h__
// system
#include <stdint.h>
/********************************************************************************
* libeep_evt header
********************************************************************************/
struct libeep_evt_header {
uint32_t ctime;
uint32_t mtime;
uint32_t atime;
int32_t version;
int32_t compression_mode;
int32_t encryption_mode;
};
typedef struct libeep_evt_header libeep_evt_header_t;
/********************************************************************************
* libeep_evt class
********************************************************************************/
struct libeep_evt_class {
int32_t tag;
char * name;
};
typedef struct libeep_evt_class libeep_evt_class_t;
libeep_evt_class_t * libeep_evt_class_new();
void libeep_evt_class_delete(libeep_evt_class_t *);
/********************************************************************************
* libeep_evt event base
********************************************************************************/
struct libeep_evt_GUID {
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
};
typedef struct libeep_evt_GUID libeep_evt_GUID_t;
libeep_evt_GUID_t * libeep_evt_GUID_new();
void libeep_evt_GUID_delete(libeep_evt_GUID_t *);
struct double_date {
double date;
double fraction;
};
typedef struct double_date double_date_t;
/********************************************************************************
* libeep_evt event
********************************************************************************/
struct libeep_evt_event {
int32_t visible_id;
libeep_evt_GUID_t * guid;
char * unused_name;
char * unused_user_visible_name;
int32_t type;
int32_t state;
int8_t original;
double duration;
double duration_offset;
double_date_t time_stamp;
int32_t code;
char * description;
char * condition;
char * videofilename;
char * impedances;
/* linked list */
struct libeep_evt_event * next_event;
};
typedef struct libeep_evt_event libeep_evt_event_t;
libeep_evt_event_t * libeep_evt_event_new();
void libeep_evt_event_delete(libeep_evt_event_t *);
/********************************************************************************
* libeep_evt
********************************************************************************/
struct libeep_evt {
libeep_evt_header_t header;
libeep_evt_event_t * evt_list_first;
libeep_evt_event_t * evt_list_last;
};
typedef struct libeep_evt libeep_evt_t;
libeep_evt_t * libeep_evt_new();
void libeep_evt_delete(libeep_evt_t *);
/********************************************************************************
* evt io
********************************************************************************/
libeep_evt_t * libeep_evt_read(const char *);
/********************************************************************************
* print stuff
********************************************************************************/
void libeep_evt_header_print(const libeep_evt_header_t *);
void libeep_evt_event_print(const libeep_evt_event_t *);
#endif
/********************************************************************************
* *
* this file is part of: *
* libeep, the project for reading and writing avr/cnt eeg and related files *
* *
********************************************************************************
* *
* LICENSE:Copyright (c) 2003-2009, *
* Advanced Neuro Technology (ANT) B.V., Enschede, The Netherlands *
* Max-Planck Institute for Human Cognitive & Brain Sciences, Leipzig, Germany *
* *
********************************************************************************
* *
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed WITHOUT ANY WARRANTY; even the implied warranty *
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
* *
*******************************************************************************/
#ifndef RAW3_H
#define RAW3_H
#define RCS_RAW3_H "$RCSfile: raw3.h,v $ $Revision: 2415 $"
#include <eep/eepmisc.h>
/* compression parameters */
#define RAW3_METHODC 3
typedef struct {
int method;
int nbits;
int nexcbits;
int length;
int hst[33];
sraw_t *res;
} raw3res_t;
typedef struct {
short chanc; /* channel sequence */
short *chanv;
raw3res_t rc[RAW3_METHODC]; /* some working buffers */
sraw_t *last;
sraw_t *cur;
} raw3_t;
/* set Verbose on for raw3 error checking (use with care!) */
void raw3_setVerbose(int onoff);
/* for each epoch, the ERR_FLAG_EPOCH can be set */
short raw3_get_ERR_FLAG_EPOCH();
/* therefore, reset using the following function */
void raw3_set_ERR_FLAG_EPOCH(short);
/*
prepare data compression for chanc * length signal data blocks
(the chanv vector is copied)
*/
raw3_t *raw3_init(int chanc, short *chanv, uint64_t length);
void raw3_free(raw3_t *raw3);
/*
compress a raw sample matrix to an output buffer
using the specified channel sequence to allow prediction by neighbor
caller must supply enough output space - use RAW3_EPOCH_SIZE
return: number of bytes filled in output buffer;
input buffer is in pure MUX format here (no EEP 2.0 control words!):
memory address->
|chan0 sample0| chan1 sample0|chan2 sample0...
|chan0 sample1| chan1 sample1|chan2 sample1...
...
(maybe I add all functions for time series buffers later)
*/
#define RAW3_EPOCH_SIZE(length, chanc) ((length + 2) * (chanc) * 4)
int compepoch_mux(raw3_t *raw3, sraw_t *in, int length, char *out);
/*
the same job backwards
return: number of bytes used from input buffer
*/
int decompepoch_mux(raw3_t *raw3, char *in, int length, sraw_t *out);
/*
find and return a good channel sequence for prediction by neighbor
buf contains the multiplexed raw data to predict from and is unchanged
chanv space (chanc elements) has to be supplied by caller