Skip to content

Commit 26ac0a6

Browse files
committed
Merge tag 'v0.4' into debian
A "usable" release! Since v0.3 a number of fixes (permissions settings, handling of datalad support, etc). TODO: We need to establishg a ChangeLog ;) * tag 'v0.4': (221 commits) Time for a new "snapshot release" ENH: it is ok not to test in the tests code that test is skipped if no datalad ENH: skip the test relying on datalad if no datalad is available ENH: make use of set_readonly in the code BF: set_readonly helper to set or reset file to/from readonly mode Fix: #93 (Missing PerformingPhysicianName entry) Sort _scans entries first by date and then by filename BF: open non part 10 compliant DICOMs fix: compatible with mac install add instructions for generating lean bids output Update README.md Update Dockerfile fix: add support for pigz enh: update to latest dcm2niix fix: minmeta added to convert and assertion removed to enable numeric comparison BF: do not try to produce scans files if layout is not fully BIDS yet more of abnoxious globs for validator to skip ENH: allow to use with existing datalad datasets which do not have .heudiconv/ as a submodule BF(TST): adjusted to using ContentTime + removed not needed () around assert statement BF+RF: save_scans_key should get a single item to be applied to all related bids files, use ContentTime not SeriesTime ...
2 parents b014997 + 4ef0396 commit 26ac0a6

31 files changed

+3593
-792
lines changed

