Skip to content

Commit 6bd6b24

Browse files
committed
Merge remote-tracking branch 'origin/master' into fix/group
* origin/master: BF: fix logging string + move etelemetry under try/except Add stop_before_pixels to the rest of dicom reads Boost perspective release date in changelog to today doc: closes #401 ENH(TST): Fix version to older pytest to ease backward compatibility testing RF: use tmpdir not tmp_path fixture FIX: minor typo in CHANGELOG.md Version boost to 0.6.0 DOC: populate detailed changelog for 0.6.0 and tune up formatting in previous one Fix miscellaneous typos in ReproIn heuristic file. BF: fix check for the sbatch (SLURM) not being available ENH: make test-compare-two-versions take any two worktrees, and just show diff if results already known Update heudiconv/convert.py apply @mgxd 's suggestions, adding a warning and a timeout environment variable need str typecast Use empty string not None Empty acq_time results in empty cell not 'n/a' Acquire a lock prior to top level bids file modification Conflicts: heudiconv/dicoms.py -- removed both "common base" and "master" conflicting portion of group_dicoms_into_seqinfos, seems to be moved elsewhere and the only change was stopping reading dicom before pixel data, and I think that is already everywhere in this PR anyways
2 parents 5c82c6d + 4c13d68 commit 6bd6b24

16 files changed

+218
-82
lines changed

CHANGELOG.md

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,72 @@ All notable changes to this project will be documented (for humans) in this file
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [0.6.0] - 2019-12-16
8+
9+
This is largely a bug fix. Metadata and order of `_key-value` fields in BIDS
10+
could change from the result of converting using previous versions, thus minor
11+
version boost.
12+
14 people contributed to this release -- thanks
13+
[everyone](https://github.com/nipy/heudiconv/graphs/contributors)!
14+
15+
### Enhancement
16+
17+
- Use [etelemetry](https://pypi.org/project/etelemetry) to inform about most
18+
recent available version of heudiconv. Please set `NO_ET` environment variable
19+
if you want to disable it ([#369][])
20+
- BIDS:
21+
- `--bids` flag became an option. It can (optionally) accept `notop` value
22+
to avoid creation of top level files (`CHANGES`, `dataset_description.json`,
23+
etc) as a workaround during parallel execution to avoid race conditions etc.
24+
([#344][])
25+
- Generate basic `.json` files with descriptions of the fields for
26+
`participants.tsv` and `_scans.tsv` files ([#376][])
27+
- Use `filelock` while writing top level files. Use
28+
`HEUDICONV_FILELOCK_TIMEOUT` environment to change the default timeout value
29+
([#348][])
30+
- `_PDT2` was added as a suffix for multi-echo (really "multi-modal")
31+
sequences ([#345][])
32+
- Calls to `dcm2niix` would include full output path to make it easier to
33+
discern in the logs what file it is working on ([#351][])
34+
- With recent [datalad]() (>= 0.10), created DataLad dataset will use
35+
`--fake-dates` functionality of DataLad to not leak data conversion dates,
36+
which might be close to actual data acquisition/patient visit ([#352][])
37+
- Support multi-echo EPI `_phase` data ([#373][] fixes [#368][])
38+
- Log location of a bad .json file to ease troubleshooting ([#379][])
39+
- Add basic pypi classifiers for the package ([#380][])
40+
41+
### Fixed
42+
- Sorting `_scans.tsv` files lacking valid dates field should not cause a crash
43+
([#337][])
44+
- Multi-echo files detection based number of echos ([#339][])
45+
- BIDS
46+
- Use `EchoTimes` from the associated multi-echo files if `EchoNumber` tag is
47+
missing ([#366][] fixes [#347][])
48+
- Tolerate empty ContentTime and/or ContentDate in DICOMs ([#372][]) and place
49+
"n/a" if value is missing ([#390][])
50+
- Do not crash and store original .json file is "JSON pretification" fails
51+
([#342][])
52+
- ReproIn heuristic
53+
- tolerate WIP prefix on Philips scanners ([#343][])
54+
- allow for use of `(...)` instead of `{...}` since `{}` are not allowed
55+
([#343][])
56+
- Support pipolar fieldmaps by providing them with `_epi` not `_magnitude`.
57+
"Loose" BIDS `_key-value` pairs might come now after `_dir-` even if they
58+
came first before ([#358][] fixes [#357][])
59+
- All heuristics saved under `.heudiconv/` under `heuristic.py` name, to avoid
60+
discrepancy during reconversion ([#354][] fixes [#353][])
61+
- Do not crash (with TypeError) while trying to sort absent file list ([#360][])
62+
- heudiconv requires nipype >= 1.0.0 ([#364][]) and blacklists `1.2.[12]` ([#375][])
63+
764
## [0.5.4] - 2019-04-29
865

966
This release includes fixes to BIDS multi-echo conversions, the
10-
re-implementation of queuing support (currently just SLURM), as well as
11-
some bugfixes.
67+
re-implementation of queuing support (currently just SLURM), as well as
68+
some bugfixes.
1269

13-
Starting today, we will (finally) push versioned releases to DockerHub.
14-
Finally, to more accurately reflect on-going development, the `latest`
15-
tag has been renamed to `unstable`.
70+
Starting today, we will (finally) push versioned releases to DockerHub.
71+
Finally, to more accurately reflect on-going development, the `latest`
72+
tag has been renamed to `unstable`.
1673

1774
### Added
1875
- Readthedocs documentation ([#327][])
@@ -189,8 +246,37 @@ TODO Summary
189246
[DBIC]: http://dbic.dartmouth.edu
190247
[datalad]: http://datalad.org
191248
[dcm2niix]: https://github.com/rordenlab/dcm2niix
192-
[#293]: https://github.com/nipy/heudiconv/issues/293
193249
[#301]: https://github.com/nipy/heudiconv/issues/301
250+
[#353]: https://github.com/nipy/heudiconv/issues/353
251+
[#354]: https://github.com/nipy/heudiconv/issues/354
252+
[#357]: https://github.com/nipy/heudiconv/issues/357
253+
[#358]: https://github.com/nipy/heudiconv/issues/358
254+
[#347]: https://github.com/nipy/heudiconv/issues/347
255+
[#366]: https://github.com/nipy/heudiconv/issues/366
256+
[#368]: https://github.com/nipy/heudiconv/issues/368
257+
[#373]: https://github.com/nipy/heudiconv/issues/373
258+
[#293]: https://github.com/nipy/heudiconv/issues/293
194259
[#304]: https://github.com/nipy/heudiconv/issues/304
195260
[#306]: https://github.com/nipy/heudiconv/issues/306
196261
[#310]: https://github.com/nipy/heudiconv/issues/310
262+
[#327]: https://github.com/nipy/heudiconv/issues/327
263+
[#328]: https://github.com/nipy/heudiconv/issues/328
264+
[#334]: https://github.com/nipy/heudiconv/issues/334
265+
[#337]: https://github.com/nipy/heudiconv/issues/337
266+
[#339]: https://github.com/nipy/heudiconv/issues/339
267+
[#342]: https://github.com/nipy/heudiconv/issues/342
268+
[#343]: https://github.com/nipy/heudiconv/issues/343
269+
[#344]: https://github.com/nipy/heudiconv/issues/344
270+
[#345]: https://github.com/nipy/heudiconv/issues/345
271+
[#348]: https://github.com/nipy/heudiconv/issues/348
272+
[#351]: https://github.com/nipy/heudiconv/issues/351
273+
[#352]: https://github.com/nipy/heudiconv/issues/352
274+
[#360]: https://github.com/nipy/heudiconv/issues/360
275+
[#364]: https://github.com/nipy/heudiconv/issues/364
276+
[#369]: https://github.com/nipy/heudiconv/issues/369
277+
[#372]: https://github.com/nipy/heudiconv/issues/372
278+
[#375]: https://github.com/nipy/heudiconv/issues/375
279+
[#376]: https://github.com/nipy/heudiconv/issues/376
280+
[#379]: https://github.com/nipy/heudiconv/issues/379
281+
[#380]: https://github.com/nipy/heudiconv/issues/380
282+
[#390]: https://github.com/nipy/heudiconv/issues/390

dev-requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-r requirements.txt
2-
pytest
2+
# Fix version to older pytest to ease backward compatibility testing
3+
pytest==3.6.4
34
tinydb
45
inotify

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
# The short X.Y version
2727
version = ''
2828
# The full version, including alpha/beta/rc tags
29-
release = '0.5.4'
29+
release = '0.6.0'
3030

3131

3232
# -- General configuration ---------------------------------------------------

docs/installation.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ If `Docker <https://docs.docker.com/install/>`_ is available on your system, you
2626
can visit `our page on Docker Hub <https://hub.docker.com/r/nipy/heudiconv/tags>`_
2727
to view available releases. To pull the latest release, run::
2828

29-
$ docker pull nipy/heudiconv:0.5.4
29+
$ docker pull nipy/heudiconv:0.6.0
3030

3131

3232
Singularity
@@ -35,4 +35,4 @@ If `Singularity <https://www.sylabs.io/singularity/>`_ is available on your syst
3535
you can use it to pull and convert our Docker images! For example, to pull and
3636
build the latest release, you can run::
3737

38-
$ singularity pull docker://nipy/heudiconv:0.5.4
38+
$ singularity pull docker://nipy/heudiconv:0.6.0

docs/tutorials.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ other users' tutorials covering their experience with ``heudiconv``.
77

88
- `YouTube tutorial <https://www.youtube.com/watch?v=O1kZAuR7E00>`_ by `James Kent <https://github.com/jdkent>`_.
99

10-
- `Walkthrough <http://reproducibility.stanford.edu/bids-tutorial-series-part-2a/>`_ by the `Standard Center for Reproducible Neuroscience <http://reproducibility.stanford.edu/>`_.
10+
- `Walkthrough <http://reproducibility.stanford.edu/bids-tutorial-series-part-2a/>`_ by the `Stanford Center for Reproducible Neuroscience <http://reproducibility.stanford.edu/>`_.
1111

1212
- `U of A Neuroimaging Core <https://neuroimaging-core-docs.readthedocs.io/en/latest/pages/heudiconv.html>`_ by `Dianne Patterson <https://github.com/dkp>`_.
1313

docs/usage.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ The second script processes a DICOM directory with ``heudiconv`` using the built
8282
DCMDIR=${DCMDIRS[${SLURM_ARRAY_TASK_ID}]}
8383
echo Submitted directory: ${DCMDIR}
8484
85-
IMG="/singularity-images/heudiconv-0.5.4-dev.sif"
85+
IMG="/singularity-images/heudiconv-0.6.0-dev.sif"
8686
CMD="singularity run -B ${DCMDIR}:/dicoms:ro -B ${OUTDIR}:/output -e ${IMG} --files /dicoms/ -o /output -f reproin -c dcm2niix -b notop --minmeta -l ."
8787
8888
printf "Command:\n${CMD}\n"
@@ -97,7 +97,7 @@ This script creates the top-level bids files (e.g.,
9797
set -eu
9898

9999
OUTDIR=${1}
100-
IMG="/singularity-images/heudiconv-0.5.4-dev.sif"
100+
IMG="/singularity-images/heudiconv-0.6.0-dev.sif"
101101
CMD="singularity run -B ${OUTDIR}:/output -e ${IMG} --files /output -f reproin --command populate-templates"
102102

103103
printf "Command:\n${CMD}\n"

heudiconv/bids.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ def get_formatted_scans_key_row(dcm_fn):
413413
acq_time = datetime.strptime(td, '%H%M%S%Y%m%d').isoformat()
414414
except (AttributeError, ValueError) as exc:
415415
lgr.warning("Failed to get date/time for the content: %s", str(exc))
416-
acq_time = None
416+
acq_time = ''
417417
# add random string
418418
# But let's make it reproducible by using all UIDs
419419
# (might change across versions?)

heudiconv/cli/run.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,11 @@ def process_args(args):
246246

247247
outdir = op.abspath(args.outdir)
248248

249-
import etelemetry
250249
try:
250+
import etelemetry
251251
latest = etelemetry.get_project("nipy/heudiconv")
252252
except Exception as e:
253-
lgr.warning("Could not check for version updates: ", e)
253+
lgr.warning("Could not check for version updates: %s", str(e))
254254
latest = {"version": 'Unknown'}
255255

256256
lgr.info(INIT_MSG(packname=__packagename__,

heudiconv/convert.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import filelock
12
import os
23
import os.path as op
34
import logging
@@ -32,6 +33,7 @@
3233
compress_dicoms
3334
)
3435

36+
LOCKFILE = 'heudiconv.lock'
3537
lgr = logging.getLogger(__name__)
3638

3739

@@ -211,14 +213,23 @@ def prep_conversion(sid, dicoms, outdir, heuristic, converter, anon_sid,
211213
clear_temp_dicoms(item_dicoms)
212214

213215
if bids_options is not None and 'notop' not in bids_options:
214-
if seqinfo:
215-
keys = list(seqinfo)
216-
add_participant_record(anon_outdir,
217-
anon_sid,
218-
keys[0].patient_age,
219-
keys[0].patient_sex)
220-
populate_bids_templates(anon_outdir,
221-
getattr(heuristic, 'DEFAULT_FIELDS', {}))
216+
lockfile = op.join(anon_outdir, LOCKFILE)
217+
if op.exists(lockfile):
218+
lgr.warning("Existing lockfile found in {0} - waiting for the "
219+
"lock to be released. To set a timeout limit, set "
220+
"the HEUDICONV_FILELOCK_TIMEOUT environmental variable "
221+
"to a value in seconds. If this process hangs, it may "
222+
"require a manual deletion of the {0}.".format(lockfile))
223+
timeout = os.getenv("HEUDICONV_LOCKFILE_TIMEOUT", -1)
224+
with filelock.SoftFileLock(lockfile, timeout=timeout):
225+
if seqinfo:
226+
keys = list(seqinfo)
227+
add_participant_record(anon_outdir,
228+
anon_sid,
229+
keys[0].patient_age,
230+
keys[0].patient_sex)
231+
populate_bids_templates(anon_outdir,
232+
getattr(heuristic, 'DEFAULT_FIELDS', {}))
222233

223234

224235
def convert(items, converter, scaninfo_suffix, custom_callable, with_prov,

0 commit comments

Comments
 (0)