napari-tapenade-processing 0.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.
@@ -0,0 +1,22 @@
1
+
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2024 Jules Vanaret
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include LICENSE
2
+ include README.md
3
+
4
+ recursive-exclude * __pycache__
5
+ recursive-exclude * *.py[co]
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.1
2
+ Name: napari-tapenade-processing
3
+ Version: 0.0.1
4
+ Summary: A simple plugin to use FooBar segmentation within napari
5
+ Home-page: https://github.com/jules-vanaret/napari-tapenade-processing
6
+ Author: Jules Vanaret
7
+ Author-email: jules.vanaret@univ-amu.fr
8
+ License: MIT
9
+ Project-URL: Bug Tracker, https://github.com/jules-vanaret/napari-tapenade-processing/issues
10
+ Project-URL: Documentation, https://github.com/jules-vanaret/napari-tapenade-processing#README.md
11
+ Project-URL: Source Code, https://github.com/jules-vanaret/napari-tapenade-processing
12
+ Project-URL: User Support, https://github.com/jules-vanaret/napari-tapenade-processing/issues
13
+ Classifier: Development Status :: 2 - Pre-Alpha
14
+ Classifier: Framework :: napari
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.8
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: numpy
29
+ Requires-Dist: magicgui
30
+ Requires-Dist: qtpy
31
+ Requires-Dist: tifffile
32
+ Provides-Extra: testing
33
+ Requires-Dist: tox; extra == "testing"
34
+ Requires-Dist: pytest; extra == "testing"
35
+ Requires-Dist: pytest-cov; extra == "testing"
36
+ Requires-Dist: pytest-qt; extra == "testing"
37
+ Requires-Dist: napari; extra == "testing"
38
+ Requires-Dist: pyqt5; extra == "testing"
39
+
40
+ # :herb: napari-tapenade-processing
41
+
42
+ <img src="https://github.com/GuignardLab/tapenade/blob/Packaging/imgs/tapenade3.png" width="100">
43
+
44
+ A collection of methods to process images of deep 3D/3D+time tissues in Napari.
45
+
46
+ `napari-tapenade-processing` is a [napari] plugin that is part of the [Tapenade](https://github.com/GuignardLab/tapenade) project. Tapenade is a tool for the analysis of dense 3D tissues acquired with deep imaging microscopy. It is designed to be user-friendly and to provide a comprehensive analysis of the data.
47
+
48
+ If you use this plugin for your research, please [cite us](https://github.com/GuignardLab/tapenade/blob/main/README.md#how-to-cite).
49
+
50
+ ## Overview
51
+
52
+ While working with large and dense 3D and 3D+time gastruloid datasets, we found that being able to visualise and interact with the data dynamically greatly helped processing it.
53
+ During the pre-processing stage, dynamical exploration and interaction led to faster tuning of the parameters by allowing direct visual feedback, and gave key biophysical insight during the analysis stage.
54
+
55
+ From a given set of raw images, segmented object instances, and object mask, the plugin allows the user to quickly run all pre-processing functions from our main pipeline with custom parameters while being able to see and interact with the result of each step. For large datasets that are cumbersome to manipulate or cannot be loaded in Napari, the plugin provides a macro recording feature: the users can experiment and design their own pipeline on a smaller subset of the dataset, then run it on the full dataset without having to load it in Napari.
56
+
57
+ <img src="imgs/Fig_Napari_preprocessing.png">
58
+
59
+ ## Installation
60
+
61
+ The plugin obviously requires [napari] to run. If you don't have it yet, follow the instructions [here](https://napari.org/stable/tutorials/fundamentals/installation.html).
62
+
63
+ The simplest way to install `napari-tapenade-processing` is via the [napari] plugin manager. Open Napari, go to `Plugins > Install/Uninstall Packages...` and search for `napari-tapenade-processing`. Click on the install button and you are ready to go!
64
+
65
+ You can also install `napari-tapenade-processing` via [pip]:
66
+
67
+ pip install napari-tapenade-processing
68
+
69
+ To install latest development version :
70
+
71
+ pip install git+https://github.com/jules-vanaret/napari-tapenade-processing.git
72
+
73
+ ## Usage
74
+
75
+ ### General overview of the plugin within Napari
76
+
77
+ <img src="imgs/proc_0.png">
78
+
79
+ To start a pre-processing pipeline, follow these steps:
80
+
81
+ 1. First, load your images in Napari. You can drag and drop them from your file explorer to the Napari viewer, or open them using the `File > Open files...` menu.
82
+ 2. Click on the `Plugins > Tapenade Processing` menu to open the plugin.
83
+ 3. The image you have loaded will be displayed as individual layers in the Layer List. They can be clicked-on to reveal a set of visual parameters (see 4) that can be adjusted. By double-clicking on a layer name, you can change it. Right-clicking a layer will give you several options. The little eye icon next to the layer name can be clicked to hide the layer.
84
+ 4. You can adjust visual parameters for each layer, like the contrast limits, the colormap, the opacity, the blending mode, etc.
85
+ 5. If you want to switch between 2D and 3D views, click on the `Toggle 2D/3D view` button (it resembles a square when in 2D mode, or a cube when in 3D mode).
86
+ 6. You can toggle the grid view (as shown in the example image) by clicking on the `Toggle grid mode` button. By right-clicking the button, you can parametrize the grid view (e.g number of columns, number of rows, etc).
87
+ 7. The plugin is composed of three tabs. The first tab is dedicated to pre-processing functions, the second tab is dedicated to the macro recording feature, and the third tab is dedicated to advanced parameters.
88
+
89
+ ### Tab 1: The pre-processing functions
90
+
91
+ <img src="imgs/proc_1.png" width=300>
92
+
93
+ The pre-processing tab is composed of the following elements:
94
+
95
+ 1. A combo box to select the pre-processing function to apply from a list.
96
+ 2. A set of comboxes that allow you to select the layers to apply the function on. If a function does not require a specific layer, the combo box will be greyed out. `Image` layers correspond to integer or float data, `Labels` layers correspond to integer data and represent segmented object instances, `Mask` layers correspond to boolean data and usually represent the sample's large scale mask (inside/outside). All layers must have data of the same shape (same number of dimensions and same dimensions). Layers can be 3D or 3D+time, respectively with the ZYX or TZYX order.
97
+ (2') If a layer does not appear in a combo box, but is present in the Layer List, you can click on the `Refresh` button to update the list of layers.
98
+ 3. A set of parameters that you can tune to adjust the function's behaviour. The parameters are specific to each function. In case of doubt, you can hover over the parameter name/widget to get a tooltip with a description.
99
+ 4. A `Run function` button to apply the function with the current parameters to the previously selected layers.
100
+
101
+
102
+ ### Tab 2: The macro recording feature
103
+
104
+ In progress...
105
+
106
+ ### Tab 3: Advanced parameters
107
+
108
+ <img src="imgs/proc_2.png" width=300>
109
+
110
+ The advanced parameters tab is composed of the following elements:
111
+
112
+ 1. A checkbox `New layers overwrite previous ones`: whether the output of the pre-processing functions should be saved as new layers or overwrite the previous ones that were used as input. This can be useful to save memory when you don't need to compare the input and output of a function.
113
+ 2. A checkbox `Results are cropped using mask`: whether the output of functions are systematically cropped using the mask layer (if it is provided). This can be useful to save memory when you don't need to process the whole image.
114
+ 3. A slider `# parallel jobs`: the number of parallel jobs to use when running a function on a 3D+time input (each frame is processed in parallel). This can be useful to speed up the processing.
115
+
116
+ ## Contributing
117
+
118
+ Contributions are very welcome. Tests can be run with [tox], please ensure
119
+ the coverage at least stays the same before you submit a pull request.
120
+
121
+ ## License
122
+
123
+ Distributed under the terms of the [MIT] license,
124
+ "napari-tapenade-processing" is free and open source software
125
+
126
+ ## Issues
127
+
128
+ If you encounter any problems, please [file an issue] along with a detailed description.
129
+
130
+
131
+ ----------------------------------
132
+
133
+ This [napari] plugin was generated with [Cookiecutter] using [@napari]'s [cookiecutter-napari-plugin] template.
134
+
135
+ [napari]: https://github.com/napari/napari
136
+ [Cookiecutter]: https://github.com/audreyr/cookiecutter
137
+ [@napari]: https://github.com/napari
138
+ [MIT]: http://opensource.org/licenses/MIT
139
+ [BSD-3]: http://opensource.org/licenses/BSD-3-Clause
140
+ [GNU GPL v3.0]: http://www.gnu.org/licenses/gpl-3.0.txt
141
+ [GNU LGPL v3.0]: http://www.gnu.org/licenses/lgpl-3.0.txt
142
+ [Apache Software License 2.0]: http://www.apache.org/licenses/LICENSE-2.0
143
+ [Mozilla Public License 2.0]: https://www.mozilla.org/media/MPL/2.0/index.txt
144
+ [cookiecutter-napari-plugin]: https://github.com/napari/cookiecutter-napari-plugin
145
+
146
+ [file an issue]: https://github.com/jules-vanaret/napari-tapenade-processing/issues
147
+
148
+ [napari]: https://github.com/napari/napari
149
+ [tox]: https://tox.readthedocs.io/en/latest/
150
+ [pip]: https://pypi.org/project/pip/
151
+ [PyPI]: https://pypi.org/
@@ -0,0 +1,112 @@
1
+ # :herb: napari-tapenade-processing
2
+
3
+ <img src="https://github.com/GuignardLab/tapenade/blob/Packaging/imgs/tapenade3.png" width="100">
4
+
5
+ A collection of methods to process images of deep 3D/3D+time tissues in Napari.
6
+
7
+ `napari-tapenade-processing` is a [napari] plugin that is part of the [Tapenade](https://github.com/GuignardLab/tapenade) project. Tapenade is a tool for the analysis of dense 3D tissues acquired with deep imaging microscopy. It is designed to be user-friendly and to provide a comprehensive analysis of the data.
8
+
9
+ If you use this plugin for your research, please [cite us](https://github.com/GuignardLab/tapenade/blob/main/README.md#how-to-cite).
10
+
11
+ ## Overview
12
+
13
+ While working with large and dense 3D and 3D+time gastruloid datasets, we found that being able to visualise and interact with the data dynamically greatly helped processing it.
14
+ During the pre-processing stage, dynamical exploration and interaction led to faster tuning of the parameters by allowing direct visual feedback, and gave key biophysical insight during the analysis stage.
15
+
16
+ From a given set of raw images, segmented object instances, and object mask, the plugin allows the user to quickly run all pre-processing functions from our main pipeline with custom parameters while being able to see and interact with the result of each step. For large datasets that are cumbersome to manipulate or cannot be loaded in Napari, the plugin provides a macro recording feature: the users can experiment and design their own pipeline on a smaller subset of the dataset, then run it on the full dataset without having to load it in Napari.
17
+
18
+ <img src="imgs/Fig_Napari_preprocessing.png">
19
+
20
+ ## Installation
21
+
22
+ The plugin obviously requires [napari] to run. If you don't have it yet, follow the instructions [here](https://napari.org/stable/tutorials/fundamentals/installation.html).
23
+
24
+ The simplest way to install `napari-tapenade-processing` is via the [napari] plugin manager. Open Napari, go to `Plugins > Install/Uninstall Packages...` and search for `napari-tapenade-processing`. Click on the install button and you are ready to go!
25
+
26
+ You can also install `napari-tapenade-processing` via [pip]:
27
+
28
+ pip install napari-tapenade-processing
29
+
30
+ To install latest development version :
31
+
32
+ pip install git+https://github.com/jules-vanaret/napari-tapenade-processing.git
33
+
34
+ ## Usage
35
+
36
+ ### General overview of the plugin within Napari
37
+
38
+ <img src="imgs/proc_0.png">
39
+
40
+ To start a pre-processing pipeline, follow these steps:
41
+
42
+ 1. First, load your images in Napari. You can drag and drop them from your file explorer to the Napari viewer, or open them using the `File > Open files...` menu.
43
+ 2. Click on the `Plugins > Tapenade Processing` menu to open the plugin.
44
+ 3. The image you have loaded will be displayed as individual layers in the Layer List. They can be clicked-on to reveal a set of visual parameters (see 4) that can be adjusted. By double-clicking on a layer name, you can change it. Right-clicking a layer will give you several options. The little eye icon next to the layer name can be clicked to hide the layer.
45
+ 4. You can adjust visual parameters for each layer, like the contrast limits, the colormap, the opacity, the blending mode, etc.
46
+ 5. If you want to switch between 2D and 3D views, click on the `Toggle 2D/3D view` button (it resembles a square when in 2D mode, or a cube when in 3D mode).
47
+ 6. You can toggle the grid view (as shown in the example image) by clicking on the `Toggle grid mode` button. By right-clicking the button, you can parametrize the grid view (e.g number of columns, number of rows, etc).
48
+ 7. The plugin is composed of three tabs. The first tab is dedicated to pre-processing functions, the second tab is dedicated to the macro recording feature, and the third tab is dedicated to advanced parameters.
49
+
50
+ ### Tab 1: The pre-processing functions
51
+
52
+ <img src="imgs/proc_1.png" width=300>
53
+
54
+ The pre-processing tab is composed of the following elements:
55
+
56
+ 1. A combo box to select the pre-processing function to apply from a list.
57
+ 2. A set of comboxes that allow you to select the layers to apply the function on. If a function does not require a specific layer, the combo box will be greyed out. `Image` layers correspond to integer or float data, `Labels` layers correspond to integer data and represent segmented object instances, `Mask` layers correspond to boolean data and usually represent the sample's large scale mask (inside/outside). All layers must have data of the same shape (same number of dimensions and same dimensions). Layers can be 3D or 3D+time, respectively with the ZYX or TZYX order.
58
+ (2') If a layer does not appear in a combo box, but is present in the Layer List, you can click on the `Refresh` button to update the list of layers.
59
+ 3. A set of parameters that you can tune to adjust the function's behaviour. The parameters are specific to each function. In case of doubt, you can hover over the parameter name/widget to get a tooltip with a description.
60
+ 4. A `Run function` button to apply the function with the current parameters to the previously selected layers.
61
+
62
+
63
+ ### Tab 2: The macro recording feature
64
+
65
+ In progress...
66
+
67
+ ### Tab 3: Advanced parameters
68
+
69
+ <img src="imgs/proc_2.png" width=300>
70
+
71
+ The advanced parameters tab is composed of the following elements:
72
+
73
+ 1. A checkbox `New layers overwrite previous ones`: whether the output of the pre-processing functions should be saved as new layers or overwrite the previous ones that were used as input. This can be useful to save memory when you don't need to compare the input and output of a function.
74
+ 2. A checkbox `Results are cropped using mask`: whether the output of functions are systematically cropped using the mask layer (if it is provided). This can be useful to save memory when you don't need to process the whole image.
75
+ 3. A slider `# parallel jobs`: the number of parallel jobs to use when running a function on a 3D+time input (each frame is processed in parallel). This can be useful to speed up the processing.
76
+
77
+ ## Contributing
78
+
79
+ Contributions are very welcome. Tests can be run with [tox], please ensure
80
+ the coverage at least stays the same before you submit a pull request.
81
+
82
+ ## License
83
+
84
+ Distributed under the terms of the [MIT] license,
85
+ "napari-tapenade-processing" is free and open source software
86
+
87
+ ## Issues
88
+
89
+ If you encounter any problems, please [file an issue] along with a detailed description.
90
+
91
+
92
+ ----------------------------------
93
+
94
+ This [napari] plugin was generated with [Cookiecutter] using [@napari]'s [cookiecutter-napari-plugin] template.
95
+
96
+ [napari]: https://github.com/napari/napari
97
+ [Cookiecutter]: https://github.com/audreyr/cookiecutter
98
+ [@napari]: https://github.com/napari
99
+ [MIT]: http://opensource.org/licenses/MIT
100
+ [BSD-3]: http://opensource.org/licenses/BSD-3-Clause
101
+ [GNU GPL v3.0]: http://www.gnu.org/licenses/gpl-3.0.txt
102
+ [GNU LGPL v3.0]: http://www.gnu.org/licenses/lgpl-3.0.txt
103
+ [Apache Software License 2.0]: http://www.apache.org/licenses/LICENSE-2.0
104
+ [Mozilla Public License 2.0]: https://www.mozilla.org/media/MPL/2.0/index.txt
105
+ [cookiecutter-napari-plugin]: https://github.com/napari/cookiecutter-napari-plugin
106
+
107
+ [file an issue]: https://github.com/jules-vanaret/napari-tapenade-processing/issues
108
+
109
+ [napari]: https://github.com/napari/napari
110
+ [tox]: https://tox.readthedocs.io/en/latest/
111
+ [pip]: https://pypi.org/project/pip/
112
+ [PyPI]: https://pypi.org/
@@ -0,0 +1,56 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+
6
+
7
+ [tool.black]
8
+ line-length = 79
9
+ target-version = ['py38', 'py39', 'py310']
10
+
11
+
12
+ [tool.ruff]
13
+ line-length = 79
14
+ select = [
15
+ "E", "F", "W", #flake8
16
+ "UP", # pyupgrade
17
+ "I", # isort
18
+ "BLE", # flake8-blind-exception
19
+ "B", # flake8-bugbear
20
+ "A", # flake8-builtins
21
+ "C4", # flake8-comprehensions
22
+ "ISC", # flake8-implicit-str-concat
23
+ "G", # flake8-logging-format
24
+ "PIE", # flake8-pie
25
+ "SIM", # flake8-simplify
26
+ ]
27
+ ignore = [
28
+ "E501", # line too long. let black handle this
29
+ "UP006", "UP007", # type annotation. As using magicgui require runtime type annotation then we disable this.
30
+ "SIM117", # flake8-simplify - some of merged with statements are not looking great with black, reanble after drop python 3.9
31
+ ]
32
+
33
+ exclude = [
34
+ ".bzr",
35
+ ".direnv",
36
+ ".eggs",
37
+ ".git",
38
+ ".mypy_cache",
39
+ ".pants.d",
40
+ ".ruff_cache",
41
+ ".svn",
42
+ ".tox",
43
+ ".venv",
44
+ "__pypackages__",
45
+ "_build",
46
+ "buck-out",
47
+ "build",
48
+ "dist",
49
+ "node_modules",
50
+ "venv",
51
+ "*vendored*",
52
+ "*_vendor*",
53
+ ]
54
+
55
+ target-version = "py38"
56
+ fix = true
@@ -0,0 +1,65 @@
1
+ [metadata]
2
+ name = napari-tapenade-processing
3
+ version = attr: napari_tapenade_processing.__version__
4
+ description = A simple plugin to use FooBar segmentation within napari
5
+ long_description = file: README.md
6
+ long_description_content_type = text/markdown
7
+ url = https://github.com/jules-vanaret/napari-tapenade-processing
8
+ author = Jules Vanaret
9
+ author_email = jules.vanaret@univ-amu.fr
10
+ license = MIT
11
+ license_files = LICENSE
12
+ classifiers =
13
+ Development Status :: 2 - Pre-Alpha
14
+ Framework :: napari
15
+ Intended Audience :: Developers
16
+ License :: OSI Approved :: MIT License
17
+ Operating System :: OS Independent
18
+ Programming Language :: Python
19
+ Programming Language :: Python :: 3
20
+ Programming Language :: Python :: 3 :: Only
21
+ Programming Language :: Python :: 3.8
22
+ Programming Language :: Python :: 3.9
23
+ Programming Language :: Python :: 3.10
24
+ Topic :: Scientific/Engineering :: Image Processing
25
+ project_urls =
26
+ Bug Tracker = https://github.com/jules-vanaret/napari-tapenade-processing/issues
27
+ Documentation = https://github.com/jules-vanaret/napari-tapenade-processing#README.md
28
+ Source Code = https://github.com/jules-vanaret/napari-tapenade-processing
29
+ User Support = https://github.com/jules-vanaret/napari-tapenade-processing/issues
30
+
31
+ [options]
32
+ packages = find:
33
+ install_requires =
34
+ numpy
35
+ magicgui
36
+ qtpy
37
+ tifffile
38
+ python_requires = >=3.8
39
+ include_package_data = True
40
+ package_dir =
41
+ =src
42
+
43
+ [options.packages.find]
44
+ where = src
45
+
46
+ [options.entry_points]
47
+ napari.manifest =
48
+ napari-tapenade-processing = napari_tapenade_processing:napari.yaml
49
+
50
+ [options.extras_require]
51
+ testing =
52
+ tox
53
+ pytest # https://docs.pytest.org/en/latest/contents.html
54
+ pytest-cov # https://pytest-cov.readthedocs.io/en/latest/
55
+ pytest-qt # https://pytest-qt.readthedocs.io/en/latest/
56
+ napari
57
+ pyqt5
58
+
59
+ [options.package_data]
60
+ * = *.yaml
61
+
62
+ [egg_info]
63
+ tag_build =
64
+ tag_date = 0
65
+
@@ -0,0 +1,7 @@
1
+ __version__ = "0.0.1"
2
+ from ._widget import TapenadeProcessingWidget
3
+
4
+ __all__ = (
5
+ "TapenadeProcessingWidget",
6
+
7
+ )
@@ -0,0 +1,99 @@
1
+ from qtpy.QtCore import Qt
2
+ from qtpy.QtWidgets import (
3
+ QHBoxLayout,
4
+ QLabel,
5
+ QPushButton,
6
+ QScrollArea,
7
+ QSizePolicy,
8
+ QStackedWidget,
9
+ QVBoxLayout,
10
+ QWidget,
11
+ )
12
+
13
+
14
+ class MultiLineTabWidget(QWidget):
15
+ def __init__(self):
16
+ super().__init__()
17
+ self.initUI()
18
+
19
+ def initUI(self):
20
+ self.layout = QVBoxLayout()
21
+ self.tabBarLayout = QVBoxLayout()
22
+
23
+ self.scrollArea = QScrollArea()
24
+ self.scrollArea.setWidgetResizable(True)
25
+ self.tabContainer = QWidget()
26
+ self.tabContainer.setLayout(self.tabBarLayout)
27
+ self.scrollArea.setWidget(self.tabContainer)
28
+
29
+ self.layout.addWidget(self.scrollArea)
30
+
31
+ self.stackedWidget = QStackedWidget()
32
+ self.layout.addWidget(self.stackedWidget)
33
+
34
+ self.setLayout(self.layout)
35
+
36
+ self.tabs = []
37
+
38
+ def addTab(self, widget, title):
39
+ tabButton = QPushButton(title)
40
+ tabButton.setCheckable(True)
41
+ tabButton.clicked.connect(lambda: self.onTabClicked(tabButton))
42
+
43
+ tabRowLayout = None
44
+ if len(self.tabs) % 3 == 0:
45
+ tabRowLayout = QHBoxLayout()
46
+ self.tabBarLayout.addLayout(tabRowLayout)
47
+ else:
48
+ tabRowLayout = self.tabBarLayout.itemAt(
49
+ self.tabBarLayout.count() - 1
50
+ ).layout()
51
+
52
+ tabRowLayout.addWidget(tabButton)
53
+ self.tabs.append(tabButton)
54
+
55
+ self.stackedWidget.addWidget(widget)
56
+
57
+ def onTabClicked(self, tabButton):
58
+ for i, btn in enumerate(self.tabs):
59
+ if btn == tabButton:
60
+ self.stackedWidget.setCurrentIndex(i)
61
+ btn.setChecked(True)
62
+ else:
63
+ btn.setChecked(False)
64
+
65
+
66
+ class RichTextPushButton(QPushButton):
67
+ def __init__(self, parent=None, text=None):
68
+ if parent is not None:
69
+ super().__init__(parent)
70
+ else:
71
+ super().__init__()
72
+ self.__lbl = QLabel(self)
73
+ if text is not None:
74
+ self.__lbl.setText(text)
75
+ self.__lyt = QHBoxLayout()
76
+ self.__lyt.setContentsMargins(0, 0, 0, 0)
77
+ self.__lyt.setSpacing(0)
78
+ self.setLayout(self.__lyt)
79
+ self.__lbl.setAttribute(Qt.WA_TranslucentBackground)
80
+ self.__lbl.setAttribute(Qt.WA_TransparentForMouseEvents)
81
+ self.__lbl.setSizePolicy(
82
+ QSizePolicy.Expanding,
83
+ QSizePolicy.Expanding,
84
+ )
85
+ self.__lbl.setTextFormat(Qt.RichText)
86
+ self.__lyt.addWidget(self.__lbl)
87
+ return
88
+
89
+ def setText(self, text):
90
+ self.__lbl.setText(text)
91
+ self.updateGeometry()
92
+ return
93
+
94
+ def sizeHint(self):
95
+ s = QPushButton.sizeHint(self)
96
+ w = self.__lbl.sizeHint()
97
+ s.setWidth(w.width())
98
+ s.setHeight(w.height())
99
+ return s
@@ -0,0 +1,99 @@
1
+ import json
2
+ import os
3
+ from collections import OrderedDict
4
+ from datetime import datetime
5
+
6
+
7
+ class MacroRecorder:
8
+ def __init__(self, adjective_dict):
9
+ self._is_recording_parameters = False
10
+ self._record_parameters_list = []
11
+
12
+ # key: napari name, value: standardized name
13
+ self._record_data_dict = {
14
+ "mask": {},
15
+ "image": {},
16
+ "labels": {},
17
+ "tracks": {},
18
+ }
19
+
20
+ self._adjective_dict = adjective_dict
21
+
22
+ def _reset_recording(self):
23
+ for k in self._record_data_dict.keys():
24
+ self._record_data_dict[k] = {}
25
+ self._record_parameters_list = []
26
+
27
+ def dump_recorded_parameters(self, path: str):
28
+ date = (
29
+ str(datetime.now())
30
+ .split(".")[:-1][0]
31
+ .replace(" ", "_")
32
+ .replace(":", "-")
33
+ )
34
+ filename = f"recorded_parameters_{date}.json"
35
+
36
+ with open(os.path.join(path, filename), "w") as f:
37
+ json.dump(self._record_parameters_list, f)
38
+
39
+ self._reset_recording()
40
+
41
+ def record(
42
+ self,
43
+ function_name: str,
44
+ layers_names_in: dict,
45
+ layers_names_out: dict,
46
+ func_params: dict,
47
+ overwrite: bool,
48
+ ):
49
+ """
50
+ layer_names are dicts that map layer_type (e.g 'mask', 'image'...) to
51
+ the names of the layers in the viewer
52
+ """
53
+
54
+ dict_in = dict()
55
+ dict_out = OrderedDict()
56
+
57
+ for layer_type in ["mask", "image", "labels", "tracks"]:
58
+ # building dict_in
59
+ layer_in = None
60
+ if layer_type in layers_names_in:
61
+ layer_name_in = layers_names_in[layer_type]
62
+
63
+ if layer_name_in is not None:
64
+ layer_in = self._record_data_dict[layer_type].get(
65
+ layer_name_in, layer_type
66
+ )
67
+
68
+ dict_in[layer_type] = layer_in
69
+ # building dict_out
70
+ if layer_type in layers_names_out:
71
+ layer_name_out = layers_names_out[layer_type]
72
+
73
+ if layer_name_out is not None:
74
+ if overwrite and layer_in is not None:
75
+ layer_out = layer_in
76
+ elif layer_in is not None:
77
+ adjective = self._adjective_dict[function_name]
78
+ layer_out = f"{layer_in}_{adjective}"
79
+ self._record_data_dict[layer_type][
80
+ layer_name_out
81
+ ] = layer_out
82
+ else:
83
+ layer_out = layer_type
84
+ self._record_data_dict[layer_type][
85
+ layer_name_out
86
+ ] = layer_out
87
+ else:
88
+ layer_out = None
89
+
90
+ dict_out[layer_type] = layer_out
91
+
92
+ params = {
93
+ "function": function_name,
94
+ "in": dict_in,
95
+ "out": dict_out,
96
+ "func_params": func_params,
97
+ }
98
+
99
+ self._record_parameters_list.append(params)