.coveragerc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[run]
2+
include = tests/*
3+
bin/*
4+
setup.py

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
*.pyc
2+
.cache/
3+
.coverage
4+
*.egg-info/

.travis.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
language: python
33
python:
44
- 2.7
5-
- 3.3
65
- 3.4
76
- 3.5
7+
- 3.6
88

99
cache:
1010
- apt
@@ -17,17 +17,25 @@ env:
1717

1818
before_install:
1919
# The ultimate one-liner setup for NeuroDebian repository
20-
# which might be needed later for tools
21-
#- bash <(wget -q -O- http://neuro.debian.net/_files/neurodebian-travis.sh)
22-
#- travis_retry sudo apt-get update -qq
23-
# for now even remove requirements.txt since dependencies aren't avail
24-
- echo '' > requirements.txt
20+
- bash <(wget -q -O- http://neuro.debian.net/_files/neurodebian-travis.sh)
21+
- travis_retry sudo apt-get update -qq
22+
- travis_retry sudo apt-get install git-annex-standalone dcm2niix
23+
# Install in our own virtualenv
24+
- python -m pip install --upgrade pip
25+
- pip install --upgrade virtualenv
26+
- virtualenv --python=python venv
27+
- source venv/bin/activate
28+
- python --version # just to check
2529
- pip install -r dev-requirements.txt
26-
- pip install codecov
30+
- pip install datalad
31+
- pip install codecov pytest
2732

33+
install:
34+
- git config --global user.email "[email protected]"
35+
- git config --global user.name "Travis Almighty"
2836

2937
script:
30-
- nosetests -s -v --with-doctest --doctest-tests --with-cov --cover-package . --logging-level=INFO tests
38+
- coverage run `which py.test` -s -v tests heuristics
3139

3240
after_success:
3341
- codecov

Dockerfile

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,36 @@
1+
12
FROM continuumio/miniconda
23

34
MAINTAINER <[email protected]>
45

5-
RUN apt-get update && apt-get upgrade -y && apt-get install -y g++ && apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y
6-
RUN cd /tmp && git clone https://github.com/neurolabusc/dcm2niix.git && cd dcm2niix/console/ && git checkout e262240bb27e8f4c9440d6b1a97dfd98ef0f9939 && g++ -O3 -I. main_console.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp -o dcm2niix -DmyDisableOpenJPEG -DmyDisableJasper && cp dcm2niix /usr/local/bin/
7-
RUN conda install -y -c conda-forge nipype && pip install https://github.com/moloney/dcmstack/archive/c12d27d2c802d75a33ad70110124500a83e851ee.zip && pip install https://github.com/nipy/nipype/archive/dd1ed4f0d5735c69c1743f29875acf09d23a62e0.zip
8-
RUN curl -O https://raw.githubusercontent.com/nipy/heudiconv/master/bin/heudiconv && chmod +x heudiconv && cp heudiconv /usr/local/bin/
9-
RUN curl -O https://raw.githubusercontent.com/nipy/heudiconv/master/heuristics/convertall.py && chmod +x convertall.py
6+
RUN apt-get update && apt-get upgrade -y && \
7+
apt-get install -y g++ pkg-config make && \
8+
apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y
9+
RUN (wget -O- http://neuro.debian.net/lists/jessie.us-nh.full | tee /etc/apt/sources.list.d/neurodebian.sources.list) && \
10+
apt-key adv --recv-keys --keyserver hkp://pool.sks-keyservers.net:80 0xA5D32F012649A5A9 && \
11+
apt-get update -qq && apt-get install -y git-annex-standalone && \
12+
apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y
13+
RUN conda install -y -c conda-forge nipype && \
14+
conda install cmake && \
15+
pip install https://github.com/moloney/dcmstack/archive/c12d27d2c802d75a33ad70110124500a83e851ee.zip && \
16+
pip install datalad && \
17+
conda clean -tipsy && rm -rf ~/.pip/
18+
RUN apt-get update && apt-get upgrade -y && \
19+
apt-get install -y pigz && \
20+
apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && \
21+
cd /tmp && git clone https://github.com/neurolabusc/dcm2niix.git && \
22+
cd dcm2niix && \
23+
git checkout 6ba27b9befcbae925209664bb8acbb00e266114a && \
24+
mkdir build && cd build && cmake -DBATCH_VERSION=ON .. && \
25+
make && make install && \
26+
cd / && rm -rf /tmp/dcm2niix
27+
28+
COPY bin/heudiconv /usr/local/bin/heudiconv
29+
RUN chmod +x /usr/local/bin/heudiconv
30+
RUN mkdir /heuristics
31+
COPY heuristics/convertall.py /heuristics
32+
RUN chmod +x /heuristics/convertall.py
33+
RUN git config --global user.email "[email protected]" && \
34+
git config --global user.name "Docker Almighty"
1035

1136
ENTRYPOINT ["/usr/local/bin/heudiconv"]

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ install:
66
mkdir -p $(DESTDIR)$(PREFIX)/share/heudiconv/heuristics
77
mkdir -p $(DESTDIR)$(PREFIX)/share/doc/heudiconv/examples/heuristics
88
mkdir -p $(DESTDIR)$(PREFIX)/bin
9-
install -t $(DESTDIR)$(PREFIX)/bin bin/heudiconv
10-
install -m 644 -t $(DESTDIR)$(PREFIX)/share/heudiconv/heuristics heuristics/*
11-
install -m 644 -t $(DESTDIR)$(PREFIX)/share/doc/heudiconv/examples/heuristics/ examples/heuristics/*
9+
install bin/heudiconv $(DESTDIR)$(PREFIX)/bin
10+
install -m 644 heuristics/* $(DESTDIR)$(PREFIX)/share/heudiconv/heuristics
1211

1312
uninstall:
1413
rm -f $(DESTDIR)$(PREFIX)/bin/heudiconv

README.md

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ structured directory layouts.
1010
- it's faster than parsesdicomdir or mri_convert if you use dcm2niix option
1111
- it tracks the provenance of the conversion from DICOM to NIfTI in W3C
1212
PROV format
13-
- the cmrr_heuristic example shows a conversion to [BIDS](http://bids.neuroimaging.io)
13+
- the cmrr_heuristic example shows a conversion to [BIDS](http://bids.neuroimaging.io)
1414
layout structure
1515

1616
## Install
@@ -33,18 +33,30 @@ as long as the following dependencies are in your path you can use the script
3333
- nibabel
3434
- dcm2niix
3535

36+
## Tutorial with example conversion to BIDS format using Docker
37+
Please read this tutorial to understand how heudiconv works in practice.
38+
39+
[Slides here](http://nipy.org/workshops/2017-03-boston/lectures/bids-heudiconv/#1)
40+
41+
To generate lean BIDS output, consider using both the `-b` and the `--minmeta` flags
42+
to your heudiconv command. The `-b` flag generates a json file with BIDS keys, while
43+
the `--minmeta` flag restricts the json file to only BIDS keys. Without `--minmeta`,
44+
the json file and the associated Nifti file contains DICOM metadata extracted using
45+
dicomstack.
46+
3647
## How it works (in some more detail)
3748

3849
Call `heudiconv` like this:
3950

40-
heudiconv -d '%s*.tar*' -s xx05 -f ~/myheuristics/convertall.py
51+
heudiconv -d '{subject}*.tar*' -s xx05 -f ~/myheuristics/convertall.py
4152

42-
where `-d '%s*tar*'` is an expression used to find DICOM files (`%s` expands to
43-
a subject ID so that the expression will match any `.tar` files, compressed
44-
or not that start with the subject ID in their name). `-s od05` specifies a
45-
subject ID for the conversion (this could be a list of multiple IDs), and
46-
`-f ~/myheuristics/convertall.py` identifies a heuristic implementation for this
47-
conversion (see below) for details.
53+
where `-d '{subject}*tar*'` is an expression used to find DICOM files
54+
(`{subject}` expands to a subject ID so that the expression will match any
55+
`.tar` files, compressed or not that start with the subject ID in their name).
56+
An additional flag for session (`{session}`) can be included in the expression
57+
as well. `-s od05` specifies a subject ID for the conversion (this could be a
58+
list of multiple IDs), and `-f ~/myheuristics/convertall.py` identifies a
59+
heuristic implementation for this conversion (see below) for details.
4860

4961
This call will locate the DICOMs (in any number of matching tarballs), extract
5062
them to a temporary directory, search for any DICOM series it can find, and
@@ -70,65 +82,82 @@ soon you'll be able to:
7082
## The heuristic file
7183

7284
The heuristic file controls how information about the dicoms is used to convert
73-
to a file system layout (e.g., BIDS). This is a python file that must have the
85+
to a file system layout (e.g., BIDS). This is a python file that must have the
7486
function `infotodict`, which takes a single argument `seqinfo`.
7587

7688
### `seqinfo` and the `s` variable
7789

78-
Each item in `seqinfo` contains the following ordered elements.
90+
`seqinfo` is a list of namedtuple objects, each containing the following fields:
91+
92+
* total_files_till_now
93+
* example_dcm_file
94+
* series_id
95+
* dcm_dir_name
96+
* unspecified2
97+
* unspecified3
98+
* dim1
99+
* dim2
100+
* dim3
101+
* dim4
102+
* TR
103+
* TE
104+
* protocol_name
105+
* is_motion_corrected
106+
* is_derived
107+
* patient_id
108+
* study_description
109+
* referring_physician_name
110+
* series_description
111+
* image_type
79112

80113
```
81-
[total_files_till_now, example_dcm_file, series_number, unspecified, unspecified,
82-
unspecified, dim1, dim2, dim3, dim4, TR, TE, SeriesDescription, MotionCorrectedOrNot]
83-
84114
128 125000-1-1.dcm 1 - -
85115
- 160 160 128 1 0.00315 1.37 AAHScout False
86116
```
87117

88118
### The dictionary returned by `infotodict`
89-
119+
90120
This dictionary contains as keys a 3-tuple `(template, a tuple of output types,
91121
annotation classes)`.
92122

93123
template - how the file should be relative to the base directory
94-
tuple of output types - what format of output should be created - nii.gz, dicom,
124+
tuple of output types - what format of output should be created - nii.gz, dicom,
95125
etc.,.
96126
annotation classes - unused
97127

98128
```
99-
Example: ('func/sub-{subject}_task-face_run-{item:02d}_acq-PA_bold', ('nii.gz',
129+
Example: ('func/sub-{subject}_task-face_run-{item:02d}_acq-PA_bold', ('nii.gz',
100130
'dicom'), None)
101131
```
102132

103133
A few fields are defined by default and can be used in the template:
104134

105-
- item: index within category
106-
- subject: participant id
135+
- item: index within category
136+
- subject: participant id
107137
- seqitem: run number during scanning
108138
- subindex: sub index within group
109-
- session: session info for multi-session studies and when session has been
139+
- session: session info for multi-session studies and when session has been
110140
defined as a parameter for heudiconv
111141

112-
Additional variables may be added and can be returned in the value of the
142+
Additional variables may be added and can be returned in the value of the
113143
dictionary returned from the function.
114144

115-
`info[some_3-tuple] = [12, 14, 16]` would assign dicom sequence groups 12, 14
145+
`info[some_3-tuple] = [12, 14, 16]` would assign dicom sequence groups 12, 14
116146
and 16 to be converted using the template specified in `some_3-tuple`.
117147

118-
if the template contained a non-sanctioned variable, it would have to be
148+
if the template contained a non-sanctioned variable, it would have to be
119149
provided in the values for that key.
120150

121151
```
122-
some_3_tuple = ('func/sub-{subject}_task-face_run-{item:02d}_acq-{acq}_bold', ('nii.gz',
152+
some_3_tuple = ('func/sub-{subject}_task-face_run-{item:02d}_acq-{acq}_bold', ('nii.gz',
123153
'dicom'), None)
124154
```
125155

126-
In the above example `{acq}` is not a standard variable. In this case, values
156+
In the above example `{acq}` is not a standard variable. In this case, values
127157
for this variable needs to be added.
128158

129159
```
130160
info[some_3-tuple] = [{'item': 12, 'acq': 'AP'},
131161
{'item': 14, 'acq': 'AP'},
132162
{'item': 16, 'acq': 'PA'}]
133163
```
134-

0 commit comments

Comments
 (0)