diff --git a/docs/source/dcp_client_installation.rst b/docs/source/dcp_client_installation.rst index 7df45200..6b3c8251 100644 --- a/docs/source/dcp_client_installation.rst +++ b/docs/source/dcp_client_installation.rst @@ -102,7 +102,7 @@ Set the ``--mode`` argument to ``local`` or ``remote`` depending on which setup 4. **The viewer** ~~~~~~~~~~~~~~~~~~~~ - In DCP, we use `napari `_ for viewing our images and masks, adding, editing or removing labels. An example of the viewer can be seen below. After adding or removing any objects and editing existing objects wherever necessary, there are two options available: + In DCP, we use `napari `_ for viewing our images and masks, adding, editing or removing labels. The newest version of DCP comes with `napari-sam `_ integration, to enable even faster labelling! Check out the turorial on the napari-hub to find out how to use this tool. An example of the viewer can be seen below. After adding or removing any objects and editing existing objects wherever necessary, there are two options available: - Click the **Move to Curation in progress folder** if you are not 100% certain about the labels you have created. You can also click on the label in the labels layer and change the name. This will result in several label files being created in the *In progress folder*, which can be examined later on. **Note:** When changing the layer name in Napari, the user should rename it such that they add their initials or any other new info after _seg. E.g., if the labels of 1_seg.tiff have been changed in the Napari viewer, then the appropriate naming would for example be: 1_seg_CB.tiff and not 1_CB_seg.tiff. - Click the **Move to Curated dataset folder** if you are certain that the labels you are now viewing are final and require no more curation. These images and labels will later be used for training the machine learning model, so make sure that you select this option only if you are certain about the labels. If several labels are displayed (opened from the 'Curation in progress' step), make sure to **click** on the single label in the labels layer list you wish to be moved to the *Curated data folder*. The other images will then be automatically deleted from this folder. diff --git a/scripts/openstack/02_setup_vm.sh b/scripts/openstack/02_setup_vm.sh index da4217a6..21923e92 100644 --- a/scripts/openstack/02_setup_vm.sh +++ b/scripts/openstack/02_setup_vm.sh @@ -1,59 +1,24 @@ # Connect to the machine via ssh -# ssh -v -i ~/.ssh/id_rsa_project1 ubuntu@134.94.88.118 -# ssh -v -i ~/.ssh/id_rsa_project2 ubuntu@134.94.88.74 +# ssh -v -i ~/.ssh/id_rsa rocky@134.94.198.230 # IP should reflect the created floatingIP -# Updates -echo "Updating distro" -sudo apt update && sudo apt upgrade +# Bring VM to latest state and install some dependencies +sudo dnf update -y # cosmetic for getting the latest kernel in +sudo shutdown 1 -r +sudo dnf config-manager --set-enabled crb +sudo dnf -y install epel-release +sudo dnf install -y gcc gcc-c++ make kernel-headers-$(uname -r) kernel-devel-$(uname -r) tar bzip2 automake elfutils-libelf-devel libglvnd libglvnd-devel libglvnd-opengl libglvnd-glx acpid pciutils dkms -# Install NVIDIA drivers -echo "Installing NVIDIA driver" -sudo apt install -y gcc make g++ -sudo apt-get install linux-headers-$(uname -r) -curl -o /tmp/NVIDIA-Driver.latest.run https://hpsrepo.fz-juelich.de/jusuf/nvidia/NVIDIA-Driver.latest -chmod 755 /tmp/NVIDIA-Driver.latest.run -sudo mkdir /etc/nvidia -curl -o /tmp/gridd.conf https://hpsrepo.fz-juelich.de/jusuf/nvidia/gridd.conf -sudo mv /tmp/gridd.conf /etc/nvidia/gridd.conf -sudo /tmp/NVIDIA-Driver.latest.run --ui=none --no-questions --disable-nouveau -# sudo reboot # run if needed +# Install Nvidia driver +sudo dnf config-manager --add-repo http://developer.download.nvidia.com/compute/cuda/repos/rhel9/$(uname -i)/cuda-rhel9.repo +sudo dnf module -y install nvidia-driver:latest-dkms +sudo shutdown 1 -r -# Add the following to ~/.bashrc -#export PATH=/usr/local/cuda-11.8/bin${PATH:+:${PATH}} -#export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib\ -# ${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} -# alias labelapp="cd /home/ubuntu/active-learning-platform && python al_framework.py" +# After rebooting the device, check the driver is instlled correctly +nvidia-smi # Install miniconda -echo "Installing Miniconda" -wget -O /tmp/Miniconda3-latest-Linux-x86_64.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -bash /tmp/Miniconda3-latest-Linux-x86_64.sh - -# Install napari -# conda env remove -n .venv -echo "Installing napari" -conda activate base && pip install napari[all] -sudo apt-get install -y libdbus-1-3 libxkbcommon-x11-0 libxcb-icccm4 \ - libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 \ - libxcb-xinerama0 libxcb-xinput0 libxcb-xfixes0 - -# Install xpra -echo "Installing xpra" -DISTRO=focal -sudo apt-get install apt-transport-https software-properties-common -sudo apt install ca-certificates -sudo wget -O "/usr/share/keyrings/xpra-2022.gpg" https://xpra.org/xpra-2022.gpg -sudo wget -O "/usr/share/keyrings/xpra-2018.gpg" https://xpra.org/xpra-2018.gpg -sudo wget -O "/etc/apt/sources.list.d/xpra.list" https://xpra.org/repos/$DISTRO/xpra.list -sudo apt-get update -sudo apt-get -y install xpra xterm - -# Install pytorch and cellpose -conda install pytorch torchvision torchaudio pytorch-cuda=11.6 -c pytorch -c nvidia -pip install pyqtgraph PyQt5 numpy numba scipy natsort cellpose - -# Install github CLI for cloning private repo -conda install -y gh --channel conda-forge +curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh +bash Miniconda3-latest-Linux-x86_64.sh # Login to github using tokens # gh auth login diff --git a/src/client/dcp_client/gui/napari_window.py b/src/client/dcp_client/gui/napari_window.py index 001720cf..4d5fbe81 100644 --- a/src/client/dcp_client/gui/napari_window.py +++ b/src/client/dcp_client/gui/napari_window.py @@ -4,6 +4,7 @@ from qtpy.QtWidgets import QPushButton, QComboBox, QLabel, QGridLayout from qtpy.QtCore import Qt +from qtpy.QtGui import QGuiApplication import napari import numpy as np @@ -30,6 +31,8 @@ def __init__(self, app: Application) -> None: super().__init__() self.app = app self.setWindowTitle("napari viewer") + screen_size = QGuiApplication.primaryScreen().geometry() + self.resize(int(screen_size.width()*0.9), int(screen_size.height()*0.8)) # Load image and get corresponding segmentation filenames img = self.app.load_image() @@ -38,6 +41,8 @@ def __init__(self, app: Application) -> None: # Set the viewer self.viewer = napari.Viewer(show=False) + self.viewer.window.add_plugin_dock_widget("napari-sam") + self.viewer.add_image(img, name=get_path_stem(self.app.cur_selected_img)) for seg_file in self.seg_files: self.viewer.add_labels( @@ -157,6 +162,7 @@ def axis_changed(self, event) -> None: """ self.active_mask_index = self.viewer.dims.current_step[0] masks = deepcopy(self.layer.data) + # if user has switched to the instance mask if self.active_mask_index == 0: class_mask_with_contours = Compute4Mask.add_contour(masks[1], masks[0]) @@ -166,6 +172,7 @@ def axis_changed(self, event) -> None: ): self.update_instance_mask(masks[0], masks[1]) self.switch_to_instance_mask() + # else if user has switched to the class mask elif self.active_mask_index == 1: if not check_equal_arrays( @@ -179,6 +186,8 @@ def switch_to_instance_mask(self) -> None: Switch the application to the active mask mode by enabling 'paint_button', 'erase_button' and 'fill_button'. """ + + self.original_class_mask[self.cur_selected_seg] = deepcopy(self.layer.data[1]) self.switch_controls("paint_button", True) self.switch_controls("erase_button", True) self.switch_controls("fill_button", True) @@ -187,6 +196,8 @@ def switch_to_labels_mask(self) -> None: """ Switch the application to non-active mask mode by enabling 'fill_button' and disabling 'paint_button' and 'erase_button'. """ + + self.original_instance_mask[self.cur_selected_seg] = deepcopy(self.layer.data[0]) if self.cur_selected_seg in [layer.name for layer in self.viewer.layers]: self.viewer.layers[self.cur_selected_seg].mode = "pan_zoom" info_message_paint = ( diff --git a/src/client/dcp_client/utils/compute4mask.py b/src/client/dcp_client/utils/compute4mask.py index f14bff5d..e9e4b3ff 100644 --- a/src/client/dcp_client/utils/compute4mask.py +++ b/src/client/dcp_client/utils/compute4mask.py @@ -48,8 +48,8 @@ def get_contours( contour[:, 0], contour[:, 1], contour_mask.shape ) contour_mask[rr, cc] = instance_id - except: - print("Could not create contour for instance id", instance_id) + except Exception as error: + print("Could not create contour for instance id", instance_id, ". Error is :", error) return contour_mask @staticmethod diff --git a/src/client/pyproject.toml b/src/client/pyproject.toml index 93af7bd7..8fe2f47a 100644 --- a/src/client/pyproject.toml +++ b/src/client/pyproject.toml @@ -1,47 +1,3 @@ [build-system] -requires = ["setuptools>=61.0"] +requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" - -[tool.setuptools] -packages = ['dcp_client'] - -[tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} - -[project] -name = "data-centric-platform-client" -version = "0.1" -requires-python = ">=3.9" -description = "The client of the data centric platform for microscopy image segmentation" -keywords = [] -classifiers = [ - "Programming Language :: Python :: 3", - "Operating System :: OS Independent", -] -readme = "README.md" -dynamic = ["dependencies"] -authors = [ - {name="Christina Bukas", email="christina.bukas@helmholtz-munich.de"}, - {name="Helena Pelin", email="helena.pelin@helmholtz-munich.de"}, - {name="Mariia Koren", email="mariia.koren@helmholtz-munich.de"}, - {name="Marie Piraud", email="marie.piraud@helmholtz-munich.de"}, -] -maintainers = [ - {name="Christina Bukas", email="christina.bukas@helmholtz-munich.de"}, - {name="Helena Pelin", email="helena.pelin@helmholtz-munich.de"} -] - -[project.optional-dependencies] -dev = [ - "pytest>=7.4.3", - "pytest-qt>=4.2.0", - "sphinx", - "sphinx-rtd-theme" -] - -[project.urls] -repository = "https://github.com/HelmholtzAI-Consultants-Munich/data-centric-platform" -documentation = "https://readthedocs.org/projects/data-centric-platform" - -[project.scripts] -dcp-client = "dcp_client.main:main" diff --git a/src/client/readme_figs/client_napari_viewer.png b/src/client/readme_figs/client_napari_viewer.png index 414171f1..42fcb5a6 100644 Binary files a/src/client/readme_figs/client_napari_viewer.png and b/src/client/readme_figs/client_napari_viewer.png differ diff --git a/src/client/requirements.txt b/src/client/requirements.txt deleted file mode 100644 index bfe018ab..00000000 --- a/src/client/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -napari[pyqt5]>=0.4.17 -bentoml[grpc]>=1.2.5 \ No newline at end of file diff --git a/src/client/setup.py b/src/client/setup.py new file mode 100644 index 00000000..73032334 --- /dev/null +++ b/src/client/setup.py @@ -0,0 +1,52 @@ +from setuptools import setup, find_packages + +setup( + name="data-centric-platform-client", + version="0.1", + description="The client of the data centric platform for microscopy image segmentation", + author=["Christina Bukas", + "Helena Pelin", + "Mariia Koren", + "Marie Piraud"], + author_email= ["christina.bukas@helmholtz-munich.de", + "helena.pelin@helmholtz-munich.de", + "mariia.koren@helmholtz-munich.de", + "marie.piraud@helmholtz-munich.de"], + url="https://github.com/HelmholtzAI-Consultants-Munich/data-centric-platform", + packages=find_packages(), + install_requires=[ + "matplotlib >=3.3", + "napari[pyqt5]>=0.4.17", + "segment-anything @ git+https://github.com/facebookresearch/segment-anything.git@main", + "torch", + "torchvision", + "napari-sam @ git+https://github.com/christinab12/napari-sam.git@main", + "bentoml[grpc]>=1.2.5", + ], + extras_require={ + "dev": [ + "pytest>=7.4.3", + "pytest-qt>=4.2.0", + "sphinx", + "sphinx-rtd-theme", + ] + }, + entry_points={ + "console_scripts": [ + "dcp-client=dcp_client.main:main", + ] + }, + python_requires=">=3.9", + keywords=[], + classifiers=[ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", + ], + long_description=open("README.md").read(), + maintainer=["Christina Bukas", "Helena Pelin"], + maintainer_email=["christina.bukas@helmholtz-munich.de", "helena.pelin@helmholtz-munich.de"], + project_urls={ + "Repository": "https://github.com/HelmholtzAI-Consultants-Munich/data-centric-platform", + "Documentation": "https://readthedocs.org/projects/data-centric-platform", + } +) diff --git a/src/server/dcp_server/service.py b/src/server/dcp_server/service.py index d464545b..16f7e3b0 100644 --- a/src/server/dcp_server/service.py +++ b/src/server/dcp_server/service.py @@ -1,23 +1,24 @@ from __future__ import annotations -import bentoml +import os import typing as t -from dcp_server.serviceclasses import CustomBentoService, CustomRunnable +import bentoml +from dcp_server.serviceclasses import CustomBentoService, CustomRunnable from dcp_server.utils.fsimagestorage import FilesystemImageStorage from dcp_server.utils.helpers import read_config -import sys, inspect models_module = __import__("models") segmentation_module = __import__("segmentationclasses") # Import configuration -service_config = read_config("service", config_path="config.yaml") -model_config = read_config("model", config_path="config.yaml") -data_config = read_config("data", config_path="config.yaml") -train_config = read_config("train", config_path="config.yaml") -eval_config = read_config("eval", config_path="config.yaml") -setup_config = read_config("setup", config_path="config.yaml") +rel_path = os.path.dirname(os.path.realpath(__file__)) +service_config = read_config("service", config_path=os.path.join(rel_path, "config.yaml")) +model_config = read_config("model", config_path=os.path.join(rel_path, "config.yaml")) +data_config = read_config("data", config_path=os.path.join(rel_path, "config.yaml")) +train_config = read_config("train", config_path=os.path.join(rel_path, "config.yaml")) +eval_config = read_config("eval", config_path=os.path.join(rel_path, "config.yaml")) +setup_config = read_config("setup", config_path=os.path.join(rel_path, "config.yaml")) # instantiate the model diff --git a/src/server/test/configs/test_config_MultiCellpose.yaml b/src/server/test/configs/test_config_MultiCellpose.yaml index 46b913d7..6cff5706 100644 --- a/src/server/test/configs/test_config_MultiCellpose.yaml +++ b/src/server/test/configs/test_config_MultiCellpose.yaml @@ -31,7 +31,7 @@ "train":{ "segmentor":{ - "n_epochs": 30, + "n_epochs": 50, "channels": [0,0], "min_train_masks": 1, "learning_rate":0.01