Skip to content

Commit

Permalink
Merge pull request #171 from bids-standard/beliy-derivate
Browse files Browse the repository at this point in the history
[WIP] Function to copy derivatives
  • Loading branch information
Remi-Gau authored Apr 17, 2021
2 parents 2d3a92a + 63a9b1b commit 87655ae
Show file tree
Hide file tree
Showing 42 changed files with 946 additions and 473 deletions.
4 changes: 2 additions & 2 deletions +bids/+internal/append_to_layout.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function subject = append_to_layout(file, subject, modality, schema)
function [subject, p] = append_to_layout(file, subject, modality, schema)
%
% appends a file to the BIDS layout by parsing it according to the provided schema
%
Expand Down Expand Up @@ -40,7 +40,7 @@
p = bids.internal.parse_filename(file, entities);

% do not index json files when using the schema
if ~isempty(p) && strcmp(p.ext, '.json')
if isempty(p) || (~isempty(p) && strcmp(p.ext, '.json'))
return
end

Expand Down
23 changes: 23 additions & 0 deletions +bids/+internal/ends_with.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function res = ends_with(str, pattern)
%
% Checks id character array 'str' ends with 'pat'
%
% USAGE res = bids.internal.endsWith(str, pat)
%
% str - character array
% pat - character array
%
% __________________________________________________________________________
%
% Based on spm_file.m and spm_select.m from SPM12.
% __________________________________________________________________________

% Copyright (C) 2011-2018 Guillaume Flandin, Wellcome Centre for Human Neuroimaging
res = false;
l_pat = length(pattern);
if l_pat > length(str)
return
end
res = strcmp(str(end - l_pat + 1:end), pattern);

end
92 changes: 92 additions & 0 deletions +bids/+internal/get_meta_list.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
function metalist = get_meta_list(filename, pattern)
%
% Read a BIDS's file metadata according to the inheritance principle
%
% USAGE::
%
% meta = bids.internal.get_metadata(filename, pattern = '^.*%s\\.json$')
%
% :param filename: fullpath name of file following BIDS standard
% :type filename: string
% :param pattern: Regular expression matching the metadata file (default is ``'^.*%s\\.json$'``)
% If provided, it must at least be ``'%s'``.
% :type pattern: string
%
%
% metalist - list of paths to metafiles
% __________________________________________________________________________

% Copyright (C) 2016-2018, Guillaume Flandin, Wellcome Centre for Human Neuroimaging
% Copyright (C) 2018--, BIDS-MATLAB developers

if nargin == 1
pattern = '^.*%s\\.json$';
end

pth = fileparts(filename);
p = bids.internal.parse_filename(filename);
metalist = {};

% Default assumes we are dealing with a file in the root directory
% like "participants.tsv"
% If the file has underscore separated entities ("sub-01_T1w.nii")
% then we look through the hierarchy for potential metadata file associated
% with queried file.
N = 1;
if isfield(p, 'entities')
N = 3;
% -There is a session level in the hierarchy
if isfield(p.entities, 'ses') && ~isempty(p.entities.ses)
N = N + 1;
end
end

for n = 1:N

% List the potential metadata files associated with this file suffix type
% Default is to assume it is a JSON file
metafile = bids.internal.file_utils('FPList', pth, sprintf(pattern, p.suffix));

if isempty(metafile)
metafile = {};
else
metafile = cellstr(metafile);
end

% For all those files we find which one is potentially associated with
% the file of interest
for i = 1:numel(metafile)

p2 = bids.internal.parse_filename(metafile{i});
entities = {};
if isfield(p2, 'entities')
entities = fieldnames(p2.entities);
end

% Check if this metadata file contains
% - the same entity-label pairs
% - same suffix
% as its data file counterpart
ismeta = true;
if ~strcmp(p.suffix, p2.suffix)
ismeta = false;
end
for j = 1:numel(entities)
if ~isfield(p.entities, entities{j}) || ...
~strcmp(p.entities.(entities{j}), p2.entities.(entities{j}))
ismeta = false;
break
end
end

% append path to list
if ismeta
metalist{end + 1, 1} = metafile{i}; %#ok<AGROW>
end

end

