Skip to content

Commit 41e09f5

Browse files
authored
Merge pull request #314 from UNFmontreal/dev
Update master to 3.2.0
2 parents 56a6c1e + 58f3c72 commit 41e09f5

35 files changed

+828
-160
lines changed

.github/workflows/codespell.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: Codespell
33

44
on:
55
push:
6-
branches: [master]
6+
branches: [master, dev]
77
pull_request:
8-
branches: [master]
8+
branches: [master, dev]
99

1010
permissions:
1111
contents: read

.github/workflows/coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
steps:
1010
- uses: actions/checkout@v1
1111
- name: Set up Python 3.11
12-
uses: actions/setup-python@v1
12+
uses: actions/setup-python@v5
1313
with:
1414
python-version: "3.11"
1515
- name: Install dependencies

.github/workflows/make_binaries.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
# Check-out repository
2020
- uses: actions/checkout@v3
2121
- name: Setup Python
22-
uses: actions/setup-python@v4
22+
uses: actions/setup-python@v5
2323
with:
2424
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
2525
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
@@ -95,4 +95,4 @@ jobs:
9595
files: |
9696
download/artifact/*
9797
env:
98-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v2
1717
- name: Set up Python
18-
uses: actions/setup-python@v1
18+
uses: actions/setup-python@v5
1919
with:
2020
python-version: '3.x'
2121
- name: Install dependencies

.github/workflows/publish_doc.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
push:
77
branches:
88
- master
9+
- dev
910
tags:
1011
- '[0-9]+.[0-9]+.[0-9]+'
1112
release:
@@ -22,7 +23,7 @@ jobs:
2223
fetch-depth: 0
2324

2425
- name: Set up Python
25-
uses: actions/setup-python@v3
26+
uses: actions/setup-python@v5
2627
with:
2728
python-version: "3.11"
2829

@@ -50,6 +51,7 @@ jobs:
5051
dcm2bids -h > docs_helper/help.txt
5152
dcm2bids_helper -h > docs_helper/helper.txt
5253
dcm2bids_scaffold -h > docs_helper/help_scaffold.txt
54+
echo "export VERSION=$(dcm2bids -v | awk '/dcm2bids/ {print $3}')" > docs_helper/version.txt
5355
5456
- name: Set git credentials
5557
run: |
@@ -76,8 +78,9 @@ jobs:
7678
mike deploy -p ${{ github.ref_name }}
7779
7880
- name: Deploy dev version
79-
if: ${{ github.ref == 'refs/heads/master' }}
81+
if: ${{ github.ref == 'refs/heads/dev' }}
8082
run: |
8183
VERSION=$(dcm2bids -v | awk '/dcm2bids/ {print $3}')
82-
echo "Version: $VERSION"
83-
mike deploy -p $VERSION dev -u
84+
echo "Version: ${VERSION}-dev"
85+
mike delete dev
86+
mike deploy -p dev

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@v4
2020
- name: Set up Python ${{ matrix.python-version }}
21-
uses: actions/setup-python@v1
21+
uses: actions/setup-python@v5
2222
with:
2323
python-version: ${{ matrix.python-version }}
2424
- name: Install dependencies

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,4 @@ tests/data/*
139139
docs_helper/help.txt
140140
docs_helper/help_scaffold.txt
141141
docs_helper/helper.txt
142+
docs_helper/version.txt

CHANGELOG.md

Lines changed: 200 additions & 0 deletions
Large diffs are not rendered by default.

Dockerfile

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Conda image for installing FSL tools
2+
FROM continuumio/miniconda3 AS build
3+
4+
# Install FSL tools with conda
5+
COPY environment.yml /tmp/environment.yml
6+
RUN conda env create -f /tmp/environment.yml
7+
8+
# Install and use conda-pack
9+
RUN conda install -c conda-forge conda-pack
10+
RUN conda-pack -n fsl -o /tmp/env.tar && \
11+
mkdir /venv && cd /venv && tar xf /tmp/env.tar && \
12+
rm /tmp/env.tar
13+
RUN /venv/bin/conda-unpack
14+
15+
# Runtime image for executing FSL tools
16+
FROM debian:stable AS runtime
17+
18+
# Copy the conda env from previous stage
19+
COPY --from=build /venv /venv
20+
21+
# Point to conda executables
22+
ENV PATH="/venv/bin:$PATH"
23+
24+
# Set FSL variables
25+
ENV FSLDIR="/venv"
26+
ENV FSLCONFDIR="${FSLDIR}/config"
27+
ENV FSLOUTPUTTYPE="NIFTI"
28+
ENV FSLMULTIFILEQUIT="TRUE"
29+
ENV FSLTCLSH="${FSLDIR}/bin/fsltclsh"
30+
ENV FSLWISH="${FSLDIR}/bin/fslwish"
31+
ENV FSLGECUDAQ="cuda.q"
32+
33+
# Update and install some utils
34+
RUN apt-get -y update && apt-get -y install dc wget npm unzip
35+
36+
# Fetch data
37+
RUN wget -P ${FSLDIR}/data https://git.fmrib.ox.ac.uk/fsl/data_standard/-/raw/master/MNI152_T1_1mm_brain.nii.gz
38+
39+
# Install bids-validator
40+
RUN npm install -g bids-validator
41+
42+
# Install dcm2niix
43+
WORKDIR /
44+
RUN wget https://github.com/rordenlab/dcm2niix/releases/download/v1.0.20240202/dcm2niix_lnx.zip
45+
RUN unzip dcm2niix_lnx.zip
46+
RUN mv dcm2niix /usr/bin/
47+
48+
# Install dcm2bids
49+
50+
WORKDIR /
51+
ADD . /dcm2bids
52+
WORKDIR /dcm2bids
53+
RUN pip install -e .
54+
55+
RUN pip install pydeface
56+
57+
ENTRYPOINT ["dcm2bids"]

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ Please take a look at the [documentation][dcm2bids-doc] to:
4848

4949
* [Learn about bids][bids-spec] with some dataset [examples][bids-examples]
5050
* [Install dcm2bids][dcm2bids-install]
51-
* [Follow the tutorial][dcm2bids-tutorial]
51+
* [Use docker and Apptainer/Singularity][dcm2bids-container]
52+
* [Follow the tutorials][dcm2bids-tutorial]
5253
* [Seek for more advanced usage][dcm2bids-advanced]
5354

5455
## Issues and Questions
@@ -68,6 +69,7 @@ Before posting your question, you may want to first browse through questions tha
6869
[dcm2bids-install]: https://unfmontreal.github.io/Dcm2Bids/latest/get-started/install/
6970
[dcm2bids-tutorial]: https://unfmontreal.github.io/Dcm2Bids/latest/tutorial/first-steps/#tutorial-first-steps
7071
[dcm2bids-advanced]: https://unfmontreal.github.io/Dcm2Bids/latest/advanced/
72+
[dcm2bids-container]: https://unfmontreal.github.io/Dcm2Bids/latest/how-to/container/
7173
[dcm2bids-upgrade]: https://unfmontreal.github.io/Dcm2Bids/dev/upgrade/
7274
[dcm2bids-issues]: https://github.com/UNFmontreal/Dcm2Bids/issues
7375
[dcm2niix-install]: https://github.com/rordenlab/dcm2niix#install

containers/Dockerfile

Lines changed: 0 additions & 26 deletions
This file was deleted.

containers/singularity.def

Lines changed: 0 additions & 2 deletions
This file was deleted.

dcm2bids/acquisition.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import logging
66
from os.path import join as opj
7+
from os import sep
78

89
from dcm2bids.utils.utils import DEFAULT
910
from dcm2bids.version import __version__
@@ -30,6 +31,8 @@ def __init__(
3031
id=None,
3132
src_sidecar=None,
3233
sidecar_changes=None,
34+
bids_uri=None,
35+
do_not_reorder_entities=None,
3336
**kwargs
3437
):
3538
self.logger = logging.getLogger(__name__)
@@ -43,6 +46,8 @@ def __init__(
4346
self.suffix = suffix
4447
self.custom_entities = custom_entities
4548
self.src_sidecar = src_sidecar
49+
self.bids_uri = bids_uri
50+
self.do_not_reorder_entities = do_not_reorder_entities
4651

4752
if sidecar_changes is None:
4853
self.sidecar_changes = {}
@@ -156,8 +161,8 @@ def setExtraDstFile(self, new_entities):
156161
"""
157162
Return:
158163
The destination filename formatted following
159-
the v1.8.0 BIDS entity key table
160-
https://bids-specification.readthedocs.io/en/v1.8.0/99-appendices/04-entity-table.html
164+
the v1.9.0 BIDS entity key table
165+
https://bids-specification.readthedocs.io/en/v1.9.0/99-appendices/04-entity-table.html
161166
"""
162167

163168
if self.custom_entities.strip() == "":
@@ -196,11 +201,14 @@ def setExtraDstFile(self, new_entities):
196201
"compliant. Make sure you know what "
197202
"you are doing.")
198203

199-
if current_name != new_name:
200-
self.logger.warning(
201-
f"""✅ Filename was reordered according to BIDS entity table order:
202-
from: {current_name}
203-
to: {new_name}""")
204+
if not self.do_not_reorder_entities:
205+
if current_name != new_name:
206+
self.logger.warning(
207+
f"""✅ Filename was reordered according to BIDS entity table order:
208+
from: {current_name}
209+
to: {new_name}""")
210+
else:
211+
new_name = current_name
204212

205213
self.extraDstFile = opj(self.participant.directory,
206214
self.datatype,
@@ -210,8 +218,8 @@ def setDstFile(self):
210218
"""
211219
Return:
212220
The destination filename formatted following
213-
the v1.8.0 BIDS entity key table
214-
https://bids-specification.readthedocs.io/en/v1.8.0/99-appendices/04-entity-table.html
221+
the v1.9.0 BIDS entity key table
222+
https://bids-specification.readthedocs.io/en/v1.9.0/99-appendices/04-entity-table.html
215223
"""
216224
current_name = self.participant.prefix + self.build_suffix
217225
new_name = ''
@@ -241,13 +249,15 @@ def setDstFile(self):
241249
"compliant. Make sure you know what "
242250
"you are doing.")
243251

244-
if current_name != new_name:
245-
self.logger.warning(
246-
f"""✅ Filename was reordered according to BIDS entity table order:
247-
from: {current_name}
248-
to: {new_name}""")
252+
self.dstFile = current_name
253+
if not self.do_not_reorder_entities:
254+
if current_name != new_name:
255+
self.logger.warning(
256+
f"""✅ Filename was reordered according to BIDS entity table order:
257+
from: {current_name}
258+
to: {new_name}""")
259+
self.dstFile = new_name
249260

250-
self.dstFile = new_name
251261

252262
def dstSidecarData(self, idList):
253263
"""
@@ -277,10 +287,16 @@ def dstSidecarData(self, idList):
277287
else:
278288
values.append(idList.get(val, val))
279289
if values[-1] != val:
280-
if isinstance(values[-1], list):
281-
values[-1] = ["bids::" + img_dest for img_dest in values[-1]]
290+
if self.bids_uri == DEFAULT.bids_uri:
291+
if isinstance(values[-1], list):
292+
values[-1] = ["bids::" + img_dest for img_dest in values[-1]]
293+
else:
294+
values[-1] = "bids::" + values[-1]
282295
else:
283-
values[-1] = "bids::" + values[-1]
296+
if isinstance(values[-1], list):
297+
values[-1] = [img_dest.replace(self.participant.name + sep, "") for img_dest in values[-1]]
298+
else:
299+
values[-1] = values[-1].replace(self.participant.name + sep, "")
284300

285301
# handle if nested list vs str
286302
flat_value_list = []

dcm2bids/cli/dcm2bids.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,21 @@ def _build_arg_parser():
4747
default=DEFAULT.output_dir,
4848
help="Output BIDS directory. [%(default)s]")
4949

50-
p.add_argument("--auto_extract_entities",
50+
g = p.add_mutually_exclusive_group()
51+
g.add_argument("--auto_extract_entities",
5152
action='store_true',
5253
help="If set, it will automatically try to extract entity"
5354
"information [task, dir, echo] based on the suffix and datatype."
5455
" [%(default)s]")
5556

57+
g.add_argument("--do_not_reorder_entities",
58+
action='store_true',
59+
help="If set, it will not reorder entities according to the relative "
60+
"ordering indicated in the BIDS specification and use the "
61+
"order defined in custom_entities by the user.\n"
62+
"Cannot be used with --auto_extract_entities. "
63+
" [%(default)s]")
64+
5665
p.add_argument("--bids_validate",
5766
action='store_true',
5867
help="If set, once your conversion is done it "
@@ -120,6 +129,7 @@ def main():
120129
logger.info(f"config: {os.path.realpath(args.config)}")
121130
logger.info(f"BIDS directory: {os.path.realpath(args.output_dir)}")
122131
logger.info(f"Auto extract entities: {args.auto_extract_entities}")
132+
logger.info(f"Reorder entities: {not args.do_not_reorder_entities}")
123133
logger.info(f"Validate BIDS: {args.bids_validate}\n")
124134

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

dcm2bids/cli/dcm2bids_helper.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from dcm2bids.utils.utils import DEFAULT
1616
from dcm2bids.utils.tools import dcm2niix_version, check_latest
1717
from dcm2bids.utils.logger import setup_logging
18-
from dcm2bids.utils.args import assert_dirs_empty
1918
from dcm2bids.version import __version__
2019

2120

@@ -59,12 +58,22 @@ def main():
5958
"""Let's go"""
6059
parser = _build_arg_parser()
6160
args = parser.parse_args()
62-
out_dir = Path(args.output_dir)
63-
log_file = (Path(DEFAULT.output_dir)
64-
/ DEFAULT.tmp_dir_name
65-
/ "log"
66-
/ f"helper_{datetime.now().strftime('%Y%m%d-%H%M%S')}.log")
6761

62+
out_dir = Path(args.output_dir)
63+
if args.output_dir != parser.get_default('output_dir'):
64+
out_dir = (Path(args.output_dir)
65+
/ DEFAULT.tmp_dir_name
66+
/ DEFAULT.helper_dir)
67+
68+
log_file = (Path(args.output_dir)
69+
/ DEFAULT.tmp_dir_name
70+
/ "log"
71+
/ f"helper_{datetime.now().strftime('%Y%m%d-%H%M%S')}.log")
72+
else:
73+
log_file = (Path(DEFAULT.output_dir)
74+
/ DEFAULT.tmp_dir_name
75+
/ "log"
76+
/ f"helper_{datetime.now().strftime('%Y%m%d-%H%M%S')}.log")
6877
if args.nest:
6978
if isinstance(args.nest, str):
7079
log_file = Path(
@@ -94,8 +103,6 @@ def main():
94103
check_latest("dcm2bids")
95104
check_latest("dcm2niix")
96105

97-
assert_dirs_empty(parser, args, out_dir)
98-
99106
app = Dcm2niixGen(dicom_dirs=args.dicom_dir, bids_dir=out_dir, helper=True)
100107

101108
rsl = app.run(force=args.overwrite)

0 commit comments

Comments
 (0)