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

[ENH] Refactorisation - Major API upgrade #200

Merged
merged 14 commits into from
Jun 8, 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
8 changes: 4 additions & 4 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ jobs:

steps:
- uses: actions/checkout@v1
- name: Set up Python 3.7
- name: Set up Python 3.10.11
uses: actions/setup-python@v1
with:
python-version: 3.7
python-version: 3.10.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-test.txt
pip install .
- name: Run coverage
run: pytest --cov --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v1
- name: Upload coverage
uses: codecov/codecov-action@v3
if: always()
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_doc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.10.4"
python-version: "3.10.11"
- name: Upgrade pip
run: |
# install pip=>20.1 to use "pip cache dir"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- ubuntu-latest # ubuntu-18.04
- macos-latest # macOS-10.14
- windows-latest # windows-2019
python-version: [3.7, 3.8, 3.9]
python-version: [3.8, 3.9, 3.10.11]

steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Your friendly DICOM converter.


[![PyPI version badge](https://img.shields.io/pypi/v/dcm2bids?logo=pypi&logoColor=white)](https://pypi.org/project/dcm2bids)
[![PyPI - Downloads](https://static.pepy.tech/badge/dcm2bids)](https://pypi.org/project/dcm2bids)

[![Anaconda-Server Badge](https://img.shields.io/conda/vn/conda-forge/dcm2bids?logo=anaconda&logoColor=white)](https://anaconda.org/conda-forge/dcm2bids)
[![Docker container badge](https://img.shields.io/docker/v/unfmontreal/dcm2bids?label=docker&logo=docker&logoColor=white)](https://hub.docker.com/r/unfmontreal/dcm2bids)

Expand Down
15 changes: 0 additions & 15 deletions dcm2bids/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-

"""
dcm2bids
--------

Reorganising NIfTI files from dcm2niix into the Brain Imaging Data Structure
"""


from .dcm2bids import Dcm2bids
from .scaffold import scaffold
from .version import __version__

__all__ = ["__version__", "Dcm2bids", "scaffold"]
93 changes: 3 additions & 90 deletions dcm2bids/structure.py → dcm2bids/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,9 @@

import logging
from os.path import join as opj
from future.utils import iteritems
from .utils import DEFAULT
from .version import __version__


class Participant(object):
""" Class representing a participant

Args:
name (str): Label of your participant
session (str): Optional label of a session
"""

def __init__(self, name, session=DEFAULT.session):
self._name = ""
self._session = ""

self.name = name
self.session = session

@property
def name(self):
"""
Returns:
A string 'sub-<subject_label>'
"""
return self._name

@name.setter
def name(self, name):
""" Prepend 'sub-' if necessary"""
if name.startswith("sub-"):
self._name = name

else:
self._name = "sub-" + name

@property
def session(self):
"""
Returns:
A string 'ses-<session_label>'
"""
return self._session

@session.setter
def session(self, session):
""" Prepend 'ses-' if necessary"""
if session.strip() == "":
self._session = ""

elif session.startswith("ses-"):
self._session = session

else:
self._session = "ses-" + session

@property
def directory(self):
""" The directory of the participant

Returns:
A path 'sub-<subject_label>' or
'sub-<subject_label>/ses-<session_label>'
"""
if self.hasSession():
return opj(self.name, self.session)
else:
return self.name

@property
def prefix(self):
""" The prefix to build filenames

Returns:
A string 'sub-<subject_label>' or
'sub-<subject_label>_ses-<session_label>'
"""
if self.hasSession():
return self.name + "_" + self.session
else:
return self.name

def hasSession(self):
""" Check if a session is set

Returns:
Boolean
"""
return self.session.strip() != DEFAULT.session
from dcm2bids.utils.utils import DEFAULT
from dcm2bids.version import __version__


class Acquisition(object):
Expand Down Expand Up @@ -313,7 +226,7 @@ def dstSidecarData(self, descriptions, intendedForList):
data["IntendedFor"] = intendedValue

# sidecarChanges
for key, value in iteritems(self.sidecarChanges):
for key, value in self.sidecarChanges.items():
data[key] = value

return data
Expand Down
Empty file added dcm2bids/cli/__init__.py
Empty file.
76 changes: 76 additions & 0 deletions dcm2bids/cli/dcm2bids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Reorganising NIfTI files from dcm2niix into the Brain Imaging Data Structure
"""

import argparse

from dcm2bids.dcm2bids_gen import Dcm2BidsGen
from dcm2bids.utils.tools import check_latest
from dcm2bids.utils.utils import DEFAULT
from dcm2bids.version import __version__

def _build_arg_parser():
p = argparse.ArgumentParser(description=__doc__, epilog=DEFAULT.doc,
formatter_class=argparse.RawTextHelpFormatter)

p.add_argument("-d", "--dicom_dir",
required=True, nargs="+",
help="DICOM directory(ies).")

p.add_argument("-p", "--participant",
required=True,
help="Participant ID.")

p.add_argument("-s", "--session",
required=False,
default=DEFAULT.cliSession,
help="Session ID. [%(default)s]")

p.add_argument("-c", "--config",
required=True,
help="JSON configuration file (see example/config.json).")

p.add_argument("-o", "--output_dir",
required=False,
default=DEFAULT.cliOutputDir,
help="Output BIDS directory. [%(default)s]")

p.add_argument("--forceDcm2niix",
action="store_true",
help="Overwrite previous temporary dcm2niix "
"output if it exists.")

p.add_argument("--clobber",
action="store_true",
help="Overwrite output if it exists.")

p.add_argument("-l", "--log_level",
required=False,
default=DEFAULT.cliLogLevel,
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help="Set logging level. [%(default)s]")

arnaudbore marked this conversation as resolved.
Show resolved Hide resolved
p.add_argument("-v", "--version",
action="version",
version=f"dcm2bids version:\t{__version__}\nBased on BIDS version:\t{DEFAULT.bids_version}",
help="Report dcm2bids version and the BIDS version.")

return p


def main():
parser = _build_arg_parser()
args = parser.parse_args()

check_latest()
check_latest("dcm2niix")

app = Dcm2BidsGen(**vars(args))
return app.run()


if __name__ == "__main__":
main()
31 changes: 16 additions & 15 deletions dcm2bids/helper.py → dcm2bids/cli/dcm2bids_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,25 @@
"""helper module"""

import argparse
import os
from pathlib import Path
import sys
from os.path import join as opj

from dcm2bids.dcm2niix import Dcm2niix
from dcm2bids.utils import DEFAULT, assert_dirs_empty
from dcm2bids.dcm2niix_gen import Dcm2niixGen
from dcm2bids.utils.args import assert_dirs_empty
from dcm2bids.utils.utils import DEFAULT


def _build_arg_parser():
p = argparse.ArgumentParser(description=__doc__, epilog=DEFAULT.EPILOG,
p = argparse.ArgumentParser(description=__doc__, epilog=DEFAULT.doc,
formatter_class=argparse.RawTextHelpFormatter)

p.add_argument("-d", "--dicom_dir",
type=Path,
required=True, nargs="+",
help="DICOM files directory.")

p.add_argument("-o", "--output_dir",
required=False, default=Path.cwd(),
type=Path,
help="Output BIDS directory. "
"(Default: %(default)s)")
required=False, default=DEFAULT.cliOutputDir,
help="Output BIDS directory."
" (Default: %(default)s)")

p.add_argument('--force',
dest='overwrite', action='store_true',
Expand All @@ -37,13 +34,17 @@ def main():
"""Let's go"""
parser = _build_arg_parser()
args = parser.parse_args()
out_folder = args.output_dir / DEFAULT.tmpDirName / DEFAULT.helperDir

out_folder = opj(args.output_dir, 'tmp_dcm2bids', 'helper')
assert_dirs_empty(parser, args, out_folder)
app = Dcm2niix(dicomDirs=args.dicom_dir, bidsDir=args.output_dir)

app = Dcm2niixGen(dicomDirs=args.dicom_dir, bidsDir=args.output_dir)
rsl = app.run()
print(f"Example in: {out_folder}")
print("Example in:")
print(opj(args.output_dir, DEFAULT.tmpDirName, DEFAULT.helperDir))

return rsl


if __name__ == "__main__":
sys.exit(main())
main()
72 changes: 72 additions & 0 deletions dcm2bids/cli/dcm2bids_scaffold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Create basic BIDS files and directories.

Based on the material provided by
https://github.com/bids-standard/bids-starter-kit
"""


import argparse
import datetime
import logging
import os
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
from dcm2bids.utils.scaffold import bids_starter_kit


def _build_arg_parser():
p = argparse.ArgumentParser(description=__doc__, epilog=DEFAULT.doc,
formatter_class=argparse.RawTextHelpFormatter)

p.add_argument("-o", "--output_dir",
required=False,
default=DEFAULT.cliOutputDir,
help="Output BIDS directory. Default: [%(default)s]")

add_overwrite_arg(p)
return p


def main():
parser = _build_arg_parser()
args = parser.parse_args()

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")
# CHANGES
write_txt(opj(args.output_dir, "CHANGES"),
bids_starter_kit.CHANGES.replace('DATE',
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",
DEFAULT.bids_version))

# participants.json
write_txt(opj(args.output_dir, "participants.json"),
bids_starter_kit.participants_json)

# participants.tsv
write_txt(opj(args.output_dir, "participants.tsv"),
bids_starter_kit.participants_tsv)

# README
write_txt(opj(args.output_dir, "README"),
bids_starter_kit.README)


if __name__ == "__main__":
main()
Loading