function [cfg] = data2bids(cfg, varargin) % DATA2BIDS is a helper function to convert MRI, MEG, EEG, iEEG or NIRS data to the % Brain Imaging Data Structure. The overall idea is that you write a MATLAB script in % which you call this function multiple times, once for each individually recorded % data file (or data set). It will write the corresponding sidecar JSON and TSV files % for each data file. % % Use as % data2bids(cfg) % or as % data2bids(cfg, data) % % The first input argument 'cfg' is the configuration structure, which contains the % details for the (meta)data and which specifies the sidecar files you want to write. % The optional 'data' argument corresponds to preprocessed raw data according to % FT_DATAYPE_RAW or an anatomical MRI according to FT_DATAYPE_VOLUME. The optional % 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 % cfg.outputfile = string, optional filename for the output data (default is automatic) % cfg.writejson = string, 'yes', 'replace', 'merge' or 'no' (default = 'yes') % cfg.writetsv = string, 'yes', 'replace', 'merge' or 'no' (default = 'yes') % % This function starts from existing data file on disk or from a FieldTrip compatible % data structure in MATLAB memory that is passed as the second input argument. % Depending on cfg.method it will add the sidecar files, copy the dataset and add % sidecar files, or convert the dataset and add the sidecar files. Each of the % methods is discussed here. % % DECORATE - data2bids will read the header details and events from the data and write % the appropriate sidecar files alongside the existing dataset. You would use this to % obtain the sidecar files for data files that are already in the BIDS organization. % % CONVERT - data2bids will read the input data (or use the specified input data) and % write it to a new output file that is BIDS compliant. The output format is NIfTI % for MRI data, and BrainVision for EEG and iEEG. Note that MEG data files are stored % in BIDS in their native format and this function will NOT convert them for you. % % COPY - data2bids will copy the data from the input data file to the output data % file, which renames it, but does not change its content. Furthermore, it will read % the header details and events from the data and construct the appropriate sidecar % files. % % 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. % cfg.bidsroot = string, top level directory for the BIDS output % cfg.sub = string, subject name % cfg.ses = string, optional session name % cfg.run = number, optional % cfg.task = string, task name is required for functional data % cfg.suffix = string, can be any of 'FLAIR', 'FLASH', 'PD', 'PDT2', 'PDmap', 'T1map', 'T1rho', 'T1w', 'T2map', 'T2star', 'T2w', 'angio', 'audio', 'bold', 'bval', 'bvec', 'channels', 'coordsystem', 'defacemask', 'dwi', 'eeg', 'emg', 'epi', 'events', 'eyetracker', 'fieldmap', 'headshape', 'ieeg', 'inplaneT1', 'inplaneT2', 'magnitude', 'magnitude1', 'magnitude2', 'meg', 'motion', 'nirs', 'phase1', 'phase2', 'phasediff', 'photo', 'physio', 'sbref', 'stim', 'video' % cfg.acq = string % cfg.ce = string % cfg.rec = string % cfg.dir = string % cfg.mod = string % cfg.echo = string % cfg.proc = string % cfg.tracksys = string % cfg.space = string % cfg.desc = 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 % % 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 % If any of these values is specified as [] or as nan, it will be written to % the tsv file as 'n/a'. % % If you specify cfg.bidsroot, this function can also write some modality agnostic % files at the top-level of the dataset. You can specify their content here and/or % subsequently edit them with a text editor. % cfg.README = string (default is a template with instructions) % cfg.LICENSE = string (no default) % cfg.CHANGES = string (no default) % % 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 % will be used to fill in the details of the corresponding JSON file. % cfg.dicomfile = string, filename of a matching DICOM file for header details (default = []) % cfg.deface = string, 'yes' or 'no' (default = 'no') % % You can specify cfg.events as a Nx3 matrix with the "trl" trial definition (see % FT_DEFINETRIAL) or as a MATLAB table. When specified as table, you can use the % "trl" format from FT_DEFINETRIAL with the first three columns corresponding to the % begsample, endsample and offset (in samples). You can also a table with the % "events.tsv" format with the first two columns corresponding to the onset and % duration (in seconds). In either case the table can have additional columns with % numerical or string values. If you do not specify cfg.events, the events will be % read from the MEG/EEG/iEEG dataset. % cfg.events = trial definition (see FT_DEFINETRIAL) or event structure (see FT_READ_EVENT) % % If NBS Presentation was used in combination with another functional data type, you % can specify cfg.presentationfile with the name of the presentation log file, which % will be aligned with the data based on triggers (MEG/EEG/iEEG) or based on the % volumes (fMRI). Events from the presentation log file will also be written to % events.tsv. To indicate how triggers (in MEG/EEG/iEEG) or volumes (in fMRI) match % the presentation events, you should specify the mapping between them. % cfg.presentationfile = string, optional filename for the presentation log file % cfg.trigger.eventtype = string (default = []) % cfg.trigger.eventvalue = string or number % cfg.trigger.skip = 'last'/'first'/'none' % cfg.presentation.eventtype = string (default = []) % cfg.presentation.eventvalue = string or number % cfg.presentation.skip = 'last'/'first'/'none' % % For EEG and iEEG data you can specify an electrode definition according to % FT_DATATYPE_SENS as an "elec" field in the input data, or you can specify it as % cfg.elec or you can specify a filename with electrode information. % cfg.elec = structure with electrode positions or filename, see FT_READ_SENS % % For NIRS data you can specify an optode definition according to % FT_DATATYPE_SENS as an "opto" field in the input data, or you can specify % 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 % % 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 % cfg.mri.SomeOption = string, please check the MATLAB code % cfg.meg.SomeOption = string, please check the MATLAB code % 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 % The information for TSV files is specified with a column header in lowercase or % snake_case and represents a list of items % 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Undocumented options exist for converting some other data types to BIDS: % - motion % - emg % - audio % - video % - eyetracking % - physio % - stim % % Most of these data types are currently (Oct 2020) not supported in the BIDS % specification, but this function converts them in a very similar way as the % officially supported data types. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Copyright (C) 2018-2024, Robert Oostenveld % % This file is part of FieldTrip, see http://www.fieldtriptoolbox.org % for the documentation and details. % % FieldTrip is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % FieldTrip 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 General Public License for more details. % % You should have received a copy of the GNU General Public License % along with FieldTrip. If not, see . % % $Id$ % these are used by the ft_preamble/ft_postamble function and scripts ft_revision = '$Id$'; ft_nargin = nargin; ft_nargout = nargout; % do the general setup of the function ft_defaults ft_preamble init ft_preamble debug if ft_abort % do not continue function execution in case the outputfile is present and the user indicated to keep it return end % ensure backward compatibility cfg = ft_checkconfig(cfg, 'renamed', {'participant', 'participants'}); % this was wrong in the documentation cfg = ft_checkconfig(cfg, 'renamed', {'anat', 'mri'}); cfg = ft_checkconfig(cfg, 'renamedval', {'native', 'no', 'convert'}); cfg = ft_checkconfig(cfg, 'renamedval', {'native', 'yes', 'copy'}); cfg = ft_checkconfig(cfg, 'renamed', {'native', 'method'}); cfg = ft_checkconfig(cfg, 'renamed', {'mri.deface', 'deface'}); cfg = ft_checkconfig(cfg, 'renamed', {'mri.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'meg.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'eeg.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'ieeg.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'events.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'channels.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'electrodes.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'coordsystem.writesidecar', 'writejson'}); cfg = ft_checkconfig(cfg, 'renamed', {'event', 'events'}); % cfg.event is used elsewhere in FieldTrip, but here it should be cfg.events with an s % prevent some common errors cfg = ft_checkconfig(cfg, 'forbidden', {'acq_time'}); % this should be in cfg.scans or in cfg.sessions cfg = ft_checkconfig(cfg, 'forbidden', {'scan', 'session', 'event'}); % these should end with an 's' cfg = ft_checkconfig(cfg, 'renamed', {'datatype', 'suffix'}); % get the options and set the defaults cfg.method = ft_getopt(cfg, 'method'); % default is handled below cfg.dataset = ft_getopt(cfg, 'dataset'); cfg.feedback = ft_getopt(cfg, 'feedback', 'yes'); cfg.outputfile = ft_getopt(cfg, 'outputfile'); % default is handled below cfg.presentationfile = ft_getopt(cfg, 'presentationfile'); % full path to the NBS presentation log file, it will be read and parsed using FT_READ_EVENT cfg.presentation = ft_getopt(cfg, 'presentation'); cfg.presentation.eventtype = ft_getopt(cfg.presentation, 'eventtype'); cfg.presentation.eventvalue = ft_getopt(cfg.presentation, 'eventvalue'); cfg.presentation.skip = ft_getopt(cfg.presentation, 'skip', 'last'); % this is a sensible default for fMRI, for MEG one should probably do 'none' cfg.trigger = ft_getopt(cfg, 'trigger'); cfg.trigger.eventtype = ft_getopt(cfg.trigger, 'eventtype'); cfg.trigger.eventvalue = ft_getopt(cfg.trigger, 'eventvalue'); cfg.trigger.skip = ft_getopt(cfg.trigger, 'skip', 'none'); % these are used to construct the directory and file name cfg.bidsroot = ft_getopt(cfg, 'bidsroot'); cfg.sub = ft_getopt(cfg, 'sub'); cfg.ses = ft_getopt(cfg, 'ses'); cfg.task = ft_getopt(cfg, 'task'); cfg.tracksys = ft_getopt(cfg, 'tracksys'); cfg.acq = ft_getopt(cfg, 'acq'); cfg.ce = ft_getopt(cfg, 'ce'); cfg.rec = ft_getopt(cfg, 'rec'); cfg.dir = ft_getopt(cfg, 'dir'); cfg.run = ft_getopt(cfg, 'run'); cfg.mod = ft_getopt(cfg, 'mod'); cfg.echo = ft_getopt(cfg, 'echo'); cfg.proc = ft_getopt(cfg, 'proc'); cfg.space = ft_getopt(cfg, 'space'); cfg.desc = ft_getopt(cfg, 'desc'); cfg.suffix = ft_getopt(cfg, 'suffix'); % do a sanity check on the fields that form the filename as key-value pair fn = {'sub', 'ses', 'task', 'tracksys', 'acq', 'ce', 'rec', 'dir', 'run', 'mod', 'echo', 'proc', 'space', 'desc'}; for i=1:numel(fn) if ischar(cfg.(fn{i})) && any(cfg.(fn{i})=='-') ft_error('the field cfg.%s cannot contain a "-"', fn{i}); end end if isempty(cfg.suffix) modality = {'meg', 'eeg', 'ieeg', 'emg', 'motion', 'audio', 'video', 'eyetracker', 'physio', 'stim', 'motion', 'nirs'}; for i=1:numel(modality) if isfield(cfg, modality{i}) && ~isempty(cfg.(modality{i})) % the user specified modality-specific options, assume that the datatype matches cfg.suffix = modality{i}; ft_notice('assuming that the suffix is %s', cfg.suffix); continue end end % for each modality end cfg.dicomfile = ft_getopt(cfg, 'dicomfile'); % get header details from the specified DICOM files cfg.deface = ft_getopt(cfg, 'deface', 'no'); % whether to deface the anatomical MRI cfg.writejson = ft_getopt(cfg, 'writejson', 'merge'); % whether to write the json file cfg.writetsv = ft_getopt(cfg, 'writetsv', 'merge'); % whether to write the tsv file cfg.mri = ft_getopt(cfg, 'mri'); cfg.meg = ft_getopt(cfg, 'meg'); cfg.eeg = ft_getopt(cfg, 'eeg'); cfg.ieeg = ft_getopt(cfg, 'ieeg'); cfg.emg = ft_getopt(cfg, 'emg'); cfg.nirs = ft_getopt(cfg, 'nirs'); cfg.audio = ft_getopt(cfg, 'audio'); cfg.video = ft_getopt(cfg, 'video'); cfg.eyetracker = ft_getopt(cfg, 'eyetracker'); cfg.physio = ft_getopt(cfg, 'physio'); cfg.stim = ft_getopt(cfg, 'stim'); cfg.motion = ft_getopt(cfg, 'motion'); cfg.channels = ft_getopt(cfg, 'channels'); cfg.electrodes = ft_getopt(cfg, 'electrodes'); cfg.optodes = ft_getopt(cfg, 'optodes'); cfg.events = ft_getopt(cfg, 'events'); % this can contain the trial definition as Nx3 array, as table, or an event structure cfg.coordsystem = ft_getopt(cfg, 'coordsystem'); % start with an empty structure for the following cfg.participants = ft_getopt(cfg, 'participants', struct()); cfg.sessions = ft_getopt(cfg, 'sessions', struct()); cfg.scans = ft_getopt(cfg, 'scans', struct()); % start with a template or empty file for the following cfg.README = ft_getopt(cfg, 'README', template_README); cfg.LICENSE = ft_getopt(cfg, 'LICENSE'); cfg.CHANGES = ft_getopt(cfg, 'CHANGES'); % some of the cfg fields can be specified (or make most sense) as a table % however, the parsing of cfg options requires fields to be structures if istable(cfg.channels) cfg.channels = table2struct(cfg.channels, 'ToScalar', true); end if istable(cfg.electrodes) cfg.electrodes = table2struct(cfg.electrodes, 'ToScalar', true); end if istable(cfg.optodes) cfg.optodes = table2struct(cfg.optodes, 'ToScalar', true); end if istable(cfg.participants) cfg.participants = table2struct(cfg.participants, 'ToScalar', true); end if istable(cfg.sessions) cfg.sessions = table2struct(cfg.sessions, 'ToScalar', true); end if istable(cfg.scans) cfg.scans = table2struct(cfg.scans, 'ToScalar', true); 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. cfg.dataset_description.BIDSVersion = ft_getopt(cfg.dataset_description, 'BIDSVersion', '1.8' ); % REQUIRED. The version of the BIDS standard that was used. cfg.dataset_description.DatasetType = ft_getopt(cfg.dataset_description, 'DatasetType', 'raw' ); % RECOMMENDED. The interpretaton of the dataset. MUST be one of 'raw' or 'derivative'. For backwards compatibility, the default value is 'raw'. cfg.dataset_description.License = ft_getopt(cfg.dataset_description, 'License' ); % RECOMMENDED. What license is this dataset distributed under? The use of license name abbreviations is suggested for specifying a license. A list of common licenses with suggested abbreviations can be found in Appendix II. cfg.dataset_description.Authors = ft_getopt(cfg.dataset_description, 'Authors' ); % OPTIONAL. List of individuals who contributed to the creation/curation of the dataset. cfg.dataset_description.Acknowledgements = ft_getopt(cfg.dataset_description, 'Acknowledgements' ); % OPTIONAL. Text acknowledging contributions of individuals or institutions beyond those listed in Authors or Funding. cfg.dataset_description.HowToAcknowledge = ft_getopt(cfg.dataset_description, 'HowToAcknowledge' ); % OPTIONAL. Instructions how researchers using this dataset should acknowledge the original authors. This field can also be used to define a publication that should be cited in publications that use the dataset. cfg.dataset_description.Funding = ft_getopt(cfg.dataset_description, 'Funding' ); % OPTIONAL. List of sources of funding (grant numbers) 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). % 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. cfg.TaskDescription = ft_getopt(cfg, 'TaskDescription' ); % OPTIONAL. Description of the task. cfg.Instructions = ft_getopt(cfg, 'Instructions' ); % OPTIONAL. Text of the instructions given to participants before the scan. This is not only important for behavioral or cognitive tasks but also in resting state paradigms (e.g. to distinguish between eyes open and eyes closed). cfg.CogAtlasID = ft_getopt(cfg, 'CogAtlasID' ); % OPTIONAL. URL of the corresponding 'Cognitive Atlas term that describes the task (e.g. Resting State with eyes closed 'http://www.cognitiveatlas.org/term/id/trm_54e69c642d89b') cfg.CogPOID = ft_getopt(cfg, 'CogPOID' ); % OPTIONAL. URL of the corresponding 'CogPO term that describes the task (e.g. Rest 'http://wiki.cogpo.org/index.php?title=Rest') cfg.Manufacturer = ft_getopt(cfg, 'Manufacturer' ); % OPTIONAL. Manufacturer of the recording system ('CTF', 'Neuromag/Elekta', '4D/BTi', 'KIT/Yokogawa', 'ITAB', 'KRISS', 'Other') cfg.ManufacturersModelName = ft_getopt(cfg, 'ManufacturersModelName' ); % OPTIONAL. Manufacturer's designation of the model (e.g. 'CTF-275'). See 'Appendix VII' with preferred names cfg.DeviceSerialNumber = ft_getopt(cfg, 'DeviceSerialNumber' ); % OPTIONAL. The serial number of the equipment that produced the composite instances. A pseudonym can also be used to prevent the equipment from being identifiable, as long as each pseudonym is unique within the dataset. cfg.SoftwareVersions = ft_getopt(cfg, 'SoftwareVersions' ); % OPTIONAL. Manufacturer's designation of the acquisition software. cfg.InstitutionName = ft_getopt(cfg, 'InstitutionName' ); % OPTIONAL. The name of the institution in charge of the equipment that produced the composite instances. cfg.InstitutionAddress = ft_getopt(cfg, 'InstitutionAddress' ); % OPTIONAL. The address of the institution in charge of the equipment that produced the composite instances. cfg.InstitutionalDepartmentName = ft_getopt(cfg, 'InstitutionalDepartmentName' ); % The department in the institution in charge of the equipment that produced the composite instances. Corresponds to DICOM Tag 0008, 1040 'Institutional Department Name'. %% MR Scanner Hardware cfg.mri.StationName = ft_getopt(cfg.mri, 'StationName' ); % Institution defined name of the machine that produced the composite instances. Corresponds to DICOM Tag 0008, 1010 'Station Name' cfg.mri.HardcopyDeviceSoftwareVersion = ft_getopt(cfg.mri, 'HardcopyDeviceSoftwareVersion' ); % (Deprecated) Manufacturer's designation of the software of the device that created this Hardcopy Image (the printer). Corresponds to DICOM Tag 0018, 101A 'Hardcopy Device Software Version'. cfg.mri.MagneticFieldStrength = ft_getopt(cfg.mri, 'MagneticFieldStrength' ); % Nominal field strength of MR magnet in Tesla. Corresponds to DICOM Tag 0018,0087 'Magnetic Field Strength' . cfg.mri.ReceiveCoilName = ft_getopt(cfg.mri, 'ReceiveCoilName' ); % Information describing the receiver coil. Corresponds to DICOM Tag 0018, 1250 'Receive Coil Name', although not all vendors populate that DICOM Tag, in which case this field can be derived from an appropriate private DICOM field. cfg.mri.ReceiveCoilActiveElements = ft_getopt(cfg.mri, 'ReceiveCoilActiveElements' ); % Information describing the active/selected elements of the receiver coil. This doesn't correspond to a tag in the DICOM ontology. The vendor-defined terminology for active coil elements can go in this field. As an example, for Siemens, coil channels are typically not activated/selected individually, but rather in pre-defined selectable 'groups' of individual channels, and the list of the 'groups' of elements that are active/selected in any given scan populates the 'Coil String' entry in Siemen's private DICOM fields (e.g., 'HEA;HEP' for the Siemens standard 32 ch coil when both the anterior and posterior groups are activated). This is a flexible field that can be used as most appropriate for a given vendor and coil to define the 'active' coil elements. Since individual scans can sometimes not have the intended coil elements selected, it is preferable for this field to be populated directly from the DICOM for each individual scan, so that it can be used as a mechanism for checking that a given scan was collected with the intended coil elements selected. cfg.mri.GradientSetType = ft_getopt(cfg.mri, 'GradientSetType' ); % It should be possible to infer the gradient coil from the scanner model. If not,e.g. because of a custom upgrade or use of a gradient insert set, then the specifications of the actual gradient coil should be reported independently. cfg.mri.MRTransmitCoilSequence = ft_getopt(cfg.mri, 'MRTransmitCoilSequence' ); % This is a relevant field if a non-standard transmit coil is used. Corresponds to DICOM Tag 0018, 9049 'MR Transmit Coil Sequence'. cfg.mri.MatrixCoilMode = ft_getopt(cfg.mri, 'MatrixCoilMode' ); % (If used) A method for reducing the number of independent channels by combining in analog the signals from multiple coil elements. There are typically different default modes when using un-accelerated or accelerated (e.g. GRAPPA, SENSE) imaging. cfg.mri.CoilCombinationMethod = ft_getopt(cfg.mri, 'CoilCombinationMethod' ); % Almost all fMRI studies using phased-array coils use root-sum-of-squares (rSOS) combination, but other methods exist. The image reconstruction is changed by the coil combination method (as for the matrix coil mode above), so anything non-standard should be reported. %% MR Sequence Specifics cfg.mri.PulseSequenceType = ft_getopt(cfg.mri, 'PulseSequenceType' ); % A general description of the pulse sequence used for the scan (i.e. MPRAGE, Gradient Echo EPI, Spin Echo EPI, Multiband gradient echo EPI). cfg.mri.ScanningSequence = ft_getopt(cfg.mri, 'ScanningSequence' ); % Description of the type of data acquired. Corresponds to DICOM Tag 0018, 0020 'Sequence Sequence'. cfg.mri.SequenceVariant = ft_getopt(cfg.mri, 'SequenceVariant' ); % Variant of the ScanningSequence. Corresponds to DICOM Tag 0018, 0021 'Sequence Variant'. cfg.mri.ScanOptions = ft_getopt(cfg.mri, 'ScanOptions' ); % Parameters of ScanningSequence. Corresponds to DICOM Tag 0018, 0022 'Scan Options'. cfg.mri.SequenceName = ft_getopt(cfg.mri, 'SequenceName' ); % Manufacturer's designation of the sequence name. Corresponds to DICOM Tag 0018, 0024 'Sequence Name'. cfg.mri.PulseSequenceDetails = ft_getopt(cfg.mri, 'PulseSequenceDetails' ); % Information beyond pulse sequence type that identifies the specific pulse sequence used (i.e. 'Standard Siemens Sequence distributed with the VB17 software,' 'Siemens WIP ### version #.##,' or 'Sequence written by X using a version compiled on MM/DD/YYYY'). cfg.mri.NonlinearGradientCorrection = ft_getopt(cfg.mri, 'NonlinearGradientCorrection' ); % Boolean stating if the image saved has been corrected for gradient nonlinearities by the scanner sequence. %% MR In-Plane Spatial Encoding cfg.mri.NumberShots = ft_getopt(cfg.mri, 'NumberShots' ); % The number of RF excitations need to reconstruct a slice or volume. Please mind that this is not the same as Echo Train Length which denotes the number of lines of k-space collected after an excitation. cfg.mri.ParallelReductionFactorInPlan = ft_getopt(cfg.mri, 'ParallelReductionFactorInPlane' ); % The parallel imaging (e.g, GRAPPA) factor. Use the denominator of the fraction of k-space encoded for each slice. For example, 2 means half of k-space is encoded. Corresponds to DICOM Tag 0018, 9069 'Parallel Reduction Factor In-plane'. cfg.mri.ParallelAcquisitionTechnique = ft_getopt(cfg.mri, 'ParallelAcquisitionTechnique' ); % The type of parallel imaging used (e.g. GRAPPA, SENSE). Corresponds to DICOM Tag 0018, 9078 'Parallel Acquisition Technique'. cfg.mri.PartialFourier = ft_getopt(cfg.mri, 'PartialFourier' ); % The fraction of partial Fourier information collected. Corresponds to DICOM Tag 0018, 9081 'Partial Fourier'. cfg.mri.PartialFourierDirection = ft_getopt(cfg.mri, 'PartialFourierDirection' ); % The direction where only partial Fourier information was collected. Corresponds to DICOM Tag 0018, 9036 'Partial Fourier Direction'. cfg.mri.PhaseEncodingDirection = ft_getopt(cfg.mri, 'PhaseEncodingDirection' ); % Possible values = []; % 'i', 'j', 'k', 'i-', 'j-', 'k-'. The letters 'i', 'j', 'k' correspond to the first, second and third axis of the data in the NIfTI file. The polarity of the phase encoding is assumed to go from zero index to maximum index unless '-' sign is present (then the order is reversed - starting from the highest index instead of zero). PhaseEncodingDirection is defined as the direction along which phase is was modulated which may result in visible distortions. Note that this is not the same as the DICOM term InPlanePhaseEncodingDirection which can have 'ROW' or 'COL' values. This parameter is REQUIRED if corresponding fieldmap data is present or when using multiple runs with different phase encoding directions (which can be later used for field inhomogeneity correction). cfg.mri.EffectiveEchoSpacing = ft_getopt(cfg.mri, 'EffectiveEchoSpacing' ); % The 'effective' sampling interval, specified in seconds, between lines in the phase-encoding direction, defined based on the size of the reconstructed image in the phase direction. It is frequently, but incorrectly, referred to as 'dwell time' (see DwellTime parameter below for actual dwell time). It is required for unwarping distortions using field maps. Note that beyond just in-plane acceleration, a variety of other manipulations to the phase encoding need to be accounted for properly, including partial fourier, phase oversampling, phase resolution, phase field-of-view and interpolation. This parameter is REQUIRED if corresponding fieldmap data is present. cfg.mri.TotalReadoutTime = ft_getopt(cfg.mri, 'TotalReadoutTime' ); % This is actually the 'effective' total readout time , defined as the readout duration, specified in seconds, that would have generated data with the given level of distortion. It is NOT the actual, physical duration of the readout train. If EffectiveEchoSpacing has been properly computed, it is just EffectiveEchoSpacing * (ReconMatrixPE - 1). . This parameter is REQUIRED if corresponding 'field/distortion' maps acquired with opposing phase encoding directions are present (see 8.9.4). %% MR Timing Parameters cfg.mri.EchoTime = ft_getopt(cfg.mri, 'EchoTime' ); % The echo time (TE) for the acquisition, specified in seconds. This parameter is REQUIRED if corresponding fieldmap data is present or the data comes from a multi echo sequence. Corresponds to DICOM Tag 0018, 0081 'Echo Time' (please note that the DICOM term is in milliseconds not seconds). cfg.mri.InversionTime = ft_getopt(cfg.mri, 'InversionTime' ); % The inversion time (TI) for the acquisition, specified in seconds. Inversion time is the time after the middle of inverting RF pulse to middle of excitation pulse to detect the amount of longitudinal magnetization. Corresponds to DICOM Tag 0018, 0082 'Inversion Time' (please note that the DICOM term is in milliseconds not seconds). cfg.mri.SliceTiming = ft_getopt(cfg.mri, 'SliceTiming' ); % The time at which each slice was acquired within each volume (frame) of the acquisition. Slice timing is not slice order -- rather, it is a list of times (in JSON format) containing the time (in seconds) of each slice acquisition in relation to the beginning of volume acquisition. The list goes through the slices along the slice axis in the slice encoding dimension (see below). Note that to ensure the proper interpretation of the SliceTiming field, it is important to check if the (optional) SliceEncodingDirection exists. In particular, if SliceEncodingDirection is negative, the entries in SliceTiming are defined in reverse order with respect to the slice axis (i.e., the final entry in the SliceTiming list is the time of acquisition of slice 0). This parameter is REQUIRED for sparse sequences that do not have the DelayTime field set. In addition without this parameter slice time correction will not be possible. cfg.mri.SliceEncodingDirection = ft_getopt(cfg.mri, 'SliceEncodingDirection' ); % Possible values 'i', 'j', 'k', 'i-', 'j-', 'k-' (the axis of the NIfTI data along which slices were acquired, and the direction in which SliceTiming is defined with respect to). 'i', 'j', 'k' identifiers correspond to the first, second and third axis of the data in the NIfTI file. A '-' sign indicates that the contents of SliceTiming are defined in reverse order -- that is, the first entry corresponds to the slice with the largest index, and the final entry corresponds to slice index zero. When present ,the axis defined by SliceEncodingDirection needs to be consistent with the 'slice_dim' field in the NIfTI header. When absent, the entries in SliceTiming must be in the order of increasing slice index as defined by the NIfTI header. cfg.mri.DwellTime = ft_getopt(cfg.mri, 'DwellTime' ); % Actual dwell time (in seconds) of the receiver per point in the readout direction, including any oversampling. For Siemens, this corresponds to DICOM field (0019,1018) (in ns). This value is necessary for the (optional) readout distortion correction of anatomicals in the HCP Pipelines. It also usefully provides a handle on the readout bandwidth, which isn't captured in the other metadata tags. Not to be confused with 'EffectiveEchoSpacing', and the frequent mislabeling of echo spacing (which is spacing in the phase encoding direction) as 'dwell time' (which is spacing in the readout direction). %% MR RF & Contrast cfg.mri.FlipAngle = ft_getopt(cfg.mri, 'FlipAngle' ); % Flip angle for the acquisition, specified in degrees. Corresponds to = []; % DICOM Tag 0018, 1314 'Flip Angle'. cfg.mri.MultibandAccelerationFactor = ft_getopt(cfg.mri, 'MultibandAccelerationFactor' ); % RECOMMENDED. The multiband factor, for multiband acquisitions. cfg.mri.NegativeContrast = ft_getopt(cfg.mri, 'NegativeContrast' ); % OPTIONAL. Boolean (true or false) value specifying whether increasing voxel intensity (within sample voxels) denotes a decreased value with respect to the contrast suffix. This is commonly the case when Cerebral Blood Volume is estimated via usage of a contrast agent in conjunction with a T2* weighted acquisition protocol. %% MR Slice Acceleration cfg.mri.MultibandAccelerationFactor = ft_getopt(cfg.mri, 'MultibandAccelerationFactor' ); % The multiband factor, for multiband acquisitions. %% Anatomical landmarks, useful for multimodaltimodal co-registration with MEG, (S)HeadCoil, TMS,etc cfg.mri.AnatomicalLandmarkCoordinates = ft_getopt(cfg.mri, 'AnatomicalLandmarkCoordinates' ); % Key:value pairs of any number of additional anatomical landmarks and their coordinates in voxel units (where first voxel has index 0,0,0) relative to the associated anatomical MRI, (e.g. {'AC' = []; % [127,119,149], 'PC' = []; % [128,93,141], 'IH' = []; % [131,114,206]}, or {'NAS' = []; % [127,213,139], 'LPA' = []; % [52,113,96], 'RPA' = []; % [202,113,91]}). %% MR Anatomical scan information cfg.mri.ContrastBolusIngredient = ft_getopt(cfg.mri, 'ContrastBolusIngredient' ); % OPTIONAL. Active ingredient of agent. Values MUST be one of: IODINE, GADOLINIUM, CARBON DIOXIDE, BARIUM, XENON Corresponds to DICOM Tag 0018,1048. %% MR Functional scan information cfg.mri.RepetitionTime = ft_getopt(cfg.mri, 'RepetitionTime' ); % REQUIRED. The time in seconds between the beginning of an acquisition of one volume and the beginning of acquisition of the volume following it (TR). Please note that this definition includes time between scans (when no data has been acquired) in case of sparse acquisition schemes. This value needs to be consistent with the pixdim[4] field (after accounting for units stored in xyzt_units field) in the NIfTI header. This field is mutually exclusive with VolumeTiming and is derived from DICOM Tag 0018, 0080 and converted to seconds. cfg.mri.VolumeTiming = ft_getopt(cfg.mri, 'VolumeTiming' ); % REQUIRED. The time at which each volume was acquired during the acquisition. It is described using a list of times (in JSON format) referring to the onset of each volume in the BOLD series. The list must have the same length as the BOLD series, and the values must be non-negative and monotonically increasing. This field is mutually exclusive with RepetitionTime and DelayTime. If defined, this requires acquisition time (TA) be defined via either SliceTiming or AcquisitionDuration be defined. %% MEG specific fields % Manufacturer and ManufacturersModelName are general cfg.meg.SamplingFrequency = ft_getopt(cfg.meg, 'SamplingFrequency' ); % REQUIRED. Sampling frequency (in Hz) of all the data in the recording, regardless of their type (e.g., 2400) cfg.meg.PowerLineFrequency = ft_getopt(cfg.meg, 'PowerLineFrequency' ); % REQUIRED. Frequency (in Hz) of the power grid at the geographical location of the MEG instrument (i.e. 50 or 60) cfg.meg.DewarPosition = ft_getopt(cfg.meg, 'DewarPosition' ); % REQUIRED. Position of the dewar during the MEG scan: 'upright', 'supine' or 'degrees' of angle from vertical: for example on CTF systems, upright=15??, supine = 90??. cfg.meg.SoftwareFilters = ft_getopt(cfg.meg, 'SoftwareFilters' ); % REQUIRED. List of temporal and/or spatial software filters applied, orideally key:valuepairsofpre-appliedsoftwarefiltersandtheir parameter values: e.g., {'SSS': {'frame': 'head', 'badlimit': 7}}, {'SpatialCompensation': {'GradientOrder': Order of the gradient compensation}}. Write 'n/a' if no software filters applied. cfg.meg.DigitizedLandmarks = ft_getopt(cfg.meg, 'DigitizedLandmarks' ); % REQUIRED. Boolean ('true' or 'false') value indicating whether anatomical landmark points (i.e. fiducials) are contained within this recording. cfg.meg.DigitizedHeadPoints = ft_getopt(cfg.meg, 'DigitizedHeadPoints' ); % REQUIRED. Boolean ('true' or 'false') value indicating whether head points outlining the scalp/face surface are contained within this recording. cfg.meg.MEGChannelCount = ft_getopt(cfg.meg, 'MEGChannelCount' ); % OPTIONAL. Number of MEG channels (e.g. 275) cfg.meg.MEGREFChannelCount = ft_getopt(cfg.meg, 'MEGREFChannelCount' ); % OPTIONAL. Number of MEG reference channels (e.g. 23). For systems without such channels (e.g. Neuromag Vectorview), MEGREFChannelCount'=0 cfg.meg.EEGChannelCount = ft_getopt(cfg.meg, 'EEGChannelCount' ); % OPTIONAL. Number of EEG channels recorded simultaneously (e.g. 21) cfg.meg.ECOGChannelCount = ft_getopt(cfg.meg, 'ECOGChannelCount' ); % OPTIONAL. Number of ECoG channels cfg.meg.SEEGChannelCount = ft_getopt(cfg.meg, 'SEEGChannelCount' ); % OPTIONAL. Number of SEEG channels cfg.meg.EOGChannelCount = ft_getopt(cfg.meg, 'EOGChannelCount' ); % OPTIONAL. Number of EOG channels cfg.meg.ECGChannelCount = ft_getopt(cfg.meg, 'ECGChannelCount' ); % OPTIONAL. Number of ECG channels cfg.meg.EMGChannelCount = ft_getopt(cfg.meg, 'EMGChannelCount' ); % OPTIONAL. Number of EMG channels cfg.meg.MiscChannelCount = ft_getopt(cfg.meg, 'MiscChannelCount' ); % OPTIONAL. Number of miscellaneous analog channels for auxiliary signals cfg.meg.TriggerChannelCount = ft_getopt(cfg.meg, 'TriggerChannelCount' ); % OPTIONAL. Number of channels for digital (TTL bit level) triggers cfg.meg.RecordingDuration = ft_getopt(cfg.meg, 'RecordingDuration' ); % OPTIONAL. Length of the recording in seconds (e.g. 3600) cfg.meg.RecordingType = ft_getopt(cfg.meg, 'RecordingType' ); % OPTIONAL. Defines whether the recording is 'continuous' or 'epoched'; this latter limited to time windows about events of interest (e.g., stimulus presentations, subject responses etc.) cfg.meg.EpochLength = ft_getopt(cfg.meg, 'EpochLength' ); % OPTIONAL. Duration of individual epochs in seconds (e.g. 1) in case of epoched data cfg.meg.ContinuousHeadLocalization = ft_getopt(cfg.meg, 'ContinuousHeadLocalization' ); % OPTIONAL. Boolean ('true' or 'false') value indicating whether continuous head localisation was performed. cfg.meg.HeadCoilFrequency = ft_getopt(cfg.meg, 'HeadCoilFrequency' ); % OPTIONAL. List of frequencies (in Hz) used by the head localisation coils ('HLC' in CTF systems, 'HPI' in Neuromag/Elekta, 'COH' in 4D/BTi) that track the subject's head position in the MEG helmet (e.g. [293, 307, 314, 321]) cfg.meg.MaxMovement = ft_getopt(cfg.meg, 'MaxMovement' ); % OPTIONAL. Maximum head movement (in mm) detected during the recording, as measured by the head localisation coils (e.g., 4.8) cfg.meg.SubjectArtefactDescription = ft_getopt(cfg.meg, 'SubjectArtefactDescription' ); % OPTIONAL. Freeform description of the observed subject artefact and its possible cause (e.g. 'Vagus Nerve Stimulator', 'non-removable implant'). If this field is set to 'n/a', it will be interpreted as absence of major source of artifacts except cardiac and blinks. cfg.meg.AssociatedEmptyRoom = ft_getopt(cfg.meg, 'AssociatedEmptyRoom' ); % OPTIONAL. Relative path in BIDS folder structure to empty-room file associated with the subject's MEG recording. The path needs to use forward slashes instead of backward slashes (e.g. 'sub-emptyroom/ses-