Skip to content

Commit

Permalink
Merge pull request #2400 from robertoostenveld/issue2395
Browse files Browse the repository at this point in the history
make splitting of label on "-" optional
  • Loading branch information
robertoostenveld committed Mar 21, 2024
2 parents 82112af + a04226e commit e6a0dcf
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 135 deletions.
110 changes: 53 additions & 57 deletions data2bids.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
% data input argument allows you to write preprocessed electrophysiological data
% and/or realigned and defaced anatomical MRI to disk.
%
% The implementation in this function aims to correspond to the latest BIDS version.
% See https://bids-specification.readthedocs.io/ for the full specification
% and http://bids.neuroimaging.io/ for further details.
%
% The configuration structure should contains
% cfg.method = string, can be 'decorate', 'copy' or 'convert', see below (default is automatic)
% cfg.dataset = string, filename of the input data
Expand Down Expand Up @@ -47,8 +51,8 @@
%
% Although you can explicitly specify cfg.outputfile yourself, it is recommended to
% use the following configuration options. This results in a BIDS compliant output
% directory and file name. With these options data2bids will also write, or if
% already present update the participants.tsv and scans.tsv files.
% directory and file name. With these options data2bids will also write or, if
% already present, update the participants.tsv and scans.tsv files.
% cfg.bidsroot = string, top level directory for the BIDS output
% cfg.sub = string, subject name
% cfg.ses = string, optional session name
Expand All @@ -66,16 +70,45 @@
% cfg.space = string
% cfg.desc = string
%
% When specifying the output directory in cfg.bidsroot, you can also specify
% additional information to be added as extra columns in the participants.tsv and
% scans.tsv files. For example:
% If you specify cfg.bidsroot, this function will also write the dataset_description.json
% file. Among others you can specify the following fields:
% cfg.dataset_description.writesidecar = 'yes' or 'no' (default = 'yes')
% cfg.dataset_description.Name = string
% cfg.dataset_description.BIDSVersion = string
% cfg.dataset_description.License = string
% cfg.dataset_description.Authors = cell-array of strings
% cfg.dataset_description.ReferencesAndLinks = cell-array of strings
% cfg.dataset_description.EthicsApprovals = cell-array of strings
% cfg.dataset_description.Funding = cell-array of strings
% cfg.dataset_description.Acknowledgements = string
% cfg.dataset_description.HowToAcknowledge = string
% cfg.dataset_description.DatasetDOI = string
%
% If you specify cfg.bidsroot, you can also specify additional information to be
% added as extra columns in the participants.tsv and scans.tsv files. For example:
% cfg.participants.age = scalar
% cfg.participants.sex = string, 'm' or 'f'
% cfg.scans.acq_time = string, should be formatted according to RFC3339 as '2019-05-22T15:13:38'
% cfg.sessions.acq_time = string, should be formatted according to RFC3339 as '2019-05-22T15:13:38'
% cfg.sessions.pathology = string, recommended when different from healthy
% In case any of these values is specified as empty (i.e. []) or as nan, it will be
% written to the tsv file as 'n/a'.
% If any of these values is specified as [] or as nan, it will be written to
% the tsv file as 'n/a'.
%
% General BIDS options that apply to all data types are
% cfg.InstitutionName = string
% cfg.InstitutionAddress = string
% cfg.InstitutionalDepartmentName = string
% cfg.Manufacturer = string
% cfg.ManufacturersModelName = string
% cfg.DeviceSerialNumber = string
% cfg.SoftwareVersions = string
%
% General BIDS options that apply to all functional data types are
% cfg.TaskName = string
% cfg.TaskDescription = string
% cfg.Instructions = string
% cfg.CogAtlasID = string
% cfg.CogPOID = string
%
% For anatomical and functional MRI data you can specify cfg.dicomfile to read the
% detailed MRI scanner and sequence details from the header of that DICOM file. This
Expand Down Expand Up @@ -117,37 +150,7 @@
% it as cfg.opto or you can specify a filename with optode information.
% cfg.opto = structure with optode positions or filename,see FT_READ_SENS
%
% General BIDS options that apply to all data types are
% cfg.InstitutionName = string
% cfg.InstitutionAddress = string
% cfg.InstitutionalDepartmentName = string
% cfg.Manufacturer = string
% cfg.ManufacturersModelName = string
% cfg.DeviceSerialNumber = string
% cfg.SoftwareVersions = string
%
% If you specify cfg.bidsroot, this function will also write the dataset_description.json
% file. Among others you can specify the following fields
% cfg.dataset_description.writesidecar = 'yes' or 'no' (default = 'yes')
% cfg.dataset_description.Name = string
% cfg.dataset_description.BIDSVersion = string
% cfg.dataset_description.License = string
% cfg.dataset_description.Authors = cell-array of strings
% cfg.dataset_description.ReferencesAndLinks = cell-array of strings
% cfg.dataset_description.EthicsApprovals = cell-array of strings
% cfg.dataset_description.Funding = cell-array of strings
% cfg.dataset_description.Acknowledgements = string
% cfg.dataset_description.HowToAcknowledge = string
% cfg.dataset_description.DatasetDOI = string
%
% General BIDS options that apply to all functional data types are
% cfg.TaskName = string
% cfg.TaskDescription = string
% cfg.Instructions = string
% cfg.CogAtlasID = string
% cfg.CogPOID = string
%
% There are more BIDS options for the mri/meg/eeg/ieeg data type specific sidecars.
% There are more BIDS options for the mri/meg/eeg/ieeg data type specific sidecars.
% Rather than listing them all here, please open this function in the MATLAB editor,
% and scroll down a bit to see what those are. In general the information in the JSON
% files is specified by a field that is specified in CamelCase
Expand All @@ -156,17 +159,13 @@
% cfg.eeg.SomeOption = string, please check the MATLAB code
% cfg.ieeg.SomeOption = string, please check the MATLAB code
% cfg.nirs.SomeOption = string, please check the MATLAB code
% cfg.coordsystem.someoption = string, please check the MATLAB code
% cfg.coordsystem.SomeOption = string, please check the MATLAB code
% The information for TSV files is specified with a column header in lowercase or
% snake_case and represents a list of items
% cfg.channels.someoption = cell-array, please check the MATLAB code
% cfg.events.someoption = cell-array, please check the MATLAB code
% cfg.electrodes.someoption = cell-array, please check the MATLAB code
% cfg.optodes.someoption = cell-array, please check the MATLAB code
%
% The implementation in this function aims to correspond to the latest BIDS version.
% See https://bids-specification.readthedocs.io/ for the full specification
% and http://bids.neuroimaging.io/ for further details.
% cfg.channels.some_option = cell-array, please check the MATLAB code
% cfg.events.some_option = cell-array, please check the MATLAB code
% cfg.electrodes.some_option = cell-array, please check the MATLAB code
% cfg.optodes.some_option = cell-array, please check the MATLAB code
%
% See also FT_DATAYPE_RAW, FT_DATAYPE_VOLUME, FT_DATATYPE_SENS, FT_DEFINETRIAL,
% FT_PREPROCESSING, FT_READ_MRI, FT_READ_EVENT
Expand All @@ -186,7 +185,7 @@
% officially supported data types.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright (C) 2018-2023, Robert Oostenveld
% Copyright (C) 2018-2024, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
Expand Down Expand Up @@ -352,7 +351,6 @@
end

