Skip to content

Commit d43aa6c

Browse files
committed
Read in TotalReadoutTime from field map metadata, if it exists. Pass TotalReadoutTime to FSL TOPUP if present.
1 parent fa959a4 commit d43aa6c

File tree

5 files changed

+57
-31
lines changed

5 files changed

+57
-31
lines changed

CPAC/distortion_correction/distortion_correction.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,12 @@ def distcor_blip_fsl_topup(wf, cfg, strat_pool, pipe_num, opt=None):
486486
"epi-1-pedir",
487487
"epi-1-TE",
488488
"epi-1-dwell",
489+
"epi-1-total-readout",
489490
"epi-2",
490491
"epi-2-pedir",
491492
"epi-2-TE",
492-
"epi-2-dwell"],
493+
"epi-2-dwell",
494+
"epi-2-total-readout"],
493495
"outputs": ["desc-reginput_bold",
494496
"space-bold_desc-brain_mask",
495497
"blip-warp"]}
@@ -588,7 +590,9 @@ def distcor_blip_fsl_topup(wf, cfg, strat_pool, pipe_num, opt=None):
588590
"phase_one",
589591
"phase_two",
590592
"dwell_time_one",
591-
"dwell_time_two"
593+
"dwell_time_two",
594+
"ro_time_one",
595+
"ro_time_two"
592596
],
593597
output_names=["acq_params"],
594598
function=phase_encode,
@@ -604,12 +608,22 @@ def distcor_blip_fsl_topup(wf, cfg, strat_pool, pipe_num, opt=None):
604608

605609
node, out = strat_pool.get_data('pe-direction')
606610
wf.connect(node, out, phase_encoding, 'unwarp_dir')
607-
608-
node, out = strat_pool.get_data('epi-1-dwell')
609-
wf.connect(node, out, phase_encoding, 'dwell_time_one')
610611

611-
node, out = strat_pool.get_data('epi-2-dwell')
612-
wf.connect(node, out, phase_encoding, 'dwell_time_two')
612+
if strat_pool.check_rpool('epi-1-dwell'):
613+
node, out = strat_pool.get_data('epi-1-dwell')
614+
wf.connect(node, out, phase_encoding, 'dwell_time_one')
615+
616+
if strat_pool.check_rpool('epi-2-dwell'):
617+
node, out = strat_pool.get_data('epi-2-dwell')
618+
wf.connect(node, out, phase_encoding, 'dwell_time_two')
619+
620+
if strat_pool.check_rpool('epi-1-total-readout'):
621+
node, out = strat_pool.get_data('epi-1-total-readout')
622+
wf.connect(node, out, phase_encoding, 'ro_time_one')
623+
624+
if strat_pool.check_rpool('epi-2-total-readout'):
625+
node, out = strat_pool.get_data('epi-2-total-readout')
626+
wf.connect(node, out, phase_encoding, 'ro_time_two')
613627

614628
topup_imports = ["import os",
615629
"import subprocess"]

CPAC/distortion_correction/utils.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,9 @@ def gradient_distortion_correction(wf, inp_image, name):
140140
return (wf, out_warpmask, out_applywarp)
141141

142142

