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

[WIP] Add slice interpolation #32

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4ccb5af
add initial interpolation widget
jamesyan-git May 30, 2022
b3a04af
incorporated changes to avoid interp_dim error
jamesyan-git Jun 2, 2022
46dceb1
basic container widget added
jamesyan-git Jun 16, 2022
d11ad4b
rough proof of concept for not asking user for input
jamesyan-git Jun 27, 2022
8f084f2
yapf
jamesyan-git Jun 27, 2022
3fcc3eb
refactored to track paint event for history
jamesyan-git Aug 2, 2022
15cb88d
added support for multiple lable IDs and multiple slices
jamesyan-git Aug 8, 2022
9cf0896
clean up yaml
jamesyan-git Aug 8, 2022
fc48307
Add docstrings
jamesyan-git Sep 26, 2022
e66aff1
add Genevieve tests, removed np.s_ and viewer
jamesyan-git Dec 2, 2022
2ecf462
remove line that reads data into array
jamesyan-git Jan 11, 2023
dd23e51
initial test for widget coverage
jamesyan-git Jan 11, 2023
7665367
add test for store_painted_sices
jamesyan-git Jan 13, 2023
c009b55
tidy up test_store_painted_slice
jamesyan-git Jan 13, 2023
a6dc939
removed unnecessary labels layer
jamesyan-git Jan 13, 2023
4442879
add test for distance_transfrom
jamesyan-git Jan 17, 2023
a7c50ff
added test for interpolate
jamesyan-git Feb 2, 2023
0d66c4e
added dimention combo box
jamesyan-git Feb 13, 2023
d5414cf
refactor interp_dim
jamesyan-git Feb 13, 2023
1dcfc45
test enter_interpolation_mode
jamesyan-git Feb 17, 2023
342b9a9
disable comboboxed when interpolating
jamesyan-git Feb 17, 2023
9f65ce4
check for layers before interpolation
jamesyan-git Feb 17, 2023
7fd2c21
Update gabrielBB action to aganders headless gui
jamesyan-git Apr 18, 2023
f9fc956
use setup-qt-libs
jamesyan-git Apr 18, 2023
5dcd6dd
update test_and_deploy to use latest versions of tests
jamesyan-git Apr 18, 2023
9ece5b0
Merge branch 'main' into slice-interpolation
jamesyan-git Apr 18, 2023
0b03144
fix tox.ini having two passenv on one line
jamesyan-git Apr 18, 2023
345dddc
Merge branch 'slice-interpolation' of github.com:jamesyan-git/zarpain…
jamesyan-git Apr 18, 2023
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
2 changes: 2 additions & 0 deletions src/zarpaint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ._add_3d_points import add_points_3d_with_alt_click
from .reader import zarr_tensorstore
from ._copy_data import copy_data
from ._interpolate_labels import interpolate_between_slices

__all__ = [
'create_labels',
Expand All @@ -19,4 +20,5 @@
'add_points_3d_with_alt_click',
'zarr_tensorstore'
'copy_data',
'interpolate_between_slices',
]
82 changes: 82 additions & 0 deletions src/zarpaint/_interpolate_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from cProfile import label
from magicgui import magic_factory
import numpy as np
from scipy.interpolate import interpn
from scipy.ndimage import distance_transform_edt


def distance_transform(image):
Copy link
Owner

Choose a reason for hiding this comment

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

imho this should be renamed signed_distance_transform

Copy link
Owner

Choose a reason for hiding this comment

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

@jamesyan-git can you rename this function? 😉

"""Distance transform for a boolean image.

Returns positive values inside the object,
and negative values outside.
"""
image = image.astype(bool)
edt = distance_transform_edt(image) - distance_transform_edt(~image)
return edt


def point_and_values(image_1, image_2, interp_dim=0):
edt_1 = distance_transform(image_1)
edt_2 = distance_transform(image_2)
values = np.stack([edt_1, edt_2], axis=interp_dim)
points = tuple([np.arange(i) for i in values.shape])
return points, values