%% Dataset description

cfg.dataset_description = ft_getopt(cfg, 'dataset_description' );
cfg.dataset_description.writesidecar = ft_getopt(cfg.dataset_description, 'writesidecar', 'yes' );
cfg.dataset_description.Name = ft_getopt(cfg.dataset_description, 'Name' ); % REQUIRED. Name of the dataset.
Expand All @@ -366,14 +364,12 @@
cfg.dataset_description.EthicsApprovals = ft_getopt(cfg.dataset_description, 'EthicsApprovals' ); % OPTIONAL. List of ethics committee approvals of the research protocols and/or protocol identifiers.
cfg.dataset_description.ReferencesAndLinks = ft_getopt(cfg.dataset_description, 'ReferencesAndLinks' ); % OPTIONAL. List of references to publication that contain information on the dataset, or links.
cfg.dataset_description.DatasetDOI = ft_getopt(cfg.dataset_description, 'DatasetDOI' ); % OPTIONAL. The Document Object Identifier of the dataset (not the corresponding paper).

% this is a structure, and in the json file an object
default.Name = 'FieldTrip';
default.Version = ft_version();
default.Description = 'data2bids converter';
default.URI = 'https://www.fieldtriptoolbox.org';
cfg.dataset_description.GeneratedBy = ft_getopt(cfg.dataset_description, 'GeneratedBy', {default});
clear default
% GeneratedBy is here a MATLAB structure, and in the file a JSON object
cfg.dataset_description.GeneratedBy = ft_getopt(cfg.dataset_description, 'GeneratedBy', struct);
cfg.dataset_description.GeneratedBy.Name = ft_getopt(cfg.dataset_description.GeneratedBy, 'Name', 'FieldTrip');
cfg.dataset_description.GeneratedBy.Version = ft_getopt(cfg.dataset_description.GeneratedBy, 'Version', ft_version);
cfg.dataset_description.GeneratedBy.Description = ft_getopt(cfg.dataset_description.GeneratedBy, 'Description', 'data2bids converter');
cfg.dataset_description.GeneratedBy.URI = ft_getopt(cfg.dataset_description.GeneratedBy, 'URI', 'https://www.fieldtriptoolbox.org');

