Skip to content
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

[FIX] Fix GPU Tractography #1069

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4b942e5
[WIP, FIX] fix bug in gpu tractography
36000 Dec 4, 2023
824e0a0
force gpu image creation
36000 Dec 4, 2023
a4a63f0
try this
36000 Dec 8, 2023
6c0e8f8
everything in pyAFQ in RAS
36000 Dec 11, 2023
1c37aa4
tidy this up
36000 Dec 11, 2023
a2fec7d
revert gputractography file; add warning when reorienting
36000 Dec 14, 2023
ac58fd0
change defaults again
36000 Dec 14, 2023
fedc619
try this
36000 Dec 14, 2023
8ccbb0e
bg
36000 Dec 14, 2023
d243084
more BFs
36000 Dec 14, 2023
d09400a
update this print statement
36000 Jan 6, 2024
1366b2b
update default to 12
36000 Jan 6, 2024
2a46fcb
turn this back off
36000 Jan 6, 2024
00d6dd6
add Singularity image
36000 Jan 6, 2024
dbd7b41
sing fixes
36000 Jan 6, 2024
005760a
add branch option to singularity
36000 Jan 6, 2024
970aabb
evolving singularity
36000 Jan 8, 2024
a03fdab
finally get singularity working
36000 Jan 8, 2024
a71d205
update image file to new dwi_affine location
36000 Jan 8, 2024
956bec5
put this back
36000 Jan 8, 2024
503a7a9
rework it so everything uses reoriented dwi
36000 Jan 8, 2024
5d4af9c
update segmentation code to get rid of prepare image nonsense
36000 Jan 8, 2024
c18149e
update as_img
36000 Jan 9, 2024
b125bb6
make sure data is in right order
36000 Jan 16, 2024
2a34b1b
BFs, remove orientation
36000 Jan 16, 2024
03f3f72
BF
36000 Jan 16, 2024
6ae3cdb
i was wrong about this
36000 Jan 17, 2024
9f672cb
Try CSA
36000 Jan 18, 2024
6c8c921
csa fixes
36000 Jan 19, 2024
30e08e1
try this
36000 Jan 19, 2024
14ae28c
bf
36000 Jan 19, 2024
b612310
clean up and clarify
36000 Jan 21, 2024
5e5da19
BFs
36000 Jan 22, 2024
646f335
BF
36000 Jan 22, 2024
c434991
set a seed here
36000 Jan 23, 2024
f9267cb
download templates into image
36000 Jan 23, 2024
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
4 changes: 2 additions & 2 deletions AFQ/api/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,8 @@ def load_next_subject():
this_bundles_file = self.export(
"bundles", collapse=False)[sub][ses]
this_mapping = self.export("mapping", collapse=False)[sub][ses]
this_img = nib.load(self.export(
"dwi", collapse=False)[sub][ses])
this_img = self.export(
"dwi", collapse=False)[sub][ses]
seg_sft = aus.SegmentedSFT.fromfile(
this_bundles_file,
this_img)
Expand Down
3 changes: 1 addition & 2 deletions AFQ/api/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,10 @@ def __init__(self,
self.output_dir = output_dir

self.kwargs = dict(
dwi=dwi_data_file,
dwi_path=dwi_data_file,
bval=bval_file,
bvec=bvec_file,
results_dir=output_dir,
dwi_affine=nib.load(dwi_data_file).affine,
bids_info=bids_info,
base_fname=get_base_fname(output_dir, dwi_data_file),
**kwargs)
Expand Down
42 changes: 26 additions & 16 deletions AFQ/definitions/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def get_name(self):
return name_from_path(self.fname) if self._from_path else self.suffix

def get_image_getter(self, task_name):
def image_getter(dwi, bids_info):
def _image_getter_helper(dwi, bids_info):
# Load data
image_file, image_data_orig, image_affine = \
self.get_path_data_affine(bids_info)
Expand All @@ -167,15 +167,20 @@ def image_getter(dwi, bids_info):
image_data_orig, image_file)

# Resample to DWI data:
dwi_img = nib.load(dwi)
image_data = _resample_image(
image_data,
dwi_img.get_fdata(),
dwi.get_fdata(),
image_affine,
dwi_img.affine)
dwi.affine)
return nib.Nifti1Image(
image_data.astype(np.float32),
dwi_img.affine), meta
dwi.affine), meta
if task_name == "data":
def image_getter(dwi, bids_info):
return _image_getter_helper(dwi, bids_info)
else:
def image_getter(data_imap, bids_info):
return _image_getter_helper(data_imap["dwi"], bids_info)
return image_getter


