Skip to content

Commit

Permalink
Merge pull request #40 from AdebayoBraimah/dev5
Browse files Browse the repository at this point in the history
Dev5
  • Loading branch information
AdebayoBraimah committed Jun 24, 2021
2 parents a1e61fe + 6f210b7 commit 2edd798
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 106 deletions.
10 changes: 10 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
CHANGES
=========

0.2.0a8
---------

This version is an alpha release that contains several bug fixes and updates.

* BUG FIX: Fixed bug in which an unexpected parent DICOM directory could throw errors.
* BUG FIX: Fixed bug in which BIDS related parameters were not added to the output file name.
* UPDATE: More robust and reliable BIDS file naming.
* ENHANCEMENT: Added support for native symbolic linking.

0.2.0a7
---------

Expand Down
24 changes: 12 additions & 12 deletions convert_source/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
f.close()

# More information about organizing author information:
# https://stackoverflow.com/questions/1523427/what-is-the-common-header-format-of-python-files
# http://epydoc.sourceforge.net/manual-fields.html#module-metadata-variables
# * https://stackoverflow.com/questions/1523427/what-is-the-common-header-format-of-python-files
# * http://epydoc.sourceforge.net/manual-fields.html#module-metadata-variables

__author__ = "Adebayo Braimah"
__credits__ = ["Adebayo Braimah",
"Cincinnati Children's Hospital Medical Center",
"Imaging Research Center",
"CCHMC Dept. of Radiology"]
__license__ = "GPL"
__version__ = _cs_version
__maintainer__ = "Adebayo Braimah"
__email__ = "adebayo.braimah@gmail.com"
__status__ = "Development"
__author__ = "Adebayo Braimah"
__credits__ = ["Adebayo Braimah",
"Cincinnati Children's Hospital Medical Center",
"Imaging Research Center",
"CCHMC Dept. of Radiology"]
__license__ = "GPL"
__version__ = _cs_version
__maintainer__ = "Adebayo Braimah"
__email__ = "adebayo.braimah@gmail.com"
__status__ = "Development"
2 changes: 1 addition & 1 deletion convert_source/batch_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ def _get_bids_name_args(bids_name_dict: Dict,
case4: bool = False

params_var: List[str] = [task, acq, ce, acq_dir, rec, echo, case1, mag2, case2, case3, case4]
params_str: List[str] = ["task", "acq", "ce", "acq_dir", "rec", "echo", "case1", "mag2", "case2", "case3", "case4"]
params_str: List[str] = ["task", "acq", "ce", "dir", "rec", "echo", "case1", "mag2", "case2", "case3", "case4"]

if len(params_str) == len(params_var):
pass
Expand Down
24 changes: 17 additions & 7 deletions convert_source/batch_symlink.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"""Command line wrapper for `convert_source`'s study directory symlink functions.
"""Command line wrapper for ``convert_source``'s study directory symlink functions.
Performs symlinking for a study's subject imaging data.
"""
import pathlib
Expand All @@ -14,13 +14,14 @@
)

_pkg_path: str = str(
pathlib.Path(
os.path.abspath(__file__)
).parents[2])
pathlib.Path(
os.path.abspath(__file__)
).parents[2])

sys.path.append(_pkg_path)

from convert_source.cs_utils.fileio import LogFile
from convert_source.cs_utils.utils import sym_link

link_version = '0.0.1'

Expand Down Expand Up @@ -106,6 +107,8 @@ def create_study_sym_links(study_dir: str,
infile: str,
mapfile: str,
outdir: str,
native: Optional[bool] = True,
overwrite: Optional[bool] = False,
log_file: Optional[LogFile] = None
) -> List[str]:
"""Creates another study directory of sym-linked subject directories to the original study directory.
Expand All @@ -124,13 +127,15 @@ def create_study_sym_links(study_dir: str,
infile: Input file of directories to be mapped.
mapfile: Corresponding file that contains the subject directories to be mapped to.
outdir: Output directory for all symlinked directories.
native: Use native UNIX linking tool instead of python's symbolic linking tool.
overwrite: Overwrite symbolic link if it already exists.
log_file: LogFile object for logging.
Returns:
List of sym-linked directories.
Raises:
IndexError is raised if the number of entries in ``infile`` and ``mapfile`` are not equal.
IndexError: Raised if the number of entries in ``infile`` and ``mapfile`` are not equal.
"""
study_dir: str = os.path.abspath(study_dir)

Expand Down Expand Up @@ -165,7 +170,10 @@ def create_study_sym_links(study_dir: str,
sub_dir: str = os.path.join(study_dir,i)
tar_dir: str = os.path.join(outdir,j)

if os.path.exists(tar_dir) and os.path.islink(tar_dir):
if os.path.exists(tar_dir) and os.path.islink(tar_dir) and overwrite:
if log_file:
log_file.log(f"(Symbolically linked) directory has been overwritten, linking the following: {i} -> {j}.")
elif os.path.exists(tar_dir) and os.path.islink(tar_dir):
if log_file:
log_file.log(f"(Symbolically linked) directory already exists: {i} -> {j}.")
elif os.path.exists(tar_dir):
Expand All @@ -174,7 +182,9 @@ def create_study_sym_links(study_dir: str,
else:
if log_file:
log_file.log(f"Symbollically linked directories: {i} -> {j}.")
os.symlink(sub_dir,tar_dir)
sym_link(src=sub_dir,
tar=tar_dir,
native=native)
dir_list.append(tar_dir)
return dir_list

Expand Down
53 changes: 29 additions & 24 deletions convert_source/cs_utils/bids_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,30 +503,35 @@ def search_bids(s: str,
bids_name_dict[modality_type]['modality_label'] = modality_label
return bids_name_dict

# Use dict.get method here
if depth(bids_search[modality_type]) == 3:
try:
for (k1,v1),(k2,v2) in zip(bids_search[modality_type][modality_label].items(),bids_map[modality_type][modality_label].items()):
for va,vb in zip(v1,v2):
if list_in_substr(in_list=[va],in_str=s):
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type][k1] = vb
else:
bids_name_dict[modality_type]['modality_label'] = modality_label
except (TypeError,KeyError):
pass
for (k1,v1),(k2,v2) in zip(bids_search[modality_type].get(modality_label,'').items(),bids_map[modality_type].get(modality_label,'').items()):
if (v1 is None) and (v2 is None):
continue
elif (v1 is None) and v2:
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type][k1] = ''.join(v2)
else:
for va,vb in zip(v1,v2):
if list_in_substr(in_list=[va],in_str=s):
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type][k1] = vb
else:
bids_name_dict[modality_type]['modality_label'] = modality_label
elif depth(bids_search[modality_type]) == 4:
try:
for (k1,v1),(k2,v2) in zip(bids_search[modality_type][modality_label][task].items(),bids_map[modality_type][modality_label][task].items()):
for (va,vb) in zip(v1,v2):
if list_in_substr(in_list=[va],in_str=s):
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type]['task'] = task
bids_name_dict[modality_type][k1] = vb
else:
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type]['task'] = task
except (TypeError,KeyError):
pass

for (k1,v1),(k2,v2) in zip(bids_search[modality_type].get(modality_label,'').get(task,'').items(),bids_map[modality_type].get(modality_label,'').get(task,'').items()):
if (v1 is None) and (v2 is None):
continue
elif (v1 is None) and v2:
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type]['task'] = task
bids_name_dict[modality_type][k1] = ''.join(v2)
else:
for (va,vb) in zip(v1,v2):
if list_in_substr(in_list=[va],in_str=s):
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type]['task'] = task
bids_name_dict[modality_type][k1] = vb
else:
bids_name_dict[modality_type]['modality_label'] = modality_label
bids_name_dict[modality_type]['task'] = task
return bids_name_dict
90 changes: 71 additions & 19 deletions convert_source/cs_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,9 @@ def gzip_file(file: str,
# Check if native method was enabled.
if native:
if platform.system().lower() == 'windows':
native = False
native: bool = False
else:
native = True
native: bool = True

# Check if the file exists
if os.path.exists(file):
Expand Down Expand Up @@ -450,9 +450,9 @@ def gunzip_file(file: str,
# Check if native method was enabled.
if native:
if platform.system().lower() == 'windows':
native = False
native: bool = False
else:
native = True
native: bool = True

# Check if the file exists
if os.path.exists(file):
Expand Down Expand Up @@ -963,18 +963,21 @@ def glob_dcm(dcm_dir: str) -> List[str]:

for dir_ in dcm_dir_list:
for root, dirs, files in os.walk(dir_):
# Only need the first DICOM file
tmp_dcm_file = files[0]
tmp_dcm_dir = root
tmp_file = os.path.join(tmp_dcm_dir, tmp_dcm_file)

# Old implementation - need to test with current use cases
dcm_files.append(tmp_file)
break

# if '.dcm' in tmp_file:
# dcm_files.append(tmp_file)
# break
try:
# Only need the first DICOM file
tmp_dcm_file = files[0]
tmp_dcm_dir = root
tmp_file = os.path.join(tmp_dcm_dir, tmp_dcm_file)

# Old implementation - need to test with current use cases
dcm_files.append(tmp_file)
break

# if '.dcm' in tmp_file:
# dcm_files.append(tmp_file)
# break
except IndexError:
continue
return dcm_files

def glob_img(img_dir: str) -> List[str]:
Expand Down Expand Up @@ -1317,7 +1320,6 @@ def comp_dict(d1: Dict,
Raises:
KeyError: Error that arises if input dictionaries do not have matching keys.
ValueError: Error that arises if one or more of the keys in either dictionary map NoneType values.
"""
for k in d1:
if (k not in d2):
Expand All @@ -1340,7 +1342,6 @@ def comp_dict(d1: Dict,
print (path, ":")
print (" - ", k," : ", d1[k])
print (" + ", k," : ", d2[k])
raise ValueError("One or both input BIDS dictionaries map to NoneType values.")
return True

def depth(d: Dict) -> int:
Expand Down Expand Up @@ -1692,4 +1693,55 @@ def _is_gzipped(file: str) -> bool:
# 'utf-8' codec cannot decode byte 0x8b in position 1.
return f.read(2).encode("utf-8").hex() == GZIP_MAGIC_NUMBER
except UnicodeDecodeError:
return True
return True

def sym_link(src: str,
tar: str,
native: Optional[bool] = False
) -> None:
"""Performs symbolic linking of some input source file or directory
to some target output file. The symbolic linking can be performed using
the UNIX system's native linking tools or via python's linking tools.
NOTE:
* ``Windows`` platforms require running this funciton with elevated privileges as this operation cannot be performed otherwise.
Usage example:
>>> sym_link(src='<source_file/directory>',
tar='<target_file>',
native=True)
...
Arguments:
src: Input source file or directory.
tar: Output target file that is linked to the source file or directory.
native: Use native UNIX linking tool instead of python's symbolic linking tool.
Returns:
None
Raises:
FileNotFoundError: Error that arises should the source directory/file not exist.
"""
# Check if native method was enabled.
if native:
if platform.system().lower() == 'windows':
native: bool = False
else:
native: bool = True

# Check if source file or directory exists
if os.path.exists(src):
pass
else:
raise FileNotFoundError("Cannot symbollicaly link a file or directory that does not exist.")

# Perform native of pythonic symbolic linking
if native:
link_cmd: Command = Command("ln")
link_cmd.cmd_list.append("-s")
link_cmd.cmd_list.append(src)
link_cmd.cmd_list.append(tar)
link_cmd.run()
else:
os.symlink(src,tar)
9 changes: 7 additions & 2 deletions convert_source/tests/03_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,13 @@ def test_comp_dict_funcs():
assert comp_dict(d1,d2) == True
with pytest.raises(KeyError):
assert comp_dict(d1,d3) == False
with pytest.raises(ValueError):
assert comp_dict(d3,d4)
# This assertion is no longer valid
# as a result of allowing NoneType
# values to be mapped in either
# dictionary.
#
# with pytest.raises(ValueError):
# assert comp_dict(d3,d4)
assert depth(d1) == 3
assert depth(d2) == 3
assert depth(d3) == 3
Expand Down
11 changes: 0 additions & 11 deletions convert_source/tests/helper.scripts/test.2.config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ modality_search:
rest:
- rsfMR
- rest
- FFE
- FEEPI
# ASL (arterial spin labeling) contrast
cbv:
Expand Down Expand Up @@ -76,11 +75,6 @@ bids_search:
ce:
dir:
rec:
visualstrobe:
acq:
ce:
dir:
rec:
# ASL (arterial spin labeling) contrast
cbv:
rest:
Expand Down Expand Up @@ -133,11 +127,6 @@ bids_map:
ce:
dir:
rec:
visualstrobe:
acq:
ce:
dir:
rec:
# ASL (arterial spin labeling) contrast
cbv:
rest:
Expand Down
2 changes: 1 addition & 1 deletion convert_source/tests/helper.scripts/test.file_structure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#######################################
# Usage function. Prints help and then
# exits.
# exits.
# Globals:
# None
# Arguments:
Expand Down
2 changes: 1 addition & 1 deletion convert_source/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.0a7
0.2.0a8
Loading

0 comments on commit 2edd798

Please sign in to comment.