diff --git a/channelloc_to_tsv.m b/channelloc_to_tsv.m new file mode 100644 index 0000000..7318aa3 --- /dev/null +++ b/channelloc_to_tsv.m @@ -0,0 +1,36 @@ +function channelloc_to_tsv(EEG) + +% From an EEG variable (i.e. EEG=pop_loadset(*.set), export the channel +% location as tsv file following the BIDS specification +% +% FORMAT channelloc_to_tvs(EEG) +% +% Author: Cyril Pernet - LIMO Team, University of Edinurgh + +% list of labels for which we know it's not an EEG channel +known_labels = {'EXG','TRIG','ECG','EOG','VEOG','HEOG','EMG','MISC'}; + +% channel.tsv +for electrode = 1:size(EEG.chanlocs,2) + ename{electrode} = EEG.chanlocs(electrode).labels; + if contains(EEG.chanlocs(electrode).labels,known_labels) + type{electrode} = EEG.chanlocs(electrode).labels; + if contains(EEG.chanlocs(electrode).labels,'EOG') + unit{electrode} = [num2str(char(181)) 'V']; + elseif contains(EEG.chanlocs(electrode).labels,'ECG') + unit{electrode} = 'mV'; + else + unit{electrode} = ' '; + end + else + type{electrode} = 'EEG'; + unit{electrode} = [num2str(char(181)) 'V']; % char(181) is mu in ASCII + end + sampling_frequency(electrode) = EEG.srate; + reference{electrode} = EEG.ref; +end + +t = table(ename',type',unit',sampling_frequency',reference','VariableNames',{'name','type','units','sampling_reference','reference'}); +channels_tsv_name = [EEG.filepath filesep EEG.filename(1:end-4) '_channels.tsv']; +writetable(t,channels_tsv_name,'FileType','text','Delimiter','\t'); + diff --git a/electrodes_to_tsv.m b/electrodes_to_tsv.m new file mode 100644 index 0000000..b5b3b41 --- /dev/null +++ b/electrodes_to_tsv.m @@ -0,0 +1,31 @@ +function electrodes_to_tsv(EEG) + +% From an EEG variable (i.e. EEG=pop_loadset(*.set), export the EEG.channel +% locations as tsv file and initiate the json file following the BIDS +% specification +% +% FORMAT electrodes_to_tsv(EEG) +% +% Author: Cyril Pernet - LIMO Team, University of Edinurgh + +% electrode.tsv +for electrode = 1:size(EEG.chanlocs,2) + ename{electrode} = EEG.chanlocs(electrode).labels; + x(electrode) = EEG.chanlocs(electrode).X; + y(electrode) = EEG.chanlocs(electrode).Y; + z(electrode) = EEG.chanlocs(electrode).Z; + type{electrode} = EEG.chanlocs(electrode).type; +end + +t = table(ename',x',y',z',type','VariableNames',{'name','x','y','z','type'}); +electrodes_tsv_name = [EEG.filepath filesep EEG.filename(1:strfind(EEG.filename,'run-')-1) 'electrodes.tsv']; +writetable(t,electrodes_tsv_name,'FileType','text','Delimiter','\t'); + +% coordsystem.json +EEGCoordinateSystem = 'RAS'; +EEGCoordinateUnits = 'mm'; +json = struct('EEGCoordinateSystem','RAS', ... + 'EEGCoordinateUnits','mm'); +jsonwrite([EEG.filepath filesep EEG.filename(1:strfind(EEG.filename,'run-')-1) 'electrodes.json'],json,struct('indent',' ')) + + diff --git a/events_to_tsv.m b/events_to_tsv.m new file mode 100644 index 0000000..e519245 --- /dev/null +++ b/events_to_tsv.m @@ -0,0 +1,24 @@ +function events_to_tsv(EEG) + +% From an EEG variable (i.e. EEG=pop_loadset(*.set), export the EEG.event +% as tsv file +% +% FORMAT electrodes_to_tsv(EEG) +% +% Author: Cyril Pernet - LIMO Team, University of Edinurgh + +for event=1:size(EEG.event,2) + onset(event) = EEG.event(event).latency; + trial_type{event} = EEG.event(event).urevent; + if ~isfield(EEG.event(event),'duration') + duration(event) = 0; + else + duration(event) = EEG.event(event).duration; + end +end + +t = table(onset',duration',trial_type','VariableNames',{'onset','duration','trial_type'}); +events_tsv_name = [EEG.filepath filesep EEG.filename(1:end-4) '_events.tsv']; +writetable(t,events_tsv_name,'FileType','text','Delimiter','\t'); + + diff --git a/rename_brainvision_files.m b/rename_brainvision_files.m new file mode 100644 index 0000000..1a089c1 --- /dev/null +++ b/rename_brainvision_files.m @@ -0,0 +1,130 @@ +function rename_brainvision_files(varargin) + +% RENAME_BRAINVISION_FILES renames a BrainVision EEG dataset, which consists of a vhdr header +% file, vmrk marker file and a data file that usually has the extension dat, eeg or seg. +% +% Use as +% rename_brainvision_files(oldname, newname, 'rmf', 'on') +% where both the old and the new filename should be strings corresponding to the +% header file, i.e. including the vhdr extension. +% 'rmf' option indicates to remove old files and can be turned 'on' of 'off' (default) +% +% See also http://www.fieldtriptoolbox.org/ and https://sccn.ucsd.edu/wiki/EEGLAB for +% open source software to process BrainVision EEG data. +% +% Robert Oostenveld https://gist.github.com/robertoostenveld/e31637a777c514bf1e86272e1092316e +% Cyril Pernet - fixed few bugs here and there https://gist.github.com/CPernet/e037df46e064ca83a49fb4c595d4566a + +%% deal with inputs + +rmf = 'off'; % by default do not delete files +if nargin >= 3 + if strcmpi(varargin{3},'rmf') + if nargin == 3 + disp('no value associated to the remove file option, assumning off') + else + rmf = varargin{4}; + end + else + error(['unrecognized option argument ''' varargin{3} '''']) + end +end + +oldheaderfile = varargin{1}; +newheaderfile = varargin{2}; +clear varargin + +% determine whether the file extensions should be in lower or upper case +if ~isempty(regexp(newheaderfile, 'VHDR$', 'once')) + switchcase = @upper; +else + switchcase = @lower; +end + +% determine the filename without extension +[~, f, ~] = fileparts(newheaderfile); + +%% do the renaming + +% deal with the header file +assert(exist(oldheaderfile, 'file')~=0, 'the file %s does not exists', oldheaderfile); +assert(exist(newheaderfile, 'file')==0, 'the file %s already exists', newheaderfile); +fid1 = fopen(oldheaderfile, 'r'); % read old +fid2 = fopen(newheaderfile, 'w'); % write new + +while ~feof(fid1) + line = fgetl(fid1); + if ~isempty(regexp(line, '^MarkerFile', 'once')) + [~, rem] = strtok(line, '='); + oldmarkerfile = rem(2:end); + [~, ~, x] = fileparts(oldmarkerfile); + newmarkerfile = [f switchcase(x)]; + line = sprintf('MarkerFile=%s', newmarkerfile); + elseif ~isempty(regexp(line, '^DataFile', 'once')) + [~, rem] = strtok(line, '='); + olddatafile = rem(2:end); + [~, ~, x] = fileparts(olddatafile); + newdatafile = [f switchcase(x)]; + line = sprintf('DataFile=%s', newdatafile); + end + fprintf(fid2, '%s\r\n', line); +end +fclose(fid1); +fclose(fid2); + +% deal with the marker file +if exist(oldmarkerfile, 'file') == 0 + [~,~,ext] = fileparts(oldmarkerfile); + [~, ff, ~] = fileparts(oldheaderfile); % re-reading as sometimes weird names comes up + if exist([ff ext], 'file') + oldmarkerfile = [ff ext]; + else + error('the file %s does not exists', oldmarkerfile); + end +end +assert(exist(newmarkerfile, 'file')==0, 'the file %s already exists', newmarkerfile); +fid1 = fopen(oldmarkerfile, 'r'); +fid2 = fopen(newmarkerfile, 'w'); + +while ~feof(fid1) + line = fgetl(fid1); + if ~isempty(regexp(line, '^HeaderFile', 'once')) + [~, rem] = strtok(line, '='); + oldheaderfile = rem(2:end); + [~, ~, x] = fileparts(oldheaderfile); + newheaderfile = [f switchcase(x)]; + line = sprintf('HeaderFile=%s', newheaderfile); + elseif ~isempty(regexp(line, '^DataFile', 'once')) + [~, rem] = strtok(line, '='); + olddatafile = rem(2:end); + [~, ~, x] = fileparts(olddatafile); + newdatafile = [f switchcase(x)]; + line = sprintf('DataFile=%s', newdatafile); + end + fprintf(fid2, '%s\r\n', line); +end +fclose(fid1); +fclose(fid2); + +% deal with the data file +if exist(olddatafile, 'file') == 0 + [~,~,ext] = fileparts(olddatafile); + [~, ff, ~] = fileparts(oldheaderfile); % re-reading as sometimes weird names comes up + if exist([ff ext], 'file') + olddatafile = [ff ext]; + else + error('the file %s does not exists', oldmarkerfile); + end +end +assert(exist(newdatafile, 'file')==0, 'the file %s already exists', newdatafile); +status = copyfile(olddatafile, newdatafile); +if ~status + error('failed to copy data from %s to %s', olddatafile, newdatafile); +end + +%% delete old files *try* in case of user restriction +if strcmpi(rmf,'on') + try delete(oldheaderfile); end + try delete(oldmarkerfile); end + try delete(olddatafile); end +end \ No newline at end of file