From d2ea8bdae3b8c6b50369dc16b047ae771f20bd8a Mon Sep 17 00:00:00 2001 From: Mallory Wittwer Date: Fri, 17 Nov 2023 14:56:26 +0100 Subject: [PATCH] Add vector intensity range selection --- setup.cfg | 3 +-- src/napari_orientationpy/_plotting.py | 7 +---- src/napari_orientationpy/_widget.py | 30 +++++++++++++++++----- src/napari_orientationpy/misorientation.py | 2 +- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/setup.cfg b/setup.cfg index 8e7ce2b..da57018 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = napari-orientationpy -version = 0.0.5 +version = 0.0.6 description = Napari plugin for the Orientationpy project. long_description = file: README.md long_description_content_type = text/markdown @@ -32,7 +32,6 @@ install_requires = magicgui qtpy napari[all]>=0.4.16 - # napari-tools-menu orientationpy seaborn diff --git a/src/napari_orientationpy/_plotting.py b/src/napari_orientationpy/_plotting.py index 92c00af..bcaa8c2 100644 --- a/src/napari_orientationpy/_plotting.py +++ b/src/napari_orientationpy/_plotting.py @@ -22,20 +22,15 @@ def stereo_plot(ax, vector_displacements, direction='Z', sample_size=4000): vect[2] / (1 - vect[0]) ] - # ax.set_facecolor((1.0, 1.0, 1.0)) ax.add_artist( plt.Circle((0, 0), 1, fill=False)) ax.set_xlim(-1.01, 1.01) ax.set_ylim(-1.01, 1.01) - # print(idx) - # print(titles) titles = np.roll(np.array(['Z' ,'Y', 'X']), shift=-idx) ax.set_ylabel(titles[1]) ax.set_xlabel(titles[2]) - # ax.set_axis_off() sns.kdeplot( pd.DataFrame({'X': projection_xy[:, 0], 'Y': projection_xy[:, 1]}), x='X', y='Y', fill=True, ax=ax - ) - # ax.plot(vects_normed[:, 0], vects_normed[:, 1], ".", markersize=5) \ No newline at end of file + ) \ No newline at end of file diff --git a/src/napari_orientationpy/_widget.py b/src/napari_orientationpy/_widget.py index 4b59488..ea1f430 100644 --- a/src/napari_orientationpy/_widget.py +++ b/src/napari_orientationpy/_widget.py @@ -1,5 +1,3 @@ -from typing import TYPE_CHECKING - from napari.utils.notifications import show_info from qtpy.QtWidgets import ( QWidget, @@ -15,11 +13,9 @@ QGroupBox, QFileDialog, ) +from superqt import QLabeledDoubleRangeSlider from qtpy.QtCore import Qt -if TYPE_CHECKING: - import napari - import orientationpy import napari from napari.qt.threading import thread_worker @@ -36,6 +32,7 @@ def rescale_intensity_quantile(image): image_normed = image / np.quantile(image_normed, 0.98) return image_normed +from skimage.exposure import rescale_intensity class OrientationWidget(QWidget): def __init__(self, napari_viewer): @@ -146,6 +143,16 @@ def __init__(self, napari_viewer): self.cb_energy_rescale.setChecked(False) vectors_layout.addWidget(self.cb_energy_rescale, 5, 1) + # Intensity range + self.intensity_range = QLabeledDoubleRangeSlider(Qt.Orientation.Horizontal) + self.intensity_range.setFocusPolicy(Qt.FocusPolicy.NoFocus) + self.intensity_range.setRange(0, 1) + self.intensity_range.setValue((0.0, 1.0)) + self.intensity_range.setEdgeLabelMode(QLabeledDoubleRangeSlider.LabelPosition.NoLabel) + self.intensity_range.setHandleLabelPosition(QLabeledDoubleRangeSlider.LabelPosition.NoLabel) + vectors_layout.addWidget(QLabel("Intensity range", self), 6, 0) + vectors_layout.addWidget(self.intensity_range, 6, 1) + # Compute button self.compute_orientation_btn = QPushButton("Compute orientation", self) self.compute_orientation_btn.clicked.connect(self._trigger_compute_orientation) @@ -216,14 +223,25 @@ def _orientation_vectors(self): slices = [slice(n // 2, None, n) for n in node_spacings] node_origins = np.stack([g[tuple(slices)] for g in np.mgrid[[slice(0, x) for x in self.image.shape]]]) energy_sample = self.energy[tuple(slices)].copy() + image_normalized = rescale_intensity(self.image, out_range=(0, 1)) + image_sample = image_normalized[tuple(slices)].copy() slices.insert(0, slice(0, None)) displacements = self.boxVectorCoords[tuple(slices)].copy() displacements *= np.mean(node_spacings) # displacements *= self.vector_scale_spinbox.value() # Outdated if self.cb_energy_rescale.isChecked(): displacements *= energy_sample + + # Filter based on intensity range + min_intensity, max_intensity = self.intensity_range.value() + intensity_filter = (min_intensity <= image_sample) & (image_sample <= max_intensity) + intensity_filter = intensity_filter.ravel() + displacements = np.reshape(displacements, (self.ndims, -1)).T origins = np.reshape(node_origins, (self.ndims, -1)).T + origins = origins[intensity_filter] + displacements = displacements[intensity_filter] + energy_sample = energy_sample.ravel()[intensity_filter] origins = origins - displacements / 2 displacement_vectors = np.stack((origins, displacements)) displacement_vectors = np.rollaxis(displacement_vectors, 1) @@ -233,7 +251,7 @@ def _orientation_vectors(self): 'edge_width': np.max(node_spacings) / 5.0, 'opacity': 1.0, 'ndim': self.ndims, - 'features': {'length': energy_sample.ravel()}, + 'features': {'length': energy_sample}, 'edge_color': 'length', 'vector_style': 'line', } diff --git a/src/napari_orientationpy/misorientation.py b/src/napari_orientationpy/misorientation.py index 0fa3b0a..4591c6a 100644 --- a/src/napari_orientationpy/misorientation.py +++ b/src/napari_orientationpy/misorientation.py @@ -55,7 +55,7 @@ def disangle(cartesians: np.ndarray, axis: int): disangle_max = np.max( np.stack( - ( + tuple( disangle(cartesians, axis=a) for a in range(n_dims) )