Skip to content

Commit

Permalink
Merge pull request #287 from bids-standard/rc0.1.0
Browse files Browse the repository at this point in the history
[REL] rc0.1.0
  • Loading branch information
Remi-Gau authored Jan 27, 2022
2 parents 4becbcd + 060e98c commit 55e7412
Show file tree
Hide file tree
Showing 216 changed files with 19,888 additions and 2,985 deletions.
7 changes: 4 additions & 3 deletions +bids/+internal/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
BIDS-MATLAB +internal package
=============================
# BIDS-MATLAB +internal package

This package contains functions for BIDS-MATLAB's internal use only.

Do not call these functions directly from your code! They are undocumented and subject to change at any time. If you call these functions from your code, your code may break or produce incorrect results!
Do not call these functions directly from your code! They are undocumented and
subject to change at any time.
If you call these functions from your code, your code may break or produce incorrect results!
12 changes: 12 additions & 0 deletions +bids/+internal/add_missing_field.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function structure = add_missing_field(structure, field)
%
% USAGE::
%
% structure = add_missing_field(structure, field)
%
% (C) Copyright 2021 BIDS-MATLAB developers

if ~isfield(structure, field)
structure(1).(field) = '';
end
end
177 changes: 177 additions & 0 deletions +bids/+internal/append_to_layout.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
function [subject, status, previous] = append_to_layout(file, subject, modality, schema, previous)
%
% appends a file to the BIDS layout by parsing it according to the provided schema
%
% USAGE::
%
% subject = append_to_layout(file, subject, modality, schema == [])
%
% :param file:
% :type file: string
% :param subject: subject sub-structure from the BIDS layout
% :type subject: strcture
% :param modality:
% :type modality: string
% :param schema:
% :type schema: strcture
%
%
% (C) Copyright 2021 BIDS-MATLAB developers

pth = [subject.path, filesep, modality];

% We speed up indexing by checking that the current file has the same basename
% as the previous one.
% In this case we can copy most of the info from the previous file
if same_data(file, previous)

% Skip file in case we are using the schema and faced with a file that
% does have the same basename as the previous file
% but not a recognized extension
% - <match>_events.tsv
% - <match>_events.mat
%
if ~isempty(schema.content) && ...
~any(ismember(file(previous.data.len:end), ...
previous.allowed_ext))
[msg, id] = error_message('unknownExtension', file, file(previous.data.len:end));
bids.internal.error_handling(mfilename, id, msg, true, schema.verbose);
status = 0;
return
end

subject.(modality)(end + 1, 1) = subject.(modality)(end, 1);
subject.(modality)(end, 1).ext = file(previous.data.len:end);
subject.(modality)(end, 1).filename = file;

dep_fname = fullfile(pth, subject.(modality)(end - 1, 1).filename);
subject.(modality)(end).dependencies.data{end + 1, 1} = dep_fname;
status = 1;
return

else

% Parse file fist to identify the suffix group in the template.
% Then reparse the file using the entity-label pairs defined in the schema.
p = bids.internal.parse_filename(file);
if isempty(p)
status = 0;
return
end

if ~isempty(schema.content)

idx = schema.find_suffix_group(modality, p.suffix);

if isempty(idx)
[msg, id] = error_message('unknownSuffix', file, p.suffix);
bids.internal.error_handling(mfilename, id, msg, true, schema.verbose);
status = 0;
return
end

datatypes = schema.get_datatypes();

this_suffix_group = datatypes.(modality)(idx);

allowed_extensions = this_suffix_group.extensions;

schema_entities = schema.return_entities_for_suffix_group(this_suffix_group);
required_entities = schema.required_entities_for_suffix_group(this_suffix_group);

present_entities = fieldnames(p.entities);
missing_entities = ~ismember(required_entities, present_entities);
unknown_entity = present_entities(~ismember(present_entities, schema_entities));

extension = p.ext;
% in case we are dealing with a folder
% (can be the case for some MEG formats: .ds)
if exist(fullfile(pth, p.filename), 'dir')
extension = [extension '/'];
end

%% Checks that this file is BIDS compliant
if ~ismember('*', allowed_extensions) && ...
~ismember(extension, allowed_extensions)
[msg, id] = error_message('unknownExtension', file, extension);
end

if ~isempty(unknown_entity)
[msg, id] = error_message('unknownEntity', file, ...
strjoin(cellstr(unknown_entity), ' '));
end

if any(missing_entities)
missing_entities = required_entities(missing_entities);
[msg, id] = error_message('missingRequiredEntity', file, ...
strjoin(cellstr(missing_entities), ' '));
end

if exist('id', 'var')
bids.internal.error_handling(mfilename, id, msg, true, schema.verbose);
status = 0;
return
end

p = bids.internal.parse_filename(file, schema_entities);
if isempty(p)
status = 0;
return
end

previous.allowed_ext = allowed_extensions;

end

p.metafile = bids.internal.get_meta_list(fullfile(subject.path, modality, file));

p.dependencies.explicit = {};
p.dependencies.data = {};
p.dependencies.group = {};

if ~isempty(subject.(modality))
[subject.(modality), p] = bids.internal.match_structure_fields(subject.(modality), p);