%% Generic fields for all data types
cfg.TaskName = ft_getopt(cfg, 'TaskName' ); % REQUIRED. Name of the task (for resting state use the 'rest' prefix). Different Tasks SHOULD NOT have the same name. The Task label is derived from this field by removing all non alphanumeric ([a-zA-Z0-9]) characters.
Expand Down
60 changes: 39 additions & 21 deletions fileio/ft_read_header.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
% 'headerformat' = name of a MATLAB function that takes the filename as input (default is automatic)
% 'password' = password structure for encrypted data set (for dhn_med10, mayo_mef30, mayo_mef21)
% 'readbids' = string, 'yes', no', or 'ifmakessense', whether to read information from the BIDS sidecar files (default = 'ifmakessense')
% 'splitlabel' = string, 'yes' or 'no', split the channel labels on the '-' and return the first part (default = 'yes' for CTF and FieldLine, 'no' for others)
%
% This returns a header structure with the following fields
% hdr.Fs = sampling frequency
Expand Down Expand Up @@ -96,7 +97,7 @@
% See also FT_READ_DATA, FT_READ_EVENT, FT_WRITE_DATA, FT_WRITE_EVENT,
% FT_CHANTYPE, FT_CHANUNIT

% Copyright (C) 2003-2021 Robert Oostenveld
% Copyright (C) 2003-2024 Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
Expand Down Expand Up @@ -190,6 +191,7 @@
chantype = ft_getopt(varargin, 'chantype', {});
password = ft_getopt(varargin, 'password', struct([]));
readbids = ft_getopt(varargin, 'readbids', 'ifmakessense');
splitlabel = ft_getopt(varargin, 'splitlabel'); % default for CTF and FieldLine is dealt with below

