Summary of what happened:
hi neurostars experts! I am currently trying to process some old diffusion MRI data from our lab. From what I understand, it was originally added into the protocol on a whim, so we only have PEPOLAR spin echoes for previous functional scans. I don’t want to ask too much of your time, but my questions are twofold.
-
I saw this thread suggesting it would be ok to use fieldmaps that are not aligned to the diffusion data, but I was led to believe the fieldmap needed to have the same orientation and shim as the data to be unwarped. Otherwise it would produce errors. I am hoping (if possible) for some assurance that this is not a big deal. Thankfully all scans were phase encoded on the anterior-posterior axis so I think that may be helpful.
-
For various reasons I need to use an in-house processing pipeline rather than qsiprep. But I would like to incorporate sdcflows to obtain an ANTs-compatible unwarp transform, so that all spatial transforms can be applied in a single interpolation. Using the init_topup_wf() from sdcflows is super easy (thank you!) but I am having trouble getting the ITK warp. I used ANTs to estimate the transform between the fieldmap reference (fixed) and the EPI reference (moving) using the fmap-any_registration parameters from qsiprep. Then I tried to use the transform module (B0FieldTransform) from sdcflows to produce the warp, but I receive the following warning:
UserWarning: Image's and B-Spline's grids are not aligned.
[grid_bspline_weights(projected_reference, level) for level in coeffs]
I suspect I’m doing something wrong with passing the affine to sdcflows, but I am wondering if anyone has a workable example for how to do this as the documentation is somewhat unclear. It also seems like there may be other routes to do this, for example the bspline module. So some general guidance would be amazing. Thank you!
Command used (and if a helper script was used, a link to the helper script or the command generated):
# Get fieldmap coefficients and target EPI.
fmapCoeff = os.path.join(testDir, f'{subID}_fmapid-pepolar_desc-coeff_fieldmap.nii.gz')
targetEPI = os.path.join(testDir, f'{subID}_epiref.nii.gz')
# Load in metadata.
with open(os.path.join(testDir, f'{subID}_epiref.json'), 'r') as inFile:
metaData = json.load(inFile)
# Load ANTs affine transform mapping EPI ref --> fmap ref.
xfm = sio.loadmat(os.path.join(testDir, f'{subID}_from-epiref_to-fmap_0GenericAffine.mat'))
disp = xfm['AffineTransform_double_3_3'][9:]
rot = xfm['AffineTransform_double_3_3'][:9]
rot = rot.reshape(3,3)
# Correct for center of rotation.
disp = disp + xfm['fixed'] - rot @ xfm['fixed']
affine = np.eye(4)
affine[:3,:3] = rot
affine[:3,3] = disp.T
# Load in coefficients.
coeffs_nii = nb.load(coeffs = fmapCoeff)
b0xfm = B0FieldTransform(coeffs = coeffs_nii)
# Apply fieldmap to target EPI.
b0xfm.apply(
moving = targetEPI,
ro_time = metaData['TotalReadoutTime'],
pe_dir = metaData['PhaseEncodingDirection'],
xfm_data2fmap = affine,
output_dtype = 'float32'
).to_filename(os.path.join(testDir, f'{subID}_epiref_unwarped.nii.gz'))
# Get ANTs (un)warp image.
unwarp_nii = b0xfm.to_displacements(metaData['TotalReadoutTime'],
metaData['PhaseEncodingDirection'],
itk_format = True
)
unwarp_nii.to_filename(os.path.join(testDir, 'pepolarSDC_unwarp_xfm.nii.gz'))
Version:
sdcflows 2.15.0
Environment (Docker, Singularity / Apptainer, custom installation):
Python 3.12.9