auto-options-python 0.1.4__py3-none-any.whl

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,58 @@
1
+ Metadata-Version: 2.4
2
+ Name: auto-options-python
3
+ Version: 0.1.4
4
+ Summary: Mange command options in python and create QWidgets for them.
5
+ Author: Volker Baecker
6
+ Author-email: volker.baecker@mri.cnrs.fr
7
+ License: MIT License
8
+
9
+ Copyright (c) 2025 Montpellier Ressources Imagerie
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Bug Tracker, https://github.com/MontpellierRessourcesImagerie/auto-options-python/issues
30
+ Project-URL: Documentation, https://montpellierressourcesimagerie.github.io/auto-options-python/
31
+ Project-URL: Source Code, https://github.com/MontpellierRessourcesImagerie/auto-options-python
32
+ Project-URL: User Support, https://github.com/MontpellierRessourcesImagerie/auto-options-python/issues
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Framework :: napari
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python
39
+ Classifier: Programming Language :: Python :: 3
40
+ Classifier: Programming Language :: Python :: 3 :: Only
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
46
+ Requires-Python: >=3.10
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+ Requires-Dist: appdirs
50
+ Requires-Dist: pyqt5
51
+ Requires-Dist: qtpy
52
+ Requires-Dist: napari
53
+ Requires-Dist: pyperclip
54
+ Requires-Dist: matplotlib
55
+ Dynamic: license-file
56
+
57
+ # auto-options-python
58
+ Mange command options in python and create QWidgets for them.
@@ -0,0 +1,19 @@
1
+ auto_options_python-0.1.4.dist-info/licenses/LICENSE,sha256=V8dHxj3sXeWgZfNq_3nAXemaXxbfmQvLHKy4jBBV-eQ,1088
2
+ autooptions/__init__.py,sha256=oW5bTiKfFmjiMLcgreBwwL6FOWSHLwasxckp50y_UdU,233
3
+ autooptions/_version.py,sha256=dCmqTphVTtnLNv5-BupgeR8iw0z5iLBjWjRFRXqOyso,520
4
+ autooptions/array_util.py,sha256=ZHgfTbxu-hc_rxJg8_sg1YfMyOHHykhHm0N4uNvEhjQ,1533
5
+ autooptions/napari_util.py,sha256=S-9v9Q_YHAD3EBqB6Y8w2xN9_7jKNuvNVS27RmXk4Hs,4496
6
+ autooptions/options.py,sha256=Ya9Nx6haj4dgtRFJD_T1quDhQj1L4bPgzAAD2GMw61o,13951
7
+ autooptions/qtutil.py,sha256=uEM_KJSnpvqb7bNCk6tMUXxvDcptdeJNJTpIfT_T4m0,9252
8
+ autooptions/widget.py,sha256=GdjkoDry-55mbKUgIbcDXwmZr2W4Ci4yCIplRTH29Y4,13929
9
+ autooptions/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ autooptions/_tests/test_array_util.py,sha256=enGGtzk1uXBMOtcgaCVhJz1zyRK7_pXOSIg1E69LQXQ,557
11
+ autooptions/_tests/test_napari_util.py,sha256=ja4cMcWx4AoIPX3PJfSd50HdJuYLDJLMMNLXb8lVyRs,4578
12
+ autooptions/_tests/test_options.py,sha256=4Y2fMfobqlSd2f4ahOypswQinqLMlDXg5hP5Wpmw9WI,6554
13
+ autooptions/_tests/test_qtutil.py,sha256=YQ2L_e5ju_umAYaC9x_aUWwUI9XcwrHZVJthnzRY73g,8875
14
+ autooptions/_tests/test_widget.py,sha256=Jtdb2uKceAe4YBfHdK1sE9YYBvhni512Fx3MFx_SQKQ,5154
15
+ scratch/options.py,sha256=lsmQ8zwzmyyR0iqxkRmpduqUdsdndHx4oShDmVrxHfg,1332
16
+ auto_options_python-0.1.4.dist-info/METADATA,sha256=oobt8KbF2FiZh2D4xRCMtxyBEldK4qLSbgPK2MsbMS4,2832
17
+ auto_options_python-0.1.4.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
18
+ auto_options_python-0.1.4.dist-info/top_level.txt,sha256=7hs1Zw5d4qriyx2pJbx7RLv2UgRAnvR9X-TqCCIzYPg,20
19
+ auto_options_python-0.1.4.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Montpellier Ressources Imagerie
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ autooptions
2
+ scratch
@@ -0,0 +1,16 @@
1
+ try:
2
+ from ._version import version as __version__
3
+ except ImportError:
4
+ __version__ = "unknown"
5
+
6
+ from .options import (
7
+ Options
8
+ )
9
+
10
+ from .widget import (
11
+ OptionsWidget,
12
+ )
13
+ __all__ = (
14
+ "Options",
15
+ "OptionsWidget",
16
+ )
File without changes
@@ -0,0 +1,24 @@
1
+ import numpy as np
2
+ from autooptions.array_util import ArrayUtil
3
+
4
+
5
+ def testStripZeroRowsAndColumns():
6
+
7
+ testData = np.array([
8
+ [1, 0, 3],
9
+ [0, 0, 0],
10
+ [5, 0, 6]
11
+ ])
12
+
13
+ data, columns, rows = ArrayUtil.stripZeroRowsAndColumns(testData)
14
+ assert data.shape == (2,2)
15
+ assert data[0 ,0] == 1
16
+ assert data[0, 1] == 3
17
+ assert data[1, 0] == 5
18
+ assert data[1, 1] == 6
19
+ assert len(columns) == 2
20
+ assert columns[0] == 0
21
+ assert columns[1] == 2
22
+ assert len(rows) == 2
23
+ assert rows[0] == 0
24
+ assert rows[1] == 2
@@ -0,0 +1,146 @@
1
+ import pytest
2
+ import numpy as np
3
+ from napari.layers import Labels, Image, Points
4
+ from autooptions.napari_util import NapariUtil
5
+
6
+ class Layer:
7
+ pass
8
+
9
+
10
+
11
+ @pytest.fixture
12
+ def layers():
13
+ layers = [Image(np.zeros(shape=(3, 3), dtype=np.uint8), name="toad", metadata={'fft': 'fft'}),
14
+ Image(np.zeros(shape=(3, 3), dtype=np.uint8), name="frog", scale=(1, 3), units="nm"),
15
+ Points(np.zeros((3, 3)), name="ant"), Labels(np.zeros(shape=(4, 4), dtype=np.uint8), name="oak"),
16
+ Points(np.zeros((2, 3)), name="bee"), Image(np.zeros(shape=(3, 3), dtype=np.uint8), name="bird")]
17
+ yield layers
18
+
19
+
20
+
21
+ def test_constructor(make_napari_viewer_proxy):
22
+ viewer = make_napari_viewer_proxy()
23
+ napariUtil = NapariUtil(viewer)
24
+ assert napariUtil.viewer == viewer
25
+
26
+
27
+ def testGetImageLayers(make_napari_viewer_proxy, layers):
28
+ viewer = make_napari_viewer_proxy()
29
+ napariUtil = NapariUtil(viewer)
30
+ for layer in layers:
31
+ viewer.add_layer(layer)
32
+
33
+ assert len(napariUtil.getImageLayers()) == 3
34
+ assert napariUtil.getImageLayers()[0] == "toad"
35
+ assert napariUtil.getImageLayers()[1] == "frog"
36
+ assert napariUtil.getImageLayers()[2] == "bird"
37
+
38
+
39
+ def testGetFFTLayers(make_napari_viewer_proxy, layers):
40
+ viewer = make_napari_viewer_proxy()
41
+ napariUtil = NapariUtil(viewer)
42
+ for layer in layers:
43
+ viewer.add_layer(layer)
44
+
45
+ fftLayers = napariUtil.getFFTLayers()
46
+ assert len(fftLayers) == 1
47
+ assert fftLayers[0] == 'toad'
48
+
49
+
50
+ def testGetLabelLayers(make_napari_viewer_proxy, layers):
51
+ viewer = make_napari_viewer_proxy()
52
+ napariUtil = NapariUtil(viewer)
53
+ for layer in layers:
54
+ viewer.add_layer(layer)
55
+
56
+ labelLayers = napariUtil.getLabelLayers()
57
+ assert len(labelLayers) == 1
58
+ assert 'oak' == labelLayers[0]
59
+
60
+
61
+ def testGetPointLayers(make_napari_viewer_proxy, layers):
62
+ viewer = make_napari_viewer_proxy()
63
+ napariUtil = NapariUtil(viewer)
64
+ for layer in layers:
65
+ viewer.add_layer(layer)
66
+
67
+ pointLayers = napariUtil.getPointsLayers()
68
+ assert len(pointLayers) == 2
69
+ assert pointLayers[0] == 'ant'
70
+ assert pointLayers[1] == 'bee'
71
+
72
+
73
+ def testGetLayersOfType(make_napari_viewer_proxy, layers):
74
+ viewer = make_napari_viewer_proxy()
75
+ napariUtil = NapariUtil(viewer)
76
+ for layer in layers:
77
+ viewer.add_layer(layer)
78
+
79
+ labelLayers = napariUtil.getLayersOfType(Labels)
80
+ assert len(labelLayers) == 1
81
+ assert labelLayers[0] == 'oak'
82
+
83
+
84
+ def testGetDataOfLayerWithName(make_napari_viewer_proxy, layers):
85
+ viewer = make_napari_viewer_proxy()
86
+ napariUtil = NapariUtil(viewer)
87
+ for layer in layers:
88
+ viewer.add_layer(layer)
89
+
90
+ data = napariUtil.getDataOfLayerWithName("oak")
91
+ assert data.shape == (4,4)
92
+ data = napariUtil.getDataOfLayerWithName("marsupilami")
93
+ assert data is None
94
+
95
+
96
+ def testGetLayerWithName(make_napari_viewer_proxy, layers):
97
+ viewer = make_napari_viewer_proxy()
98
+ napariUtil = NapariUtil(viewer)
99
+ for layer in layers:
100
+ viewer.add_layer(layer)
101
+
102
+ layer = napariUtil.getLayerWithName("bee")
103
+ assert layer.name == "bee"
104
+ layer = napariUtil.getLayerWithName("marsupilami")
105
+ assert layer is None
106
+
107
+
108
+ def testGetDataAndScaleOfLayerWithName(make_napari_viewer_proxy, layers):
109
+ viewer = make_napari_viewer_proxy()
110
+ napariUtil = NapariUtil(viewer)
111
+ for layer in layers:
112
+ viewer.add_layer(layer)
113
+
114
+ data, scale, unit = napariUtil.getDataAndScaleOfLayerWithName('frog')
115
+ assert data.shape == (3,3)
116
+ assert scale[0] == 1
117
+ assert scale[1] == 3
118
+ assert unit == "nanometer"
119
+
120
+
121
+ def testGetOriginalPath(make_napari_viewer_proxy, layers):
122
+ viewer = make_napari_viewer_proxy()
123
+ napariUtil = NapariUtil(viewer)
124
+ for layer in layers:
125
+ viewer.add_layer(layer)
126
+ toad = napariUtil.getLayerWithName('toad')
127
+ toad.metadata['original_path'] = "d/e/f"
128
+ assert napariUtil.getOriginalPath(napariUtil.getLayerWithName('bee')) is None
129
+ layer = Layer()
130
+ layer.source = Layer()
131
+ layer.source.path = "a/b/c"
132
+ layer.metadata = {}
133
+ assert napariUtil.getOriginalPath(layer)
134
+ assert napariUtil.getOriginalPath(toad) == 'd/e/f'
135
+
136
+
137
+ def testCopOriginalPath(make_napari_viewer_proxy, layers):
138
+ viewer = make_napari_viewer_proxy()
139
+ napariUtil = NapariUtil(viewer)
140
+ for layer in layers:
141
+ viewer.add_layer(layer)
142
+ toad = napariUtil.getLayerWithName('toad')
143
+ toad.metadata['original_path'] = "d/e/f"
144
+ frog = napariUtil.getLayerWithName('frog')
145
+ napariUtil.copyOriginalPath(toad, frog)
146
+ assert napariUtil.getOriginalPath(frog) == "d/e/f"
@@ -0,0 +1,172 @@
1
+ import os
2
+ import pytest
3
+ from autooptions.options import Options
4
+
5
+
6
+ class TestOptions:
7
+
8
+
9
+ @pytest.fixture()
10
+ def options(self):
11
+ options = Options("Autooptions Test", "Magic Filter")
12
+ options.addImage('image', value=None, transient=True)
13
+ options.addInt('size xy', value=3, widget="input")
14
+ options.addInt('size z', value=1, widget="input")
15
+ options.addChoice('footprint', value=None, choices=["none", "cube", "ball", "octahedron"])
16
+ options.addInt('radius', value=1, widget="input")
17
+ yield options
18
+
19
+
20
+ def onSomething(self, value):
21
+ pass
22
+
23
+
24
+ def testConstructor(self):
25
+ options = Options("Autooptions Test", "Magic Filter")
26
+ assert options.applicationName == "Autooptions Test"
27
+ assert options.optionsName == "Magic Filter"
28
+ assert os.path.exists(os.path.dirname(options.optionsPath))
29
+
30
+
31
+ def testSetDefaultItems(self):
32
+ options = Options("Autooptions Test", "Magic Filter")
33
+ items = {'image': {'value': None, 'type': 'image', 'transient': True, 'position': 0, 'callback': None},
34
+ 'size xy': {'type': 'int', 'value': 3, 'transient': False, 'position': 1, 'widget': 'input',
35
+ 'callback': 'onInputChanged'},
36
+ 'size z': {'type': 'int', 'value': 1, 'transient': False, 'position': 2, 'widget': 'input', 'callback': None},
37
+ 'footprint': {'name': 'footprint', 'value': None, 'type': 'choice',
38
+ 'choices': ['none', 'cube', 'ball', 'octahedron'], 'transient': False, 'position': None,
39
+ 'callback': None},
40
+ 'radius': {'type': 'int', 'value': 1, 'transient': False, 'position': 4, 'widget': 'input', 'callback': None}}
41
+ options.setDefaultValues(items)
42
+ assert options.getItems() == items
43
+
44
+
45
+ def testGetItems(self, options):
46
+ items = options.getItems()
47
+ assert items['size xy']['value'] == 3
48
+ assert list(items.keys()) == ['image', 'size xy', 'size z', 'footprint', 'radius']
49
+
50
+
51
+ def testSaveAndLoad(self, options):
52
+ if os.path.exists(options.optionsPath):
53
+ os.remove(options.optionsPath)
54
+ oldItems = options.getItems().copy()
55
+ options.load()
56
+ self.items = None
57
+ options.load()
58
+ assert oldItems == options.getItems()
59
+
60
+
61
+ def testGet(self, options):
62
+ option = options.get("size xy")
63
+ assert option["value"] == 3
64
+
65
+
66
+ def testValue(self, options):
67
+ value = options.value("size xy")
68
+ assert value == 3
69
+
70
+
71
+ def testSet(self, options):
72
+ option = {'type': 'int', 'value': 1.365, 'transient': False, 'position': 5, 'widget': 'input', 'callback': None}
73
+ options.set("sigma", option)
74
+ optionRetrieved = options.get("sigma")
75
+ assert optionRetrieved == option
76
+
77
+
78
+
79
+ def testSetValue(self, options):
80
+ options.setValue("size xy", 8)
81
+ assert options.value("size xy") == 8
82
+
83
+
84
+ def testAddImage(self):
85
+ options = Options("Autooptions Test", "Magic Filter")
86
+ options.addImage('input image', value="img01", transient=True)
87
+ assert options.value("input image") == "img01"
88
+ options.addImage('mask', value="mask", transient=True)
89
+ assert options.value("mask") == "mask"
90
+ assert options.get("mask")["position"] == 2
91
+ assert options.get("mask")["type"] == "image"
92
+
93
+
94
+ def testAddLabels(self):
95
+ options = Options("Autooptions Test", "Magic Filter")
96
+ options.addLabels('labels', value="img01_seg", transient=True)
97
+ assert options.value("labels") == "img01_seg"
98
+ assert options.get("labels")["type"] == "labels"
99
+
100
+
101
+ def testAddPoints(self):
102
+ options = Options("Autooptions Test", "Magic Filter")
103
+ options.addPoints('centroids', value="centroids_layer", transient=True)
104
+ assert options.value("centroids") == "centroids_layer"
105
+ assert options.get("centroids")["type"] == "points"
106
+
107
+
108
+ def testAddFFT(self):
109
+ options = Options("Autooptions Test", "Magic Filter")
110
+ options.addFFT('fft1', value="img01_fft", transient=True)
111
+ assert options.value("fft1") == "img01_fft"
112
+ assert options.get("fft1")["type"] == "fft"
113
+
114
+
115
+ def testAddInt(self, options):
116
+ options.addInt('threshold', value=50, callback=self.onSomething)
117
+ assert options.get("threshold")["callback"] == "onSomething"
118
+ assert options.value("threshold") == 50
119
+ assert options.get("threshold")["type"] == "int"
120
+ assert options.get("threshold")["widget"] == "input"
121
+
122
+
123
+ def testAddFloat(self, options):
124
+ options.addFloat('sigma', value=1.3)
125
+ assert options.value("sigma") == 1.3
126
+ assert options.get("sigma")["type"] == "float"
127
+ assert options.get("sigma")["widget"] == "input"
128
+
129
+
130
+ def testAddChoice(self, options):
131
+ options.addChoice("no choice")
132
+ assert options.value("no choice") is None
133
+ assert options.get("no choice")["type"] == "choice"
134
+ assert options.get("no choice")["choices"] == []
135
+ options.addChoice("fruits", value="apple", choices=["orange", "banana", "apple"])
136
+ assert options.value("fruits") == "apple"
137
+ assert options.get("fruits")["type"] == "choice"
138
+ assert options.get("fruits")["choices"] == ["orange", "banana", "apple"]
139
+
140
+
141
+ def testAddStr(self, options):
142
+ options.addStr('experimenter', value="Albert")
143
+ assert options.value("experimenter") == "Albert"
144
+ assert options.get("experimenter")["type"] == "str"
145
+ assert options.get("experimenter")["widget"] == "input"
146
+
147
+
148
+ def testAddBool(self, options):
149
+ options.addBool('use gpu', value=True)
150
+ assert options.value("use gpu") == True
151
+ assert options.get("use gpu")["type"] == "bool"
152
+ assert options.get("use gpu")["widget"] == "checkbox"
153
+ options.addBool('remove background', value=False)
154
+ assert options.value("remove background") == False
155
+ assert options.get("remove background")["type"] == "bool"
156
+ assert options.get("remove background")["widget"] == "checkbox"
157
+
158
+
159
+ def testGetBaseOption(self, options):
160
+ option = options.getBaseOption(7, True, None, self.onSomething)
161
+ assert option["value"] == 7
162
+ assert option["transient"] == True
163
+ assert option["position"] == 6
164
+ assert option["callback"] == "onSomething"
165
+
166
+
167
+ def test_GetPosition(self, options):
168
+ position = options._getPosition(None)
169
+ assert position == 6
170
+ position = options._getPosition(3)
171
+ assert position == 3
172
+