-
Notifications
You must be signed in to change notification settings - Fork 13
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
Make feature maps work for all layers #80
base: master
Are you sure you want to change the base?
Changes from 5 commits
e0ae6fe
3979610
d257b54
14d4dd5
64fc49f
9731298
6d63b0d
cee7703
7015d70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,10 +29,17 @@ def __init__(self, layer: "napari.layers.Layer", viewer: "napari.Viewer" = None) | |
|
||
self._view = QTableWidget() | ||
self._view.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) | ||
|
||
if hasattr(layer, "properties"): | ||
self.set_content(layer.properties) | ||
else: | ||
self.set_content({}) | ||
content = layer.properties | ||
elif hasattr(layer, "features"): | ||
content = layer.features.to_dict('list') | ||
|
||
# to accomodate passing features to surfaces through the metadata | ||
elif 'features' in layer.metadata.keys(): | ||
layer.features = layer.metadata['features'] | ||
content = layer.features.to_dict('list') | ||
self.set_content(content) | ||
jo-mueller marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
self._view.clicked.connect(self._clicked_table) | ||
self._view.horizontalHeader().sectionDoubleClicked.connect(self._double_clicked_table) | ||
|
@@ -71,49 +78,15 @@ def _clicked_table(self): | |
self._viewer.dims.current_step = current_step | ||
|
||
def _double_clicked_table(self): | ||
if "label" in self._table.keys(): | ||
selected_column = list(self._table.keys())[self._view.currentColumn()] | ||
print("Selected column", selected_column) | ||
if selected_column is not None: | ||
if isinstance(self._layer, napari.layers.Labels): | ||
from ._parametric_images import visualize_measurement_on_labels, map_measurements_on_labels | ||
new_layer = self._viewer.add_image( map_measurements_on_labels(self._layer, selected_column, self._viewer) , | ||
name=selected_column + " in " + self._layer.name , | ||
affine=self._layer.affine , | ||
scale=self._layer.scale, | ||
rotate=self._layer.rotate | ||
) | ||
new_layer.contrast_limits = [np.min(self._table[selected_column]), np.max(self._table[selected_column])] | ||
new_layer.colormap = "jet" | ||
elif isinstance(self._layer, napari.layers.Points): | ||
features = self._layer.features | ||
new_layer = self._viewer.add_points(self._layer.data, | ||
features=features, | ||
face_color=selected_column, | ||
face_colormap="jet", | ||
size=self._layer.size, | ||
name=selected_column + " in " + self._layer.name, | ||
affine=self._layer.affine, | ||
scale=self._layer.scale, | ||
rotate=self._layer.rotate | ||
) | ||
new_layer.contrast_limits = [np.min(self._table[selected_column]), np.max(self._table[selected_column])] | ||
|
||
if "vertex_index" in self._table.keys(): | ||
selected_column = list(self._table.keys())[self._view.currentColumn()] | ||
print("Selected column (T)", selected_column) | ||
if selected_column is not None and isinstance(self._layer, napari.layers.Surface): | ||
values = np.asarray(self._table[selected_column]) | ||
data = self._layer.data | ||
data = [np.asarray(data[0]).copy(), np.asarray(data[1]).copy(), values] | ||
|
||
new_layer = self._viewer.add_surface(data, | ||
name=selected_column + " in " + self._layer.name) | ||
new_layer.contrast_limits = [np.min(self._table[selected_column]), np.max(self._table[selected_column])] | ||
if "annotation" in selected_column or "CLUSTER_ID" in selected_column: | ||
new_layer.colormap = "hsv" | ||
else: | ||
new_layer.colormap = "jet" | ||
Comment on lines
-74
to
-116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure, you can remove this entire code? It seems that this breaks backwards compatibility. E.g. where is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved the setting of the colormap into the new
The reason for doing it this way is that the color displays for different layers are controlled by different attributes (e.g., |
||
""" | ||
If table header is double clicked, create a feature map from the selected column. | ||
""" | ||
from ._parametric_images import create_feature_map | ||
selected_column = list(self._table.keys())[self._view.currentColumn()] | ||
print('Selected', selected_column) | ||
layer = create_feature_map(self._layer, selected_column) | ||
layer.name = selected_column + " in " + self._layer.name | ||
self._viewer.add_layer(layer) | ||
|
||
def _after_labels_clicked(self): | ||
if "label" in self._table.keys() and hasattr(self._layer, "selected_label"): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import numpy as np | ||
|
||
|
||
def test_label_featuremaps(make_napari_viewer): | ||
from napari_skimage_regionprops import regionprops | ||
from .._parametric_images import create_feature_map | ||
|
||
viewer = make_napari_viewer() | ||
|
||
image = np.asarray([ | ||
[0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 0, 0, 2, 2], | ||
[1, 1, 1, 0, 0, 2, 2], | ||
[1, 1, 1, 0, 0, 2, 2], | ||
[0, 0, 0, 0, 0, 0, 0], | ||
[0, 0, 3, 3, 3, 0, 0], | ||
[0, 0, 3, 3, 3, 0, 4], | ||
]).astype(float) | ||
|
||
image_layer = viewer.add_image(image) | ||
labels_layer = viewer.add_labels(image.astype(int)) | ||
|
||
# analyze a few things | ||
regionprops(image_layer, labels_layer, True, False, False, False, False, False, viewer) | ||
feature_map = create_feature_map(viewer.layers[-1], 'area') | ||
|
||
assert feature_map.data.max() == 9 | ||
|
||
|
||
def test_vector_featuremaps(make_napari_viewer): | ||
from napari_skimage_regionprops import regionprops | ||
from .._parametric_images import create_feature_map | ||
import pandas as pd | ||
|
||
viewer = make_napari_viewer() | ||
|
||
np.random.seed(0) | ||
vectors = np.random.random((10, 2, 3)) | ||
feature1 = np.random.random((10)) | ||
feature2 = np.random.random((10)) | ||
features = pd.DataFrame({'feature1': feature1, 'feature2': feature2}) | ||
layer = viewer.add_vectors(vectors, features=features) | ||
|
||
feature_map = create_feature_map(layer, 'feature1') | ||
viewer.add_layer(feature_map) | ||
|
||
|
||
def test_points_featuremaps(make_napari_viewer): | ||
from napari_skimage_regionprops import regionprops | ||
from .._parametric_images import create_feature_map | ||
import pandas as pd | ||
|
||
viewer = make_napari_viewer() | ||
|
||
np.random.seed(0) | ||
points = np.random.random((10, 2)) | ||
feature1 = np.random.random((10)) | ||
feature2 = np.random.random((10)) | ||
features = pd.DataFrame({'feature1': feature1, 'feature2': feature2}) | ||
layer = viewer.add_points(points, features=features) | ||
|
||
feature_map = create_feature_map(layer, 'feature1') | ||
viewer.add_layer(feature_map) | ||
|
||
|
||
def test_surface_featuremaps(make_napari_viewer): | ||
from napari_skimage_regionprops import regionprops | ||
from .._parametric_images import create_feature_map | ||
import pandas as pd | ||
|
||
viewer = make_napari_viewer() | ||
|
||
np.random.seed(0) | ||
vertices = np.random.random((10, 3)) | ||
faces = np.random.randint(size=(10, 3), high=9, low=0) | ||
surface = (vertices, faces) | ||
feature1 = np.random.random((10)) | ||
feature2 = np.random.random((10)) | ||
features = pd.DataFrame({'feature1': feature1, 'feature2': feature2}) | ||
layer = viewer.add_surface(surface, metadata={'features': features}) | ||
|
||
feature_map = create_feature_map(layer, 'feature1') | ||
assert np.array_equal(feature_map.data[2], feature1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give an example (plugin) where there is data in
layer.metadata['features']
but not inlayer.features
? Might it be possible to talk to the developers of these plugins so that they uselayer.features
? It would make more plugjns compatible to each other if we all use the same API 😉