Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Broken scaffold no more #209

Merged
merged 6 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions dcm2bids/cli/dcm2bids_scaffold.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
import datetime
import logging
import os
import sys
from os.path import join as opj

from dcm2bids.utils.io import write_txt
from dcm2bids.utils.args import add_overwrite_arg, assert_dirs_empty
from dcm2bids.utils.utils import DEFAULT, run_shell_command
from dcm2bids.utils.utils import DEFAULT, run_shell_command, TreePrinter
from dcm2bids.utils.scaffold import bids_starter_kit
from dcm2bids.utils.logger import setup_logging


def _build_arg_parser():
Expand All @@ -38,18 +39,26 @@ def main():
parser = _build_arg_parser()
args = parser.parse_args()

setup_logging("info")
logger = logging.getLogger(__name__)

assert_dirs_empty(parser, args, args.output_dir)

for _ in ["code", "derivatives", "sourcedata"]:
os.makedirs(opj(args.output_dir, _), exist_ok=True)

logging.info("The files used to create your BIDS directory comes from"
"https://github.com/bids-standard/bids-starter-kit")
logger.info("Currently running the following command: \n" +
" ".join(sys.argv) + "\n")
logger.info("The files used to create your BIDS directory were taken from "
"https://github.com/bids-standard/bids-starter-kit. \n")

# CHANGES
write_txt(opj(args.output_dir, "CHANGES"),
bids_starter_kit.CHANGES.replace('DATE',
datetime.date.today().strftime("%Y-%m-%d")))

datetime.date.today().strftime(
"%Y-%m-%d")
)
)
# dataset_description
write_txt(opj(args.output_dir, "dataset_description"),
bids_starter_kit.dataset_description.replace("BIDS_VERSION",
Expand All @@ -63,14 +72,23 @@ def main():
write_txt(opj(args.output_dir, "participants.tsv"),
bids_starter_kit.participants_tsv)

# .bidsignore
write_txt(opj(args.output_dir, ".bidsignore"),
"tmp_dcm2bids")

# README
try:
run_shell_command(['wget', '-q', '-O', opj(args.output_dir, "README"),
'https://github.com/bids-standard/bids-starter-kit/blob/main/templates/README.MD'])
except:
'https://raw.githubusercontent.com/bids-standard/bids-starter-kit/main/templates/README.MD'],
log=False)
except Exception:
write_txt(opj(args.output_dir, "README"),
bids_starter_kit.README)

# output tree representation of where the scaffold was built.

TreePrinter(args.output_dir).print_tree()


if __name__ == "__main__":
main()
7 changes: 1 addition & 6 deletions dcm2bids/utils/io.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
# -*- coding: utf-8 -*-

import inspect
import json
import os
import os.path as opj
from pathlib import Path
from collections import OrderedDict

import dcm2bids


def load_json(filename):
""" Load a JSON file
Expand All @@ -30,7 +25,7 @@ def save_json(filename, data):


def write_txt(filename, lines):
with open(filename, "a+") as f:
with open(filename, "w") as f:
f.write(f"{lines}\n")


Expand Down
67 changes: 64 additions & 3 deletions dcm2bids/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,14 @@ def splitext_(path, extensions=None):
return os.path.splitext(path)


def run_shell_command(commandLine):
def run_shell_command(commandLine, log=True):
""" Wrapper of subprocess.check_output
Returns:
Run command with arguments and return its output
"""
logger = logging.getLogger(__name__)
logger.info("Running %s", commandLine)
if log:
logger = logging.getLogger(__name__)
logger.info("Running: %s", " ".join(commandLine))
return check_output(commandLine)


Expand All @@ -131,3 +132,63 @@ def convert_dir(dir):
str: direction - bids format
"""
return DEFAULT.entity_dir[dir]


class TreePrinter:
"""
Generates and prints a tree representation of a given a directory.
"""

BRANCH = "│"
LAST = "└──"
JUNCTION = "├──"
BRANCH_PREFIX = "│ "
SPACE = " "

def __init__(self, root_dir):
self.root_dir = Path(root_dir)

def print_tree(self):
"""
Prints the tree representation of the root directory and
its subdirectories and files.
"""
tree = self._generate_tree(self.root_dir)
logger = logging.getLogger(__name__)
logger.info(f"Tree representation of {self.root_dir}{os.sep}")
logger.info(f"{self.root_dir}{os.sep}")
for item in tree:
logger.info(item)

def _generate_tree(self, directory, prefix=""):
"""
Generates the tree representation of the <directory> recursively.

Parameters:
- directory: Path
The directory for which a tree representation is needed.
- prefix: str
The prefix to be added to each entry in the tree.

Returns a list of strings representing the tree.
"""
tree = []
entries = sorted(directory.iterdir(), key=lambda path: str(path).lower())
entries = sorted(entries, key=lambda entry: entry.is_file())
entries_count = len(entries)

for index, entry in enumerate(entries):
connector = self.LAST if index == entries_count - 1 else self.JUNCTION
if entry.is_dir():
sub_tree = self._generate_tree(
entry,
prefix=prefix
+ (
self.BRANCH_PREFIX if index != entries_count - 1 else self.SPACE
),
)
tree.append(f"{prefix}{connector} {entry.name}{os.sep}")
tree.extend(sub_tree)
else:
tree.append(f"{prefix}{connector} {entry.name}")
return tree