small-fish-gui 1.10.4__tar.gz → 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/PKG-INFO +14 -16
  2. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/README.md +1 -3
  3. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/pyproject.toml +23 -13
  4. small_fish_gui-2.0.1/src/small_fish_gui/README.md +77 -0
  5. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/__init__.py +1 -1
  6. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/__main__.py +1 -1
  7. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/integrity.py +8 -1
  8. small_fish_gui-2.0.1/src/small_fish_gui/batch/output.py +16 -0
  9. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/pipeline.py +43 -24
  10. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/prompt.py +44 -26
  11. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/update.py +19 -3
  12. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/utils.py +2 -0
  13. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/values.txt +5 -5
  14. small_fish_gui-2.0.1/src/small_fish_gui/default_values.py +51 -0
  15. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/__init__.py +3 -1
  16. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/_napari_widgets.py +15 -4
  17. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/layout.py +123 -54
  18. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/napari_visualiser.py +12 -8
  19. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/prompts.py +61 -74
  20. small_fish_gui-2.0.1/src/small_fish_gui/gui/tooltips.py +15 -0
  21. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/hints.py +23 -4
  22. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/DetectionVitrine_filtre.png +0 -0
  23. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/DetectionVitrine_signal.png +0 -0
  24. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/FocciVitrine.png +0 -0
  25. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/FocciVitrine_no_spots.png +0 -0
  26. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/Segmentation2D.png +0 -0
  27. small_fish_gui-2.0.1/src/small_fish_gui/illustrations/Segmentation2D_with_labels.png +0 -0
  28. small_fish_gui-2.0.1/src/small_fish_gui/logo.png +0 -0
  29. small_fish_gui-1.10.4/src/small_fish_gui/pipeline/main.py → small_fish_gui-2.0.1/src/small_fish_gui/main_menu.py +16 -15
  30. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/_colocalisation.py +60 -41
  31. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/_preprocess.py +13 -12
  32. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/actions.py +102 -14
  33. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/detection.py +5 -1
  34. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/segmentation.py +206 -73
  35. small_fish_gui-2.0.1/src/small_fish_gui/pipeline/spots.py +205 -0
  36. small_fish_gui-2.0.1/src/small_fish_gui/pipeline/testing.ipynb +3636 -0
  37. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/requirements.txt +4 -4
  38. small_fish_gui-1.10.4/src/small_fish_gui/README.md +0 -105
  39. small_fish_gui-1.10.4/src/small_fish_gui/pipeline/spots.py +0 -81
  40. small_fish_gui-1.10.4/src/small_fish_gui/pipeline/testing.ipynb +0 -2067
  41. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/LICENSE +0 -0
  42. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/error_log.txt +0 -0
  43. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/.github/workflows/python-publish.yml +0 -0
  44. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/LICENSE +0 -0
  45. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/__init__.py +0 -0
  46. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/input.py +0 -0
  47. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/batch/test.py +0 -0
  48. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/animation.py +0 -0
  49. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/screenshot/general_help_screenshot.png +0 -0
  50. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/screenshot/mapping_help_screenshot.png +0 -0
  51. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/screenshot/segmentation_help_screenshot.png +0 -0
  52. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/testing.ipynb +0 -0
  53. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/gui/theme.py +0 -0
  54. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/interface/__init__.py +0 -0
  55. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/interface/image.py +0 -0
  56. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/interface/inoutput.py +0 -0
  57. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/interface/testing.py +0 -0
  58. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/__init__.py +0 -0
  59. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/_custom_errors.py +0 -0
  60. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/_signaltonoise.py +0 -0
  61. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/test.py +0 -0
  62. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/pipeline/utils.py +0 -0
  63. {small_fish_gui-1.10.4 → small_fish_gui-2.0.1}/src/small_fish_gui/utils.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: small_fish_gui
3
- Version: 1.10.4
3
+ Version: 2.0.1
4
4
  Summary: Small Fish is a python application for the analysis of smFish images. It provides a ready to use graphical interface to combine famous python packages for cell analysis without any need for coding.
5
- Project-URL: Homepage, https://github.com/2Echoes/small_fish
6
- Project-URL: Wiki, https://github.com/2Echoes/small_fish_gui/wiki
7
- Project-URL: Issues, https://github.com/2Echoes/small_fish/issues
5
+ Project-URL: Homepage, https://github.com/SmallFishGUI/small_fish
6
+ Project-URL: Wiki, https://github.com/SmallFishGUI/small_fish_gui/wiki
7
+ Project-URL: Issues, https://github.com/SmallFishGUI/small_fish/issues
8
8
  Author-email: Slimani Floric <floric.slimani@live.com>
9
9
  License-File: LICENSE
