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

Volumes modules #747

Merged
merged 9 commits into from
Oct 16, 2023
Prev Previous commit
Next Next commit
Move image.datasets -> image.volume_space_management
  • Loading branch information
EmmaRenauld committed Oct 5, 2023
commit 3348a8c6ab0c73824f3cc5ad19f609ad1c7df04e
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 4,41 @@
from dipy.core.interpolation import trilinear_interpolate4d, \
nearestneighbor_interpolate
from dipy.io.stateful_tractogram import Origin, Space
from dipy.segment.mask import bounding_box


from scilpy.utils.util import voxel_to_world


class WorldBoundingBox(object):
Copy link
Collaborator

@AlexVCaron AlexVCaron Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to discuss this more. This class is used as a pickle in the scil_crop_volume.py script. Moving it here won't work, it must be a top of module to be picklable (https://docs.python.org/3/library/pickle.html).

And even, it will bug all pickled WorldBoundingBox kept by scilpy user (a pickle is bound to the module in which it was created, which is main up till now). As such, the script parameters --input_bbox won't work with old boxes.

If we intend to deprecate those boxes, we should deprecate this pickle usage instead and rely on another saving method for the bounding box. It is legacy and really the worst way of doing this job.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arnaudbore @frheault @EmmaRenauld I would move this code back to the script, if we all agree. With a todo to change the way it works, remove pickling from the solution.

Copy link
Contributor Author

@EmmaRenauld EmmaRenauld Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

@frheault , I will remove scil_crop_volume from files to give to people at the retreat. Seems more complicated than expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexVCaron Tests were passing, though. Do you have an example of pickle file that we could add to the tests?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not test the input and output pickle, so we don't check this behavior. I'll prepare a little package for here and the retreat.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is some data. You have the pickled bbox, created from the current master.

Loading the box does not work. However, contrary to what I thought, it is still possible to create and load boxes with the bbox class in the module. I still think we should change to another way than pickle, but we'll talk about it at the retreat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I will try to play with this eventually.

"""
Used in scil_crop_volume.
toDo. See if can be merged with class Dataset below
"""
def __init__(self, minimums, maximums, voxel_size):
self.minimums = minimums
self.maximums = maximums
self.voxel_size = voxel_size


def compute_nifti_bounding_box(img):
"""Finds bounding box from data and transforms it in world space for use
on data with different attributes like voxel size.

Used in scil_crop_volume.
toDo. See if can be merged with class Dataset below
"""
data = img.get_fdata(dtype=np.float32, caching='unchanged')
affine = img.affine
voxel_size = img.header.get_zooms()[0:3]

voxel_bb_mins, voxel_bb_maxs = bounding_box(data)

world_bb_mins = voxel_to_world(voxel_bb_mins, affine)
world_bb_maxs = voxel_to_world(voxel_bb_maxs, affine)
wbbox = WorldBoundingBox(world_bb_mins, world_bb_maxs, voxel_size)

return wbbox


class DataVolume(object):
Expand Down
6 changes: 3 additions & 3 deletions scilpy/tracking/propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 33,7 @@ def __init__(self, dataset, step_size, rk_order, space, origin):
"""
Parameters
----------
dataset: scilpy.image.datasets.DataVolume
dataset: scilpy.image.volume_space_management.DataVolume
EmmaRenauld marked this conversation as resolved.
Show resolved Hide resolved
Trackable Dataset object.
step_size: float
The step size for tracking. Important: step size should be in the
Expand Down Expand Up @@ -255,7 255,7 @@ def __init__(self, dataset, step_size, rk_order, dipy_sphere,
"""
Parameters
----------
dataset: scilpy.image.datasets.DataVolume
dataset: scilpy.image.volume_space_management.DataVolume
Trackable Dataset object.
step_size: float
The step size for tracking.
Expand Down Expand Up @@ -321,7 321,7 @@ def __init__(self, dataset, step_size,

Parameters
----------
dataset: scilpy.image.datasets.DataVolume
dataset: scilpy.image.volume_space_management.DataVolume
Trackable Dataset object.
step_size: float
The step size for tracking.
Expand Down
2 changes: 1 addition & 1 deletion scilpy/tracking/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 17,7 @@
from dipy.reconst.shm import sh_to_sf_matrix
from dipy.tracking.streamlinespeed import compress_streamlines

from scilpy.image.datasets import DataVolume
from scilpy.image.volume_space_management import DataVolume
from scilpy.tracking.propagator import AbstractPropagator, PropagationStatus
from scilpy.reconst.utils import find_order_from_nb_coeff
from scilpy.tracking.seed import SeedGenerator
Expand Down
2 changes: 1 addition & 1 deletion scripts/scil_compute_local_tracking_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 59,7 @@
add_verbose_arg,
assert_inputs_exist, assert_outputs_exist,
verify_compression_th)
from scilpy.image.datasets import DataVolume
from scilpy.image.volume_space_management import DataVolume
from scilpy.tracking.propagator import ODFPropagator
from scilpy.tracking.seed import SeedGenerator
from scilpy.tracking.tools import get_theta
Expand Down
27 changes: 1 addition & 26 deletions scripts/scil_crop_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 14,7 @@
import argparse
import pickle

from dipy.segment.mask import crop, bounding_box
from dipy.segment.mask import crop
import nibabel as nib
import numpy as np

Expand All @@ -23,31 23,6 @@
assert_outputs_exist)
from scilpy.utils.util import voxel_to_world, world_to_voxel

# TODO move that elsewhere


class WorldBoundingBox(object):
def __init__(self, minimums, maximums, voxel_size):
self.minimums = minimums
self.maximums = maximums
self.voxel_size = voxel_size


def compute_nifti_bounding_box(img):
"""Finds bounding box from data and transforms it in world space for use
on data with different attributes like voxel size."""
data = img.get_fdata(dtype=np.float32, caching='unchanged')
affine = img.affine
voxel_size = img.header.get_zooms()[0:3]

voxel_bb_mins, voxel_bb_maxs = bounding_box(data)

world_bb_mins = voxel_to_world(voxel_bb_mins, affine)
world_bb_maxs = voxel_to_world(voxel_bb_maxs, affine)
wbbox = WorldBoundingBox(world_bb_mins, world_bb_maxs, voxel_size)

return wbbox


def crop_nifti(img, wbbox):
"""Applies cropping from a world space defined bounding box and fixes the
Expand Down