From e66e47fa656500f88d6eea15d897226766460555 Mon Sep 17 00:00:00 2001 From: Natali124 Date: Sat, 4 May 2024 22:23:37 +0200 Subject: [PATCH 1/4] adding widget for adding points layer --- src/napari_brainbow_diagnose/__init__.py | 2 ++ .../_read_csv_widget.py | 33 +++++++++++++++++++ src/napari_brainbow_diagnose/napari.yaml | 6 ++++ 3 files changed, 41 insertions(+) create mode 100644 src/napari_brainbow_diagnose/_read_csv_widget.py diff --git a/src/napari_brainbow_diagnose/__init__.py b/src/napari_brainbow_diagnose/__init__.py index 4655e41..4e026ca 100644 --- a/src/napari_brainbow_diagnose/__init__.py +++ b/src/napari_brainbow_diagnose/__init__.py @@ -10,6 +10,7 @@ ) from ._tooltip_pointer import tooltip_pointer_widget from ._widget import DiagnoseWidget +from ._read_csv_widget import read_csv_widget __all__ = ( "tooltip_pointer_widget", @@ -17,4 +18,5 @@ "fetch_chroms_data", "load_chroms_data_sample", "DiagnoseWidget", + "read_csv_widget", ) diff --git a/src/napari_brainbow_diagnose/_read_csv_widget.py b/src/napari_brainbow_diagnose/_read_csv_widget.py new file mode 100644 index 0000000..bfac6ab --- /dev/null +++ b/src/napari_brainbow_diagnose/_read_csv_widget.py @@ -0,0 +1,33 @@ +import napari + +import pandas as pd +import numpy as np + +from magicgui import magicgui +from magicgui import magic_factory +import pathlib + +def rgb_to_xy(r, g, b): + s = r+g+b + r = r/s + g = g/s + b = b/s + x = (r-b)/np.sqrt(3) + y = g + return x, y + +@magic_factory(call_button="Create a Points layer", auto_call=False) +def read_csv_widget(filename = pathlib.Path('/path/to/csv/file.csv')): + # Getting the current viewer + viewer = napari.current_viewer() + # Import data + df = pd.read_csv(filename, names=['axis-0', 'axis-1', 'axis-2', 'red', 'green', 'blue']) + # Create points layer + coordinates = df[['axis-0', 'axis-1', 'axis-2']].values + colors = df[['red', 'green', 'blue']].values + points_layer = viewer.add_points(coordinates, name='points', face_color=colors, edge_color=colors, size=20, out_of_slice_display=True) + + # Add Maxwell coordinates + df['x'], df['y'] = rgb_to_xy(df['red'], df['green'], df['blue']) + features_table = {'red': df['red'].values, 'green': df['green'].values, 'blue': df['blue'].values, 'x': df['x'].values, 'y': df['y'].values} + points_layer.features = features_table \ No newline at end of file diff --git a/src/napari_brainbow_diagnose/napari.yaml b/src/napari_brainbow_diagnose/napari.yaml index 7f3bca8..3d66508 100644 --- a/src/napari_brainbow_diagnose/napari.yaml +++ b/src/napari_brainbow_diagnose/napari.yaml @@ -14,6 +14,9 @@ contributions: - id: napari-brainbow-diagnose.DiagnoseWidget python_name: napari_brainbow_diagnose._widget:DiagnoseWidget title: Diagnose Brainbow Image + - id: napari-brainbow-diagnose.read_csv_widget + python_name: napari_brainbow_diagnose._read_csv_widget:read_csv_widget + title: Load a Points layer sample_data: - command: napari-brainbow-diagnose.make_rgb_cube_data display_name: RGB Cube @@ -26,3 +29,6 @@ contributions: display_name: Diagnose Brainbow Image - command: napari-brainbow-diagnose.tooltip_pointer_widget display_name: Brainbow Tooltip + - command: napari-brainbow-diagnose.read_csv_widget + display_name: Load a Points layer + From 5d2e5c4415c916c53083868576aac2e752713101 Mon Sep 17 00:00:00 2001 From: Natali124 Date: Fri, 17 May 2024 14:18:47 +0200 Subject: [PATCH 2/4] fixed minor issues --- src/napari_brainbow_diagnose/_read_csv_widget.py | 14 +++----------- .../_utils_channel_space.py | 13 +++++++++++++ src/napari_brainbow_diagnose/napari.yaml | 5 +++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/napari_brainbow_diagnose/_read_csv_widget.py b/src/napari_brainbow_diagnose/_read_csv_widget.py index bfac6ab..8e62767 100644 --- a/src/napari_brainbow_diagnose/_read_csv_widget.py +++ b/src/napari_brainbow_diagnose/_read_csv_widget.py @@ -5,17 +5,9 @@ from magicgui import magicgui from magicgui import magic_factory +from ._utils_channel_space import rgb_to_maxwell_triangle import pathlib -def rgb_to_xy(r, g, b): - s = r+g+b - r = r/s - g = g/s - b = b/s - x = (r-b)/np.sqrt(3) - y = g - return x, y - @magic_factory(call_button="Create a Points layer", auto_call=False) def read_csv_widget(filename = pathlib.Path('/path/to/csv/file.csv')): # Getting the current viewer @@ -28,6 +20,6 @@ def read_csv_widget(filename = pathlib.Path('/path/to/csv/file.csv')): points_layer = viewer.add_points(coordinates, name='points', face_color=colors, edge_color=colors, size=20, out_of_slice_display=True) # Add Maxwell coordinates - df['x'], df['y'] = rgb_to_xy(df['red'], df['green'], df['blue']) - features_table = {'red': df['red'].values, 'green': df['green'].values, 'blue': df['blue'].values, 'x': df['x'].values, 'y': df['y'].values} + df['maxwell_x'], df['maxwell_y'] = rgb_to_maxwell_triangle(df['red'], df['green'], df['blue']) + features_table = {'red': df['red'].values, 'green': df['green'].values, 'blue': df['blue'].values, 'maxwell_x': df['maxwell_x'].values, 'maxwell_y': df['maxwell_y'].values} points_layer.features = features_table \ No newline at end of file diff --git a/src/napari_brainbow_diagnose/_utils_channel_space.py b/src/napari_brainbow_diagnose/_utils_channel_space.py index ebd5cc8..44ad868 100644 --- a/src/napari_brainbow_diagnose/_utils_channel_space.py +++ b/src/napari_brainbow_diagnose/_utils_channel_space.py @@ -26,6 +26,19 @@ def rgb_to_hsv(rgb: np.ndarray, channel_axis: int = -1) -> np.ndarray: return skc.rgb2hsv(rgb, channel_axis=channel_axis) +def rgb_to_maxwell_triangle(r, g, b): + """ + Given coordinates in rgb color space, returns x and y coordinates of the Maxwell triangle. + """ + s = r+g+b + r = r/s + g = g/s + b = b/s + x = (r-b)/np.sqrt(3) + y = g + return x, y + + # TODO ajouter un paramètre pour choisir l'axe des canaux def get_channels_ranges(a: np.ndarray) -> np.ndarray: """ diff --git a/src/napari_brainbow_diagnose/napari.yaml b/src/napari_brainbow_diagnose/napari.yaml index 3d66508..3f0856d 100644 --- a/src/napari_brainbow_diagnose/napari.yaml +++ b/src/napari_brainbow_diagnose/napari.yaml @@ -25,10 +25,11 @@ contributions: display_name: Chroms Cortex Sample key: unique_id.2 widgets: + - command: napari-brainbow-diagnose.read_csv_widget + display_name: Load a Points layer - command: napari-brainbow-diagnose.DiagnoseWidget display_name: Diagnose Brainbow Image - command: napari-brainbow-diagnose.tooltip_pointer_widget display_name: Brainbow Tooltip - - command: napari-brainbow-diagnose.read_csv_widget - display_name: Load a Points layer + From 6784c983eb77a4ffe499fb573c8b442e950fc42a Mon Sep 17 00:00:00 2001 From: Natali124 Date: Thu, 13 Jun 2024 22:51:05 +0200 Subject: [PATCH 3/4] added widget for adding features without reading csv and adding selected features --- .Rhistory | 0 src/napari_brainbow_diagnose/__init__.py | 3 +- .../_read_csv_widget.py | 56 +++++++++++++++++-- .../_utils_channel_space.py | 5 ++ src/napari_brainbow_diagnose/napari.yaml | 5 ++ 5 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 .Rhistory diff --git a/.Rhistory b/.Rhistory new file mode 100644 index 0000000..e69de29 diff --git a/src/napari_brainbow_diagnose/__init__.py b/src/napari_brainbow_diagnose/__init__.py index 4e026ca..1d93e41 100644 --- a/src/napari_brainbow_diagnose/__init__.py +++ b/src/napari_brainbow_diagnose/__init__.py @@ -10,7 +10,7 @@ ) from ._tooltip_pointer import tooltip_pointer_widget from ._widget import DiagnoseWidget -from ._read_csv_widget import read_csv_widget +from ._read_csv_widget import read_csv_widget, add_features_widget __all__ = ( "tooltip_pointer_widget", @@ -19,4 +19,5 @@ "load_chroms_data_sample", "DiagnoseWidget", "read_csv_widget", + "add_features_widget" ) diff --git a/src/napari_brainbow_diagnose/_read_csv_widget.py b/src/napari_brainbow_diagnose/_read_csv_widget.py index 8e62767..35cbef8 100644 --- a/src/napari_brainbow_diagnose/_read_csv_widget.py +++ b/src/napari_brainbow_diagnose/_read_csv_widget.py @@ -1,19 +1,20 @@ import napari +from napari.layers import Points import pandas as pd import numpy as np from magicgui import magicgui from magicgui import magic_factory -from ._utils_channel_space import rgb_to_maxwell_triangle +from ._utils_channel_space import rgb_to_maxwell_triangle, calculate_brightness import pathlib -@magic_factory(call_button="Create a Points layer", auto_call=False) +@magic_factory(call_button="(test) Create a Points layer", auto_call=False) def read_csv_widget(filename = pathlib.Path('/path/to/csv/file.csv')): # Getting the current viewer viewer = napari.current_viewer() # Import data - df = pd.read_csv(filename, names=['axis-0', 'axis-1', 'axis-2', 'red', 'green', 'blue']) + df = pd.read_csv(filename, usecols=range(6), names=['axis-0', 'axis-1', 'axis-2', 'red', 'green', 'blue']) # Create points layer coordinates = df[['axis-0', 'axis-1', 'axis-2']].values colors = df[['red', 'green', 'blue']].values @@ -21,5 +22,50 @@ def read_csv_widget(filename = pathlib.Path('/path/to/csv/file.csv')): # Add Maxwell coordinates df['maxwell_x'], df['maxwell_y'] = rgb_to_maxwell_triangle(df['red'], df['green'], df['blue']) - features_table = {'red': df['red'].values, 'green': df['green'].values, 'blue': df['blue'].values, 'maxwell_x': df['maxwell_x'].values, 'maxwell_y': df['maxwell_y'].values} - points_layer.features = features_table \ No newline at end of file + df['brightness'] = calculate_brightness(df['red'], df['green'], df['blue']) + + df = df.sort_values(by='brightness').reset_index(drop=True) + + features_table = { + 'red': df['red'].values, 'green': df['green'].values, 'blue': df['blue'].values, + 'maxwell_x': df['maxwell_x'].values, 'maxwell_y': df['maxwell_y'].values, + 'brightness_index': df.index, 'brightness': df['brightness'] + } + points_layer.features = features_table + + +# Add color features to an existing points layer which has features 'red', 'green', and 'blue' +@magic_factory(call_button="Add Features to Points Layer", auto_call=False, points_layer={"label": "Select Points Layer"}, points_selection={"label": "Add selected points feature"}) +def add_features_widget(points_layer: Points, points_selection: bool): + # Extract existing features + if not all(col in points_layer.features for col in ['red', 'green', 'blue']): + raise ValueError("Selected points layer does not have 'red', 'green', and 'blue' features.") + + red = points_layer.features['red'] + green = points_layer.features['green'] + blue = points_layer.features['blue'] + + # Add Maxwell coordinates + maxwell_x, maxwell_y = rgb_to_maxwell_triangle(red, green, blue) + brightness = calculate_brightness(red, green, blue) + + features_table = { + 'red': red.values, + 'green': green.values, + 'blue': blue.values, + 'maxwell_x': maxwell_x.values, + 'maxwell_y': maxwell_y.values, + 'brightness': brightness.values, + 'range': np.arange(len(brightness)) + } + + for key, value in features_table.items(): + points_layer.features[key] = value + + if points_selection: + selected = points_layer.selected_data + clustering = np.zeros(len(points_layer.data)) + for point_index in selected: + clustering[point_index] = 1 + + points_layer.features['selected_points'] = clustering diff --git a/src/napari_brainbow_diagnose/_utils_channel_space.py b/src/napari_brainbow_diagnose/_utils_channel_space.py index 44ad868..20b746c 100644 --- a/src/napari_brainbow_diagnose/_utils_channel_space.py +++ b/src/napari_brainbow_diagnose/_utils_channel_space.py @@ -38,6 +38,11 @@ def rgb_to_maxwell_triangle(r, g, b): y = g return x, y +def calculate_brightness(r, g, b): + """ + Given standardized values (from 0 to 1) of rgb return brightness + """ + return (1 / 2)*(np.maximum(np.maximum(r, g), b) + np.minimum(np.minimum(r, g), b)) # TODO ajouter un paramètre pour choisir l'axe des canaux def get_channels_ranges(a: np.ndarray) -> np.ndarray: diff --git a/src/napari_brainbow_diagnose/napari.yaml b/src/napari_brainbow_diagnose/napari.yaml index 3f0856d..186936d 100644 --- a/src/napari_brainbow_diagnose/napari.yaml +++ b/src/napari_brainbow_diagnose/napari.yaml @@ -17,6 +17,9 @@ contributions: - id: napari-brainbow-diagnose.read_csv_widget python_name: napari_brainbow_diagnose._read_csv_widget:read_csv_widget title: Load a Points layer + - id: napari-brainbow-diagnose.add_features_widget + python_name: napari_brainbow_diagnose._read_csv_widget:add_features_widget + title: Add color features to existing Points layer sample_data: - command: napari-brainbow-diagnose.make_rgb_cube_data display_name: RGB Cube @@ -27,6 +30,8 @@ contributions: widgets: - command: napari-brainbow-diagnose.read_csv_widget display_name: Load a Points layer + - command: napari-brainbow-diagnose.add_features_widget + display_name: Add color features to existing Points layer - command: napari-brainbow-diagnose.DiagnoseWidget display_name: Diagnose Brainbow Image - command: napari-brainbow-diagnose.tooltip_pointer_widget From c401adceb14c138ec334719c6af99ea9c6198af4 Mon Sep 17 00:00:00 2001 From: Natali124 Date: Fri, 14 Jun 2024 13:22:30 +0200 Subject: [PATCH 4/4] updated feature for clustering --- src/napari_brainbow_diagnose/_read_csv_widget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/napari_brainbow_diagnose/_read_csv_widget.py b/src/napari_brainbow_diagnose/_read_csv_widget.py index 35cbef8..5fe63f7 100644 --- a/src/napari_brainbow_diagnose/_read_csv_widget.py +++ b/src/napari_brainbow_diagnose/_read_csv_widget.py @@ -68,4 +68,4 @@ def add_features_widget(points_layer: Points, points_selection: bool): for point_index in selected: clustering[point_index] = 1 - points_layer.features['selected_points'] = clustering + points_layer.features['CLUSTER'] = clustering.astype(int)