10
10
  Classifier: License :: OSI Approved :: BSD License
@@ -12,24 +12,24 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Requires-Python: >=3.9
14
14
  Requires-Dist: aicsimageio>=4.14.0
15
- Requires-Dist: aicspylibczi==3.3.1
15
+ Requires-Dist: aicspylibczi>=3.3.1
16
16
  Requires-Dist: big-fish==0.6.2
17
- Requires-Dist: cellpose==3.0.7
18
- Requires-Dist: czifile==2019.7.2
17
+ Requires-Dist: cellpose>=4.0.6
18
+ Requires-Dist: czifile>=2019.7.2
19
19
  Requires-Dist: freesimplegui>=5.1.1
20
- Requires-Dist: imageio==2.34.0
20
+ Requires-Dist: imageio>=2.34.0
21
21
  Requires-Dist: napari-console>=0.0.9
22
22
  Requires-Dist: napari-plugin-engine>=0.2.0
23
23
  Requires-Dist: napari-plugin-manager>=0.1.0a2
24
24
  Requires-Dist: napari-svg>=0.1.10
25
25
  Requires-Dist: napari>=0.4.19.post1
26
26
  Requires-Dist: numpy>=1.24.4
27
- Requires-Dist: openpyxl==3.1.2
27
+ Requires-Dist: openpyxl>=3.1.2
28
28
  Requires-Dist: pandas>=1.5.3
29
- Requires-Dist: pyarrow==11.0.0
30
- Requires-Dist: scikit-image==0.19.1
31
- Requires-Dist: scikit-learn==1.3.2
32
- Requires-Dist: scipy>=1.9.1
29
+ Requires-Dist: pyarrow>=11.0.0
30
+ Requires-Dist: scikit-image>=0.19.1
31
+ Requires-Dist: scikit-learn>=1.3.2
32
+ Requires-Dist: scipy==1.9.1
33
33
  Description-Content-Type: text/markdown
34
34
 
35
35
  # Small Fish
@@ -39,7 +39,7 @@ Cell segmentation is peformed using *cellpose* (published work) : https://github
39
39
 
40
40
  Spot detection is performed via *big-fish* (published work) : https://github.com/fish-quant/big-fish
41
41
 
42
- Time stacks are not yet supported.
42
+ Time stacks are not supported.
43
43
 
44
44
  ## Installation
45
45
 
@@ -72,6 +72,4 @@ python -m small_fish
72
72
  ## Developpement
73
73
 
74
74
  Optional features to include in future versions :
75
- - batch processing
76
75
  - time stack (which would include cell tracking)
77
- - 3D segmentation
@@ -5,7 +5,7 @@ Cell segmentation is peformed using *cellpose* (published work) : https://github
5
5
 
6
6
  Spot detection is performed via *big-fish* (published work) : https://github.com/fish-quant/big-fish
7
7
 
8
- Time stacks are not yet supported.
8
+ Time stacks are not supported.
9
9
 
10
10
  ## Installation
11
11
 
@@ -38,6 +38,4 @@ python -m small_fish
38
38
  ## Developpement
39
39
 
40
40
  Optional features to include in future versions :
41
- - batch processing
42
41
  - time stack (which would include cell tracking)
43
- - 3D segmentation
@@ -1,10 +1,11 @@
1
1
  [build-system]
2
2
  requires = ["hatchling"]
3
3
  build-backend = "hatchling.build"
4
+ #requires = ["setuptools>=61.2", "wheel"]
4
5
 
5
6
  [project]
6
7
  name = "small_fish_gui"
7
- version = "1.10.4"
8
+ version = "2.0.1"
8
9
  authors = [
9
10
  { name="Slimani Floric", email="floric.slimani@live.com" },
10
11
  ]
@@ -18,9 +19,9 @@ classifiers = [
18
19
  ]
