napari-mlarray 0.0.1__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,13 @@
1
+ try:
2
+ from ._version import version as __version__
3
+ except ImportError:
4
+ __version__ = "unknown"
5
+
6
+
7
+ from ._reader import napari_get_reader
8
+ from ._writer import write_single_image
9
+
10
+ __all__ = (
11
+ "napari_get_reader",
12
+ "write_single_image",
13
+ )
@@ -0,0 +1,77 @@
1
+ """
2
+ This module is an example of a barebones numpy reader plugin for napari.
3
+
4
+ It implements the Reader specification, but your plugin may choose to
5
+ implement multiple readers or even other plugin contributions. see:
6
+ https://napari.org/stable/plugins/building_a_plugin/guides.html#readers
7
+ """
8
+ from mlarray import MLArray
9
+
10
+
11
+ def napari_get_reader(path):
12
+ """A basic implementation of a Reader contribution.
13
+
14
+ Parameters
15
+ ----------
16
+ path : str or list of str
17
+ Path to file, or list of paths.
18
+
19
+ Returns
20
+ -------
21
+ function or None
22
+ If the path is a recognized format, return a function that accepts the
23
+ same path or list of paths, and returns a list of layer data tuples.
24
+ """
25
+ if isinstance(path, list):
26
+ # reader plugins may be handed single path, or a list of paths.
27
+ # if it is a list, it is assumed to be an image stack...
28
+ # so we are only going to look at the first file.
29
+ path = path[0]
30
+
31
+ # the get_reader function should make as many checks as possible
32
+ # (without loading the full file) to determine if it can read
33
+ # the path. Here, we check the dtype of the array by loading
34
+ # it with memmap, so that we don't actually load the full array into memory.
35
+ # We pretend that this reader can only read integer arrays.
36
+ try:
37
+ if not str(path).endswith(".mla"):
38
+ return None
39
+ # napari_get_reader should never raise an exception, because napari
40
+ # raises its own specific errors depending on what plugins are
41
+ # available for the given path, so we catch
42
+ # the OSError that np.load might raise if the file is malformed
43
+ except OSError:
44
+ return None
45
+
46
+ # otherwise we return the *function* that can read ``path``.
47
+ return reader_function
48
+
49
+
50
+ def reader_function(path):
51
+ """Take a path or list of paths and return a list of LayerData tuples.
52
+
53
+ Readers are expected to return data as a list of tuples, where each tuple
54
+ is (data, [add_kwargs, [layer_type]]), "add_kwargs" and "layer_type" are
55
+ both optional.
56
+
57
+ Parameters
58
+ ----------
59
+ path : str or list of str
60
+ Path to file, or list of paths.
61
+
62
+ Returns
63
+ -------
64
+ layer_data : list of tuples
65
+ A list of LayerData tuples where each tuple in the list contains
66
+ (data, metadata, layer_type), where data is a numpy array, metadata is
67
+ a dict of keyword arguments for the corresponding viewer.add_* method
68
+ in napari, and layer_type is a lower-case string naming the type of
69
+ layer. Both "meta", and "layer_type" are optional. napari will
70
+ default to layer_type=="image" if not provided
71
+ """
72
+ # handle both a string and a list of strings
73
+ paths = [path] if isinstance(path, str) else path
74
+ # load all files into array
75
+ mlarrays = [MLArray.open(_path) for _path in paths]
76
+ layer_data = [(mlarray, {"affine": mlarray.affine, "metadata": mlarray.meta.to_dict()}, "labels" if mlarray.meta.is_seg.is_seg == True else "image") for mlarray in mlarrays]
77
+ return layer_data
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.0.1'
32
+ __version_tuple__ = version_tuple = (0, 0, 1)
33
+
34
+ __commit_id__ = commit_id = None
@@ -0,0 +1,128 @@
1
+ """
2
+ This module contains four napari widgets declared in
3
+ different ways:
4
+
5
+ - a pure Python function flagged with `autogenerate: true`
6
+ in the plugin manifest. Type annotations are used by
7
+ magicgui to generate widgets for each parameter. Best
8
+ suited for simple processing tasks - usually taking
9
+ in and/or returning a layer.
10
+ - a `magic_factory` decorated function. The `magic_factory`
11
+ decorator allows us to customize aspects of the resulting
12
+ GUI, including the widgets associated with each parameter.
13
+ Best used when you have a very simple processing task,
14
+ but want some control over the autogenerated widgets. If you
15
+ find yourself needing to define lots of nested functions to achieve
16
+ your functionality, maybe look at the `Container` widget!
17
+ - a `magicgui.widgets.Container` subclass. This provides lots
18
+ of flexibility and customization options while still supporting
19
+ `magicgui` widgets and convenience methods for creating widgets
20
+ from type annotations. If you want to customize your widgets and
21
+ connect callbacks, this is the best widget option for you.
22
+ - a `QWidget` subclass. This provides maximal flexibility but requires
23
+ full specification of widget layouts, callbacks, events, etc.
24
+
25
+ References:
26
+ - Widget specification: https://napari.org/stable/plugins/building_a_plugin/guides.html#widgets
27
+ - magicgui docs: https://pyapp-kit.github.io/magicgui/
28
+
29
+ Replace code below according to your needs.
30
+ """
31
+ from typing import TYPE_CHECKING
32
+
33
+ from magicgui import magic_factory
34
+ from magicgui.widgets import CheckBox, Container, create_widget
35
+ from qtpy.QtWidgets import QHBoxLayout, QPushButton, QWidget
36
+ from skimage.util import img_as_float
37
+
38
+ if TYPE_CHECKING:
39
+ import napari
40
+
41
+
42
+ # Uses the `autogenerate: true` flag in the plugin manifest
43
+ # to indicate it should be wrapped as a magicgui to autogenerate
44
+ # a widget.
45
+ def threshold_autogenerate_widget(
46
+ img: "napari.types.ImageData",
47
+ threshold: "float",
48
+ ) -> "napari.types.LabelsData":
49
+ return img_as_float(img) > threshold
50
+
51
+
52
+ # the magic_factory decorator lets us customize aspects of our widget
53
+ # we specify a widget type for the threshold parameter
54
+ # and use auto_call=True so the function is called whenever
55
+ # the value of a parameter changes
56
+ @magic_factory(
57
+ threshold={"widget_type": "FloatSlider", "max": 1}, auto_call=True
58
+ )
59
+ def threshold_magic_widget(
60
+ img_layer: "napari.layers.Image", threshold: "float"
61
+ ) -> "napari.types.LabelsData":
62
+ return img_as_float(img_layer.data) > threshold
63
+
64
+
65
+ # if we want even more control over our widget, we can use
66
+ # magicgui `Container`
67
+ class ImageThreshold(Container):
68
+ def __init__(self, viewer: "napari.viewer.Viewer"):
69
+ super().__init__()
70
+ self._viewer = viewer
71
+ # use create_widget to generate widgets from type annotations
72
+ self._image_layer_combo = create_widget(
73
+ label="Image", annotation="napari.layers.Image"
74
+ )
75
+ self._threshold_slider = create_widget(
76
+ label="Threshold", annotation=float, widget_type="FloatSlider"
77
+ )
78
+ self._threshold_slider.min = 0
79
+ self._threshold_slider.max = 1
80
+ # use magicgui widgets directly
81
+ self._invert_checkbox = CheckBox(text="Keep pixels below threshold")
82
+
83
+ # connect your own callbacks
84
+ self._threshold_slider.changed.connect(self._threshold_im)
85
+ self._invert_checkbox.changed.connect(self._threshold_im)
86
+
87
+ # append into/extend the container with your widgets
88
+ self.extend(
89
+ [
90
+ self._image_layer_combo,
91
+ self._threshold_slider,
92
+ self._invert_checkbox,
93
+ ]
94
+ )
95
+
96
+ def _threshold_im(self):
97
+ image_layer = self._image_layer_combo.value
98
+ if image_layer is None:
99
+ return
100
+
101
+ image = img_as_float(image_layer.data)
102
+ name = image_layer.name + "_thresholded"
103
+ threshold = self._threshold_slider.value
104
+ if self._invert_checkbox.value:
105
+ thresholded = image < threshold
106
+ else:
107
+ thresholded = image > threshold
108
+ if name in self._viewer.layers:
109
+ self._viewer.layers[name].data = thresholded
110
+ else:
111
+ self._viewer.add_labels(thresholded, name=name)
112
+
113
+
114
+ class ExampleQWidget(QWidget):
115
+ # your QWidget.__init__ can optionally request the napari viewer instance
116
+ # use a type annotation of 'napari.viewer.Viewer' for any parameter
117
+ def __init__(self, viewer: "napari.viewer.Viewer"):
118
+ super().__init__()
119
+ self.viewer = viewer
120
+
121
+ btn = QPushButton("Click me!")
122
+ btn.clicked.connect(self._on_click)
123
+
124
+ self.setLayout(QHBoxLayout())
125
+ self.layout().addWidget(btn)
126
+
127
+ def _on_click(self):
128
+ print("napari has", len(self.viewer.layers), "layers")
@@ -0,0 +1,41 @@
1
+ """
2
+ This module is an example of a barebones writer plugin for napari.
3
+
4
+ It implements the Writer specification.
5
+ see: https://napari.org/stable/plugins/building_a_plugin/guides.html#writers
6
+
7
+ Replace code below according to your needs.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from collections.abc import Sequence
12
+ from typing import TYPE_CHECKING, Any, Union
13
+ from mlarray import MLArray, Meta
14
+
15
+ if TYPE_CHECKING:
16
+ DataType = Union[Any, Sequence[Any]]
17
+ FullLayerData = tuple[DataType, dict, str]
18
+
19
+
20
+ def write_single_image(path: str, data: Any, meta: dict) -> list[str]:
21
+ """Writes a single image layer.
22
+
23
+ Parameters
24
+ ----------
25
+ path : str
26
+ A string path indicating where to save the image file.
27
+ data : The layer data
28
+ The `.data` attribute from the napari layer.
29
+ meta : dict
30
+ A dictionary containing all other attributes from the napari layer
31
+ (excluding the `.data` layer attribute).
32
+
33
+ Returns
34
+ -------
35
+ [path] : A list containing the string path to the saved file.
36
+ """
37
+ mlarray = MLArray(data, meta=Meta.from_dict(meta["metadata"]))
38
+ mlarray.save(path)
39
+
40
+ # return path to any file(s) that were successfully written
41
+ return [path]
@@ -0,0 +1,22 @@
1
+ name: napari-mlarray
2
+ display_name: Mlarray
3
+ # use 'hidden' to remove plugin from napari hub search results
4
+ visibility: public
5
+ # see https://napari.org/stable/plugins/technical_references/manifest.html#fields for valid categories
6
+ # categories: []
7
+ contributions:
8
+ commands:
9
+ - id: napari-mlarray.get_reader
10
+ python_name: napari_mlarray._reader:napari_get_reader
11
+ title: Open data with Mlarray
12
+ - id: napari-mlarray.write_single_image
13
+ python_name: napari_mlarray._writer:write_single_image
14
+ title: Save image data with Mlarray
15
+ readers:
16
+ - command: napari-mlarray.get_reader
17
+ accepts_directories: false
18
+ filename_patterns: ['*.mla']
19
+ writers:
20
+ - command: napari-mlarray.write_single_image
21
+ layer_types: ['image']
22
+ filename_extensions: ['.mla']
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: napari-mlarray
3
+ Version: 0.0.1
4
+ Summary: A reader/writer Napari plugin for MLArray images.
5
+ Author: Karol-G
6
+ Author-email: karol.gotkowski@dkfz.de
7
+ License:
8
+ The MIT License (MIT)
9
+
10
+ Copyright (c) 2026 Division of Medical Image Computing, German Cancer Research Center (DKFZ), Heidelberg, Germany
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in
20
+ all copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
+ THE SOFTWARE.
29
+
30
+ Classifier: Development Status :: 2 - Pre-Alpha
31
+ Classifier: Framework :: napari
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Programming Language :: Python
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3 :: Only
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
43
+ Requires-Python: >=3.10
44
+ Description-Content-Type: text/markdown
45
+ License-File: LICENSE
46
+ Requires-Dist: mlarray
47
+ Provides-Extra: all
48
+ Requires-Dist: napari[all]; extra == "all"
49
+ Dynamic: license-file
50
+
51
+ # napari-mlarray
52
+
53
+ [![License MIT](https://img.shields.io/pypi/l/napari-mlarray.svg?color=green)](https://github.com/MIC-DKFZ/napari-mlarray/raw/main/LICENSE)
54
+ [![PyPI](https://img.shields.io/pypi/v/napari-mlarray.svg?color=green)](https://pypi.org/project/napari-mlarray)
55
+ [![Python Version](https://img.shields.io/pypi/pyversions/napari-mlarray.svg?color=green)](https://python.org)
56
+ [![tests](https://github.com/MIC-DKFZ/napari-mlarray/workflows/tests/badge.svg)](https://github.com/MIC-DKFZ/napari-mlarray/actions)
57
+ [![codecov](https://codecov.io/gh/MIC-DKFZ/napari-mlarray/branch/main/graph/badge.svg)](https://codecov.io/gh/MIC-DKFZ/napari-mlarray)
58
+ [![napari hub](https://img.shields.io/endpoint?url=https://api.napari-hub.org/shields/napari-mlarray)](https://napari-hub.org/plugins/napari-mlarray)
59
+ [![npe2](https://img.shields.io/badge/plugin-npe2-blue?link=https://napari.org/stable/plugins/index.html)](https://napari.org/stable/plugins/index.html)
60
+ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-purple.json)](https://github.com/copier-org/copier)
61
+
62
+ A reader/writer Napari plugin for [MLArray](https://github.com/MIC-DKFZ/mlarray) images. MLArray is an array format specialized for Machine Learning with Blosc2 backend and standardized metadata.
63
+
64
+ ## Installation
65
+
66
+ You can install `napari-mlarray` via [pip]:
67
+
68
+ ```
69
+ pip install napari-mlarray
70
+ ```
71
+
72
+ If napari is not already installed, you can install `napari-mlarray` with napari and Qt via:
73
+
74
+ ```
75
+ pip install "napari-mlarray[all]"
76
+ ```
77
+
78
+
79
+
80
+ ## Contributing
81
+
82
+ Contributions are very welcome. Tests can be run with [tox], please ensure
83
+ the coverage at least stays the same before you submit a pull request.
84
+
85
+ ## License
86
+
87
+ Distributed under the terms of the [MIT] license,
88
+ "napari-mlarray" is free and open source software
89
+
90
+ ## Issues
91
+
92
+ If you encounter any problems, please [file an issue] along with a detailed description.
93
+
94
+ [napari]: https://github.com/napari/napari
95
+ [copier]: https://copier.readthedocs.io/en/stable/
96
+ [@napari]: https://github.com/napari
97
+ [MIT]: http://opensource.org/licenses/MIT
98
+ [BSD-3]: http://opensource.org/licenses/BSD-3-Clause
99
+ [GNU GPL v3.0]: http://www.gnu.org/licenses/gpl-3.0.txt
100
+ [GNU LGPL v3.0]: http://www.gnu.org/licenses/lgpl-3.0.txt
101
+ [Apache Software License 2.0]: http://www.apache.org/licenses/LICENSE-2.0
102
+ [Mozilla Public License 2.0]: https://www.mozilla.org/media/MPL/2.0/index.txt
103
+ [napari-plugin-template]: https://github.com/napari/napari-plugin-template
104
+
105
+ [napari]: https://github.com/napari/napari
106
+ [tox]: https://tox.readthedocs.io/en/latest/
107
+ [pip]: https://pypi.org/project/pip/
108
+ [PyPI]: https://pypi.org/
109
+
110
+ ## Acknowledgments
111
+
112
+ <p align="left">
113
+ <img src="https://github.com/MIC-DKFZ/vidata/raw/main/imgs/Logos/HI_Logo.png" width="150"> &nbsp;&nbsp;&nbsp;&nbsp;
114
+ <img src="https://github.com/MIC-DKFZ/vidata/raw/main/imgs/Logos/DKFZ_Logo.png" width="500">
115
+ </p>
116
+
117
+ This repository is developed and maintained by the Applied Computer Vision Lab (ACVL)
118
+ of [Helmholtz Imaging](https://www.helmholtz-imaging.de/) and the
119
+ [Division of Medical Image Computing](https://www.dkfz.de/en/medical-image-computing) at DKFZ.
@@ -0,0 +1,12 @@
1
+ napari_mlarray/__init__.py,sha256=c2b0_m5sORovlHyyozJS1l00lXjFM7ULIkrHqojq5N4,249
2
+ napari_mlarray/_reader.py,sha256=TT6-L8t7wlYRA5laoVH-frf-ogBxXlEQWE7y70IUHHs,3045
3
+ napari_mlarray/_version.py,sha256=qf6R-J7-UyuABBo8c0HgaquJ8bejVbf07HodXgwAwgQ,704
4
+ napari_mlarray/_widget.py,sha256=K6MYwgFiQg7-dORp-kC_VivrfppiUwMmevbPMhwMT9c,4810
5
+ napari_mlarray/_writer.py,sha256=tAFCX1-LnmDqeDFpO2H22Xrju58-3D-d0ZrEvdAXMbE,1206
6
+ napari_mlarray/napari.yaml,sha256=HILzIxDmFpRPgCmM7uVzzZ86Ayp2ecWiSXHTCC1qjx4,796
7
+ napari_mlarray-0.0.1.dist-info/licenses/LICENSE,sha256=LKlNG6Bx5z0YnzAp9GjCxCR0aypSPO_JcUHmuVGtwds,1162
8
+ napari_mlarray-0.0.1.dist-info/METADATA,sha256=tHD_AJuOHEEWg3OU6FepCJSMQDbVPHtCGoVa1y6ZBHg,5541
9
+ napari_mlarray-0.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
10
+ napari_mlarray-0.0.1.dist-info/entry_points.txt,sha256=ibu_ymiLzJPNpL0x0Fdendi5fQiq_baxx224E5pAW0c,62
11
+ napari_mlarray-0.0.1.dist-info/top_level.txt,sha256=ZfJPiLTSmZ9eakEU1J6znzWi6dS_OTGAXQSI08HOgQg,15
12
+ napari_mlarray-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [napari.manifest]
2
+ napari-mlarray = napari_mlarray:napari.yaml
@@ -0,0 +1,22 @@
1
+
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2026 Division of Medical Image Computing, German Cancer Research Center (DKFZ), Heidelberg, Germany
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 @@
1
+ napari_mlarray