Skip to content

Commit

Permalink
Merge pull request #685 from grlee77/parrec_adc_fix
Browse files Browse the repository at this point in the history
FIX: Read .PAR files corresponding to ADC maps
  • Loading branch information
effigies committed Oct 24, 2018
2 parents d5494f3 + d6310d5 commit 118d305
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 2 deletions.
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

0 comments on commit 118d305

Please sign in to comment.