19
20
  dependencies = [
20
21
  "big-fish==0.6.2",
21
- "cellpose==3.0.7",
22
- "czifile==2019.7.2",
23
- "imageio==2.34.0",
22
+ "cellpose>=4.0.6",
23
+ "czifile>=2019.7.2",
24
+ "imageio>=2.34.0",
24
25
  "napari>=0.4.19.post1",
25
26
  "napari-console>=0.0.9",
26
27
  "napari-plugin-engine>=0.2.0",
@@ -29,16 +30,25 @@ dependencies = [
29
30
  "numpy>=1.24.4",
30
31
  "pandas>=1.5.3",
31
32
  "FreeSimpleGUI>=5.1.1",
32
- "scipy>=1.9.1",
33
- "scikit-image==0.19.1",
34
- "scikit-learn==1.3.2",
35
- "openpyxl==3.1.2",
36
- "pyarrow==11.0.0",
33
+ "scipy == 1.9.1",
34
+ "scikit-image>=0.19.1",
35
+ "scikit-learn>=1.3.2",
36
+ "openpyxl>=3.1.2",
37
+ "pyarrow>=11.0.0",
37
38
  "aicsimageio>=4.14.0",
38
- "aicspylibczi==3.3.1",
39
+ "aicspylibczi>=3.3.1",
39
40
  ]
40
41
 
42
+
43
+
41
44
  [project.urls]
42
- Homepage = "https://github.com/2Echoes/small_fish"
43
- Wiki = "https://github.com/2Echoes/small_fish_gui/wiki"
44
- Issues = "https://github.com/2Echoes/small_fish/issues"
45
+ Homepage = "https://github.com/SmallFishGUI/small_fish"
46
+ Wiki = "https://github.com/SmallFishGUI/small_fish_gui/wiki"
47
+ Issues = "https://github.com/SmallFishGUI/small_fish/issues"
48
+
49
+ [tool.setuptools]
50
+ include-package-data = false
51
+
52
+ [tool.setuptools.packages.find]
53
+ include = ["sepal_ui*"]
54
+ exclude = ["logo*", "illustrations*"]
@@ -0,0 +1,77 @@
1
+ # Small Fish - A User-Friendly Graphical Interface for smFISH Image Quantification
2
+
3
+ [![License: BSD-2-Clause](https://img.shields.io/badge/License-BSD_2--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause)
4
+ [![GitHub stars](https://img.shields.io/github/stars/SmallFishGUI/small_fish_gui.svg?style=social)](https://github.com/SmallFishGUI/small_fish_gui) [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
5
+
6
+ **Small Fish** is a python application for smFish image analysis. It provides a ready to use graphical interface to synthetize state-of-the-art scientific packages into an automated workflow. Small Fish is designed to simplify images quantification and analysis for people without coding skills.
7
+
8
+ Cell segmentation is peformed in 2D and 3D throught cellpose 4.0+(published work) : https://github.com/MouseLand/cellpose; compatible with your own cellpose models.
9
+
10
+ Spot detection is performed via *big-fish* a python implementation of FishQuant (published work) : https://github.com/fish-quant/big-fish.
11
+
12
+ ***The workflow is fully explained in the [wiki](https://github.com/2Echoes/small_fish_gui/wiki) ! Make sure to check it out.***
13
+
14
+ ## What can you do with small fish ?
15
+
16
+ ✅ Single molecule quantification
17
+ ✅ Transcriptomics
18
+ ✅ Foci quantification
19
+ ✅ Transcription sites quantification
20
+ ✅ Nuclear signal quantification
21
+ ✅ Signal to noise analysis
22
+ ✅ Cell segmentation
23
+ ✅ Multichannel colocalisation
24
+
25
+ <p align="center">
26
+ <img src="https://raw.githubusercontent.com/SmallFishGUI/small_fish_gui/main/illustrations/Segmentation2D.png" width="500" title="Fish_signal" alt="Fish signal">
27
+ </p>
28
+ <p align="center"><strong>Raw 3D fish signal with dapi</p></strong>
29
+
30
+ <p align="center">
31
+ <img src="https://raw.githubusercontent.com/SmallFishGUI/small_fish_gui/main/illustrations/Segmentation2D_with_labels.png" width="500" title="Cell segmentation" alt="Segmentation">
32
+ </p>
33
+ <p align="center"><strong>2D segmentation</p></strong>
34
+
35
+ <p align="center">
36
+ <img src="https://raw.githubusercontent.com/SmallFishGUI/small_fish_gui/main/illustrations/FocciVitrine.png" width="500" title="Detection_signal" alt="Detection_signal">
37
+ </p>
38
+ <p align="center"><strong> 3D Spot detection</p></strong>
39
+
40
+ <p align="center">
41
+ <img src="https://raw.githubusercontent.com/SmallFishGUI/small_fish_gui/main/illustrations/FocciVitrine_no_spots.png" width="500" title="Detection filter" alt="detection">
42
+ </p>
43
+ <p align="center"><strong>Cluster detection</p></strong>
44
+
45
+ Analysis can be performed either fully interactively throught a Napari interface or performed automatically through a batch processing allowing for reproducible quantifications.
46
+
47
+ ## Installation
48
+ If you don't have a python installation yet I would recommend the [miniconda distribution](https://docs.anaconda.com/free/miniconda/miniconda-other-installer-links/).
49
+
50
+ It is higly recommanded to create a specific [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html) or [virtual](https://docs.python.org/3.6/library/venv.html) environnement to install small fish.
51
+
52
+ ```bash
53
+ conda create -n small_fish python=3.9
54
+ conda activate small_fish
55
+ ```
56
+ Then download the small_fish package :
57
+ ```bash
58
+ pip install small_fish_gui
59
+ ```
60
+ <b> (Recommended) </b> Results visualisation is achieved through *Napari* which you can install with :
61
+
62
+ ```bash
63
+ pip install napari[all]
64
+ ```
65
+
66
+ ## Run Small fish
67
+
68
+ First activate your python environnement :
69
+ ```bash
70
+ conda activate small_fish
71
+ ```
72
+ Then launch Small fish :
73
+ ```bash
74
+ python -m small_fish_gui
75
+ ```
76
+
77
+ You are all set! Try it yourself or check the [get started](https://github.com/2Echoes/small_fish_gui/wiki/Get-started) section in the wiki.
@@ -37,7 +37,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37
37
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38
38
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
39
  """
40
- __version__ = "1.10.4"
40
+ __version__ = "2.0.1"
41
41
  __wiki__ = "https://github.com/2Echoes/small_fish_gui/wiki"
42
42
 
43
43
  import os
@@ -9,7 +9,7 @@ AVAILABLE_ARGUMENTS = {
9
9
 
10
10
 
11
11
  def main():
12
- import small_fish_gui.pipeline.main
12
+ import small_fish_gui.main_menu
13
13
 
14
14
  def _get_version() :
15
15
  return __version__
@@ -63,11 +63,18 @@ def check_channel_map_integrity(
63
63
  ) :
64
64
 
65
65
  #Check integrity
66
- channels_values = np.array(list(maping.values()), dtype= int)
66
+ try :
67
+ channels_values = np.array(list(maping.values()), dtype= int)
68
+ except Exception :
69
+ res = False
70
+ sg.popup("Incorrect values for channel mapping. ({0})".format(maping.values()))
71
+ return res
72
+
67
73
  total_channels = len(maping)
68
74
  unique_channel = len(np.unique(channels_values))
69
75
  res= True
70
76
 
77
+
71
78
  if expected_dim != total_channels :
72
79
  sg.popup("Image has {0} dimensions but {1} were mapped.".format(expected_dim, total_channels))
73
80
  res = False
@@ -0,0 +1,16 @@
1
+ import numpy as np
2
+ import os
3
+
4
+ def output_masks(
5
+ batch_path : str,
6
+ acquisition_name : str,
7
+ nucleus_label : np.ndarray,
8
+ cytoplasm_label : np.ndarray = None,
9
+ ) :
10
+
11
+ os.makedirs(batch_path + "/segmentation_masks/", exist_ok=True)
12
+ output_path = batch_path + "/segmentation_masks/{0}".format(acquisition_name)
13
+
14
+ np.save(output_path + "_nucleus.npy", arr= nucleus_label)
15
+ if type(cytoplasm_label) != type(None) :
16
+ np.save(output_path + "_cytoplasm.npy", arr= cytoplasm_label)
@@ -2,13 +2,15 @@
2
2
  Submodule keeping necessary calls from main pipeline for batch processing.
3
3
  """
4
4
 
5
- import os
5
+ import os, traceback
6
6
  import pandas as pd
7
7
  import FreeSimpleGUI as sg
8
+ import numpy as np
8
9
 
9
10
  from ..hints import pipeline_parameters
10
11
 
11
12
  from .input import open_image
13
+ from .output import output_masks
12
14
  from ..interface import write_results
13
15
  from ..pipeline import reorder_shape, reorder_image_stack, prepare_image_detection
14
16
  from ..pipeline import cell_segmentation, launch_detection, launch_features_computation
@@ -17,6 +19,7 @@ from ..pipeline import get_nucleus_signal
17
19
  from ..pipeline import _cast_segmentation_parameters, convert_parameters_types
18
20
  from ..pipeline import plot_segmentation, output_spot_tiffvisual
19
21
  from ..utils import get_datetime
22
+ from .utils import clean_filename
20
23
 
21
24
  def window_print(window: sg.Window, *args) :
22
25
  print(*args)
@@ -62,7 +65,6 @@ def batch_pipeline(
62
65
  filenames_list.sort()
63
66
 
64
67
 
65
- error_log = open(main_dir + "error_log", mode='w')
66
68
  error_count = 0
67
69
 
68
70
  #These columns usually kept for coloc analysis will be dropped for memory gain in batch mode
@@ -100,11 +102,18 @@ def batch_pipeline(
100
102
  cytoplasm_label, nucleus_label = cell_segmentation(
101
103
  im_seg,
102
104
  cyto_model_name= parameters['cyto_model_name'],
103
- cyto_diameter= parameters['cytoplasm diameter'],
105
+ cyto_diameter= parameters['cytoplasm_diameter'],
104
106
  nucleus_model_name= parameters['nucleus_model_name'],
105
- nucleus_diameter= parameters['nucleus diameter'],
106
- channels=[parameters['cytoplasm channel'], parameters['nucleus channel']],
107
- do_only_nuc=parameters['Segment only nuclei']
107
+ nucleus_diameter= parameters['nucleus_diameter'],
108
+ channels=[parameters['cytoplasm_channel'], parameters['nucleus_channel']],
109
+ anisotropy= parameters['anisotropy'],
110
+ nucleus_3D_segmentation=parameters['nucleus_segmentation_3D'],
111
+ cyto_3D_segmentation= parameters['cytoplasm_segmentation_3D'],
112
+ do_only_nuc=parameters['segment_only_nuclei'],
113
+ flow_threshold_cyto=parameters['flow_threshold_cyto'],
114
+ flow_threshold_nuc=parameters['flow_threshold_cyto'],
115
+ cellprob_threshold_cyto=parameters['cellprob_threshold_cyto'],
116
+ cellprob_threshold_nuc=parameters['cellprob_threshold_nuc'],
108
117
  )
109
118
 
110
119
  parameters['segmentation_done'] = True
@@ -117,12 +126,20 @@ def batch_pipeline(
117
126
 
118
127
  if parameters['save segmentation'] :
119
128
  plot_segmentation(
120
- cyto_image=im_seg[parameters['cytoplasm channel']],
129
+ cyto_image=im_seg[parameters['cytoplasm_channel']],
121
130
  cyto_label= cytoplasm_label,
122
- nuc_image= im_seg[parameters['nucleus channel']],
131
+ nuc_image= im_seg[parameters['nucleus_channel']],
123
132
  nuc_label=nucleus_label,
124
- path= main_dir + "segmentation/" + file,
125
- do_only_nuc= parameters['Segment only nuclei'],
133
+ path= main_dir + "segmentation/" + clean_filename(file),
134
+ do_only_nuc= parameters['segment_only_nuclei'],
135
+ )
136
+
137
+ if parameters["save_masks"] :
138
+ output_masks(
139
+ batch_path= main_dir,
140
+ acquisition_name= clean_filename(file),
141
+ nucleus_label= nucleus_label,
142
+ cytoplasm_label= cytoplasm_label if not parameters['segment_only_nuclei'] else None,
126
143
  )
127
144
 
128
145
  else :
@@ -161,7 +178,7 @@ def batch_pipeline(
161
178
  image,
162
179
  spots_list= spots_list,
163
180
  dot_size=2,
164
- path_output= main_dir + "detection/" + file + "_spot_detection.tiff"
181
+ path_output= main_dir + "detection/" + clean_filename(file) + "_spot_detection.tiff"
165
182
  )
166
183
 
167
184
  #4. Spots extraction
@@ -172,8 +189,7 @@ def batch_pipeline(
172
189
  #Only spots have one file per image to avoir memory overload
173
190
  parameters['do_spots_excel'] = parameters['xlsx']
174
191
  parameters['do_spots_csv'] = parameters['csv']
175
- parameters['do_spots_feather'] = parameters['feather']
176
- parameters['spots_filename'] = "spots_extractions_{0}".format(file)
192
+ parameters['spots_filename'] = "spots_extractions_{0}".format(clean_filename(file))
177
193
  parameters['spots_extraction_folder'] = main_dir + "results/spots_extraction/"
178
194
 
179
195
  launch_spots_extraction(
@@ -195,8 +211,8 @@ def batch_pipeline(
195
211
  spots=spots,
196
212
  clusters=clusters,
197
213
  spots_cluster_id=spot_cluster_id,
198
- nucleus_label = nucleus_label,
199
- cell_label= cytoplasm_label,
214
+ nucleus_label = nucleus_label if nucleus_label.ndim == 2 else np.max(nucleus_label,axis=0),
215
+ cell_label= cytoplasm_label if cytoplasm_label.ndim == 2 else np.max(cytoplasm_label, axis=0),
200
216
  user_parameters=parameters,
201
217
  frame_results=frame_result,
202
218
  )
@@ -226,7 +242,6 @@ def batch_pipeline(
226
242
  path= main_dir + "results/",
227
243
  filename=batch_name,
228
244
  do_excel= parameters["xlsx"],
229
- do_feather= parameters["feather"],
230
245
  do_csv= parameters["csv"],
231
246
  overwrite=True,
232
247
  batch_mode=True,
@@ -242,7 +257,6 @@ def batch_pipeline(
242
257
  path= main_dir + "results/",
243
258
  filename=batch_name + '_cell_result',
244
259
  do_excel= parameters["xlsx"],
245
- do_feather= parameters["feather"],
246
260
  do_csv= parameters["csv"],
247
261
  overwrite=True,
248
262
  batch_mode=True,
@@ -257,15 +271,20 @@ def batch_pipeline(
257
271
 
258
272
  except Exception as error :
259
273
 
260
- error_count +=1
261
- print("Exception raised for acquisition, writting error in error log.")
274
+
275
+ with open(main_dir + "error_log", mode='a') as error_log :
276
+
277
+ error_count +=1
278
+ print("Exception raised for acquisition, writting error in error log.")
262
279
 
263
- log = [
264
- f"Error raised during acquisition {acquisition_id}.\n"
265
- ]
266
- log.append(str(error) + '\n')
280
+ log = [
281
+ f"Error raised during acquisition {acquisition_id}.\n",
282
+ f"{error}\n",
283
+ f"traceback :\n{traceback.format_exc()}"
284
+ ]
285
+
267
286
 
268
- error_log.writelines(log)
287
+ error_log.writelines(log)
269
288
 
270
289
  print("Ignoring current acquisition and proceeding to next one.")
271
290
  continue
@@ -4,6 +4,7 @@ Submodule with main function to call to launch batch mode.
4
4
 
5
5
  import os
6
6
  import FreeSimpleGUI as sg
7
+ import small_fish_gui.default_values as default
7
8
 
8
9
  from .utils import get_elmt_from_key, create_map, call_auto_map
9
10
  from .pipeline import batch_pipeline
@@ -24,7 +25,17 @@ def batch_promp(
24
25
 
25
26
 
26
27
  #LOAD FILES
27
- files_table = sg.Table(values=files_values, headings=['Filenames'], col_widths=100, max_col_width= 200, def_col_width=100, num_rows= 10, auto_size_columns=False)
28
+ files_table = sg.Table(
29
+ values=files_values,
30
+ headings=['Filenames'],
31
+ col_widths=100,
32
+ max_col_width= 200,
33
+ def_col_width=100,
34
+ num_rows= 10,
35
+ auto_size_columns=False,
36
+ expand_y=True,
37
+ justification='left',
38
+ )
28
39
 
29
40
  #DIMENSION SANITY
30
41
  sanity_progress = sg.ProgressBar(10, size_px=(500,10), border_width=2)
@@ -45,11 +56,11 @@ def batch_promp(
45
56
  #Input tab
46
57
  input_layout = _input_parameters_layout(
47
58
  ask_for_segmentation=True,
48
- is_3D_stack_preset= preset.setdefault("is_3D_stack" ,False),
59
+ is_3D_stack_preset= preset.setdefault("is_3D_stack" ,default.IS_3D_STACK),
49
60
  time_stack_preset=False,
50
- multichannel_preset=preset.setdefault("is_multichannel" ,False),
51
- do_dense_regions_deconvolution_preset=preset.setdefault("do_dense_regions_deconvolution" ,False),
52
- do_clustering_preset= preset.setdefault("do_cluster_computation", False),
61
+ multichannel_preset=preset.setdefault("is_multichannel" ,default.IS_MULTICHANNEL),
62
+ do_dense_regions_deconvolution_preset=preset.setdefault("do_dense_regions_deconvolution", default.DO_DENSE_REGIONS_DECONVOLUTION),
63
+ do_clustering_preset= preset.setdefault("do_cluster_computation", default.DO_CLUSTER_COMPUTATION),
53
64
  do_Napari_correction=False,
54
65
  do_segmentation_preset= preset.setdefault("segmentation_done", False),
55
66
  )
@@ -74,19 +85,20 @@ def batch_promp(
74
85
 
75
86
  #Segmentation tab
76
87
  segmentation_layout = _segmentation_layout(
77
- multichannel=True,
78
- cytoplasm_model_preset=preset.setdefault("cyto_model_name",'cyto3'),
79
- cytoplasm_channel_preset=preset.setdefault("cytoplasm channel",0),
80
- cyto_diameter_preset=preset.setdefault("cytoplasm diameter",180),
81
- nucleus_model_preset=preset.setdefault("nucleus_model_name",'nuclei'),
82
- nucleus_channel_preset=preset.setdefault("nucleus channel",0),
83
- nucleus_diameter_preset=preset.setdefault("nucleus diameter",150),
84
- segment_only_nuclei_preset=preset.setdefault("Segment only nuclei",False)
88
+ multichannel=True,
89
+ is_3D_stack=True,
90
+ cytoplasm_model_preset=preset.setdefault("cyto_model_name",default.CYTO_MODEL),
91
+ cytoplasm_channel_preset=preset.setdefault("cytoplasm_channel",default.CHANNEL),
92
+ cyto_diameter_preset=preset.setdefault("cytoplasm_diameter",default.CYTO_DIAMETER),
93
+ nucleus_model_preset=preset.setdefault("nucleus_model_name",default.NUC_MODEL),
94
+ nucleus_channel_preset=preset.setdefault("nucleus channel",default.CHANNEL),
95
+ nucleus_diameter_preset=preset.setdefault("nucleus_diameter",default.NUC_DIAMETER),
96
+ segment_only_nuclei_preset=preset.setdefault("segment_only_nuclei",default.SEGMENT_ONLY_NUCLEI),
85
97
  )
86
98
 
87
99
  apply_segmentation_button = sg.Button('apply', key='apply-segmentation')
88
100
  segmentation_layout += [[apply_segmentation_button]]
89
- seg_keys_to_hide = ['show segmentation', 'saving path', 'filename', 'other_nucleus_image']
101
+ seg_keys_to_hide = ['show_segmentation', 'saving path', 'filename', 'other_nucleus_image', 'save_segmentation_visual', 'saving path_browse']
90
102
  segmentation_tab = sg.Tab("Segmentation", segmentation_layout, visible=False)
91
103
 
92
104
  #Detection tab
@@ -100,13 +112,14 @@ def batch_promp(
100
112
  )
101
113
  apply_detection_button = sg.Button('apply', key='apply-detection')
102
114
  detection_layout += [[apply_detection_button]]
103
- detection_keys_to_hide = ['do_spots_csv', 'do_spots_excel', 'do_spots_feather','spots_filename','spots_extraction_folder']
115
+ detection_keys_to_hide = ['do_spots_csv', 'do_spots_excel', 'spots_filename','spots_extraction_folder', 'spots_extraction_folder_browse']
104
116
  detection_tab = sg.Tab("Detection", detection_layout, visible=False)
105
117
 
106
118
  #Output tab
107
119
  show_batch_folder_text = sg.Text('', key= 'batch_folder_text')
108
120
  apply_output_button = sg.Button('apply', key='apply-output')
109
- save_segmentation_box = sg.Checkbox("save segmentation", disabled=True, key='save segmentation')
121
+ save_segmentation_visual_box = sg.Checkbox("save segmentation", disabled=True, key='save segmentation', tooltip= "Save png files illustrating segmentation borders.")
122
+ save_segmentation_masks_box = sg.Check("save labels", disabled=True, key="save_masks", tooltip= "Save segmentation labels as .npy files.")
110
123
  save_detection_box = sg.Checkbox("create spot detection visuals", key= 'save detection', tooltip="Create multichannel tiff with raw spot signal and detected spots.\nWarning if processing a lot of files make sure you have enough free space on your hard drive.")
111
124
  extract_spots_box = sg.Checkbox("extract spots", key='extract spots')
112
125
  batch_name_input = sg.InputText(size=25, key='batch_name')
@@ -115,13 +128,16 @@ def batch_promp(
115
128
  [show_batch_folder_text],
116
129
  [sg.Text("Select a folder : "), sg.FolderBrowse(initial_folder=os.getcwd(), key='output_folder', target=(1,-1))],
117
130
  [sg.Text("Name for batch : "), batch_name_input],
118
- [save_segmentation_box],
119
131
  [save_detection_box],
120
132
  [extract_spots_box],
121
133
  [sg.Text("Data extension", font=('bold',15), pad=(0,10))],
122
- [sg.Checkbox(".csv", key='csv'),sg.Checkbox(".xlsx", key='xlsx'),sg.Checkbox(".feather", key='feather'),],
134
+ [sg.Checkbox(".csv", key='csv'),sg.Checkbox(".xlsx", key='xlsx')],
135
+ [sg.Text("Segmentation", font=('bold',15), pad=(0,10))],
136
+ [save_segmentation_visual_box],
137
+ [save_segmentation_masks_box],
123
138
  [apply_output_button],
124
139
  ]
140
+
125
141
  output_tab = sg.Tab("Output", output_layout, visible=True)
126
142
 
127
143
  ##TAB GROUP
@@ -129,9 +145,10 @@ def batch_promp(
129
145
  tab_col = sg.Column( #Allow the tab to be scrollable
130
146
  [[_tab_group]],
131
147
  scrollable=True,
132
- vertical_scroll_only=True,
148
+ vertical_scroll_only=False,
133
149
  s= (390,390),
134
- pad=((0,0),(5,5))
150
+ pad=((0,0),(5,5)),
151
+ expand_x=True,
135
152
  )
136
153
 
137
154
  tab_dict= {
@@ -172,14 +189,14 @@ def batch_promp(
172
189
  #########################################
173
190
  ##### Window Creation
174
191
  #########################################
175
- stream_output = sg.Output(size=(100,10), pad=(30,10), visible=True)
192
+ stream_output = sg.Output(size=(100,10), pad=(30,10), visible=True, expand_x=True, expand_y=True)
176
193
  layout = [
177
194
  [sg.Text("Batch Processing", font=('bold',20), pad=((300,0),(0,2)))],
178
195
  [sg.Text("Select a folder : "), sg.FolderBrowse(initial_folder=os.getcwd(), key='Batch_folder'), sg.Button('Load')],
179
196
  [files_table],
180
197
  [sanity_header, sanity_check_button, sanity_progress],
181
198
  [dimension_number_text],
182
- [tab_col, launch_col],
199
+ [tab_col, sg.Push(), launch_col, sg.Push()],
183
200
  [stream_output],
184
201
  ]
185
202
 
@@ -227,6 +244,8 @@ def batch_promp(
227
244
  timeout = 500
228
245
  print("Welcome to small fish batch analysis. Please start by loading some files and setting parameters.")
229
246
 
247
+ if values is None : return results_df, cell_results_df, acquisition_id, preset, False, None,None
248
+
230
249
  batch_folder = values.get('Batch_folder')
231
250
  is_multichanel = values.get('is_multichannel')
232
251
  is_3D = values.get('is_3D_stack')
@@ -386,6 +405,7 @@ def batch_promp(
386
405
  segmentation_correct_text= segmentation_ok_text,
387
406
  do_segmentation=do_segmentation,
388
407
  is_multichannel=is_multichanel,
408
+ is_3D=is_3D,
389
409
  is_mapping_ok=Master_parameters_dict['_is_mapping_correct']
390
410
  )
391
411
 
@@ -422,7 +442,5 @@ def batch_promp(
422
442
  except Exception as e :
423
443
  stream_output.restore_stderr()
424
444
  stream_output.restore_stdout()
425
- raise e
426
-
427
-
428
- window.close()
445
+ window.close()
446
+ raise e
@@ -87,15 +87,26 @@ def update_detection_tab(
87
87
 
88
88
  tab_elmt.update(visible=is_mapping_ok)
89
89
 
90
- def update_segmentation_tab(tab_elmt : sg.Tab, segmentation_correct_text : sg.Text, do_segmentation, is_multichannel, is_mapping_ok) :
90
+ def update_segmentation_tab(
91
+ tab_elmt : sg.Tab,
92
+ segmentation_correct_text : sg.Text,
93
+ do_segmentation : bool,
94
+ is_multichannel : bool,
95
+ is_3D : bool,
96
+ is_mapping_ok: bool
97
+ ) :
91
98
 
92
99
  #Access elements
93
- cytoplasm_channel_elmt = get_elmt_from_key(tab_elmt, key= 'cytoplasm channel')
94
- nucleus_channel_elmt = get_elmt_from_key(tab_elmt, key= 'nucleus channel')
100
+ cytoplasm_channel_elmt = get_elmt_from_key(tab_elmt, key= 'cytoplasm_channel')
101
+ nucleus_channel_elmt = get_elmt_from_key(tab_elmt, key= 'nucleus_channel')
102
+ do_nucleus_3D_elmt = get_elmt_from_key(tab_elmt, key= "nucleus_segmentation_3D")
103
+ do_cytoplasm_3D_elmt = get_elmt_from_key(tab_elmt, key= "cytoplasm_segmentation_3D")
95
104
 
96
105
  #Update values
97
106
  cytoplasm_channel_elmt.update(disabled = not is_multichannel)
98
107
  nucleus_channel_elmt.update(disabled = not is_multichannel)
108
+ do_nucleus_3D_elmt.update(disabled = not is_3D)
109
+ do_cytoplasm_3D_elmt.update(disabled = not is_3D)
99
110
  segmentation_correct_text.update(visible= do_segmentation)
100
111
 
101
112
  tab_elmt.update(visible=is_mapping_ok and do_segmentation)
@@ -126,7 +137,12 @@ def update_output_tab(
126
137
  do_segmentation,
127
138
  output_folder,
128
139
  ) :
140
+
141
+ #Segmentation
129
142
  segmentation_box = get_elmt_from_key(tab_elmt, "save segmentation")
130
143
  segmentation_box.update(disabled = not do_segmentation)
144
+ segmentation_save_masks_elmt = get_elmt_from_key(tab_elmt, "save_masks")
145
+ segmentation_save_masks_elmt.update(disabled = not do_segmentation)
146
+
131
147
  batch_folder_text = get_elmt_from_key(tab_elmt, "batch_folder_text")
132
148
  batch_folder_text.update(value = output_folder)
@@ -64,3 +64,5 @@ def create_map(
64
64
 
65
65
  return maping
66
66
 
67
+ def clean_filename(filename : str) :
68
+ return "_".join(filename.split('.')[:-1])