143-
def phase_encode(unwarp_dir, phase_one, phase_two, dwell_time_one,
144-
dwell_time_two):
145-
"""
146-
147-
Calculate readout time and populate parameter file
143+
def phase_encode(unwarp_dir, phase_one, phase_two, dwell_time_one=None,
144+
dwell_time_two=None, ro_time_one=None, ro_time_two=None):
145+
"""Calculate readout time and populate parameter file
148146
149147
Parameters
150148
__________
@@ -159,8 +157,10 @@ def phase_encode(unwarp_dir, phase_one, phase_two, dwell_time_one,
159157
echo spacing of phase one
160158
dwell_time_two
161159
echo spacing of phase two
162-
fsl_dir
163-
FSL directory
160+
ro_time_one
161+
total readout time of phase one
162+
ro_time_two
163+
total readout time of phase two
164164
165165
Returns
166166
_______
@@ -177,22 +177,30 @@ def phase_encode(unwarp_dir, phase_one, phase_two, dwell_time_one,
177177
unwarp_dir = unwarp_dir.decode()
178178

179179
if unwarp_dir in ["x", "x-", "-x","i","-i","i-"]:
180-
dim = nibabel.load(phase_one).shape[0]
181-
n_PE_steps = dim - 1
182-
ro_time_one = np.round(dwell_time_one * n_PE_steps, 6)
183-
ro_time_two = np.round(dwell_time_two * n_PE_steps, 6)
180+
if not ro_time_one or not ro_time_two:
181+
if dwell_time_one and dwell_time_two:
182+
dim = nibabel.load(phase_one).shape[0]
183+
n_PE_steps = dim - 1
184+
ro_time_one = np.round(dwell_time_one * n_PE_steps, 6)
185+
ro_time_two = np.round(dwell_time_two * n_PE_steps, 6)
186+
else:
187+
raise Exception("[!] No dwell time or total readout time "
188+
"present for the acq-fMRI EPI field maps.")
184189
ro_times = [f"-1 0 0 {ro_time_one}", f"1 0 0 {ro_time_two}"]
185190
elif unwarp_dir in ["y", "y-", "-y","j","-j","j-"]:
186-
dim = nibabel.load(phase_one).shape[1]
187-
n_PE_steps = dim - 1
188-
ro_time_one = np.round(dwell_time_one * n_PE_steps, 6)
189-
ro_time_two = np.round(dwell_time_two * n_PE_steps, 6)
191+
if not ro_time_one or not ro_time_two:
192+
if dwell_time_one and dwell_time_two:
193+
dim = nibabel.load(phase_one).shape[1]
194+
n_PE_steps = dim - 1
195+
ro_time_one = np.round(dwell_time_one * n_PE_steps, 6)
196+
ro_time_two = np.round(dwell_time_two * n_PE_steps, 6)
197+
else:
198+
raise Exception("[!] No dwell time or total readout time "
199+
"present for the acq-fMRI EPI field maps.")
190200
ro_times = [f"0 -1 0 {ro_time_one}", f"0 1 0 {ro_time_two}"]
191201
else:
192202
raise Exception(f"unwarp_dir={unwarp_dir} is unsupported.")
193203

194-
195-
196204
# get number of volumes
197205
dims = [
198206
int(subprocess.check_output([f"fslval", phase_one, "dim4"]).decode(sys.stdout.encoding)),

CPAC/utils/bids_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ def collect_bids_files_configs(bids_dir, aws_input_creds=''):
702702
file_paths = []
703703
config_dict = {}
704704

705-
suffixes = ['T1w', 'T2w', 'bold', 'acq-fMRI_epi', 'phasediff', 'magnitude',
705+
suffixes = ['T1w', 'T2w', 'bold', 'epi', 'phasediff', 'magnitude',
706706
'magnitude1', 'magnitude2']
707707

708708
if bids_dir.lower().startswith("s3://"):

CPAC/utils/build_data_config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,11 @@ def get_BIDS_data_dct(bids_base_dir, file_list=None, anat_scan=None,
564564
fmap_pedir_sess = os.path.join(bids_base_dir,
565565
"sub-{participant}/ses-{session}/fmap/"
566566
"sub-{participant}_ses-{session}/"
567-
"dir-*_acq-fMRI_epi.nii.gz")
567+
"*acq-fMR*_epi.nii.gz")
568568

569569
fmap_pedir = os.path.join(bids_base_dir,
570570
"sub-{participant}/fmap/sub-{participant}"
571-
"_dir-*_acq-fMRI_epi.nii.gz")
571+
"*acq-fMR*_epi.nii.gz")
572572

573573
sess_glob = os.path.join(bids_base_dir, "sub-*/ses-*/*")
574574

@@ -582,7 +582,7 @@ def get_BIDS_data_dct(bids_base_dir, file_list=None, anat_scan=None,
582582

583583
fmap_pedir_scan_glob = os.path.join(bids_base_dir,
584584
"sub-*fmap/"
585-
"sub-*_dir-*_acq-fMRI_epi.nii.gz")
585+
"sub-*_*acq-fMR*_epi.nii.gz")
586586

587587
part_tsv_glob = os.path.join(bids_base_dir, "*participants.tsv")
588588

@@ -648,7 +648,7 @@ def get_BIDS_data_dct(bids_base_dir, file_list=None, anat_scan=None,
648648
fmap_mag = os.path.join(bids_base_dir,
649649
"sub-{participant}/fmap/sub-{participant}"
650650
"*magnitud*.nii.gz")
651-
651+
652652
'''
653653
if fnmatch.fnmatch(filepath, fmap_pedir_scan_glob):
654654
# check if there is a scan level for the fmap magnitude files

CPAC/utils/datasource.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,9 @@ def get_fmap_phasediff_metadata(data_config_scan_params):
335335
echo_time = data_config_scan_params.get("EchoTime")
336336
dwell_time = data_config_scan_params.get("DwellTime")
337337
pe_direction = data_config_scan_params.get("PhaseEncodingDirection")
338+
total_readout = data_config_scan_params.get("TotalReadoutTime")
338339

339-
return (echo_time, dwell_time, pe_direction)
340+
return (echo_time, dwell_time, pe_direction, total_readout)
340341

341342

342343
def calc_deltaTE_and_asym_ratio(dwell_time, echo_time_one, echo_time_two,
@@ -445,7 +446,8 @@ def ingress_func_metadata(wf, cfg, rpool, sub_dict, subject_id,
445446
input_names=['data_config_scan_params'],
446447
output_names=['echo_time',
447448
'dwell_time',
448-
'pe_direction'],
449+
'pe_direction',
450+
'total_readout'],
449451
function=get_fmap_phasediff_metadata,
450452
imports=get_fmap_metadata_imports),
451453
name=f'{key}_get_metadata')
@@ -459,6 +461,8 @@ def ingress_func_metadata(wf, cfg, rpool, sub_dict, subject_id,
459461
'dwell_time', {}, "", "fmap_dwell_ingress")
460462
rpool.set_data(f'{key}-pedir', get_fmap_metadata,
461463
'pe_direction', {}, "", "fmap_pedir_ingress")
464+
rpool.set_data(f'{key}-total-readout', get_fmap_metadata,
465+
'total_readout', {}, "", "fmap_readout_ingress")
462466

463467
fmap_TE_list.append(f"{key}-TE")
464468

0 commit comments

Comments
 (0)