def xi_coords(shape, percent=0.5, interp_dim=0):
slices = [slice(0, i) for i in shape]
xi = np.moveaxis(np.mgrid[slices], 0, -1).reshape(np.prod(shape), len(shape)).astype('float')
xi = np.insert(xi, interp_dim, percent, axis=1)
return xi


def slice_iterator(slice_index_1, slice_index_2):
intermediate_slices = np.arange(slice_index_1 + 1, slice_index_2)
n_slices = slice_index_2 - slice_index_1 + 1 # inclusive
stepsize = 1 / n_slices
intermediate_percentages = np.arange(0 + stepsize, 1, stepsize)
return zip(intermediate_slices, intermediate_percentages)


def interpolated_slice(percent, points, values, interp_dim=0, method='linear'):
# Find the original image shape
img_shape = list(values.shape)
del img_shape[interp_dim]
# Calculate the interpolated slice
xi = xi_coords(img_shape, percent=percent, interp_dim=interp_dim)
interpolated_img = interpn(points, values, xi, method=method)
interpolated_img = np.reshape(interpolated_img, img_shape) > 0
return interpolated_img


## Second draft, writes directly into tensorstore zarr array
@magic_factory(
call_button='Interpolate'
)
def interpolate_between_slices(label_layer: "napari.layers.Labels", slice_index_1: int, slice_index_2: int, label_id: int =1, interp_dim: int =0):
if slice_index_1 > slice_index_2:
slice_index_1, slice_index_2 = slice_index_2, slice_index_1
layer_data = np.asarray(label_layer.data)
Copy link
Contributor

Choose a reason for hiding this comment

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

This line needs to be removed. (I assume it's here because you were debugging something, but we can't have an entire full size volume read into memory).

We should replace the following two lines with:

    slice_1 = np.take(label_layer.data, slice_index_1, axis=interp_dim)
    slice_2 = np.take(label_layer.data, slice_index_2, axis=interp_dim)

slice_1 = np.take(layer_data, slice_index_1, axis=interp_dim)
slice_2 = np.take(layer_data, slice_index_2, axis=interp_dim)
# slice_1 = np.asarray(label_layer.data[slice_index_1])
# slice_2 = np.asarray(label_layer.data[slice_index_2])

#TODO: possible extension, handle all label ids separately
slice_1 = slice_1.astype(bool)
slice_2 = slice_2.astype(bool)
# interp_dim should just be the slider "dimension" right?
points, values = point_and_values(slice_1, slice_2, interp_dim)
#TODO: Thread this?
for slice_number, percentage in slice_iterator(slice_index_1, slice_index_2):
interpolated_img = interpolated_slice(percentage, points, values, interp_dim=interp_dim, method='linear')
indices = [slice(None) for _ in range(label_layer.data.ndim)]
indices[interp_dim] = slice_number
indices = tuple(indices)
label_layer.data[indices][interpolated_img] = label_id
label_layer.refresh() # will update the current view

# interpolate_between_slices(label_layer, image_1, image_2, slice_index_1, slice_index_2)
# print("Done!")
# print("Please scroll through napari to see the interpolated label slices")
1 change: 0 additions & 1 deletion src/zarpaint/_tests/test_watershed.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ def test_watershed_split_2d(make_napari_viewer):
# create 2 squares with one corner overlapping
data[1:10, 1:10] = 1
data[8:17, 8:17] = 1
print(data)

# palce points in the centre of the 2 squares
points = np.asarray([[5, 5], [12, 12]])
Expand Down
5 changes: 5 additions & 0 deletions src/zarpaint/napari.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ contributions:
- id: zarpaint.copy_data
title: Copy Data…
python_name: zarpaint:copy_data
- id: zarpaint.interpolate_labels
title: Interpolate Labels…
python_name: zarpaint:interpolate_between_slices

readers:
- command: zarpaint.get_reader
Expand All @@ -42,3 +45,5 @@ contributions:
display_name: Split With Watershed
- command: zarpaint.copy_data
display_name: Copy Data
- command: zarpaint.interpolate_labels
display_name: Interpolate Labels