Expand All @@ -198,11 +203,16 @@ def get_name(self):
return "entire_volume"

def get_image_getter(self, task_name):
def image_getter(dwi):
dwi_img = nib.load(dwi)
def _image_getter_helper(dwi):
return nib.Nifti1Image(
np.ones(dwi_img.get_fdata()[..., 0].shape, dtype=np.float32),
dwi_img.affine), dict(source="Entire Volume")
np.ones(dwi.get_fdata()[..., 0].shape, dtype=np.float32),
dwi.affine), dict(source="Entire Volume")
if task_name == "data":
def image_getter(dwi):
return _image_getter_helper(dwi)
else:
def image_getter(data_imap):
return _image_getter_helper(data_imap["dwi"])
return image_getter


Expand Down Expand Up @@ -266,7 +276,7 @@ def get_name(self):
return "roi"

def get_image_getter(self, task_name):
def _image_getter_helper(dwi_affine, mapping,
def _image_getter_helper(mapping,
data_imap, segmentation_params):
image_data = None
bundle_dict = data_imap["bundle_dict"]
Expand All @@ -280,7 +290,7 @@ def _image_getter_helper(dwi_affine, mapping,
bundle_entry = bundle_dict.transform_rois(
bundle_name,
mapping,
dwi_affine)
data_imap["dwi_affine"])
rois = []
if self.use_endpoints:
rois.extend(
Expand Down Expand Up @@ -316,25 +326,25 @@ def _image_getter_helper(dwi_affine, mapping,
f"an ROI Image: {bundle_dict._dict}"))
return nib.Nifti1Image(
image_data.astype(np.float32),
dwi_affine), dict(source="ROIs")
data_imap["dwi_affine"]), dict(source="ROIs")

if task_name == "data":
raise ValueError((
"RoiImage cannot be used in this context, as they"
"require later derivatives to be calculated"))
elif task_name == "mapping":
def image_getter(
dwi_affine, mapping,
mapping,
data_imap, segmentation_params):
return _image_getter_helper(
dwi_affine, mapping,
mapping,
data_imap, segmentation_params)
else:
def image_getter(
dwi_affine, mapping_imap,
mapping_imap,
data_imap, segmentation_params):
return _image_getter_helper(
dwi_affine, mapping_imap["mapping"],
mapping_imap["mapping"],
data_imap, segmentation_params)
return image_getter

Expand Down
50 changes: 8 additions & 42 deletions AFQ/segmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ def _read_tg(self, tg=None):

return tg

def segment(self, bundle_dict, tg, mapping, fdata=None, fbval=None,
fbvec=None, reg_prealign=None,
reg_template=None, img_affine=None, reset_tg_space=False):
def segment(self, bundle_dict, tg, mapping, img,
reg_prealign=None,
reg_template=None, reset_tg_space=False):
"""
Segment streamlines into bundles based on either waypoint ROIs
[Yeatman2012]_ or RecoBundles [Garyfallidis2017]_.
Expand All @@ -341,17 +341,14 @@ def segment(self, bundle_dict, tg, mapping, fdata=None, fbval=None,
Bundles to segment
mapping : DiffeomorphicMap, or equivalent interface
A mapping between DWI space and a template.
fdata, fbval, fbvec : str
Full path to data, bvals, bvecs
img : Nifti1Image
Image to use as reference.
reg_prealign : array, optional.
The linear transformation to be applied to align input images to
the reference space before warping under the deformation field.
Default: None.
reg_template : str or nib.Nifti1Image, optional.
Template to use for registration. Default: MNI T2.
img_affine : array, optional.
The spatial transformation from the measurement to the scanner
space.
reset_tg_space : bool, optional
Whether to reset the space of the input tractogram after
segmentation is complete. Default: False.
Expand All @@ -371,19 +368,8 @@ def segment(self, bundle_dict, tg, mapping, fdata=None, fbval=None,
bundles using local and global streamline-based registration and
clustering, Neuroimage, 2017.
"""
if img_affine is not None:
if (mapping is None
or fdata is not None
or fbval is not None
or fbvec is not None):

self.logger.error(
"Provide either the full path to data, bvals, bvecs,"
+ "or provide the affine of the image and the mapping")

self.logger.info("Preparing Segmentation Parameters")
self.img_affine = img_affine
self.prepare_img(fdata, fbval, fbvec)
self.img_affine = img.affine
self.img = img
self.logger.info("Preprocessing Streamlines")
tg = self._read_tg(tg)