% this should be a cell array
if ~iscell(chantype); chantype = {chantype}; end
Expand Down Expand Up @@ -283,7 +285,7 @@
% for realtime analysis end-of-file-chasing the res4 does not correctly
% estimate the number of samples, so we compute it on the fly
sz = 0;
files = dir([filename '/*.*meg4']);
files = dir([filename filesep '*.*meg4']);
for j=1:numel(files)
sz = sz + files(j).bytes;
end
Expand Down Expand Up @@ -657,7 +659,11 @@
case {'ctf_ds', 'ctf_meg4', 'ctf_res4'}
% check the presence of the required low-level toolbox
ft_hastoolbox('ctf', 1);
orig = readCTFds(filename);

% default for CTF is to remove the site-specific numbers from each channel name, e.g. 'MZC01-1706' becomes 'MZC01'
splitlabel = ft_getopt(varargin, 'splitlabel', true);

orig = readCTFds(filename);
if isempty(orig)
% this is to deal with data from the 64 channel system and the error
% readCTFds: .meg4 file header=MEG4CPT Valid header options: MEG41CP MEG42CP
Expand All @@ -669,10 +675,7 @@
hdr.nSamplesPre = orig.res4.preTrigPts;
hdr.nTrials = orig.res4.no_trials;
hdr.label = cellstr(orig.res4.chanNames);
for i=1:numel(hdr.label)
% remove the site-specific numbers from each channel name, e.g. 'MZC01-1706' becomes 'MZC01'
hdr.label{i} = strtok(hdr.label{i}, '-');
end

% read the balance coefficients, these are used to compute the synthetic gradients
try
coeftype = cellstr(char(orig.res4.scrr(:).coefType));
Expand Down Expand Up @@ -1926,6 +1929,11 @@
coilaccuracy = 0;
end

if ft_senstype(hdr, 'fieldline_v3')
% default for FieldLine v3 is to remove the electronics chassis number from the channel names
splitlabel = ft_getopt(varargin, 'splitlabel', true);
end

% add a gradiometer structure for forward and inverse modelling
try
[grad, elec] = mne2grad(info, strcmp(coordsys, 'dewar'), coilaccuracy, coildeffile);
Expand All @@ -1939,20 +1947,6 @@
disp(lasterr);
end

% remove the electronics chassis number from the fieldline channel names
if ft_senstype(hdr, 'fieldline_v3') && any(contains(hdr.label, '-s'))
for i=1:length(hdr.label)
tok = split(hdr.label{i}, '-');
hdr.label{i} = tok{1};
end
end
if isfield(hdr, 'grad') && ft_senstype(hdr.grad, 'fieldline_v3') && any(contains(hdr.grad.label, '-s'))
for i=1:length(hdr.grad.label)
tok = split(hdr.grad.label{i}, '-');
hdr.grad.label{i} = tok{1};
end
end

iscontinuous = 0;
isepoched = 0;
isaverage = 0;
Expand Down Expand Up @@ -2956,6 +2950,29 @@
hdr.nTrials = double(hdr.nTrials);
hdr.nChans = double(hdr.nChans);

if ~isempty(splitlabel) && istrue(splitlabel)
% this is default for CTF and FieldLine v3
for i=1:numel(hdr.label)
hdr.label{i} = strtok(hdr.label{i}, '-');
end
% also update the grad, elec and opto structure
if isfield(hdr, 'grad')
for i=1:numel(hdr.grad.label)
hdr.grad.label{i} = strtok(hdr.grad.label{i}, '-');
end
end
if isfield(hdr, 'elec')
for i=1:numel(hdr.elec.label)
hdr.elec.label{i} = strtok(hdr.elec.label{i}, '-');
end
end
if isfield(hdr, 'opto')
for i=1:numel(hdr.opto.label)
hdr.opto.label{i} = strtok(hdr.opto.label{i}, '-');
end
end
end

if inflated
% compressed file has been unzipped on the fly, clean up
if strcmp(headerformat, 'brainvision_vhdr')
Expand All @@ -2974,6 +2991,7 @@
% fprintf('added header to cache\n');
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION to determine the file size in bytes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand Down
Loading

0 comments on commit e6a0dcf

Please sign in to comment.