end

if isempty(subject.(modality))
subject.(modality) = p;

else
subject.(modality)(end + 1, 1) = p;

end

status = 1;

end

end

function status = same_data(file, previous)

status = strncmp(previous.data.base, file, previous.data.len);

end

function [msg, msg_id] = error_message(msg_id, file, extra)

msg = sprintf('Skipping file %s.\n', file);

switch msg_id

case 'unknownExtension'
msg = sprintf('%s Unknown extension %s', msg, extra);

case 'missingRequiredEntity'
msg = sprintf('%s Missing REQUIRED entity: %s', msg, extra);

case 'unknownEntity'
msg = sprintf('%s Unknown entities: %s', msg, extra);

case 'unknownSuffix'
msg = sprintf('%s Unknown suffix: %s', msg, extra);

end

end
28 changes: 28 additions & 0 deletions +bids/+internal/camel_case.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function str = camel_case(str)
%
% Removes non alphanumeric characters and uppercase first letter of all
% words but the first
%
% USAGE::
%
% str = camel_case(str)
%
% :param str:
% :type str: string
%
% :returns:
% :str: (string) returns the input with an upper case for first letter
% for all words but the first one (``camelCase``) and
% removes invalid characters (like spaces).
%
% (C) Copyright 2018 BIDS-MATLAB developers

% camel case: upper case for first letter for all words but the first one
spaceIdx = regexp(str, '[a-zA-Z0-9]*', 'start');
str(spaceIdx(2:end)) = upper(str(spaceIdx(2:end)));

% remove invalid characters
[unvalidCharacters] = regexp(str, '[^a-zA-Z0-9]');
str(unvalidCharacters) = [];

end
41 changes: 41 additions & 0 deletions +bids/+internal/download_moae_ds.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
function output_dir = download_moae_ds(download_data, output_dir)
%
% Will download the lightweight "Mother of all experiment" dataset from the
% SPM website.
%
% (C) Copyright 2021 BIDS-MATLAB developers

if nargin < 1
download_data = true();
end
if nargin < 2
output_dir = fullfile(bids.internal.root_dir(), 'examples');
end

if download_data

% URL of the data set to download
URL = 'http://www.fil.ion.ucl.ac.uk/spm/download/data/MoAEpilot/MoAEpilot.bids.zip';

% clean previous runs
if exist(fullfile(output_dir, 'MoAEpilot'), 'dir')
if bids.internal.is_octave()
confirm_recursive_rmdir(false, 'local');
end
rmdir(fullfile(output_dir, 'MoAEpilot'), 's');
end

%% Get data
% Downloading dataset
urlwrite(URL, 'MoAEpilot.zip');

% Unzipping dataset
unzip('MoAEpilot.zip');
delete('MoAEpilot.zip');
movefile('MoAEpilot', fullfile(output_dir));

end

output_dir = fullfile(output_dir, 'MoAEpilot');

end
28 changes: 28 additions & 0 deletions +bids/+internal/ends_with.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function res = ends_with(str, pattern)
%
% Checks id character array 'str' ends with 'pat'
%
% USAGE::
%
% res = bids.internal.endsWith(str, pattern)
%
% :param str:
% :type str: character array
% :param pattern:
% :type pattern: character array
%
%
% Based on the equivalent function from SPM12
%
% (C) Copyright 2011-2018 Guillaume Flandin, Wellcome Centre for Human Neuroimaging
%
% (C) Copyright 2018 BIDS-MATLAB developers

res = false;
l_pat = length(pattern);
if l_pat > length(str)
return
end
res = strcmp(str(end - l_pat + 1:end), pattern);

end
51 changes: 51 additions & 0 deletions +bids/+internal/error_handling.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function error_handling(varargin)
%
% USAGE::
%
% error_handling(function_name, id, msg, tolerant, verbose)
%
% :param function_name: default = ``bidsMatlab``
% :type function_name:
% :param id: default = ``unspecified``
% :type id: string
% :param msg: default = ``unspecified``
% :type msg: string
% :param tolerant:
% :type tolerant: boolean
% :param verbose:
% :type verbose: boolean
%
% (C) Copyright 2018 BIDS-MATLAB developers

default_function_name = 'bidsMatlab';
default_id = 'unspecified';
default_msg = 'unspecified';
default_tolerant = true;
default_verbose = false;

p = inputParser;

addOptional(p, 'function_name', default_function_name, @ischar);
addOptional(p, 'id', default_id, @ischar);
addOptional(p, 'msg', default_msg, @ischar);
addOptional(p, 'tolerant', default_tolerant, @islogical);
addOptional(p, 'verbose', default_verbose, @islogical);

parse(p, varargin{:});

function_name = bids.internal.file_utils(p.Results.function_name, 'basename');

id = [function_name, ':' p.Results.id];
msg = p.Results.msg;

if ~p.Results.tolerant
errorStruct.identifier = id;
errorStruct.message = msg;
error(errorStruct);
end

if p.Results.verbose
warning(id, msg);
end

end
Loading

0 comments on commit 55e7412

Please sign in to comment.