Measureing intensity on vectors and surfaces#
Often, we want to measure the intensity of a signal on a vector or surface. This can be done using the measure_intensity_on_vectors() function. This function takes a vector or surface as input and returns the intensity of the signal on the vector or surface.
from napari_stress import vectors, sample_data, measurements, frame_by_frame
import napari
import numpy as np
import napari_segment_blobs_and_things_with_membranes as nsbatwm
import napari_process_points_and_surfaces as nppas
Segmentation of sample data#
We use napari-segment-blobs-and-things-with-membranes to segment the sample data. By using the frame_by_frame
option, we can segment each frame individually without having to write for-loops.
droplet = sample_data.get_droplet_4d()[0][0]
droplet_rescaled = frame_by_frame(nsbatwm.rescale)(droplet, scale_x=1, scale_y=1, scale_z=2)
droplet_binary = frame_by_frame(nsbatwm.threshold_otsu)(droplet_rescaled)
Create surface#
To create a surface from the rescaled and binarized droplet data, we use napari-process-points-and-surfaces, which provides the marching-cubes algorithm to create a surface from a binary image.
surface = frame_by_frame(nppas.label_to_surface)(droplet_binary, 1)
surface_smooth = frame_by_frame(nppas.smooth_surface)(surface)
viewer = napari.Viewer(ndisplay=3)
viewer.add_image(droplet_rescaled, name="droplet")
viewer.add_surface(surface_smooth, name="droplet")
napari.utils.nbscreenshot(viewer)
Measureing intensity#
We now calculate the surface normals of the surface and use them to measure the intensity of the signal on the surface. To be able to measure intensity in a rregion around the surface, we can pass the length_multiplier
value to the function, which will create a vector with the length of the surface normal multiplied by the length_multiplier
value. The intensity of the signal on the vector is then measured.
Moreover, the center
parameter determines whether the vector is centered on the surface or not. If center
is set to True
, the vector is centered on the surface. If center
is set to False
, the vector can point outwards or inwards, depending on the sign of the length_multiplier
parameter.
normals = vectors.normal_vectors_on_surface(surface_smooth, length_multiplier=5, center=True)
vectors_LDtuple = measurements.intensity._sample_intensity_along_vector(normals, droplet_rescaled)
layer = napari.layers.Layer.create(vectors_LDtuple[0], vectors_LDtuple[1], vectors_LDtuple[2])
vector_layer = viewer.add_layer(layer)
napari.utils.nbscreenshot(viewer)
Projecting vector measurements on surface#
Lastly, we can project the vector measurements on the surface. The measurements are stored in a features
table that is attached to the last added vectors layer:
viewer.layers[-1].features.head()
step_0 | step_1 | step_2 | step_3 | step_4 | intensity_mean | intensity_std | intensity_max | intensity_min | |
---|---|---|---|---|---|---|---|---|---|
0 | 163.143768 | 119.508354 | 70.187156 | 36.135386 | 20.747821 | 81.944497 | 59.131438 | 163.143768 | 20.747821 |
1 | 166.786490 | 124.618316 | 71.018596 | 37.731357 | 23.359034 | 84.702758 | 60.182248 | 166.786490 | 23.359034 |
2 | 175.819763 | 138.049967 | 81.683062 | 39.697817 | 16.711681 | 90.392458 | 66.414832 | 175.819763 | 16.711681 |
3 | 172.347860 | 138.653992 | 80.542078 | 39.854559 | 18.776891 | 90.035076 | 64.855847 | 172.347860 | 18.776891 |
4 | 160.743460 | 118.354990 | 68.113843 | 33.601110 | 19.586847 | 80.080050 | 59.022170 | 160.743460 | 19.586847 |
To colour the surface according to either of these measurements, we can simply do so by the following lines of code:
values_to_visualize = viewer.layers[-1].features['intensity_max'].values
new_surface_tuple = (surface_smooth[0], surface_smooth[1], values_to_visualize)
vector_layer.visible = False
viewer.add_surface(new_surface_tuple, name="droplet", colormap='inferno')
napari.utils.nbscreenshot(viewer)