diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4202f04e..7053663e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: rev: 5.12.0 hooks: - id: isort - args: ["--profile", "black", --line-length=72] + args: ["--profile", "black", --line-length=79] - repo: https://github.com/charliermarsh/ruff-pre-commit # Ruff version. rev: 'v0.0.262' diff --git a/README.md b/README.md index 0654ad41..011f072c 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,15 @@ A napari plugin for 3D cell segmentation: training, inference, and data review. ## Installation -Note : we recommend using conda to create a new environment for the plugin. +**Note** : we recommend using conda to create a new environment for the plugin. +**M1 Mac users, please see the [M1 install section](#m1-mac-users)** conda create --name napari-cellseg3d python=3.8 conda activate napari-cellseg3d You can install `napari-cellseg3d` via [pip]: - pip install napari-cellseg3d + pip install napari-cellseg3d[all] OR directly via [napari-hub]: @@ -44,12 +45,25 @@ OR directly via [napari-hub]: then from the “Plugins” menu within the napari application, select “Install/Uninstall Package(s)...” - Copy `napari-cellseg3d` and paste it where it says “Install by name/url…” - Click “Install” +- Restart napari + +### M1 Mac users + +Create a new conda env using the provided conda/napari_cellseg3d_m1.yml file : + + conda env create -f conda/napari_cellseg3d_m1.yml + conda activate napari_cellseg3d_m1 + +Then install PyQt5 from conda separately : + + conda install -c anaconda PyQt5 + ## Documentation Available at https://AdaptiveMotorControlLab.github.io/CellSeg3d -You can also generate docs by running ``make html`` in the docs folder. +You can also generate docs by running ``make html`` in the docs/ folder. ## Usage diff --git a/conda/napari_cellseg3d_m1.yml b/conda/napari_cellseg3d_m1.yml new file mode 100644 index 00000000..8209be9e --- /dev/null +++ b/conda/napari_cellseg3d_m1.yml @@ -0,0 +1,26 @@ +name: napari_cellseg3d_m1 +channels: + - anaconda + - conda-forge + - defaults +dependencies: + - python=3.8 + - pip + - pip: + - numpy + - napari>=0.4.14 + - QtPy + - opencv-python>=4.5.5 + - scikit-image>=0.19.2 + - matplotlib>=3.4.1 + - tifffile>=2022.2.9 + - imageio-ffmpeg>=0.4.5 + - torch>=1.11 + - monai[nibabel,einops]>=0.9.0 + - tqdm + - nibabel + - scikit-image + - pillow + - tqdm + - matplotlib + - vispy>=0.9.6 diff --git a/napari_cellseg3d/code_models/model_workers.py b/napari_cellseg3d/code_models/model_workers.py index 8b1caf8e..c5675a11 100644 --- a/napari_cellseg3d/code_models/model_workers.py +++ b/napari_cellseg3d/code_models/model_workers.py @@ -457,6 +457,7 @@ def model_output( # self.config.model_info.get_model().get_output(model, inputs) # ) + def model_output(inputs): return post_process_transforms( self.config.model_info.get_model().get_output(model, inputs) diff --git a/napari_cellseg3d/code_plugins/plugin_base.py b/napari_cellseg3d/code_plugins/plugin_base.py index 7c5fbaa5..5191e66f 100644 --- a/napari_cellseg3d/code_plugins/plugin_base.py +++ b/napari_cellseg3d/code_plugins/plugin_base.py @@ -118,6 +118,7 @@ def show_menu(_, event): def _build_io_panel(self): self.io_panel = ui.GroupedWidget("Data") + self.save_label = ui.make_label("Save location :", parent=self) # self.io_panel.setToolTip("IO Panel") @@ -130,6 +131,7 @@ def _build_io_panel(self): self.filetype_choice, self.image_filewidget, self.labels_filewidget, + self.save_label, self.results_filewidget, ], ) diff --git a/napari_cellseg3d/code_plugins/plugin_crop.py b/napari_cellseg3d/code_plugins/plugin_crop.py index 5f502978..97485bf4 100644 --- a/napari_cellseg3d/code_plugins/plugin_crop.py +++ b/napari_cellseg3d/code_plugins/plugin_crop.py @@ -440,8 +440,8 @@ def _add_crop_sliders( for i in range(len(crop_sizes)): if crop_sizes[i] > im1_stack.shape[i]: crop_sizes[i] = im1_stack.shape[i] - warnings.warn( - f"WARNING : Crop dimension in axis {i} was too large at {crop_sizes[i]}, it was set to {im1_stack.shape[i]}" + logger.warning( + f"Crop dimension in axis {i} was too large at {crop_sizes[i]}, it was set to {im1_stack.shape[i]}" ) cropx, cropy, cropz = crop_sizes diff --git a/napari_cellseg3d/dev_scripts/convert.py b/napari_cellseg3d/dev_scripts/convert.py index 129c16be..d772a1c2 100644 --- a/napari_cellseg3d/dev_scripts/convert.py +++ b/napari_cellseg3d/dev_scripts/convert.py @@ -2,7 +2,7 @@ import os import numpy as np -from dask_image.imread import imread +from tifffile import imread from tifffile import imwrite # input_seg_path = "C:/Users/Cyril/Desktop/Proj_bachelor/code/pytorch-test3dunet/cropped_visual/train/lab" @@ -19,8 +19,8 @@ filenames.append(os.path.basename(filename)) # print(os.path.basename(filename)) for file in paths: - img = imread(file) - image = img.compute() + image = imread(file) + # image = img.compute() image[image >= 1] = 1 image = image.astype(np.uint16) diff --git a/napari_cellseg3d/dev_scripts/view_brain.py b/napari_cellseg3d/dev_scripts/view_brain.py index e5879638..145d4e45 100644 --- a/napari_cellseg3d/dev_scripts/view_brain.py +++ b/napari_cellseg3d/dev_scripts/view_brain.py @@ -1,5 +1,5 @@ import napari -from dask_image.imread import imread +from tifffile import imread y = imread("/Users/maximevidal/Documents/3drawdata/wholebrain.tif") diff --git a/napari_cellseg3d/dev_scripts/view_sample.py b/napari_cellseg3d/dev_scripts/view_sample.py index 329944ac..8e87f85c 100644 --- a/napari_cellseg3d/dev_scripts/view_sample.py +++ b/napari_cellseg3d/dev_scripts/view_sample.py @@ -1,5 +1,5 @@ import napari -from dask_image.imread import imread +from tifffile import imread # Visual x = imread( diff --git a/napari_cellseg3d/utils.py b/napari_cellseg3d/utils.py index 7897fdf3..6a3b57d3 100644 --- a/napari_cellseg3d/utils.py +++ b/napari_cellseg3d/utils.py @@ -4,7 +4,6 @@ from pathlib import Path import numpy as np -from dask_image.imread import imread as dask_imread from pandas import DataFrame from pandas import Series from skimage import io @@ -301,7 +300,7 @@ def check_csv(project_path, ext): filename_pattern_original = Path(project_path) / Path( f"dataset/Original_size/Original/*{ext}" ) - images_original = dask_imread(filename_pattern_original) + images_original = tfl_imread(filename_pattern_original) z, y, x = images_original.shape record = Series( [ @@ -426,7 +425,9 @@ def get_time_filepath(): return "{:%H_%M_%S}".format(datetime.now()) -def load_images(dir_or_path, filetype="", as_folder: bool = False): +def load_images( + dir_or_path, filetype="", as_folder: bool = False +): # TODO(cyril):refactor w/o as_folder """Loads the images in ``directory``, with different behaviour depending on ``filetype`` and ``as_folder`` * If ``as_folder`` is **False**, will load the path as a single 3D **.tif** image. @@ -446,7 +447,7 @@ def load_images(dir_or_path, filetype="", as_folder: bool = False): as_folder (bool): Whether to load a folder of images as stack or a single 3D image Returns: - dask.array.Array: dask array with loaded images + np.array: array with loaded images """ if not as_folder: @@ -459,7 +460,12 @@ def load_images(dir_or_path, filetype="", as_folder: bool = False): raise ValueError("If loading as a folder, filetype must be specified") if as_folder: - images_original = dask_imread(filename_pattern_original) + try: + images_original = tfl_imread(filename_pattern_original) + except ValueError: + LOGGER.error( + "Loading a stack this way is no longer supported. Use napari to load a stack." + ) else: images_original = tfl_imread( filename_pattern_original diff --git a/notebooks/full_plot.ipynb b/notebooks/full_plot.ipynb index 857384d4..5c640e1b 100644 --- a/notebooks/full_plot.ipynb +++ b/notebooks/full_plot.ipynb @@ -11,9 +11,21 @@ "import os\n", "import numpy as np\n", "from PIL import Image\n", - "from dask_image.imread import imread" + "from tifffile import imread" ] }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import sys\n", + "!{sys.executable} -m pip install plotly" + ], + "metadata": { + "collapsed": false + } + }, { "cell_type": "markdown", "id": "cb6ce5bf-0a09-46a4-988c-2183d09a8211", diff --git a/pyproject.toml b/pyproject.toml index 4ecb1b86..11b8dced 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,17 +9,15 @@ authors = [ requires-python = ">=3.8" dependencies = [ "numpy", - "napari[all]>=0.4.14", + "napari>=0.4.14", "QtPy", "opencv-python>=4.5.5", - "dask-image>=0.6.0", "scikit-image>=0.19.2", "matplotlib>=3.4.1", "tifffile>=2022.2.9", "imageio-ffmpeg>=0.4.5", "torch>=1.11", "monai[nibabel,einops]>=0.9.0", - "itk", "tqdm", "nibabel", "scikit-image", @@ -54,10 +52,14 @@ profile = "black" line_length = 79 [project.optional-dependencies] +all = [ + "napari[all]>=0.4.14", +] dev = [ "isort", "black", "ruff", + "tuna", "pre-commit", ] docs = [ diff --git a/requirements.txt b/requirements.txt index 3ba73405..f97de33c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,6 @@ matplotlib>=3.4.1 tifffile>=2022.2.9 imageio-ffmpeg>=0.4.5 torch>=1.11 -monai[nibabel,scikit-image,itk,einops]>=0.9.0 +monai[nibabel,scikit-image,einops]>=0.9.0 pillow vispy>=0.9.6 diff --git a/setup.cfg b/setup.cfg index e12775ca..3a0bdaae 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,35 +1,3 @@ -[metadata] -name = napari-cellseg3d -version = 0.0.2rc6 -author = Cyril Achard, Maxime Vidal, Jessy Lauer, Mackenzie Mathis -author_email = cyril.achard@epfl.ch, maxime.vidal@epfl.ch, mackenzie@post.harvard.edu - -license = MIT -description = plugin for cell segmentation -long_description = file: README.md -long_description_content_type = text/markdown -classifiers = - Development Status :: 2 - Pre-Alpha - Intended Audience :: Science/Research - Framework :: napari - Topic :: Software Development :: Testing - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Operating System :: OS Independent - License :: OSI Approved :: MIT License - Topic :: Scientific/Engineering :: Artificial Intelligence - Topic :: Scientific/Engineering :: Image Processing - Topic :: Scientific/Engineering :: Visualization - -url = https://github.com/AdaptiveMotorControlLab/CellSeg3d -project_urls = - Bug Tracker = https://github.com/AdaptiveMotorControlLab/CellSeg3d/issues - Documentation = https://adaptivemotorcontrollab.github.io/cellseg3d-docs/res/welcome.html - Source Code = https://github.com/AdaptiveMotorControlLab/CellSeg3d - [options] packages = find: include_package_data = True @@ -37,38 +5,9 @@ python_requires = >=3.8 package_dir = =. -# add your package requirements here -# the long list after monai is due to monai optional requirements... Not sure how to know in advance which readers it wil use -install_requires = - numpy - napari[all]>=0.4.14 - QtPy - opencv-python>=4.5.5 - dask-image>=0.6.0 - scikit-image>=0.19.2 - matplotlib>=3.4.1 - tifffile>=2022.2.9 - imageio-ffmpeg>=0.4.5 - torch>=1.11 - monai[nibabel,einops]>=0.9.0 - itk - tqdm - nibabel - scikit-image - pillow - tqdm - matplotlib - vispy>=0.9.6 - [options.packages.find] where = . -[options.package_data] -napari-cellseg3d = - res/*.png - code_models/models/pretrained/*.json - napari.yaml - [options.entry_points] napari.manifest = napari-cellseg3d = napari_cellseg3d:napari.yaml diff --git a/tox.ini b/tox.ini index 3409f43c..292b8fa4 100644 --- a/tox.ini +++ b/tox.ini @@ -29,7 +29,7 @@ passenv = deps = pytest # https://docs.pytest.org/en/latest/contents.html pytest-cov # https://pytest-cov.readthedocs.io/en/latest/ - dask-image +; dask-image ; # you can remove these if you don't use them napari PyQt5