Expand Down Expand Up @@ -416,24 +402,6 @@ def segment(self, bundle_dict, tg, mapping, fdata=None, fbval=None,

return fiber_groups

def prepare_img(self, fdata, fbval, fbvec):
"""
Prepare image data from DWI data.
Parameters
----------
fdata, fbval, fbvec : str
Full path to data, bvals, bvecs
"""
if self.img_affine is None:
self.img, _, _, _ = \
ut.prepare_data(fdata, fbval, fbvec,
b0_threshold=self.b0_threshold)
self.img_affine = self.img.affine

self.fdata = fdata
self.fbval = fbval
self.fbvec = fbvec

def cross_streamlines(self, fgarray, template=None):
"""
Classify the streamlines by whether they cross the midline.
Expand Down Expand Up @@ -945,9 +913,7 @@ def segment_reco(self, tg=None):
self.presegment_bundle_dict,
self.tg,
self.mapping,
self.fdata,
self.fbval,
self.fbvec,
self.img,
reg_template=self.reg_template,
reg_prealign=self.reg_prealign)
roiseg_fg = roiseg.fiber_groups
Expand Down
33 changes: 21 additions & 12 deletions AFQ/tasks/data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import nibabel as nib
import nibabel.orientations as nio
import numpy as np
import logging

from dipy.io.gradients import read_bvals_bvecs
import dipy.core.gradients as dpg
Expand Down Expand Up @@ -33,16 +35,20 @@
extract_odf, anisotropic_index, anisotropic_power)


logger = logging.getLogger('AFQ')


DIPY_GH = "https://github.com/dipy/dipy/blob/master/dipy/"


@pimms.calc("data", "gtab", "img")
def get_data_gtab(dwi, bval, bvec, min_bval=None,
@pimms.calc("data", "gtab", "dwi", "dwi_affine")
def get_data_gtab(dwi_path, bval, bvec, min_bval=None,
max_bval=None, filter_b=True, b0_threshold=50):
"""
DWI data as an ndarray for selected b values,
A DIPY GradientTable with all the gradient information,
and unaltered DWI data in a Nifti1Image.
and DWI data in a Nifti1Image,
and the affine transformation of the DWI data.

Parameters
----------
Expand All @@ -61,9 +67,10 @@ def get_data_gtab(dwi, bval, bvec, min_bval=None,
The value of b under which
it is considered to be b0. Default: 50.
"""
img = nib.load(dwi)
data = img.get_fdata()
img = nib.load(dwi_path)
bvals, bvecs = read_bvals_bvecs(bval, bvec)

data = img.get_fdata()
if filter_b and (min_bval is not None):
valid_b = np.logical_or(
(bvals >= min_bval), (bvals <= b0_threshold))
Expand All @@ -79,25 +86,27 @@ def get_data_gtab(dwi, bval, bvec, min_bval=None,
gtab = dpg.gradient_table(
bvals, bvecs,
b0_threshold=b0_threshold)
return data, gtab, img
img = nib.Nifti1Image(data, img.affine)
return data, gtab, img, img.affine


@pimms.calc("b0")
@as_file('_desc-b0_dwi.nii.gz')
def b0(dwi, data, gtab, img):
def b0(dwi_path, gtab):
"""
full path to a nifti file containing the mean b0
"""
mean_b0 = np.mean(data[..., gtab.b0s_mask], -1)
mean_b0_img = nib.Nifti1Image(mean_b0, img.affine)
data = nib.load(dwi_path)
mean_b0 = np.mean(data.get_fdata()[..., gtab.b0s_mask], -1)
mean_b0_img = nib.Nifti1Image(mean_b0, data.affine)
meta = dict(b0_threshold=gtab.b0_threshold,
source=dwi)
source=dwi_path)
return mean_b0_img, meta


@pimms.calc("masked_b0")
@as_file('_desc-maskedb0_dwi.nii.gz')
def b0_mask(base_fname, b0, brain_mask):
def b0_mask(b0, brain_mask):
"""
full path to a nifti file containing the
mean b0 after applying the brain mask
Expand Down Expand Up @@ -970,7 +979,7 @@ def get_data_plan(kwargs):
if kwargs["bids_info"] is not None:
bm_def.find_path(
kwargs["bids_info"]["bids_layout"],
kwargs["dwi"],
kwargs["dwi_path"],
kwargs["bids_info"]["subject"],
kwargs["bids_info"]["session"])
data_tasks["brain_mask_res"] = pimms.calc("brain_mask")(
Expand Down
Loading
Loading