Commit 1b98cbce authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'various_fixes' into 'master'

Various fixes

See merge request fsl/fslpy!103
parents 62c51e9e 3c678cf9
Pipeline #3415 failed with stages
in 1 minute and 28 seconds
...@@ -193,9 +193,9 @@ Assuming that the input T1w's already exist, we can then simply run BET for ever ...@@ -193,9 +193,9 @@ Assuming that the input T1w's already exist, we can then simply run BET for ever
from fsl.utils.filetree import FileTree from fsl.utils.filetree import FileTree
from fsl.wrappers.bet import bet from fsl.wrappers.bet import bet
tree = FileTree.read(<tree filename>) tree = FileTree.read(<tree filename>)
variables = tree.get_all_vars('T1w') # extract the set of variables for all existing T1w files
for single_variable_set in variables: # Iterates over set of variables that correspond to each T1-weighted image file matching the template
T1w_tree = tree.update(**single_variable_set) for T1w_tree in tree.get_all_trees('T1w', glob_vars='all'):
# get retrieves the filenames based on the current set of variables # get retrieves the filenames based on the current set of variables
# make_dir=True ensures that the output directory containing the "bet_output" actually exists # make_dir=True ensures that the output directory containing the "bet_output" actually exists
bet(input=T1w_tree.get('T1w'), output=T1w_tree.get('bet_output', make_dir=True), mask=True) bet(input=T1w_tree.get('T1w'), output=T1w_tree.get('bet_output', make_dir=True), mask=True)
......
...@@ -171,7 +171,7 @@ class FileTree(object): ...@@ -171,7 +171,7 @@ class FileTree(object):
:return: sorted sequence of paths :return: sorted sequence of paths
""" """
text, variables = self.get_template(short_name) text, variables = self.get_template(short_name)
return tuple(utils.get_all(text, variables, glob_vars=glob_vars)) return tuple(str(Path(fn)) for fn in utils.get_all(text, variables, glob_vars=glob_vars))
def get_all_vars(self, short_name: str, glob_vars=()) -> Tuple[Dict[str, str]]: def get_all_vars(self, short_name: str, glob_vars=()) -> Tuple[Dict[str, str]]:
""" """
...@@ -185,16 +185,33 @@ class FileTree(object): ...@@ -185,16 +185,33 @@ class FileTree(object):
""" """
return tuple(self.extract_variables(short_name, fn) for fn in self.get_all(short_name, glob_vars=glob_vars)) return tuple(self.extract_variables(short_name, fn) for fn in self.get_all(short_name, glob_vars=glob_vars))
def get_all_trees(self, short_name: str, global_vars=()) -> Tuple["FileTree"]:
"""
Gets all the trees that generate the existing files matching the pattern
tree.get_all(short_name) == tuple(tree.get(short_name) for tree in tree.get_all_trees(short_name))
:param short_name: short name of the path template
:param glob_vars: sequence of undefined variables that can take any possible values when looking for matches on the disk.
Any defined variables in `glob_vars` will be ignored.
If glob_vars is set to 'all', all undefined variables will be used to look up matches.
:return: sequence of FileTrees used to generate each file on disk matching the pattern of `short_name`
"""
return tuple(self.update(**vars) for vars in self.get_all_vars(short_name, glob_vars=global_vars))
def update(self, **variables) -> "FileTree": def update(self, **variables) -> "FileTree":
""" """
Creates a new filetree with updated variables Creates a new FileTree with updated variables
:param variables: new values for the variables :param variables: new values for the variables
Setting variables to None will explicitly unset them Setting a variable to None will cause the variable to be unset
:return: New FileTree with same templates for directory names and filenames, but updated variables :return: New FileTree with same templates for directory names and filenames, but updated variables
""" """
new_tree = deepcopy(self) new_tree = deepcopy(self)
new_tree.variables.update(variables) new_tree.variables.update(variables)
for key, value in variables.items():
if value is None:
del new_tree.variables[key]
return new_tree return new_tree
def extract_variables(self, short_name: str, filename: str) -> Dict[str, str]: def extract_variables(self, short_name: str, filename: str) -> Dict[str, str]:
......
...@@ -170,6 +170,8 @@ def extract_variables(template, filename, known_vars=None): ...@@ -170,6 +170,8 @@ def extract_variables(template, filename, known_vars=None):
raise ValueError('Multiple values found for {}'.format(var)) raise ValueError('Multiple values found for {}'.format(var))
else: else:
extracted_value[var] = value extracted_value[var] = value
if any('/' in value for value in extracted_value.values()):
continue
for name in find_variables(template): for name in find_variables(template):
if name not in extracted_value: if name not in extracted_value:
extracted_value[name] = None extracted_value[name] = None
......
...@@ -77,8 +77,8 @@ def test_custom_tree(): ...@@ -77,8 +77,8 @@ def test_custom_tree():
assert len(tree.get_all('sub_file', glob_vars='all')) == 2 assert len(tree.get_all('sub_file', glob_vars='all')) == 2
assert len(tree.get_all('sub_file')) == 1 assert len(tree.get_all('sub_file')) == 1
assert len(tree.update(opt=None).get_all('sub_file')) == 1 assert len(tree.update(opt=None).get_all('sub_file')) == 1
assert len(tree.update(opt=None).get_all('sub_file', glob_vars=['opt'])) == 1 assert len(tree.update(opt=None).get_all('sub_file', glob_vars=['opt'])) == 2
assert len(tree.update(opt=None).get_all('sub_file', glob_vars='all')) == 1 assert len(tree.update(opt=None).get_all('sub_file', glob_vars='all')) == 2
for fn, settings in zip(tree.get_all('sub_file', glob_vars='all'), for fn, settings in zip(tree.get_all('sub_file', glob_vars='all'),
tree.get_all_vars('sub_file', glob_vars='all')): tree.get_all_vars('sub_file', glob_vars='all')):
...@@ -90,6 +90,10 @@ def test_custom_tree(): ...@@ -90,6 +90,10 @@ def test_custom_tree():
tree.get_all('opt_file') tree.get_all('opt_file')
assert len(tree.get_all('opt_file', glob_vars=['opt'])) == 1 assert len(tree.get_all('opt_file', glob_vars=['opt'])) == 1
for short_name in ('sub_file', 'opt_file'):
for glob_vars in (['opt'], 'all'):
assert tree.get_all(short_name, glob_vars) == tuple(stree.get(short_name) for stree in tree.get_all_trees(short_name, glob_vars))
for vars in ({'opt': None}, {'opt': 'test'}): for vars in ({'opt': None}, {'opt': 'test'}):
filename = tree.update(**vars).get('sub_file') filename = tree.update(**vars).get('sub_file')
assert vars == tree.extract_variables('sub_file', filename) assert vars == tree.extract_variables('sub_file', filename)
......
...@@ -21,3 +21,7 @@ def test_get_variables(): ...@@ -21,3 +21,7 @@ def test_get_variables():
utils.extract_variables('{var}[_{other_var}]_{var}', 'test_foo_bar') utils.extract_variables('{var}[_{other_var}]_{var}', 'test_foo_bar')
with pytest.raises(ValueError): with pytest.raises(ValueError):
utils.extract_variables('bar{var}[_{other_var}]_{var}', 'test') utils.extract_variables('bar{var}[_{other_var}]_{var}', 'test')
assert {'subject': '01', 'session': 'A'} == utils.extract_variables('sub-{subject}/[ses-{session}]/T1w.nii.gz', 'sub-01/ses-A/T1w.nii.gz')
with pytest.raises(ValueError):
utils.extract_variables('sub-{subject}/[ses-{session}]/T1w.nii.gz', 'sub-01/other/T1w.nii.gz')
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment