Skip to content

FIX: Read .PAR files corresponding to ADC maps #685

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

Merged
merged 3 commits into from
Oct 24, 2018
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: 7 additions & 1 deletion nibabel/parrec.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,13 @@ def get_bvals_bvecs(self):
if self.general_info['diffusion'] == 0:
return None, None
reorder = self.get_sorted_slice_indices()
n_slices, n_vols = self.get_data_shape()[-2:]
if len(self.get_data_shape()) == 3:
# Any original diffusion scans will have >=2 volumes. However, a
# single dynamic is possible for a post-processed diffusion volume
# such as an ADC map. The b-values are unavailable in this case.
return None, None
else:
n_slices, n_vols = self.get_data_shape()[-2:]
bvals = self.image_defs['diffusion_b_factor'][reorder].reshape(
(n_slices, n_vols), order='F')
# All bvals within volume should be the same
Expand Down
124 changes: 124 additions & 0 deletions nibabel/tests/data/ADC_Map.PAR
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# === DATA DESCRIPTION FILE ======================================================
#
# CAUTION - Investigational device.
# Limited by Federal Law to investigational use.
#
# Dataset name: e:\dicom\\ADC_Map
#
# CLINICAL TRYOUT Research image export tool V4.2
#
# === GENERAL INFORMATION ========================================================
#
. Patient name : ADC_Map
. Examination name : ADC_Map
. Protocol name : ADC_Map
. Examination date/time : 2018.01.01 / 01:01:01
. Series Type : Image MRSeries
. Acquisition nr : 8
. Reconstruction nr : 3
. Scan Duration [sec] : 276
. Max. number of cardiac phases : 1
. Max. number of echoes : 1
. Max. number of slices/locations : 22
. Max. number of dynamics : 1
. Max. number of mixes : 1
. Patient position : Feet First Supine
. Preparation direction : Anterior-Posterior
. Technique : DwiSE
. Scan resolution (x, y) : 132 134
. Scan mode : MS
. Repetition time [ms] : 4600.000
. FOV (ap,fh,rl) [mm] : 80.000 78.500 80.000
. Water Fat shift [pixels] : 63.247
. Angulation midslice(ap,fh,rl)[degr]: 0.109 -18.122 13.705
. Off Centre midslice(ap,fh,rl) [mm] : 25.981 -8.163 16.342
. Flow compensation <0=no 1=yes> ? : 0
. Presaturation <0=no 1=yes> ? : 0
. Phase encoding velocity [cm/sec] : 0.000000 0.000000 0.000000
. MTC <0=no 1=yes> ? : 0
. SPIR <0=no 1=yes> ? : 1
. EPI factor <0,1=no EPI> : 151
. Dynamic scan <0=no 1=yes> ? : 0
. Diffusion <0=no 1=yes> ? : 1
. Diffusion echo time [ms] : 0.0000
. Max. number of diffusion values : 3
. Max. number of gradient orients : 4
. Number of label types <0=no ASL> : 0
#
# === PIXEL VALUES =============================================================
# PV = pixel value in REC file, FP = floating point value, DV = displayed value on console
# RS = rescale slope, RI = rescale intercept, SS = scale slope
# DV = PV * RS + RI FP = DV / (RS * SS)
#
# === IMAGE INFORMATION DEFINITION =============================================
# The rest of this file contains ONE line per image, this line contains the following information:
#
# slice number (integer)
# echo number (integer)
# dynamic scan number (integer)
# cardiac phase number (integer)
# image_type_mr (integer)
# scanning sequence (integer)
# index in REC file (in images) (integer)
# image pixel size (in bits) (integer)
# scan percentage (integer)
# recon resolution (x y) (2*integer)
# rescale intercept (float)
# rescale slope (float)
# scale slope (float)
# window center (integer)
# window width (integer)
# image angulation (ap,fh,rl in degrees ) (3*float)
# image offcentre (ap,fh,rl in mm ) (3*float)
# slice thickness (in mm ) (float)
# slice gap (in mm ) (float)
# image_display_orientation (integer)
# slice orientation ( TRA/SAG/COR ) (integer)
# fmri_status_indication (integer)
# image_type_ed_es (end diast/end syst) (integer)
# pixel spacing (x,y) (in mm) (2*float)
# echo_time (float)
# dyn_scan_begin_time (float)
# trigger_time (float)
# diffusion_b_factor (float)
# number of averages (integer)
# image_flip_angle (in degrees) (float)
# cardiac frequency (bpm) (integer)
# minimum RR-interval (in ms) (integer)
# maximum RR-interval (in ms) (integer)
# TURBO factor <0=no turbo> (integer)
# Inversion delay (in ms) (float)
# diffusion b value number (imagekey!) (integer)
# gradient orientation number (imagekey!) (integer)
# contrast type (string)
# diffusion anisotropy type (string)
# diffusion (ap, fh, rl) (3*float)
# label type (ASL) (imagekey!) (integer)
#
# === IMAGE INFORMATION ==========================================================
# sl ec dyn ph ty idx pix scan% rec size (re)scale window angulation offcentre thick gap info spacing echo dtime ttime diff avg flip freq RR-int turbo delay b grad cont anis diffusion L.ty