% Go up to the parent folder
pth = fullfile(pth, '..');
end
end
91 changes: 14 additions & 77 deletions +bids/+internal/get_metadata.m
Original file line number Diff line number Diff line change
@@ -1,101 +1,38 @@
function meta = get_metadata(filename, pattern)
function meta = get_metadata(metafile)
%
% Read a BIDS's file metadata according to the inheritance principle
%
% USAGE::
%
% meta = bids.internal.get_metadata(filename, pattern = '^.*%s\\.json$')
% meta = bids.internal.get_metadata(metafile)
%
% :param filename: fullpath name of file following BIDS standard
% :type filename: string
% :param pattern: Regular expression matching the metadata file (default is ``'^.*%s\\.json$'``)
% If provided, it must at least be ``'%s'``.
% :type pattern: string
% :param metafile: list of fullpath names of metadata files.
% :type metafile: string or array of strings
%
% :returns: - :meta: metadata structure
%
% meta - metadata structure
% .. todo
%
% add explanation on how the inheritance principle is implemented.
% __________________________________________________________________________

% Copyright (C) 2016-2018, Guillaume Flandin, Wellcome Centre for Human Neuroimaging
% Copyright (C) 2018--, BIDS-MATLAB developers

% assume most files are of the form *_suffix.json
% add an exception for files with no suffix, like participants.tsv
if nargin == 1
pattern = '^.*_?%s\\.json$';
end

pth = fileparts(filename);
p = bids.internal.parse_filename(filename);

meta = struct();
metafile = cellstr(metafile);

N = 3;

% -There is a session level in the hierarchy
if isfield(p, 'entities') && isfield(p.entities, 'ses') && ~isempty(p.entities.ses)
N = N + 1;
end

% -Loop from the directory where the file of interest is back to the
% top level of the BIDS hierarchy
for n = 1:N

% -List the potential metadata files associated with this file suffix type
% Default is to assume it is a JSON file
metafile = bids.internal.file_utils('FPList', pth, sprintf(pattern, p.suffix));

if isempty(metafile)
metafile = {};
for i = 1:numel(metafile)
if bids.internal.ends_with(metafile{i}, '.json')
meta = update_metadata(meta, bids.util.jsondecode(metafile{i}), metafile{i});
else
metafile = cellstr(metafile);
end

% -For all those files we find which one is potentially associated with
% the file of interest
for i = 1:numel(metafile)

p2 = bids.internal.parse_filename(metafile{i});
entities = {};
if isfield(p2, 'entities')
entities = fieldnames(p2.entities);
end

% Check if this metadata file contains
% - the same entity-label pairs
% - same prefix
% as its data file counterpart
ismeta = true;
if ~strcmp(p.suffix, p2.suffix)
ismeta = false;
end
for j = 1:numel(entities)
if ~isfield(p.entities, entities{j}) || ...
~strcmp(p.entities.(entities{j}), p2.entities.(entities{j}))
ismeta = false;
break
end
end

% -Read the content of the metadata file if it is a JSON file and update
% the metadata concerning the file of interest otherwise store the filename
if ismeta
if strcmp(p2.ext, '.json')
meta = update_metadata(meta, bids.util.jsondecode(metafile{i}), metafile{i});
else
meta.filename = metafile{i};
end
end

meta.filename = metafile{i};
end

% -Go up to the parent folder
pth = fullfile(pth, '..');

end

if isempty(meta)
warning('No metadata for %s', filename);
warning('No metadata for %s', metafile);
end

end
Expand Down
12 changes: 10 additions & 2 deletions +bids/+internal/parse_filename.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,16 @@
end

% identidy an eventual prefix to the file
tmp = regexp(parts{1}, '(sub)', 'split');
p.prefix = tmp{1};
% and amends the sub entity accordingly
p.prefix = '';
if strfind(parts{1}, 'sub-')
tmp = regexp(parts{1}, '(sub-)', 'split');
p.prefix = tmp{1};
if ~isempty(p.prefix)
p.entities.sub = p.entities.([p.prefix 'sub']);
p.entities = rmfield(p.entities, [p.prefix 'sub']);
end
end

% -Extra fields can be added to the structure and ordered specifically.
if nargin == 2
Expand Down
23 changes: 23 additions & 0 deletions +bids/+internal/starts_with.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function res = starts_with(str, pattern)
%
% Checks id character array 'str' starts with 'pat'
%
% USAGE res = bids.internal.startsWith(str, pat)
%
% str - character array
% pat - character array
%
% __________________________________________________________________________
%
% Based on spm_file.m and spm_select.m from SPM12.
% __________________________________________________________________________

% Copyright (C) 2011-2018 Guillaume Flandin, Wellcome Centre for Human Neuroimaging
res = false;
l_pat = length(pattern);
if l_pat > length(str)
return
end
res = strcmp(str(1:l_pat), pattern);

end
Loading

0 comments on commit 87655ae

Please sign in to comment.