From 7c753610471641c98ed633e2d72eb60c11220341 Mon Sep 17 00:00:00 2001 From: ShalinGhe Date: Thu, 8 Aug 2024 20:29:04 +0200 Subject: [PATCH 1/5] first multichannel imitialization --- cellpose/gui/gui.py | 117 ++++++++++++++++++++++++++++++++++++++++++++ cellpose/gui/io.py | 3 ++ 2 files changed, 120 insertions(+) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 64934269..efcfa7b6 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -483,6 +483,123 @@ def onViewChanged(self): # if an exception of any kind occurs, the specific exception is printed to the console print(f"An error occurred while changing the view: {e}") +def generate_multi_channel_ui(self, num_layers, is_tiff): + """ + Generates UI components for multi-channel images. + + This method creates and initializes sliders, color buttons, and on/off buttons based on the number of layers + in the loaded multi-channel TIFF image. It also ensures that these components are displayed or hidden appropriately. + + Args: + num_layers (int): The number of layers in the loaded multi-channel TIFF image. + is_tiff (bool): Flag indicating whether the image is a TIFF file. + + Returns: + None + """ + # Position of elements in the layout + c = 0 + + # Clear existing elements in the layout + for i in reversed(range(self.rightBoxLayout.count())): + widget = self.rightBoxLayout.itemAt(i).widget() + if widget is not None: + widget.setParent(None) + + # Initialize lists for buttons and sliders + self.sliders = [] + self.marker_buttons = [] + self.on_off_buttons = [] + + # Initialize colors + colors = [ + (255, 0, 0), # Red + (0, 255, 0), # Green + (0, 0, 255), # Blue + (255, 255, 0), # Yellow + (255, 0, 255), # Magenta + (0, 255, 255), # Cyan + (255, 165, 0) # Orange + ] + + if is_tiff: + # Multi-layer TIFF image case + self.marker_buttons = [self.create_color_button(colors[r % len(colors)], r) for r in range(num_layers)] + self.on_off_buttons = [self.create_on_off_button() for _ in range(num_layers)] + + for r in range(num_layers): + c += 1 + + # Create label for each marker + label = QLabel(f'Marker {r + 1}') + label.setStyleSheet("color: white") + label.setFont(self.boldmedfont) + + # Get the corresponding color button and on/off button + color_button = self.marker_buttons[r] + on_off_button = self.on_off_buttons[r] + + # Add components to the layout + self.rightBoxLayout.addWidget(label, c, 0, 1, 1) + self.rightBoxLayout.addWidget(color_button, c, 9, 1, 1) + self.rightBoxLayout.addWidget(on_off_button, c, 10, 1, 1) + + # Create and add the slider + slider_name = r + slider_color = colors[r % len(colors)] + slider = Slider(self, slider_name, slider_color) + slider.setMinimum(-.1) + slider.setMaximum(255.1) + slider.setValue([0, 255]) + slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") + slider.setFixedWidth(250) + + self.sliders.append(slider) + self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) + + else: + # Non-TIFF image case + colornames = ["red", "Chartreuse", "DodgerBlue"] + names = ["red", "green", "blue"] + + for r in range(3): + c += 1 + + if r == 0: + label = QLabel('gray/
red') + else: + label = QLabel(names[r] + ":") + label.setStyleSheet(f"color: {colornames[r]}") + label.setFont(self.boldmedfont) + + self.rightBoxLayout.addWidget(label, c, 0, 1, 2) + + slider = Slider(self, names[r], colors[r]) + slider.setMinimum(-.1) + slider.setMaximum(255.1) + slider.setValue([0, 255]) + slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") + slider.setFixedWidth(250) + + self.sliders.append(slider) + self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) + + # Add a stretch widget to the layout + stretch_widget = QWidget() + self.rightBoxLayout.addWidget(stretch_widget) + + # Show or hide color dialog and on/off buttons based on the is_tiff flag + if is_tiff: + for button in self.marker_buttons: + button.show() + for button in self.on_off_buttons: + button.show() + else: + for button in self.marker_buttons: + button.hide() + for button in self.on_off_buttons: + button.hide() + def make_buttons(self): self.boldfont = QtGui.QFont("Arial", 11, QtGui.QFont.Bold) self.boldmedfont = QtGui.QFont("Arial", 9, QtGui.QFont.Bold) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index 1598ce01..c45bceb1 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -109,6 +109,7 @@ def _load_image(parent, filename=None, load_seg=True, load_3D=False): if filename is None: name = QFileDialog.getOpenFileName(parent, "Load image") filename = name[0] + is_tiff = False #checks if the file is a tiff if filename and (filename.endswith('.tif') or filename.endswith('.tiff')): @@ -116,6 +117,8 @@ def _load_image(parent, filename=None, load_seg=True, load_3D=False): filename) if successful_import: parent.grayscale_image_stack = grayscale_image_stack + num_layers = len(grayscale_image_stack) + is_tiff = True # Initialize the colors and colored_image_stack attributes parent.color_initialization() From ab5822a84a7042f5797e974b41149176712cfee8 Mon Sep 17 00:00:00 2001 From: ShalinGhe Date: Fri, 9 Aug 2024 02:21:08 +0200 Subject: [PATCH 2/5] Fixed some bugs and updated level_change function --- cellpose/gui/gui.py | 295 +++++++++++++++++++++----------------------- cellpose/gui/io.py | 16 +-- 2 files changed, 152 insertions(+), 159 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index efcfa7b6..11a5cca4 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -9,6 +9,7 @@ from qtpy.QtWidgets import QScrollArea, QMainWindow, QApplication, QWidget, QScrollBar, QComboBox, QGridLayout, QPushButton, QFrame, QCheckBox, QLabel, QProgressBar, QLineEdit, QMessageBox, QGroupBox, QColorDialog import pyqtgraph as pg from qtpy.QtGui import QIcon, QColor +from PIL import Image import numpy as np from scipy.stats import mode @@ -483,122 +484,7 @@ def onViewChanged(self): # if an exception of any kind occurs, the specific exception is printed to the console print(f"An error occurred while changing the view: {e}") -def generate_multi_channel_ui(self, num_layers, is_tiff): - """ - Generates UI components for multi-channel images. - - This method creates and initializes sliders, color buttons, and on/off buttons based on the number of layers - in the loaded multi-channel TIFF image. It also ensures that these components are displayed or hidden appropriately. - - Args: - num_layers (int): The number of layers in the loaded multi-channel TIFF image. - is_tiff (bool): Flag indicating whether the image is a TIFF file. - - Returns: - None - """ - # Position of elements in the layout - c = 0 - - # Clear existing elements in the layout - for i in reversed(range(self.rightBoxLayout.count())): - widget = self.rightBoxLayout.itemAt(i).widget() - if widget is not None: - widget.setParent(None) - - # Initialize lists for buttons and sliders - self.sliders = [] - self.marker_buttons = [] - self.on_off_buttons = [] - - # Initialize colors - colors = [ - (255, 0, 0), # Red - (0, 255, 0), # Green - (0, 0, 255), # Blue - (255, 255, 0), # Yellow - (255, 0, 255), # Magenta - (0, 255, 255), # Cyan - (255, 165, 0) # Orange - ] - - if is_tiff: - # Multi-layer TIFF image case - self.marker_buttons = [self.create_color_button(colors[r % len(colors)], r) for r in range(num_layers)] - self.on_off_buttons = [self.create_on_off_button() for _ in range(num_layers)] - - for r in range(num_layers): - c += 1 - - # Create label for each marker - label = QLabel(f'Marker {r + 1}') - label.setStyleSheet("color: white") - label.setFont(self.boldmedfont) - - # Get the corresponding color button and on/off button - color_button = self.marker_buttons[r] - on_off_button = self.on_off_buttons[r] - - # Add components to the layout - self.rightBoxLayout.addWidget(label, c, 0, 1, 1) - self.rightBoxLayout.addWidget(color_button, c, 9, 1, 1) - self.rightBoxLayout.addWidget(on_off_button, c, 10, 1, 1) - - # Create and add the slider - slider_name = r - slider_color = colors[r % len(colors)] - slider = Slider(self, slider_name, slider_color) - slider.setMinimum(-.1) - slider.setMaximum(255.1) - slider.setValue([0, 255]) - slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") - slider.setFixedWidth(250) - - self.sliders.append(slider) - self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) - - else: - # Non-TIFF image case - colornames = ["red", "Chartreuse", "DodgerBlue"] - names = ["red", "green", "blue"] - - for r in range(3): - c += 1 - - if r == 0: - label = QLabel('gray/
red') - else: - label = QLabel(names[r] + ":") - label.setStyleSheet(f"color: {colornames[r]}") - label.setFont(self.boldmedfont) - - self.rightBoxLayout.addWidget(label, c, 0, 1, 2) - - slider = Slider(self, names[r], colors[r]) - slider.setMinimum(-.1) - slider.setMaximum(255.1) - slider.setValue([0, 255]) - slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") - slider.setFixedWidth(250) - - self.sliders.append(slider) - self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) - - # Add a stretch widget to the layout - stretch_widget = QWidget() - self.rightBoxLayout.addWidget(stretch_widget) - - # Show or hide color dialog and on/off buttons based on the is_tiff flag - if is_tiff: - for button in self.marker_buttons: - button.show() - for button in self.on_off_buttons: - button.show() - else: - for button in self.marker_buttons: - button.hide() - for button in self.on_off_buttons: - button.hide() + def make_buttons(self): self.boldfont = QtGui.QFont("Arial", 11, QtGui.QFont.Bold) @@ -655,41 +541,45 @@ def make_buttons(self): self.autobtn.setChecked(True) self.satBoxG.addWidget(self.autobtn, b0, 1, 1, 8) - + #--- Initialization of Non-Tiff cases ---# c = 0 # position of the elements in the right side menu - self.sliders = [] - # ---Create a list (extendable) of color/on-off buttons ---# + # Define color names and labels for non-TIFF images + colornames = ["red", "Chartreuse", "DodgerBlue"] + names = ["red", "green", "blue"] colors = ["red", "green", "blue"] - self.marker_buttons = [self.create_color_button(color) for color in colors] - self.on_off_buttons = [self.create_on_off_button() for color in colors] + # Initialize sliders list + self.sliders = [] + + # Add labels and sliders for non-TIFF images for r in range(3): c += 1 - label = QLabel(f'Marker {r + 1}') # create a label for each marker - color_button = self.marker_buttons[r] # get the corresponding color button - self.marker_buttons = [self.create_color_button(color) for color in colors] - on_off_button = self.on_off_buttons[r] # get the corresponding on-off button - label.setStyleSheet("color: white") + # Create a label for each color channel + if r == 0: + label = QLabel('gray/
red') + else: + label = QLabel(names[r] + ":") + label.setStyleSheet(f"color: {colornames[r]}") label.setFont(self.boldmedfont) - self.rightBoxLayout.addWidget(label, c, 0, 1, 1) - self.rightBoxLayout.addWidget(color_button, c, 9, 1, 1) # add the color button to the layout - self.rightBoxLayout.addWidget(on_off_button, c, 10, 1, 1) # add the on-off button to the layout - self.sliders.append(Slider(self, colors[r], None)) - self.sliders[-1].setMinimum(-.1) - self.sliders[-1].setMaximum(255.1) - self.sliders[-1].setValue([0, 255]) - self.sliders[-1].setToolTip( - "NOTE: manually changing the saturation bars does not affect normalization in segmentation" - ) + self.rightBoxLayout.addWidget(label, c, 0, 1, 2) - self.sliders[-1].setFixedWidth(250) - self.rightBoxLayout.addWidget(self.sliders[-1], c, 2, 1, 7) - stretch_widget = QWidget() - self.rightBoxLayout.addWidget(stretch_widget) + # Create and configure the slider + slider = Slider(self, colors[r], None) + slider.setMinimum(-.1) + slider.setMaximum(255.1) + slider.setValue([0, 255]) + slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") + slider.setFixedWidth(250) + # Add the slider to the layout + self.sliders.append(slider) + self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) + # Add a stretch widget to the layout + stretch_widget = QWidget() + self.rightBoxLayout.addWidget(stretch_widget) b += 1 self.drawBox = QGroupBox("Drawing") self.drawBox.setFont(self.boldfont) @@ -1143,6 +1033,97 @@ def make_buttons(self): return b + + def generate_multi_channel_ui(self, num_layers, is_tiff): + """ + Generates UI components for multi-channel images. + + This method creates and initializes sliders, color buttons, and on/off buttons based on the number of layers + in the loaded multi-channel TIFF image. It also ensures that these components are displayed or hidden appropriately. + + Args: + num_layers (int): The number of layers in the loaded multi-channel TIFF image. + is_tiff (bool): Flag indicating whether the image is a TIFF file. + """ + # Position of elements in the layout + c = 0 + + # Clear existing elements in the layout + for i in reversed(range(self.rightBoxLayout.count())): + widget = self.rightBoxLayout.itemAt(i).widget() + if widget is not None: + widget.setParent(None) + + # Initialize lists for buttons and sliders + self.sliders = [] + self.marker_buttons = [] + self.on_off_buttons = [] + + # Initialize colors + colors = [ + (255, 0, 0), # Red + (0, 255, 0), # Green + (0, 0, 255), # Blue + (255, 255, 0), # Yellow + (255, 0, 255), # Magenta + (0, 255, 255), # Cyan + (255, 165, 0) # Orange + ] + + if is_tiff: + for r in range(num_layers): + color = colors[r % len(colors)] + color_button = self.create_color_button(color) + self.marker_buttons.append(color_button) + self.on_off_buttons.append(self.create_on_off_button()) + + for r in range(num_layers): + c += 1 + + # Create label for each marker + label = QLabel(f'Marker {r + 1}') + label.setStyleSheet("color: white") + label.setFont(self.boldmedfont) + + # Get the corresponding color button and on/off button + color_button = self.marker_buttons[r] + on_off_button = self.on_off_buttons[r] + + # Add components to the layout + self.rightBoxLayout.addWidget(label, c, 0, 1, 1) + self.rightBoxLayout.addWidget(color_button, c, 9, 1, 1) + self.rightBoxLayout.addWidget(on_off_button, c, 10, 1, 1) + + # Create and add the slider + slider_name = r + slider_color = colors[r % len(colors)] + slider = Slider(self, slider_name, slider_color) + slider.setMinimum(-.1) + slider.setMaximum(255.1) + slider.setValue([0, 255]) + slider.setToolTip("NOTE: manually changing the saturation bars does not affect normalization in segmentation") + slider.setFixedWidth(250) + + self.sliders.append(slider) + self.rightBoxLayout.addWidget(slider, c, 2, 1, 7) + + + # Add a stretch widget to the layout + stretch_widget = QWidget() + self.rightBoxLayout.addWidget(stretch_widget) + + # Show or hide color dialog and on/off buttons based on the is_tiff flag + if is_tiff and num_layers > 3: + for button in self.marker_buttons: + button.show() + for button in self.on_off_buttons: + button.show() + else: + for button in self.marker_buttons: + button.hide() + for button in self.on_off_buttons: + button.hide() + def create_color_button(self, color): """ Creates and initializes all the buttons and UI elements used in the GUI. @@ -1156,11 +1137,12 @@ def create_color_button(self, color): color_button = QPushButton() color_button.setStyleSheet(self.get_color_button_style(color)) color_button.clicked.connect(self.open_color_dialog) + print(f"Created button with color: rgb({color[0]}, {color[1]}, {color[2]})") return color_button def create_on_off_button(self): """ - Creates a new QPushButton for toggling on and off, with an initial "off" state, + Creates a new QPushButton for toggling on and off, with an initial "on" state, and connects its clicked signal to the toggle_on_off method. Returns: @@ -1168,8 +1150,8 @@ def create_on_off_button(self): """ on_off_button = QPushButton() on_off_button.setCheckable(True) - on_off_button.setChecked(False) - on_off_button.setIcon(QIcon("cellpose/resources/icon/visibility_off.png")) # Icon for "off" state + on_off_button.setChecked(True) # Initial state is "on" + on_off_button.setIcon(QIcon("cellpose/resources/icon/visibility_on.png")) # Icon for "on" state on_off_button.setIconSize(QtCore.QSize(12, 12)) on_off_button.clicked.connect(self.toggle_on_off) return on_off_button @@ -1226,15 +1208,24 @@ def get_color_button_style(self, color_name): """ def level_change(self, r): - r = ["red", "green", "blue"].index(r) - if self.loaded: - sval = self.sliders[r].value() - self.saturation[r][self.currentZ] = sval - if not self.autobtn.isChecked(): - for r in range(3): - for i in range(len(self.saturation[r])): - self.saturation[r][i] = self.saturation[r][self.currentZ] - self.update_plot() + if self.tiff_loaded: + if int(r) < len(self.sliders): + r_index = r + print("slider name " + str(r)) + print("slider array " + str(len(self.sliders))) + print(f"Slider {r} value: {self.sliders[r_index].value()}") + self.adjust_channel_bounds(r_index, self.sliders[r_index].value()) + self.update_plot() + else: + r = ["red", "green", "blue"].index(r) + if self.loaded: + sval = self.sliders[r].value() + self.saturation[r][self.currentZ] = sval + if not self.autobtn.isChecked(): + for r in range(3): + for i in range(len(self.saturation[r])): + self.saturation[r][i] = self.saturation[r][self.currentZ] + self.update_plot() def keyPressEvent(self, event): if self.loaded: diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index c45bceb1..d11a8567 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -9,7 +9,7 @@ import tifffile import logging import fastremap - +from PIL import Image from ..io import imread, imsave, outlines_to_text, add_model, remove_model, save_rois, save_settings, save_features_csv from ..models import normalize_default, MODEL_DIR, MODEL_LIST_PATH, get_user_models @@ -109,24 +109,25 @@ def _load_image(parent, filename=None, load_seg=True, load_3D=False): if filename is None: name = QFileDialog.getOpenFileName(parent, "Load image") filename = name[0] - is_tiff = False + print("keine tiff") #checks if the file is a tiff if filename and (filename.endswith('.tif') or filename.endswith('.tiff')): successful_import, grayscale_image_stack = initialize_tiff_images( filename) + print(successful_import) if successful_import: parent.grayscale_image_stack = grayscale_image_stack - num_layers = len(grayscale_image_stack) - is_tiff = True # Initialize the colors and colored_image_stack attributes parent.color_initialization() parent.generate_color_image_stack() - # Initialize the Buttons and sliders - # parent.generate_multi_channel_ui() - + # Initialize the Buttons and sliders for multi-layer TIFF + num_layers = len(grayscale_image_stack) + is_tiff = True + parent.generate_multi_channel_ui(num_layers, is_tiff) + print(f"GUI_INFO: Tiff loaded with {len(grayscale_image_stack)} layers") manual_file = os.path.splitext(filename)[0] + "_seg.npy" load_mask = False @@ -786,4 +787,5 @@ def initialize_tiff_images(tiff_file_path): return ret, processed_images return ret, [] except Exception as e: + print(e) return False, [] From 5c584f70f605c59057856c9623c1589dfcebb0a1 Mon Sep 17 00:00:00 2001 From: ShalinGhe Date: Fri, 9 Aug 2024 10:36:11 +0200 Subject: [PATCH 3/5] Adapted helper functions to handle button colors correctly and added function to convert RGB tuple to a hex color string --- cellpose/gui/gui.py | 87 +++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 11a5cca4..9d78b549 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -14,6 +14,7 @@ import numpy as np from scipy.stats import mode import cv2 +from webcolors import rgb_to_hex from . import guiparts, menus, io from .. import models, core, dynamics, version, denoise, train @@ -1059,23 +1060,12 @@ def generate_multi_channel_ui(self, num_layers, is_tiff): self.marker_buttons = [] self.on_off_buttons = [] - # Initialize colors - colors = [ - (255, 0, 0), # Red - (0, 255, 0), # Green - (0, 0, 255), # Blue - (255, 255, 0), # Yellow - (255, 0, 255), # Magenta - (0, 255, 255), # Cyan - (255, 165, 0) # Orange - ] - if is_tiff: - for r in range(num_layers): - color = colors[r % len(colors)] - color_button = self.create_color_button(color) - self.marker_buttons.append(color_button) - self.on_off_buttons.append(self.create_on_off_button()) + self.marker_buttons = [ + self.create_color_button(rgb_to_hex(color)) + for color in self.colors_stack[:num_layers] + ] + self.on_off_buttons = [self.create_on_off_button() for _ in range(num_layers)] for r in range(num_layers): c += 1 @@ -1096,7 +1086,7 @@ def generate_multi_channel_ui(self, num_layers, is_tiff): # Create and add the slider slider_name = r - slider_color = colors[r % len(colors)] + slider_color = rgb_to_hex(self.colors_stack[r]) slider = Slider(self, slider_name, slider_color) slider.setMinimum(-.1) slider.setMaximum(255.1) @@ -1124,20 +1114,20 @@ def generate_multi_channel_ui(self, num_layers, is_tiff): for button in self.on_off_buttons: button.hide() - def create_color_button(self, color): + def create_color_button(self, hex_color): """ - Creates and initializes all the buttons and UI elements used in the GUI. - This includes buttons for changing views, drawing, segmentation, model - selection, and image restoration. Also initializes color buttons with - specific colors (red, green, blue) and on-off buttons. + Creates a color button with the specified color. - Returns: - int: The number of buttons and UI elements created. - """ + Args: + color (tuple): RGB color tuple. + + Returns: + QPushButton: The created color button. + """ color_button = QPushButton() - color_button.setStyleSheet(self.get_color_button_style(color)) + color_button.setStyleSheet(self.get_color_button_style(hex_color)) color_button.clicked.connect(self.open_color_dialog) - print(f"Created button with color: rgb({color[0]}, {color[1]}, {color[2]})") + print(f"Created button with color: {hex_color}") return color_button def create_on_off_button(self): @@ -1187,7 +1177,7 @@ def open_color_dialog(self): if color.isValid(): self.sender().setStyleSheet(self.get_color_button_style(color.name())) - def get_color_button_style(self, color_name): + def get_color_button_style(self, hex_color): """ Returns a string with the CSS style for a QPushButton with the specified background color, a solid border, a border width of 1 pixel, and a size of 12x12 pixels. @@ -1199,33 +1189,36 @@ def get_color_button_style(self, color_name): """ return f""" QPushButton {{ - background-color: {color_name}; + background-color: {hex_color}; border-style: solid; border-width: 1px; height: 12px; width: 12px; }} """ + + def rgb_to_hex(self, rgb_tuple): + """ + Converts an RGB tuple to a hex color string. + + Args: + rgb_tuple (tuple): The RGB tuple (e.g., (255, 0, 0) for red). + + Returns: + str: The hex color string (e.g., '#ff0000' for red). + """ + return '#{:02x}{:02x}{:02x}'.format(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2]) def level_change(self, r): - if self.tiff_loaded: - if int(r) < len(self.sliders): - r_index = r - print("slider name " + str(r)) - print("slider array " + str(len(self.sliders))) - print(f"Slider {r} value: {self.sliders[r_index].value()}") - self.adjust_channel_bounds(r_index, self.sliders[r_index].value()) - self.update_plot() - else: - r = ["red", "green", "blue"].index(r) - if self.loaded: - sval = self.sliders[r].value() - self.saturation[r][self.currentZ] = sval - if not self.autobtn.isChecked(): - for r in range(3): - for i in range(len(self.saturation[r])): - self.saturation[r][i] = self.saturation[r][self.currentZ] - self.update_plot() + r = ["red", "green", "blue"].index(r) + if self.loaded: + sval = self.sliders[r].value() + self.saturation[r][self.currentZ] = sval + if not self.autobtn.isChecked(): + for r in range(3): + for i in range(len(self.saturation[r])): + self.saturation[r][i] = self.saturation[r][self.currentZ] + self.update_plot() def keyPressEvent(self, event): if self.loaded: From 8b30c0165d120229e250b293e1ba6b8780cb2235 Mon Sep 17 00:00:00 2001 From: ShalinGhe Date: Fri, 9 Aug 2024 10:48:23 +0200 Subject: [PATCH 4/5] Added documentation for improved understandind of codebase --- cellpose/gui/gui.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 9d78b549..9ab3ef75 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -361,6 +361,15 @@ def minimap_window(self): self.minimap_window_instance = None def color_initialization(self): + """ + Initializes the color stack for multi-channel images. + + This method assigns initial colors to each layer in the grayscale image stack. + It uses a predefined list of colors and cycles through them if there are more layers + than colors available. + + The colors are assigned in a cyclic manner to ensure that each layer has a color. + """ colors = [ (255, 0, 0), # Red (0, 255, 0), # Green @@ -1061,6 +1070,7 @@ def generate_multi_channel_ui(self, num_layers, is_tiff): self.on_off_buttons = [] if is_tiff: + # Create color buttons and on/off buttons for each layer self.marker_buttons = [ self.create_color_button(rgb_to_hex(color)) for color in self.colors_stack[:num_layers] @@ -1119,7 +1129,7 @@ def create_color_button(self, hex_color): Creates a color button with the specified color. Args: - color (tuple): RGB color tuple. + hex_color (str): Hex color string. Returns: QPushButton: The created color button. @@ -1179,10 +1189,11 @@ def open_color_dialog(self): def get_color_button_style(self, hex_color): """ - Returns a string with the CSS style for a QPushButton with the specified background color, a solid border, a border width of 1 pixel, and a size of 12x12 pixels. + Returns a string with the CSS style for a QPushButton with the specified background color, + a solid border, a border width of 1 pixel, and a size of 12x12 pixels. Args: - color_name (str): The name of the color to use for the button's background. + hex_color (str): The hex color string to use for the button's background. Returns: str: The CSS style for the button. From e7a0614c412f2c4989f0a3bea7e84eebc40994b6 Mon Sep 17 00:00:00 2001 From: Robert Krasniqi Date: Fri, 9 Aug 2024 19:43:37 +0200 Subject: [PATCH 5/5] fixxed error with rgb_to_hex function: moved it out --- cellpose/gui/gui.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 9ab3ef75..611d90b8 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -14,7 +14,6 @@ import numpy as np from scipy.stats import mode import cv2 -from webcolors import rgb_to_hex from . import guiparts, menus, io from .. import models, core, dynamics, version, denoise, train @@ -145,6 +144,17 @@ def make_cmap(cm=0): cmap = pg.ColorMap(pos=np.linspace(0.0, 255, 256), color=color) return cmap +def rgb_to_hex(rgb_tuple): + """ + Converts an RGB tuple to a hex color string. + + Args: + rgb_tuple (tuple): The RGB tuple (e.g., (255, 0, 0) for red). + + Returns: + str: The hex color string (e.g., '#ff0000' for red). + """ + return '#{:02x}{:02x}{:02x}'.format(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2]) def run(image=None): from ..io import logger_setup @@ -1207,18 +1217,7 @@ def get_color_button_style(self, hex_color): width: 12px; }} """ - - def rgb_to_hex(self, rgb_tuple): - """ - Converts an RGB tuple to a hex color string. - - Args: - rgb_tuple (tuple): The RGB tuple (e.g., (255, 0, 0) for red). - Returns: - str: The hex color string (e.g., '#ff0000' for red). - """ - return '#{:02x}{:02x}{:02x}'.format(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2]) def level_change(self, r): r = ["red", "green", "blue"].index(r)