1 1 1 1 11 5 0 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 34.69 -43.87 16.27 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
2 1 1 1 11 5 1 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 33.86 -40.47 16.28 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
3 1 1 1 11 5 2 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 33.03 -37.07 16.29 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
4 1 1 1 11 5 3 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 32.20 -33.67 16.29 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
5 1 1 1 11 5 4 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 31.37 -30.27 16.30 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
6 1 1 1 11 5 5 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 30.54 -26.86 16.31 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
7 1 1 1 11 5 6 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 29.71 -23.46 16.31 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
8 1 1 1 11 5 7 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 28.88 -20.06 16.32 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
9 1 1 1 11 5 8 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 28.05 -16.66 16.33 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
10 1 1 1 11 5 9 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 27.22 -13.26 16.33 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
11 1 1 1 11 5 10 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 26.40 -9.86 16.34 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
12 1 1 1 11 5 11 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 25.57 -6.46 16.35 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
13 1 1 1 11 5 12 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 24.74 -3.06 16.35 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
14 1 1 1 11 5 13 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 23.91 0.34 16.36 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
15 1 1 1 11 5 14 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 23.08 3.74 16.37 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
16 1 1 1 11 5 15 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 22.25 7.14 16.37 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
17 1 1 1 11 5 16 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 21.42 10.54 16.38 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
18 1 1 1 11 5 17 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 20.59 13.94 16.39 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
19 1 1 1 11 5 18 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 19.76 17.34 16.39 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
20 1 1 1 11 5 19 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 18.93 20.74 16.40 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
21 1 1 1 11 5 20 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 18.10 24.14 16.41 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1
22 1 1 1 11 5 21 16 101 144 144 0.00000 0.00067 1.46578e-001 1 1 0.11 -18.12 13.70 17.27 27.54 16.41 5.000 -1.500 0 1 0 2 0.556 0.556 134.09 0.00 0.00 0.00 1 90.00 0 0 0 151 0.0 1 4 0 0 0.000 0.000 0.000 1

# === END OF DATA DESCRIPTION FILE ===============================================
23 changes: 22 additions & 1 deletion nibabel/tests/test_parrec.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
# Fake truncated
TRUNC_PAR = pjoin(DATA_PATH, 'phantom_truncated.PAR')
TRUNC_REC = pjoin(DATA_PATH, 'phantom_truncated.REC')
# Post-processed diffusion: ADC Map
ADC_PAR = pjoin(DATA_PATH, 'ADC_Map.PAR')
# Fake V4
V4_PAR = pjoin(DATA_PATH, 'phantom_fake_v4.PAR')
# Fake V4.1
Expand Down Expand Up @@ -530,7 +532,7 @@ def test_diffusion_parameters_v4():
def test_null_diffusion_params():
# Test non-diffusion PARs return None for diffusion params
for par, fobj in gen_par_fobj():
if basename(par) in ('DTI.PAR', 'DTIv40.PAR', 'NA.PAR'):
if basename(par) in ('DTI.PAR', 'DTIv40.PAR', 'NA.PAR', 'ADC_Map.PAR'):
continue
gen_info, slice_info = parse_PAR_header(fobj)
with suppress_warnings():
Expand Down Expand Up @@ -833,6 +835,25 @@ def test_dualTR():
assert_equal(dualTR_hdr.get_zooms()[3], expected_TRs[0]/1000)


def test_ADC_map():
# test reading an apparent diffusion coefficient map
with open(ADC_PAR, 'rt') as fobj:

# two truncation warnings expected because general_info indicates:
# 1.) multiple directions
# 2.) multiple b-values
# but neither of these exist in the post-processed ADC volume.
with clear_and_catch_warnings(modules=[parrec], record=True) as wlist:
adc_hdr = PARRECHeader.from_fileobj(fobj, permit_truncated=True)
assert_equal(len(wlist), 2)

# general_info indicates it is a diffusion scan, but because it is
# a post-processed image, the bvals and bvecs aren't available
bvals, bvecs = adc_hdr.get_bvals_bvecs()
assert_equal(bvals, None)
assert_equal(bvecs, None)


def test_alternative_header_field_names():
# some V4.2 files had variant spellings for some of the fields in the
# header. This test reads one such file and verifies that the fields with
Expand Down