Authored by Francois Tadel

Updated Brainstorm functions

... ... @@ -5,9 +5,9 @@ function [ template ] = db_template(structureName)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -21,7 +21,7 @@ function [ template ] = db_template(structureName)
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2008-2016
% Authors: Francois Tadel, 2008-2019
switch lower(structureName)
... ... @@ -210,8 +210,9 @@ switch lower(structureName)
'Label', [], ...
'Type', []), ...
'Channel', [], ... % [nChannels] Structure array, one structure per sensor
'IntraElectrodes', [], ...
'History', []);
case 'dipolemat'
template = struct(...
'Comment', '', ...
... ... @@ -266,6 +267,7 @@ switch lower(structureName)
'pmap', [], ...
'tmap', [], ...
'df', 0, ...
'SPM', [], ...
'Correction', 'no', ...
'Type', '', ...
'Comment', '', ...
... ... @@ -306,6 +308,7 @@ switch lower(structureName)
'Scalp', '', ...
'InnerSkull', '', ...
'OuterSkull', '', ...
'Fibers', '', ...
'UseDefaultAnat', 0, ...
'UseDefaultChannel', 1);
case 'subject'
... ... @@ -321,6 +324,7 @@ switch lower(structureName)
'iCortex', [], ...
'iInnerSkull', [], ...
'iOuterSkull', [], ...
'iFibers', [], ...
'iOther', [], ...
'UseDefaultAnat', 0 , ...
'UseDefaultChannel', 1);
... ... @@ -437,16 +441,18 @@ switch lower(structureName)
'label', '', ...
'color', [], ...
'epochs', [], ... % [list of epochs indices]
'samples', [], ... % [list of time indices]
'times', [], ... % [list of time values]
'reactTimes', [], ... % [list of reaction times, when applicable]
'select', 1);
'select', 1, ...
'channels', [], ...
'notes', []);
template.channels = {};
template.notes = {};
% ==== EPOCH ====
case 'epoch'
template = struct(...
'label', '', ...
'samples', [], ... % [iStart, iStop]
'times', [], ... % [tStart, tStop]
'nAvg', 1, ... % Number of epochs averaged to produce this block
'select', 1, ...
... ... @@ -464,7 +470,6 @@ switch lower(structureName)
'byteorder', '', ... % ieee-le, ieee-be...
'prop', struct(... % Properties of the recordings
'times', [], ... % [tStart, tStop]
'samples', [], ... % [iStart, iStop]
'sfreq', 0, ... % Sampling frequency
'nAvg', 1, ... % Number of trials used to create this file
'currCtfComp', [], ... % {0,1,3} Current CTF compensation order already applied to the recordings
... ... @@ -472,7 +477,8 @@ switch lower(structureName)
'epochs', repmat(db_template('epoch'), 0), ...
'events', repmat(db_template('event'), 0), ...
'header', [], ...
'channelflag', []);
'channelflag', [], ...
'acq_date', []);
case 'importoptions'
template = struct(...
... ... @@ -498,7 +504,8 @@ switch lower(structureName)
'EventsMode', 'ask', ... % Where to get the events from: {'ask', 'ignore', Filename, ChannelName, ChannelNames}
'EventsTrackMode', 'ask', ... % {'value','bit','ttl','rttl','ask'}
'EventsTypes', '', ... % String with a list of eventtypes to use to group the epochs (EEGLAB only)
'DisplayMessages', 1); % If 0, do not show any of the message boxes that the user would normally see
'DisplayMessages', 1, ... % If 0, do not show any of the message boxes that the user would normally see
'Precision', []); % Precision when reading the file {'double' (default), 'single'} (only for supported file formats)
% ==== COLORMAPS ====
case 'colormap'
... ... @@ -511,6 +518,7 @@ switch lower(structureName)
'MaxMode', 'global', ...
'MinValue', [], ...
'MaxValue', [], ...
'UseStatThreshold', 0, ...
'Contrast', 0, ...
'Brightness', 0);
... ... @@ -534,7 +542,9 @@ switch lower(structureName)
'isFiltered', 0, ...
'ColormapType', '', ...
'DisplayUnits', [], ...
'StatClusters', []);
'StatClusters', [], ...
'StatThreshUnder', [], ...
'StatThreshOver', []);
case 'loadedresults'
template = struct(...
... ... @@ -551,6 +561,7 @@ switch lower(structureName)
'ZScore', [], ...
'SurfaceFile', [], ...
'HeadModelType', [], ...
'HeadModelFile', [], ...
'GridLoc', [], ...
'GridOrient', [], ...
'GridAtlas', [], ...
... ... @@ -561,7 +572,9 @@ switch lower(structureName)
'ColormapType', '', ...
'DisplayUnits', [], ...
'Atlas', [], ...
'StatClusters', []);
'StatClusters', [], ...
'StatThreshUnder', [], ...
'StatThreshOver', []);
case 'loadeddipoles'
template = struct(...
... ... @@ -604,7 +617,9 @@ switch lower(structureName)
'GridAtlas', [], ...
'SurfaceFile', [], ...
'sPAC', [], ...
'StatClusters', []);
'StatClusters', [], ...
'StatThreshUnder', [], ...
'StatThreshOver', []);
case 'loadedmatrix'
template = struct(...
... ... @@ -614,7 +629,9 @@ switch lower(structureName)
'DisplayUnits', [], ...
'SurfaceFile', '', ...
'Atlas', [], ...
'StatClusters', []);
'StatClusters', [], ...
'StatThreshUnder', [], ...
'StatThreshOver', []);
case 'loadedsurface'
template = struct(...
... ... @@ -629,6 +646,7 @@ switch lower(structureName)
'SulciMap', [], ...
'tess2mri_interp', [], ... % Interpolation matrix (Surface -> MRI)
'mrimask', [], ... % MRI mask
'envelope', [], ...
'Atlas', db_template('Atlas'), ...
'iAtlas', 1, ...
'isAtlasModified', 0);
... ... @@ -670,6 +688,21 @@ switch lower(structureName)
'Orient', [], ...
'Weight', []);
case 'intraelectrode'
template = struct(...
'Name', '', ... % Identification
'Type', '', ... % 'SEEG' / 'ECOG'
'Model', '', ... % String identifying the make and model
'Loc', [], ... % [3xN] positions with all the relevant points (eg. tip and entry)
'Color', [], ... % [1x3] color vector
'ContactNumber', [], ...
'ContactSpacing', [], ...
'ContactDiameter', [], ...
'ContactLength', [], ...
'ElecDiameter', [], ...
'ElecLength', [], ...
'Visible', 1);
case 'dataset'
template = struct(...
'DataFile', '', ...
... ... @@ -685,6 +718,8 @@ switch lower(structureName)
'Channel', repmat(db_template('ChannelDesc'), 0), ...
'MegRefCoef', [], ...
'Projector', repmat(db_template('Projector'), 0), ...
'IntraElectrodes', repmat(db_template('IntraElectrode'), 0), ...
'isChannelModified', 0, ...
'HeadPoints', [], ...
'Figure', repmat(db_template('Figure'), 0));
... ... @@ -696,6 +731,7 @@ switch lower(structureName)
'hLines', [], ...
'hLinePatches', [], ...
'hLinesZeroY', [], ...
'hLineDecodingY',[], ...
'LinesLabels', [], ...
'LinesColor', [], ...
'hColumnScale', [], ...
... ... @@ -704,7 +740,8 @@ switch lower(structureName)
'ChannelOffsets',[], ...
'DataMinMax', [], ...
'DisplayFactor', [], ...
'DisplayUnits', []);
'DisplayUnits', [], ...
'DownsampleFactor', []);
case 'displayhandlestopography'
template = struct(...
'hSurf', [], ...
... ... @@ -722,6 +759,7 @@ switch lower(structureName)
'hZeroLines', [], ... % 2D Layout
'hAxesLegend', [], ... % 2D Layout
'hLabelLegend', [], ... % 2D Layout
'hOverlayLegend', [], ... % 2D Layout
'Channel', [], ... % 2D Layout
'Vertices', [], ... % 2D Layout
'SelChan', [], ... % 2D Layout
... ... @@ -801,8 +839,7 @@ switch lower(structureName)
'Version', [], ...
'BrainstormHomeDir', [], ...
'ScreenDef', [], ...
'isGUI', 1, ...
'isServer', 0, ...
'GuiLevel', 1, ...
'GUI', [], ...
'CloneLock', 1, ...
'ProgressBar', [], ...
... ... @@ -813,6 +850,7 @@ switch lower(structureName)
'Nodes', [], ...
'isCut', 0), ...
'FontCache', struct(), ...
'ColorChooser', [], ...
'ProcessMenuCache', struct()), ...
'DataBase', struct(...
'ProtocolInfo', [], ...
... ... @@ -828,6 +866,7 @@ switch lower(structureName)
'DataSet', repmat(db_template('DataSet'), 0), ...
'Mri', repmat(db_template('LoadedMri'), 0), ...
'Surface', repmat(db_template('LoadedSurface'), 0), ...
'Fibers', repmat(db_template('LoadedFibers'), 0), ...
'UserTimeWindow', struct(...
'Time', [], ...
'SamplingRate', [], ...
... ... @@ -839,8 +878,9 @@ switch lower(structureName)
'NumberOfSamples', 0), 0), ...
'CurrentEpoch', []), ...
'UserFrequencies', struct(...
'Freqs', [], ...
'iCurrentFreq', []), ...
'Freqs', [], ...
'iCurrentFreq', [], ...
'HideFreqPanel', 0), ...
'ChannelEditor', struct(...
'ChannelFile', '', ...
'ChannelMat', [], ...
... ... @@ -848,6 +888,7 @@ switch lower(structureName)
'LocColumns', [], ...
'OrientColumns', [], ...
'isModified', 0), ...
'Guidelines', [], ... % Temporary variables for the guidelines panels
'HeadModeler', struct(...
'BFS', [], ...
'nbSpheres', [], ...
... ... @@ -933,7 +974,8 @@ switch lower(structureName)
'FileName', '', ...
'Atlas', [], ...
'GridAtlas', [], ...
'GridLoc', []), ...
'GridLoc', [], ...
'GridSmooth', 1), ...
'ColormapType', '', ...
'hPatch', [], ...
'nVertices', 0, ...
... ... @@ -954,8 +996,9 @@ switch lower(structureName)
'CutsPosition', [0 0 0], ... % Position of the three orthogonal MRI slices
'Resect', 'none', ... % Either [x,y,z] resect values, or {'left', 'right', 'none'}
'MipAnatomy', [], ... % 3 cells: Maximum intensity power in each direction (MRI amplitudes)
'MipFunctional', [] ... % 3 cellsMaximum intensity power in each direction (sources amplitudes)
);
'MipFunctional', [], ... % 3 cells: Maximum intensity power in each direction (sources amplitudes)
'StatThreshOver', [], ...
'StatThreshUnder', []);
template.MipAnatomy = cell(3,1);
template.MipFunctional = cell(3,1);
... ... @@ -974,11 +1017,13 @@ switch lower(structureName)
'AutoScaleY', 1, ...
'NormalizeAmp', 0, ...
'Resolution', [0 0], ...
'YLabel', [], ...
'ShowEvents', 1, ...
'ShowEventsMode', 'dot', ...
'ShowLegend', [], ...
'YLabel', [], ...
'ShowXGrid', 0, ...
'ShowYGrid', 0);
'ShowYGrid', 0, ...
'ShowZeroLines', 1);
case 'topoinfo'
template = struct(...
... ... @@ -987,16 +1032,7 @@ switch lower(structureName)
'FileType', '', ...
'TopoType', '', ...
'DataToPlot', [], ...
'UseSmoothing', 1);
case 'electrodeinfo'
template = struct(...
'ElecType', [], ...
'ElecDiameter', [], ...
'ElecHeight', [], ...
'StripDiameter', [], ...
'StripLength', [], ...
'WireWidth', []);
'UseSmoothing', 1);
case 'tfinfo'
template = struct(...
... ... @@ -1009,7 +1045,8 @@ switch lower(structureName)
'iFreqs', [], ...
'RowName', [], ...
'RefRowName', [], ...
'InputTarget', []);
'InputTarget', [], ...
'NeuronNames', []);
case 'nodelist'
template = struct(...
... ... @@ -1081,6 +1118,29 @@ switch lower(structureName)
template = struct(...
'WInterp', [], ...
'Signature', []);
case 'fibers'
template = struct(...
'Comment', [], ...
'Header', [], ...
'Points', [], ...
'Colors', [], ...
'Scouts', struct(...
'ConnectFile', [], ...
'Assignment', []), ...
'History', []);
case 'loadedfibers'
template = struct(...
'FileName', '', ...
'Comment', [], ...
'Header', [], ...
'Points', [], ...
'Colors', [], ...
'Scouts', struct(...
'ConnectFile', [], ...
'Assignment', []), ...
'History', []);
otherwise
error('Unknown data template : %s', structureName);
... ...
... ... @@ -5,9 +5,9 @@ function isExist = file_exist(filename)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ...
... ... @@ -15,9 +15,9 @@ function [foundFiles, iDepth] = file_find( baseDir, filePattern, maxDepth, isSin
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -64,7 +64,7 @@ else
foundFiles = bst_fullfile(baseDir, listDir(1).name);
else
for i = 1:length(listDir)
foundFiles = cat(2, {bst_fullfile(baseDir, listDir(i).name)});
foundFiles = cat(2, foundFiles, {bst_fullfile(baseDir, listDir(i).name)});
end
end
return
... ...
... ... @@ -17,9 +17,9 @@ function filename = file_standardize( filename, isFullPath, repchar, isStrict )
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ...
... ... @@ -13,9 +13,9 @@ function [uniqueFile, tag] = file_unique(filename, allFiles, isCaseSensitive)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ...
... ... @@ -9,9 +9,9 @@ function [sFile, newEvents] = import_events(sFile, ChannelMat, EventFile, FileFo
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -25,14 +25,14 @@ function [sFile, newEvents] = import_events(sFile, ChannelMat, EventFile, FileFo
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2010-2014
% Authors: Francois Tadel, 2010-2018
%% ===== PARSE INPUTS =====
if (nargin < 5) || isempty(EventName)
EventName = [];
end
% CALL: import_events(sFile, [], EventMat)
if (nargin == 3) && isstruct(EventFile)
if (nargin >= 3) && isstruct(EventFile)
newEvents = EventFile;
EventFile = [];
FileFormat = [];
... ... @@ -58,18 +58,30 @@ if isempty(EventFile) && isempty(newEvents)
% Get default directories and formats
DefaultFormats = bst_get('DefaultFormats');
% Get file
[EventFile, FileFormat] = java_getfile( 'open', 'Import events...', ... % Window title
fPath, ... % Default directory
'single', 'files', ... % Selection mode
[EventFiles, FileFormat] = java_getfile( 'open', 'Import events...', ... % Window title
fPath, ... % Default directory
'multiple', 'files', ... % Selection mode
bst_get('FileFilters', 'events'), ...
DefaultFormats.EventsIn);
% If no file was selected: exit
if isempty(EventFile)
if isempty(EventFiles)
return
end
% Save default export format
DefaultFormats.EventsIn = FileFormat;
bst_set('DefaultFormats', DefaultFormats);
% Call this function recursively for each selected event file, and
% concatenate the result together
for iEventFile = 1:length(EventFiles)
[sFile, events] = import_events(sFile, ChannelMat, EventFiles{iEventFile}, FileFormat, EventName);
if isempty(newEvents)
newEvents = events;
else
newEvents(end+1:end+length(events)) = events;
end
end
return
end
%% ===== READ FILE =====
... ... @@ -82,6 +94,8 @@ if isempty(newEvents)
newEvents = in_events_ant(sFile, EventFile);
case 'BESA'
newEvents = in_events_besa(sFile, EventFile);
case 'BIDS'
newEvents = in_events_bids(sFile, EventFile);
case 'BRAINAMP'
newEvents = in_events_brainamp(sFile, EventFile);
case 'BST'
... ... @@ -109,6 +123,8 @@ if isempty(newEvents)
newEvents = in_events_trl(sFile, EventFile);
case 'KIT'
newEvents = in_events_kit(sFile, EventFile);
case 'RICOH'
newEvents = in_events_ricoh(sFile, EventFile);
case 'KDF'
newEvents = in_events_kdf(sFile, EventFile);
case 'PRESENTATION'
... ... @@ -132,6 +148,13 @@ if isempty(newEvents)
return
end
end
% Fix events structure
if ~isempty(newEvents)
newEvents = struct_fix_events(newEvents);
end
if ~isempty(sFile.events)
sFile.events = struct_fix_events(sFile.events);
end
%% ===== MERGE EVENTS LISTS =====
... ... @@ -144,8 +167,7 @@ for iNew = 1:length(newEvents)
iEvt = [];
end
% Make sure that the sample indices are round values
newEvents(iNew).samples = round(newEvents(iNew).samples);
newEvents(iNew).times = newEvents(iNew).samples ./ sFile.prop.sfreq;
newEvents(iNew).times = round(newEvents(iNew).times * sFile.prop.sfreq) ./ sFile.prop.sfreq;
% If event does not exist yet: add it at the end of the list
if isempty(iEvt)
if isempty(sFile.events)
... ... @@ -159,18 +181,20 @@ for iNew = 1:length(newEvents)
else
% Merge events occurrences
sFile.events(iEvt).times = [sFile.events(iEvt).times, newEvents(iNew).times];
sFile.events(iEvt).samples = [sFile.events(iEvt).samples, newEvents(iNew).samples];
sFile.events(iEvt).epochs = [sFile.events(iEvt).epochs, newEvents(iNew).epochs];
sFile.events(iEvt).reactTimes = [sFile.events(iEvt).reactTimes, newEvents(iNew).reactTimes];
% Sort by sample indices
if (size(sFile.events(iEvt).samples, 2) > 1)
[tmp__, iSort] = unique(sFile.events(iEvt).samples(1,:));
sFile.events(iEvt).samples = sFile.events(iEvt).samples(:,iSort);
sFile.events(iEvt).channels = [sFile.events(iEvt).channels, newEvents(iNew).channels];
sFile.events(iEvt).notes = [sFile.events(iEvt).notes, newEvents(iNew).notes];
% Sort by time
if (size(sFile.events(iEvt).times, 2) > 1)
[tmp__, iSort] = unique(bst_round(sFile.events(iEvt).times(1,:), 9));
sFile.events(iEvt).times = sFile.events(iEvt).times(:,iSort);
sFile.events(iEvt).epochs = sFile.events(iEvt).epochs(iSort);
if ~isempty(sFile.events(iEvt).reactTimes)
sFile.events(iEvt).reactTimes = sFile.events(iEvt).reactTimes(iSort);
end
sFile.events(iEvt).channels = sFile.events(iEvt).channels(iSort);
sFile.events(iEvt).notes = sFile.events(iEvt).notes(iSort);
end
end
% Add color if does not exist yet
... ...
... ... @@ -6,9 +6,9 @@ function ChannelMat = in_channel_nk(ChannelFile, version)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ...
... ... @@ -10,9 +10,9 @@ function events = in_events_brainamp(sFile, EventFile)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -86,13 +86,15 @@ for iEvt = 1:length(uniqueEvt)
% Add event structure
events(iEvt).label = uniqueEvt{iEvt};
events(iEvt).epochs = ones(1, length(iMrk));
events(iEvt).samples = [Markers{iMrk,3}];
samples = [Markers{iMrk,3}];
if any([Markers{iMrk,4}] > 1)
events(iEvt).samples(2,:) = [Markers{iMrk,3}] + [Markers{iMrk,4}];
samples(2,:) = [Markers{iMrk,3}] + [Markers{iMrk,4}];
end
events(iEvt).times = events(iEvt).samples ./ sFile.prop.sfreq;
events(iEvt).times = samples ./ sFile.prop.sfreq;
events(iEvt).reactTimes = [];
events(iEvt).select = 1;
events(iEvt).channels = cell(1, size(events(iEvt).times, 2));
events(iEvt).notes = cell(1, size(events(iEvt).times, 2));
end
... ...
... ... @@ -3,9 +3,9 @@ function events = in_events_xltek(sFile, EventFile)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -68,11 +68,12 @@ for iEvt = 1:length(uniqueEvt)
iMrk = find(strcmpi(evtLabel, uniqueEvt{iEvt}));
% Add event structure
events(iEvt).label = uniqueEvt{iEvt};
events(iEvt).samples = unique(round(evtTime(iMrk) .* sFile.prop.sfreq));
events(iEvt).times = events(iEvt).samples ./ sFile.prop.sfreq;
events(iEvt).epochs = ones(1, length(events(iEvt).samples));
events(iEvt).times = unique(round(evtTime(iMrk) .* sFile.prop.sfreq)) ./ sFile.prop.sfreq;
events(iEvt).epochs = ones(1, length(events(iEvt).times));
events(iEvt).reactTimes = [];
events(iEvt).select = 1;
events(iEvt).channels = cell(1, size(events(iEvt).times, 2));
events(iEvt).notes = cell(1, size(events(iEvt).times, 2));
end
... ...
... ... @@ -5,9 +5,9 @@ function [sFile, ChannelMat] = in_fopen_brainamp(DataFile)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -110,7 +110,7 @@ while 1
hdr.chgain(iChan) = chFactor * chUnit;
elseif strcmpi(curBlock, 'Coordinates')
tmpLoc = str2num(argLine{2});
tmpLoc = str2num(argLine{2});
% Spherical (R,TH,PHI)
if (length(tmpLoc) == 3) && (tmpLoc(1) == 1)
% Convert Spherical(degrees) => Spherical(radians) => Cartesian
... ... @@ -160,13 +160,13 @@ if (strcmpi(hdr.DataFormat, 'BINARY') && strcmpi(hdr.DataOrientation, 'MULTIPLEX
dirInfo = dir(DataFile);
% Get number of samples
switch lower(hdr.BinaryFormat)
case 'int_16';
case 'int_16'
hdr.bytesize = 2;
hdr.byteformat = 'int16';
case 'int_32';
case 'int_32'
hdr.bytesize = 4;
hdr.byteformat = 'int32';
case 'ieee_float_32';
case 'ieee_float_32'
hdr.bytesize = 4;
hdr.byteformat = 'float32';
end
... ... @@ -193,8 +193,7 @@ sFile.header = hdr;
[tmp__, sFile.comment, tmp__] = bst_fileparts(DataFile);
% Consider that the sampling rate of the file is the sampling rate of the first signal
sFile.prop.sfreq = 1e6 ./ hdr.SamplingInterval;
sFile.prop.samples = [0, hdr.nsamples - 1];
sFile.prop.times = sFile.prop.samples ./ sFile.prop.sfreq;
sFile.prop.times = [0, hdr.nsamples - 1] ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
% No info on bad channels
sFile.channelflag = ones(hdr.NumberOfChannels, 1);
... ... @@ -211,7 +210,7 @@ for i = 1:hdr.NumberOfChannels
else
ChannelMat.Channel(i).Name = sprintf('E%d', i);
end
if ~isempty(hdr.chloc)
if ~isempty(hdr.chloc) && (i <= size(hdr.chloc,1))
ChannelMat.Channel(i).Loc = hdr.chloc(i,:)';
else
ChannelMat.Channel(i).Loc = [0; 0; 0];
... ...
... ... @@ -5,9 +5,9 @@ function [sFile, ChannelMat] = in_fopen_deltamed(DataFile)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -21,7 +21,7 @@ function [sFile, ChannelMat] = in_fopen_deltamed(DataFile)
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2013-2014
% Authors: Francois Tadel, 2013-2018
%% ===== GET FILES =====
% Build header files names (.txt)
... ... @@ -47,6 +47,8 @@ while 1
if isempty(newLine) || ismember(newLine(1), {';', char(10), char(13)})
continue;
end
% Remove double-quotes
newLine(newLine == '"') = [];
% Read block names
if (newLine(1) == '[')
curBlock = newLine;
... ... @@ -115,12 +117,13 @@ sFile.header = hdr;
% Comment: short filename
[tmp__, sFile.comment, tmp__] = bst_fileparts(DataFile);
% Consider that the sampling rate of the file is the sampling rate of the first signal
sFile.prop.sfreq = hdr.Sampling;
sFile.prop.samples = [0, hdr.DurationInSamples - 1];
sFile.prop.times = sFile.prop.samples ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
sFile.prop.sfreq = hdr.Sampling;
sFile.prop.times = [0, hdr.DurationInSamples - 1] ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
% No info on bad channels
sFile.channelflag = ones(hdr.NbOfChannels, 1);
% Acquisition date
sFile.acq_date = str_date(hdr.Date);
%% ===== CREATE EMPTY CHANNEL FILE =====
... ... @@ -152,18 +155,17 @@ if ~isempty(hdr.event)
events = repmat(db_template('event'), 1, length(uniqueEvt));
% Format list
for iEvt = 1:length(uniqueEvt)
% Ask for a label
% Find list of occurences of this event
iOcc = find(strcmpi(allNames, uniqueEvt{iEvt}));
% Fill events structure
events(iEvt).label = uniqueEvt{iEvt};
events(iEvt).color = [];
events(iEvt).times = [hdr.event(iOcc).sample] ./ sFile.prop.sfreq;
events(iEvt).epochs = ones(1, length(events(iEvt).times));
events(iEvt).reactTimes = [];
events(iEvt).select = 1;
% Find list of occurences of this event
iOcc = find(strcmpi(allNames, uniqueEvt{iEvt}));
% Get time and samples
events(iEvt).samples = [hdr.event(iOcc).sample];
events(iEvt).times = events(iEvt).samples ./ sFile.prop.sfreq;
% Epoch: set as 1 for all the occurrences
events(iEvt).epochs = ones(1, length(events(iEvt).samples));
events(iEvt).channels = cell(1, size(events(iEvt).times, 2));
events(iEvt).notes = cell(1, size(events(iEvt).times, 2));
end
% Import this list
sFile = import_events(sFile, [], events);
... ...
... ... @@ -7,7 +7,7 @@ function [sFile, ChannelMat] = in_fopen_edf(DataFile, ImportOptions)
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2018 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -143,11 +143,11 @@ end
iAnnotChans = find(strcmpi({hdr.signal.label}, 'EDF Annotations')); % Mutliple "EDF Annotation" channels allowed in EDF+
iStatusChan = find(strcmpi({hdr.signal.label}, 'Status'), 1); % Only one "Status" channel allowed in BDF
iOtherChan = setdiff(1:hdr.nsignal, [iAnnotChans iStatusChan]);
% Remove channels with lower sampling rates
iIgnoreChan = find([hdr.signal(iOtherChan).sfreq] < max([hdr.signal(iOtherChan).sfreq])); % Ignore all the channels with lower sampling rate
if ~isempty(iIgnoreChan)
iOtherChan = setdiff(iOtherChan, iIgnoreChan);
end
% % Remove channels with lower sampling rates
% iIgnoreChan = find([hdr.signal(iOtherChan).sfreq] < max([hdr.signal(iOtherChan).sfreq])); % Ignore all the channels with lower sampling rate
% if ~isempty(iIgnoreChan)
% iOtherChan = setdiff(iOtherChan, iIgnoreChan);
% end
% Get all the other channels
if isempty(iOtherChan)
error('This file does not contain any data channel.');
... ... @@ -169,7 +169,21 @@ end
% Detect interrupted signals (time non-linear)
hdr.interrupted = ischar(hdr.unknown1) && (length(hdr.unknown1) >= 5) && isequal(hdr.unknown1(1:5), 'EDF+D');
if hdr.interrupted
warning('Interrupted EDF file ("EDF+D"): requires conversion to "EDF+C"');
if ImportOptions.DisplayMessages
[res, isCancel] = java_dialog('question', ...
['Interrupted EDF file ("EDF+D") detected. It is recommended to convert it' 10 ...
'to a continuous ("EDF+C") file first. Do you want to continue reading this' 10 ...
'file as continuous and attempt to fix the timing of event markers?' 10 ...
'NOTE: This may not work as intended, use at your own risk!']);
hdr.fixinterrupted = ~isCancel && strcmpi(res, 'yes');
else
hdr.fixinterrupted = 1;
end
if ~hdr.fixinterrupted
warning(['Interrupted EDF file ("EDF+D"): requires conversion to "EDF+C". ' 10 ...
'Brainstorm will read this file as a continuous file ("EDF+C"), the timing of the samples after the first discontinuity will be wrong.' 10 ...
'This may not cause any major problem unless there are time markers in the file, they might be inaccurate in all the segments >= 2.']);
end
end
... ... @@ -189,11 +203,6 @@ end
sFile.header = hdr;
% Comment: short filename
[tmp__, sFile.comment, tmp__] = bst_fileparts(DataFile);
% Consider that the sampling rate of the file is the sampling rate of the first signal
sFile.prop.sfreq = hdr.signal(iOtherChan(1)).sfreq;
sFile.prop.samples = [0, hdr.signal(iOtherChan(1)).nsamples * hdr.nrec - 1];
sFile.prop.times = sFile.prop.samples ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
% No info on bad channels
sFile.channelflag = ones(hdr.nsignal,1);
% Acquisition date
... ... @@ -206,6 +215,17 @@ sFile.acq_date = str_date(hdr.startdate);
SplitType = repmat({''}, 1, hdr.nsignal);
SplitName = repmat({''}, 1, hdr.nsignal);
for i = 1:hdr.nsignal
% Removing trailing dots (eg. "Fc5." instead of "FC5", as in: https://www.physionet.org/pn4/eegmmidb/)
if (hdr.signal(i).label(end) == '.') && (length(hdr.signal(i).label) > 1)
hdr.signal(i).label(end) = [];
if (hdr.signal(i).label(end) == '.') && (length(hdr.signal(i).label) > 1)
hdr.signal(i).label(end) = [];
if (hdr.signal(i).label(end) == '.') && (length(hdr.signal(i).label) > 1)
hdr.signal(i).label(end) = [];
end
end
end
% Remove extra spaces
signalLabel = strrep(hdr.signal(i).label, ' - ', '-');
% Find space chars (label format "Type Name")
iSpace = find(signalLabel == ' ');
... ... @@ -300,8 +320,31 @@ iMisc = find(strcmpi({ChannelMat.Channel.Type}, 'Misc'));
iEeg = find(strcmpi({ChannelMat.Channel.Type}, 'EEG'));
if ~isempty(iMisc) && isempty(iEeg)
[ChannelMat.Channel(iMisc).Type] = deal('EEG');
iEeg = iMisc;
end
%% ===== DETECT MULTIPLE SAMPLING RATES =====
% Use the first "EEG" channel as the reference sampling rate (or the first channel if no "EEG" channels available)
if ~isempty(iEeg) && ismember(iEeg(1), iOtherChan)
iChanFreqRef = iEeg(1);
else
iChanFreqRef = iOtherChan(1);
end
% Mark as bad channels with sampling rates different from EEG
iChanWrongRate = find([sFile.header.signal.sfreq] ~= sFile.header.signal(iChanFreqRef).sfreq);
iChanWrongRate = intersect(iChanWrongRate, iOtherChan);
if ~isempty(iChanWrongRate)
sFile.channelflag(iChanWrongRate) = -1;
end
% Consider that the sampling rate of the file is the sampling rate of the first signal
sFile.prop.sfreq = hdr.signal(iChanFreqRef).sfreq;
sFile.prop.times = [0, hdr.signal(iChanFreqRef).nsamples * hdr.nrec - 1] ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
%% ===== READ EDF ANNOTATION CHANNEL =====
if ~isempty(iEvtChans) % && ~isequal(ImportOptions.EventsMode, 'ignore')
... ... @@ -312,11 +355,11 @@ if ~isempty(iEvtChans) % && ~isequal(ImportOptions.EventsMode, 'ignore')
% Read EDF annotations
if strcmpi(sFile.format, 'EEG-EDF')
evtList = {};
% Process separately the multiple annotation channels
for ichan = 1:length(iEvtChans)
% Read annotation channel epoch by epoch
for irec = 1:hdr.nrec
bst_progress('text', sprintf('Reading annotations... [%d%%]', round((irec + (ichan-1)*hdr.nrec)/length(iEvtChans)/hdr.nrec*100)));
% In EDF+, the first annotation channel has epoch time stamps (EDF
% calls epochs records). So read all annotation channels per epoch.
for irec = 1:hdr.nrec
for ichan = 1:length(iEvtChans)
bst_progress('text', sprintf('Reading annotations... [%d%%]', round((ichan + (irec-1)*length(iEvtChans))/length(iEvtChans)/hdr.nrec*100)));
% Sample indices for the current epoch (=record)
SampleBounds = [irec-1,irec] * sFile.header.signal(iEvtChans(ichan)).nsamples - [0,1];
% Read record
... ... @@ -326,11 +369,41 @@ if ~isempty(iEvtChans) % && ~isequal(ImportOptions.EventsMode, 'ignore')
if isempty(Fsplit)
continue;
end
% Get first time stamp
if (irec == 1)
t0 = str2double(char(Fsplit{1}));
if ichan == 1
% Get record time stamp
t0_rec = str2double(char(Fsplit{1}));
if (irec == 1)
t0_file = t0_rec;
% Find discontinuities
elseif abs(t0_rec - prev_rec - hdr.reclen) > 1e-8
% Brainstorm fills partial/interrupted records with zeros
bstTime = prev_rec + hdr.reclen;
timeDiff = bstTime - t0_rec;
% If we want to fix timing, apply skip to initial timestamp
if hdr.fixinterrupted
t0_file = t0_file - timeDiff;
end
% Warn user of discontinuity
if timeDiff > 0
expectMsg = 'blank data';
else
expectMsg = 'skipped data';
end
startTime = min(t0_rec - t0_file - [0, timeDiff]); % before and after t0_file adjustment
endTime = max(t0_rec - t0_file - [0, timeDiff]);
fprintf('WARNING: Found discontinuity between %.3fs and %.3fs, expect %s in between.\n', startTime, endTime, expectMsg);
% Create event for users information
if timeDiff < 0
endTime = startTime; % no extent in this case, there is skipped time.
end
evtList(end+1,:) = {'EDF+D Discontinuity', [startTime; endTime]};
end
prev_rec = t0_rec;
end
% If there is an initial time: 3 values (ex: "+44.00000+44.47200Event1)
%% FIXME: There can be multiple text annotations (separated by 20) for a single onset/duration.
%% The zero characters should not be removed above as they delimit the TALs (Time-stamped Annotations Lists)
% If there is an initial time: 3 values (ex: "+44.00000+44.47200Event1Event2)
if (mod(length(Fsplit),2) == 1) && (length(Fsplit) >= 3)
iStart = 2;
% If there is no initial time: 2 values (ex: "+44.00000Epoch1)
... ... @@ -363,7 +436,7 @@ if ~isempty(iEvtChans) % && ~isequal(ImportOptions.EventsMode, 'ignore')
continue;
end
% Add to list of read events
evtList(end+1,:) = {label, (t-t0) + [0;duration]};
evtList(end+1,:) = {label, (t-t0_file) + [0;duration]};
end
end
end
... ... @@ -386,11 +459,12 @@ if ~isempty(iEvtChans) % && ~isequal(ImportOptions.EventsMode, 'ignore')
t = t(1,:);
end
% Set event
sFile.events(iEvt).label = strtrim(uniqueEvt{iEvt});
sFile.events(iEvt).times = t;
sFile.events(iEvt).samples = round(t .* sFile.prop.sfreq);
sFile.events(iEvt).epochs = 1 + 0*t(1,:);
sFile.events(iEvt).select = 1;
sFile.events(iEvt).label = strtrim(uniqueEvt{iEvt});
sFile.events(iEvt).times = round(t .* sFile.prop.sfreq) ./ sFile.prop.sfreq;
sFile.events(iEvt).epochs = 1 + 0*t(1,:);
sFile.events(iEvt).select = 1;
sFile.events(iEvt).channels = cell(1, size(sFile.events(iEvt).times, 2));
sFile.events(iEvt).notes = cell(1, size(sFile.events(iEvt).times, 2));
end
end
... ...
... ... @@ -5,7 +5,7 @@ function [sFile, ChannelMat] = in_fopen_micromed(DataFile)
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2018 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -396,8 +396,7 @@ sFile.byteorder = byteorder;
sFile.filename = DataFile;
sFile.format = 'EEG-MICROMED';
sFile.prop.sfreq = double(hdr.sampling_freq);
sFile.prop.samples = [0, hdr.num_samples - 1];
sFile.prop.times = sFile.prop.samples ./ sFile.prop.sfreq;
sFile.prop.times = [0, hdr.num_samples - 1] ./ sFile.prop.sfreq;
sFile.prop.nAvg = 1;
sFile.channelflag = ones(hdr.num_channels,1);
sFile.device = 'Micromed';
... ... @@ -468,11 +467,12 @@ for iEvt = 1:length(uniqueEvt)
% Get all the occurrences
iOcc = find(strcmpi(allEvt, uniqueEvt{iEvt}));
% Create event structure
sFile.events(iEvt).label = uniqueEvt{iEvt};
sFile.events(iEvt).samples = sort(allSmp(iOcc)) - 1; % Samples are 1-based in the file, I guess?
sFile.events(iEvt).times = sFile.events(iEvt).samples ./ sFile.prop.sfreq;
sFile.events(iEvt).epochs = ones(size(sFile.events(iEvt).samples));
sFile.events(iEvt).select = 1;
sFile.events(iEvt).label = uniqueEvt{iEvt};
sFile.events(iEvt).times = (sort(allSmp(iOcc)) - 1) ./ sFile.prop.sfreq; % Samples are 1-based in the file, I guess?
sFile.events(iEvt).epochs = ones(size(sFile.events(iEvt).times));
sFile.events(iEvt).select = 1;
sFile.events(iEvt).channels = cell(1, size(sFile.events(iEvt).times, 2));
sFile.events(iEvt).notes = cell(1, size(sFile.events(iEvt).times, 2));
end
... ...
... ... @@ -3,9 +3,9 @@ function [sFile, ChannelMat] = in_fopen_nicolet(DataFile)
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -19,7 +19,7 @@ function [sFile, ChannelMat] = in_fopen_nicolet(DataFile)
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2017
% Authors: Francois Tadel, 2017-2018
%% ===== READ HEADER =====
... ... @@ -62,31 +62,36 @@ sFile.header = hdr;
% Comment: short filename
[fPath, fBase, fExt] = bst_fileparts(DataFile);
sFile.comment = fBase;
% Acquisition date
try
sFile.acq_date = datestr(datenum(hdr.obj.segments.startDate), 'dd-mmm-yyyy');
catch
sFile.acq_date = '01-Jan-2000';
end
% Multiple segments
if (hdr.nSegments > 1)
for i = 1:hdr.nSegments
sFile.epochs(i).label = sprintf('Segment #%d', i);
sFile.epochs(i).samples = [0, sfreq * hdr.obj.segments(i).duration - 1];
sFile.epochs(i).times = sFile.epochs(i).samples ./ sfreq;
sFile.epochs(i).times = [0, sfreq * hdr.obj.segments(i).duration - 1] ./ sfreq;
sFile.epochs(i).nAvg = 1;
sFile.epochs(i).select = 1;
sFile.epochs(i).bad = 0;
sFile.epochs(i).channelflag = [];
end
end
sFile.prop.samples = [0, sfreq * max([hdr.obj.segments.duration]) - 1];
sFile.prop.times = sFile.prop.samples ./ sfreq;
sFile.prop.nAvg = 1;
sFile.prop.times = [0, sfreq * max([hdr.obj.segments.duration]) - 1] ./ sfreq;
sFile.prop.nAvg = 1;
%% ===== CREATE EMPTY CHANNEL FILE =====
ChannelMat = db_template('channelmat');
ChannelMat.Comment = [sFile.device ' channels'];
ChannelMat.Channel = repmat(db_template('channeldesc'), [1, hdr.numchan]);
% For each channel
for i = hdr.selchan
ChannelMat.Channel(i).Type = 'EEG';
ChannelMat.Channel(i).Name = strrep(str_clean(hdr.obj.segments(1).chName{hdr.selchan(i)}), ' ', '');
for i = 1:length(hdr.selchan)
ChannelMat.Channel(i).Type = 'EEG';
ChannelMat.Channel(i).Name = strrep(str_clean(hdr.obj.segments(1).chName{hdr.selchan(i)}), ' ', '');
ChannelMat.Channel(i).Name = strrep(ChannelMat.Channel(i).Name, '-Ref', '');
ChannelMat.Channel(i).Name = strrep(ChannelMat.Channel(i).Name, '-ref', '');
ChannelMat.Channel(i).Name = strrep(ChannelMat.Channel(i).Name, '-REF', '');
... ... @@ -121,7 +126,6 @@ for iEvt = 1:length(uniqueEvt)
% Create event structure
sFile.events(iEvt).label = uniqueEvt{iEvt};
sFile.events(iEvt).times = [];
sFile.events(iEvt).samples = [];
sFile.events(iEvt).epochs = [];
sFile.events(iEvt).select = 1;
% Get all the occurrences
... ... @@ -143,9 +147,11 @@ for iEvt = 1:length(uniqueEvt)
allTime = sort(([hdr.obj.eventMarkers(iOcc(iEvtEpoch)).dateOLE] - hdr.obj.segments(iEpoch).dateOLE) * 3600 * 24 + [hdr.obj.eventMarkers(iOcc(iEvtEpoch)).dateFraction]);
% Add to all the events
sFile.events(iEvt).times = [sFile.events(iEvt).times, allTime];
sFile.events(iEvt).samples = [sFile.events(iEvt).samples, allTime .* sFile.prop.sfreq];
sFile.events(iEvt).epochs = [sFile.events(iEvt).epochs, iEpoch * ones(size(allTime))];
end
% Add channels and notes fields
sFile.events(iEvt).channels = cell(1, size(sFile.events(iEvt).times, 2));
sFile.events(iEvt).notes = cell(1, size(sFile.events(iEvt).times, 2));
end
... ...
... ... @@ -7,7 +7,7 @@ function [sFile, ChannelMat] = in_fopen_nk(DataFile)
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2018 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -389,6 +389,9 @@ if ~isempty(PntFile)
hdr.starttime = sprintf('%02d:%02d:%02d', numDate(4), numDate(5), numDate(6));
% Close file
fclose(fid);
else
hdr.startdate = [];
hdr.starttime = [];
end
... ... @@ -418,8 +421,7 @@ for i = 1:nEpochs
% Compute from the
hdr.ctl(1).data(i).num_samples = floor((end_address - hdr.ctl(1).data(i).rec_address) / hdr.num_channels / 2); % /2 because we are counting int16 values
end
sFile.epochs(i).samples = [0, hdr.ctl(1).data(i).num_samples - 1];
sFile.epochs(i).times = sFile.epochs(i).samples ./ hdr.sample_rate;
sFile.epochs(i).times = [0, hdr.ctl(1).data(i).num_samples - 1] ./ hdr.sample_rate;
sFile.epochs(i).label = sprintf('Block #%d', i);
sFile.epochs(i).nAvg = 1;
sFile.epochs(i).select = 1;
... ... @@ -429,10 +431,9 @@ for i = 1:nEpochs
end
cumTime = [0, cumsum(epochLength(1:end-1))];
% Consider that the sampling rate of the file is the sampling rate of the first signal
sFile.prop.sfreq = hdr.sample_rate;
sFile.prop.samples = [min([sFile.epochs.samples]), max([sFile.epochs.samples])];
sFile.prop.times = [min([sFile.epochs.times]), max([sFile.epochs.times])];
sFile.prop.nAvg = 1;
sFile.prop.sfreq = hdr.sample_rate;
sFile.prop.times = [min([sFile.epochs.times]), max([sFile.epochs.times])];
sFile.prop.nAvg = 1;
% No info on bad channels
sFile.channelflag = ones(hdr.num_channels,1);
% Save full header in the file link
... ... @@ -470,7 +471,8 @@ if ~isempty(hdr.logs)
sFile.events(iEvt).label = str_clean(uniqueEvt{iEvt});
sFile.events(iEvt).select = 1;
sFile.events(iEvt).times = t;
sFile.events(iEvt).samples = round(t .* sFile.prop.sfreq);
sFile.events(iEvt).channels = cell(1, size(sFile.events(iEvt).times, 2));
sFile.events(iEvt).notes = cell(1, size(sFile.events(iEvt).times, 2));
end
end
... ...
... ... @@ -18,9 +18,9 @@ function [F, TimeVector] = in_fread(sFile, ChannelMat, iEpoch, SamplesBounds, iC
% @=============================================================================
% This function is part of the Brainstorm software:
% http://neuroimage.usc.edu/brainstorm
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c)2000-2017 University of Southern California & McGill University
% Copyright (c)2000-2019 University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
... ... @@ -34,7 +34,7 @@ function [F, TimeVector] = in_fread(sFile, ChannelMat, iEpoch, SamplesBounds, iC
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2009-2015
% Authors: Francois Tadel, 2009-2019
%% ===== PARSE INPUTS =====
if (nargin < 6)
... ... @@ -45,7 +45,7 @@ if (nargin < 5)
end
TimeVector = [];
% Read channel ranges for faster access
isChanRange = ismember(sFile.format, {'CTF', 'CTF-CONTINUOUS', 'KDF', 'EEG-EDF', 'EEG-BDF', 'BST-BIN', 'EEG-DELTAMED', 'EEG-COMPUMEDICS-PFS', 'EEG-MICROMED', 'EEG-NEURONE', 'EEG-NK'});
isChanRange = ismember(sFile.format, {'