diff --git a/dcm2bids/dcm2bids.py b/dcm2bids/dcm2bids.py index 1b1bab51..ea305c2b 100644 --- a/dcm2bids/dcm2bids.py +++ b/dcm2bids/dcm2bids.py @@ -80,31 +80,17 @@ def dicomDirs(self): @dicomDirs.setter def dicomDirs(self, value): - if isinstance(value, list): - dicom_dirs = value - else: - dicom_dirs = [value] + dicom_dirs = value if isinstance(value, list) else [value] - valid_dirs = [] - for _dir in dicom_dirs: - valid_dirs.append(valid_path(_dir, "folder")) + valid_dirs = [valid_path(_dir, "folder") for _dir in dicom_dirs] self._dicomDirs = valid_dirs def set_logger(self): """ Set a basic logger""" - logDir = os.path.join(self.bidsDir, DEFAULT.tmpDirName, "log") - logFile = os.path.join( - logDir, - "{}_{}.log".format( - self.participant.prefix, datetime.now().isoformat().replace(":", "") - ), - ) - - # os.makedirs(logdir, exist_ok=True) - # python2 compatibility - if not os.path.exists(logDir): - os.makedirs(logDir) + logDir = self.bidsDir / DEFAULT.tmpDirName / "log" + logFile = logDir / f"{self.participant.prefix}_{datetime.now().isoformat().replace(':', '')}.log" + logDir.mkdir(parents=True, exist_ok=True) setup_logging(self.logLevel, logFile) self.logger = logging.getLogger(__name__) @@ -148,29 +134,28 @@ def move(self, acquisition, intendedForList): """Move an acquisition to BIDS format""" for srcFile in glob(acquisition.srcRoot + ".*"): - _, ext = splitext_(srcFile) - dstFile = os.path.join(self.bidsDir, acquisition.dstRoot + ext) + ext = Path(srcFile).suffixes + dstFile = (self.bidsDir / acquisition.dstRoot).with_suffix("".join(ext)) - if not os.path.exists(os.path.dirname(dstFile)): - os.makedirs(os.path.dirname(dstFile)) + dstFile.parent.mkdir(parents = True, exist_ok = True) # checking if destination file exists - if os.path.isfile(dstFile): + if dstFile.exists(): self.logger.info("'%s' already exists", dstFile) if self.clobber: - self.logger.info("Overwriting because of 'clobber' option") + self.logger.info("Overwriting because of --clobber option") else: - self.logger.info("Use clobber option to overwrite") + self.logger.info("Use --clobber option to overwrite") continue # it's an anat nifti file and the user using a deface script if ( self.config.get("defaceTpl") - and acquisition.dataType == "anat" + and acquisition.dataType == "func" and ".nii" in ext - ): + ): try: os.remove(dstFile) except FileNotFoundError: @@ -181,9 +166,9 @@ def move(self, acquisition, intendedForList): cmd = [w.replace('dstFile', dstFile) for w in defaceTpl] run_shell_command(cmd) - intendedForList[acquisition.indexSidecar].append(acquisition.dstIntendedFor + ext) + intendedForList[acquisition.indexSidecar].append(acquisition.dstIntendedFor + "".join(ext)) - elif ext == ".json": + elif ".json" in ext: data = acquisition.dstSidecarData(self.config["descriptions"], intendedForList) save_json(dstFile, data) @@ -214,7 +199,7 @@ def _build_arg_parser(): p.add_argument("-s", "--session", required=False, - default=DEFAULT.cliSession, + default="", help="Session ID.") p.add_argument("-c", "--config", @@ -225,8 +210,8 @@ def _build_arg_parser(): p.add_argument("-o", "--output_dir", required=False, type=Path, - default=DEFAULT.cliOutputDir, - help="Output BIDS directory, [%(default)s]") + default=Path.cwd(), + help="Output BIDS directory. (Default: %(default)s)") p.add_argument("--forceDcm2niix", action="store_true", diff --git a/dcm2bids/dcm2niix.py b/dcm2bids/dcm2niix.py index b59265b9..60ac51ae 100644 --- a/dcm2bids/dcm2niix.py +++ b/dcm2bids/dcm2niix.py @@ -4,6 +4,7 @@ import logging import os +from pathlib import Path import shlex import shutil from glob import glob @@ -41,11 +42,9 @@ def outputDir(self): Returns: A directory to save all the output files of dcm2niix """ - if self.participant: - tmpDir = self.participant.prefix - else: - tmpDir = DEFAULT.helperDir - return os.path.join(self.bidsDir, DEFAULT.tmpDirName, tmpDir) + tmpDir = self.participant.prefix if self.participant else DEFAULT.helperDir + + return self.bidsDir / DEFAULT.tmpDirName / tmpDir def run(self, force=False): """ Run dcm2niix if necessary diff --git a/dcm2bids/helper.py b/dcm2bids/helper.py index df806e40..bcb77ffd 100644 --- a/dcm2bids/helper.py +++ b/dcm2bids/helper.py @@ -21,10 +21,10 @@ def _build_arg_parser(): help="DICOM files directory.") p.add_argument("-o", "--output_dir", - required=False, default=DEFAULT.cliOutputDir, + required=False, default=Path.cwd(), type=Path, - help="Output BIDS directory." - " (Default: %(default)s)") + help="Output BIDS directory. " + "(Default: %(default)s)") p.add_argument('--force', dest='overwrite', action='store_true', @@ -37,12 +37,11 @@ def main(): """Let's go""" parser = _build_arg_parser() args = parser.parse_args() - out_folder = os.path.join(args.output_dir, 'tmp_dcm2bids', 'helper') + out_folder = args.output_dir / DEFAULT.tmpDirName / DEFAULT.helperDir assert_dirs_empty(parser, args, out_folder) app = Dcm2niix(dicomDirs=args.dicom_dir, bidsDir=args.output_dir) rsl = app.run() - print("Example in:") - print(os.path.join(args.output_dir, DEFAULT.tmpDirName, DEFAULT.helperDir)) + print(f"Example in: {out_folder}") return rsl diff --git a/dcm2bids/structure.py b/dcm2bids/structure.py index 72156820..97b08aa4 100644 --- a/dcm2bids/structure.py +++ b/dcm2bids/structure.py @@ -251,12 +251,12 @@ def setDstFile(self): self.logger.warning("Entity \"{}\"".format(list(current_dict.keys())) + " is not a valid BIDS entity.") - new_name += f"_{'_'.join(suffix_list)}" # Allow multiple single key (without value) + new_name += f"_{'_'.join(suffix_list)}" # Allow multiple single keys (without value) if len(suffix_list) != 1: self.logger.warning("There was more than one suffix found " - f"({suffix_list}). this is not BIDS " - "compliant. Make sure you know what" + f"({suffix_list}). This is not BIDS " + "compliant. Make sure you know what " "you are doing.") if current_name != new_name: diff --git a/dcm2bids/utils.py b/dcm2bids/utils.py index 75b54188..d487157f 100644 --- a/dcm2bids/utils.py +++ b/dcm2bids/utils.py @@ -17,14 +17,12 @@ class DEFAULT(object): """ Default values of the package""" # cli dcm2bids - cliSession = "" - cliOutputDir = os.getcwd() cliLogLevel = "INFO" EPILOG="Documentation at https://github.com/unfmontreal/Dcm2Bids" # dcm2bids.py - outputDir = cliOutputDir - session = cliSession # also Participant object + outputDir = Path.cwd() + session = "" # also Participant object clobber = False forceDcm2niix = False defaceTpl = None @@ -67,7 +65,7 @@ def load_json(filename): def save_json(filename, data): - with open(filename, "w") as f: + with filename.open("w") as f: json.dump(data, f, indent=4) @@ -133,14 +131,14 @@ def valid_path(in_path, type="folder"): if isinstance(in_path, str): in_path = Path(in_path) - if type=='folder': + if type == 'folder': if in_path.is_dir() or in_path.parent.is_dir(): - return str(in_path) + return in_path else: raise NotADirectoryError(in_path) - elif type=="file": + elif type == "file": if in_path.is_file(): - return str(in_path) + return in_path else: raise FileNotFoundError(in_path) @@ -163,25 +161,30 @@ def assert_dirs_empty(parser, args, required): If true, create the directory if it does not exist. """ def check(path): - if os.path.isdir(path): - if not args.overwrite: - parser.error( - f"Output directory {path} isn't empty, so some files " - "could be overwritten or deleted.\nRerun the command with " - "--force option to overwrite existing output files.") - else: - for the_file in os.listdir(path): - file_path = os.path.join(path, the_file) - try: - if os.path.isfile(file_path): - os.unlink(file_path) - elif os.path.isdir(file_path): - shutil.rmtree(file_path) - except Exception as e: - print(e) - - if isinstance(required, str): - required = [required] + if not path.is_dir(): + return + + if not any(path.iterdir()): + return + + if not args.overwrite: + parser.error( + f"Output directory {path} isn't empty, so some files " + "could be overwritten or deleted.\nRerun the command with " + "--force option to overwrite existing output files.") + else: + for the_file in path.iterdir(): + file_path = path / the_file + try: + if file_path.is_file(): + file_path.unlink() + elif file_path.is_dir(): + shutil.rmtree(file_path) + except Exception as e: + print(e) + + if isinstance(required, str) or isinstance(required, Path): + required = [Path(required)] for cur_dir in required: check(cur_dir)