Skip to content

Commit

Permalink
IO: Updated AnyWave marker file reader
Browse files Browse the repository at this point in the history
  • Loading branch information
ftadel committed Mar 28, 2022
1 parent a6fa6dd commit 5c14f54
Showing 1 changed file with 64 additions and 50 deletions.
114 changes: 64 additions & 50 deletions toolbox/io/in_events_anywave.m
Expand Up @@ -2,6 +2,8 @@
% IN_EVENTS_ANYWAVE: Read the events descriptions for a AnyWave file.
%
% USAGE: events = in_events_anywave(sFile, EventFile)
%
% REFERENCE: https://meg.univ-amu.fr/wiki/AnyWave:ADES#The_marker_file_.28.mrk.29

% @=============================================================================
% This function is part of the Brainstorm software:
Expand All @@ -22,6 +24,7 @@
% =============================================================================@
%
% Authors: Konstantinos Nasiotis, 2020
% Francois Tadel, 2022

%% Matlab generated script - LOAD THE EVENT FILE
% Initialize variables.
Expand All @@ -45,6 +48,11 @@
% Close the text file.
fclose(fileID);

if isempty(dataArray) || isempty(dataArray{1})
events = [];
return;
end

% Convert the contents of columns containing numeric text to numbers.
% Replace non-numeric text with NaN.
raw = repmat({''},length(dataArray{1}),length(dataArray)-1);
Expand All @@ -69,13 +77,13 @@
invalidThousandsSeparator = false;
if any(numbers==',')
thousandsRegExp = '^\d+?(\,\d{3})*\.{0,1}\d*$';
if isempty(regexp(numbers, thousandsRegExp, 'once'));
if isempty(regexp(numbers, thousandsRegExp, 'once'))
numbers = NaN;
invalidThousandsSeparator = true;
end
end
% Convert numeric text to numbers.
if ~invalidThousandsSeparator;
if ~invalidThousandsSeparator
numbers = textscan(strrep(numbers, ',', ''), '%f');
numericData(row, col) = numbers{1};
raw{row, col} = numbers{1};
Expand All @@ -85,11 +93,9 @@
end
end


% Split data into numeric and cell columns.
rawNumericColumns = raw(:, [2,3,4,6]);
rawCellColumns = raw(:, [1,5]);

rawNumericColumns = raw(:, [2,3,4]);
rawCellColumns = raw(:, [1,5,6]);

% Replace non-numeric cells with NaN
R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),rawNumericColumns); % Find non-numeric cells
Expand All @@ -100,56 +106,64 @@
frequencies = cell2mat(rawNumericColumns(:, 1));
times = cell2mat(rawNumericColumns(:, 2));
duration = cell2mat(rawNumericColumns(:, 3));
Electrode_label = rawCellColumns(:, 2);
VarName15 = cell2mat(rawNumericColumns(:, 4));

% Clear temporary variables
clearvars filename delimiter startRow formatSpec fileID dataArray ans raw col numericData rawData row regexstr result numbers invalidThousandsSeparator thousandsRegExp me rawNumericColumns rawCellColumns R;


%% Combine electrode and label

% Get rid of the EEG prefix on the electrode channels and combine with the
% event label
all_event_labels = cell(length(Electrode_label),1);
for iEvent = 1:length(Electrode_label)
Electrode_label{iEvent} = erase(Electrode_label{iEvent}, {'EEG',','});
all_event_labels{iEvent} = [Label{iEvent} ' ' Electrode_label{iEvent}];
OptionalCol = rawCellColumns(:, [2,3]);


%% ===== DETECT CHANNELS/COLORS =====
Color = cell(size(Label,1), 1);
Channels = cell(size(Label,1), 1);
for iMrk = 1:size(OptionalCol,1)
for iCol = 1:size(OptionalCol,2)
% Empty column
if isempty(OptionalCol{iMrk,iCol})
continue;
% Color: #RRGGBB
elseif (OptionalCol{iMrk,iCol}(1) == '#')
if (length(OptionalCol{iMrk,iCol}) == 7)
Color{iMrk} = [hex2dec(OptionalCol{iMrk,iCol}(2:3)), hex2dec(OptionalCol{iMrk,iCol}(4:5)), hex2dec(OptionalCol{iMrk,iCol}(6:7))] ./ 255;
end
% Channel names: separated with commas
else
Channels{iMrk} = str_split(OptionalCol{iMrk,iCol}, ',');
end
end
end

[uniqueLabels, ia, iAssignmentOnUniqueLabels] =unique(all_event_labels);


%% Add everything in the brainstorm format
%% ===== DETECT NOTES =====
% Second column of the file: contains an integer, most likely a frequency, or -1 if not defined
Notes = cell(size(Label,1), 1);
for iMrk = 1:size(OptionalCol,1)
% No value
if isnan(frequencies(iMrk)) || (frequencies(iMrk) == -1)
continue;
end
% Frequency value
Notes{iMrk} = [num2str(frequencies(iMrk)) ' Hz'];
end

%% ===== CREATE BRAINSTORM STRUCTURE =====
% Initialize returned structure
events = repmat(db_template('event'), 0);
% Triggers
if ~isempty(uniqueLabels)
% Create events structures: one per category of event
for i = 1:length(uniqueLabels)
% Add a new event category
iEvt = length(events) + 1;

% Add event structure
events(iEvt).label = uniqueLabels{i};
events(iEvt).epochs = ones(1,sum(iAssignmentOnUniqueLabels == i));
% Extended events
if all(duration(iAssignmentOnUniqueLabels == i) == 0)
events(iEvt).times = times(iAssignmentOnUniqueLabels == i)';
else
events(iEvt).times = [times(iAssignmentOnUniqueLabels == i)'; duration(iAssignmentOnUniqueLabels == i)'];
end
events(iEvt).reactTimes = [];
events(iEvt).select = 1;
events(iEvt).color = rand(1,3);
events(iEvt).channels = cell(1, size(events(iEvt).times, 2));

all_frequencies = frequencies(iAssignmentOnUniqueLabels == i);
for iNote = 1:sum(iAssignmentOnUniqueLabels == i)
events(iEvt).notes{iNote} = [num2str(all_frequencies(iNote)) ' Hz'];
end
% Create one category of event per label
uniqueLabels = unique(Label);
for i = 1:length(uniqueLabels)
% Add a new event category
iEvt = length(events) + 1;
iOcc = find(strcmp(Label, uniqueLabels{i}));
% Add event structure
events(iEvt).label = uniqueLabels{i};
events(iEvt).epochs = ones(1,length(iOcc));
% Extended events
if all(duration(iOcc) == 0)
events(iEvt).times = times(iOcc)';
else
events(iEvt).times = [times(iOcc)'; times(iOcc)' + duration(iOcc)'];
end
events(iEvt).reactTimes = [];
events(iEvt).select = 1;
events(iEvt).color = Color{iOcc(1)};
events(iEvt).channels = Channels(iOcc);
events(iEvt).notes = Notes(iOcc);
end


Expand Down

0 comments on commit 5c14f54

Please sign in to comment.