napari-tmidas 0.1.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.
- napari_tmidas/__init__.py +25 -0
- napari_tmidas/_reader.py +73 -0
- napari_tmidas/_sample_data.py +22 -0
- napari_tmidas/_tests/__init__.py +0 -0
- napari_tmidas/_tests/test_reader.py +31 -0
- napari_tmidas/_tests/test_sample_data.py +7 -0
- napari_tmidas/_tests/test_widget.py +66 -0
- napari_tmidas/_tests/test_writer.py +7 -0
- napari_tmidas/_version.py +21 -0
- napari_tmidas/_widget.py +129 -0
- napari_tmidas/_writer.py +66 -0
- napari_tmidas/napari.yaml +57 -0
- napari_tmidas-0.1.1.dist-info/LICENSE +28 -0
- napari_tmidas-0.1.1.dist-info/METADATA +134 -0
- napari_tmidas-0.1.1.dist-info/RECORD +18 -0
- napari_tmidas-0.1.1.dist-info/WHEEL +5 -0
- napari_tmidas-0.1.1.dist-info/entry_points.txt +2 -0
- napari_tmidas-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from ._version import version as __version__
|
|
3
|
+
except ImportError:
|
|
4
|
+
__version__ = "unknown"
|
|
5
|
+
|
|
6
|
+
from ._reader import napari_get_reader
|
|
7
|
+
from ._sample_data import make_sample_data
|
|
8
|
+
from ._widget import (
|
|
9
|
+
ExampleQWidget,
|
|
10
|
+
ImageThreshold,
|
|
11
|
+
threshold_autogenerate_widget,
|
|
12
|
+
threshold_magic_widget,
|
|
13
|
+
)
|
|
14
|
+
from ._writer import write_multiple, write_single_image
|
|
15
|
+
|
|
16
|
+
__all__ = (
|
|
17
|
+
"napari_get_reader",
|
|
18
|
+
"write_single_image",
|
|
19
|
+
"write_multiple",
|
|
20
|
+
"make_sample_data",
|
|
21
|
+
"ExampleQWidget",
|
|
22
|
+
"ImageThreshold",
|
|
23
|
+
"threshold_autogenerate_widget",
|
|
24
|
+
"threshold_magic_widget",
|
|
25
|
+
)
|
napari_tmidas/_reader.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
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/guides.html?#readers
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def napari_get_reader(path):
|
|
13
|
+
"""A basic implementation of a Reader contribution.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
path : str or list of str
|
|
18
|
+
Path to file, or list of paths.
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
function or None
|
|
23
|
+
If the path is a recognized format, return a function that accepts the
|
|
24
|
+
same path or list of paths, and returns a list of layer data tuples.
|
|
25
|
+
"""
|
|
26
|
+
if isinstance(path, list):
|
|
27
|
+
# reader plugins may be handed single path, or a list of paths.
|
|
28
|
+
# if it is a list, it is assumed to be an image stack...
|
|
29
|
+
# so we are only going to look at the first file.
|
|
30
|
+
path = path[0]
|
|
31
|
+
|
|
32
|
+
# if we know we cannot read the file, we immediately return None.
|
|
33
|
+
if not path.endswith(".npy"):
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
# otherwise we return the *function* that can read ``path``.
|
|
37
|
+
return reader_function
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def reader_function(path):
|
|
41
|
+
"""Take a path or list of paths and return a list of LayerData tuples.
|
|
42
|
+
|
|
43
|
+
Readers are expected to return data as a list of tuples, where each tuple
|
|
44
|
+
is (data, [add_kwargs, [layer_type]]), "add_kwargs" and "layer_type" are
|
|
45
|
+
both optional.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
path : str or list of str
|
|
50
|
+
Path to file, or list of paths.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
layer_data : list of tuples
|
|
55
|
+
A list of LayerData tuples where each tuple in the list contains
|
|
56
|
+
(data, metadata, layer_type), where data is a numpy array, metadata is
|
|
57
|
+
a dict of keyword arguments for the corresponding viewer.add_* method
|
|
58
|
+
in napari, and layer_type is a lower-case string naming the type of
|
|
59
|
+
layer. Both "meta", and "layer_type" are optional. napari will
|
|
60
|
+
default to layer_type=="image" if not provided
|
|
61
|
+
"""
|
|
62
|
+
# handle both a string and a list of strings
|
|
63
|
+
paths = [path] if isinstance(path, str) else path
|
|
64
|
+
# load all files into array
|
|
65
|
+
arrays = [np.load(_path) for _path in paths]
|
|
66
|
+
# stack arrays into single array
|
|
67
|
+
data = np.squeeze(np.stack(arrays))
|
|
68
|
+
|
|
69
|
+
# optional kwargs for the corresponding viewer.add_* method
|
|
70
|
+
add_kwargs = {}
|
|
71
|
+
|
|
72
|
+
layer_type = "image" # optional, default is "image"
|
|
73
|
+
return [(data, add_kwargs, layer_type)]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module is an example of a barebones sample data provider for napari.
|
|
3
|
+
|
|
4
|
+
It implements the "sample data" specification.
|
|
5
|
+
see: https://napari.org/stable/plugins/guides.html?#sample-data
|
|
6
|
+
|
|
7
|
+
Replace code below according to your needs.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import numpy
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def make_sample_data():
|
|
16
|
+
"""Generates an image"""
|
|
17
|
+
# Return list of tuples
|
|
18
|
+
# [(data1, add_image_kwargs1), (data2, add_image_kwargs2)]
|
|
19
|
+
# Check the documentation for more information about the
|
|
20
|
+
# add_image_kwargs
|
|
21
|
+
# https://napari.org/stable/api/napari.Viewer.html#napari.Viewer.add_image
|
|
22
|
+
return [(numpy.random.rand(512, 512), {})]
|
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from napari_tmidas import napari_get_reader
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# tmp_path is a pytest fixture
|
|
7
|
+
def test_reader(tmp_path):
|
|
8
|
+
"""An example of how you might test your plugin."""
|
|
9
|
+
|
|
10
|
+
# write some fake data using your supported file format
|
|
11
|
+
my_test_file = str(tmp_path / "myfile.npy")
|
|
12
|
+
original_data = np.random.rand(20, 20)
|
|
13
|
+
np.save(my_test_file, original_data)
|
|
14
|
+
|
|
15
|
+
# try to read it back in
|
|
16
|
+
reader = napari_get_reader(my_test_file)
|
|
17
|
+
assert callable(reader)
|
|
18
|
+
|
|
19
|
+
# make sure we're delivering the right format
|
|
20
|
+
layer_data_list = reader(my_test_file)
|
|
21
|
+
assert isinstance(layer_data_list, list) and len(layer_data_list) > 0
|
|
22
|
+
layer_data_tuple = layer_data_list[0]
|
|
23
|
+
assert isinstance(layer_data_tuple, tuple) and len(layer_data_tuple) > 0
|
|
24
|
+
|
|
25
|
+
# make sure it's the same as it started
|
|
26
|
+
np.testing.assert_allclose(original_data, layer_data_tuple[0])
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_get_reader_pass():
|
|
30
|
+
reader = napari_get_reader("fake.file")
|
|
31
|
+
assert reader is None
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from napari_tmidas._widget import (
|
|
4
|
+
ExampleQWidget,
|
|
5
|
+
ImageThreshold,
|
|
6
|
+
threshold_autogenerate_widget,
|
|
7
|
+
threshold_magic_widget,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_threshold_autogenerate_widget():
|
|
12
|
+
# because our "widget" is a pure function, we can call it and
|
|
13
|
+
# test it independently of napari
|
|
14
|
+
im_data = np.random.random((100, 100))
|
|
15
|
+
thresholded = threshold_autogenerate_widget(im_data, 0.5)
|
|
16
|
+
assert thresholded.shape == im_data.shape
|
|
17
|
+
# etc.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# make_napari_viewer is a pytest fixture that returns a napari viewer object
|
|
21
|
+
# you don't need to import it, as long as napari is installed
|
|
22
|
+
# in your testing environment
|
|
23
|
+
def test_threshold_magic_widget(make_napari_viewer):
|
|
24
|
+
viewer = make_napari_viewer()
|
|
25
|
+
layer = viewer.add_image(np.random.random((100, 100)))
|
|
26
|
+
|
|
27
|
+
# our widget will be a MagicFactory or FunctionGui instance
|
|
28
|
+
my_widget = threshold_magic_widget()
|
|
29
|
+
|
|
30
|
+
# if we "call" this object, it'll execute our function
|
|
31
|
+
thresholded = my_widget(viewer.layers[0], 0.5)
|
|
32
|
+
assert thresholded.shape == layer.data.shape
|
|
33
|
+
# etc.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_image_threshold_widget(make_napari_viewer):
|
|
37
|
+
viewer = make_napari_viewer()
|
|
38
|
+
layer = viewer.add_image(np.random.random((100, 100)))
|
|
39
|
+
my_widget = ImageThreshold(viewer)
|
|
40
|
+
|
|
41
|
+
# because we saved our widgets as attributes of the container
|
|
42
|
+
# we can set their values without having to "interact" with the viewer
|
|
43
|
+
my_widget._image_layer_combo.value = layer
|
|
44
|
+
my_widget._threshold_slider.value = 0.5
|
|
45
|
+
|
|
46
|
+
# this allows us to run our functions directly and ensure
|
|
47
|
+
# correct results
|
|
48
|
+
my_widget._threshold_im()
|
|
49
|
+
assert len(viewer.layers) == 2
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# capsys is a pytest fixture that captures stdout and stderr output streams
|
|
53
|
+
def test_example_q_widget(make_napari_viewer, capsys):
|
|
54
|
+
# make viewer and add an image layer using our fixture
|
|
55
|
+
viewer = make_napari_viewer()
|
|
56
|
+
viewer.add_image(np.random.random((100, 100)))
|
|
57
|
+
|
|
58
|
+
# create our widget, passing in the viewer
|
|
59
|
+
my_widget = ExampleQWidget(viewer)
|
|
60
|
+
|
|
61
|
+
# call our widget method
|
|
62
|
+
my_widget._on_click()
|
|
63
|
+
|
|
64
|
+
# read captured output and check that it's as we expected
|
|
65
|
+
captured = capsys.readouterr()
|
|
66
|
+
assert captured.out == "napari has 1 layers\n"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
|
5
|
+
|
|
6
|
+
TYPE_CHECKING = False
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
11
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
12
|
+
else:
|
|
13
|
+
VERSION_TUPLE = object
|
|
14
|
+
|
|
15
|
+
version: str
|
|
16
|
+
__version__: str
|
|
17
|
+
__version_tuple__: VERSION_TUPLE
|
|
18
|
+
version_tuple: VERSION_TUPLE
|
|
19
|
+
|
|
20
|
+
__version__ = version = '0.1.1'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 1, 1)
|
napari_tmidas/_widget.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
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/guides.html?#widgets
|
|
27
|
+
- magicgui docs: https://pyapp-kit.github.io/magicgui/
|
|
28
|
+
|
|
29
|
+
Replace code below according to your needs.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from typing import TYPE_CHECKING
|
|
33
|
+
|
|
34
|
+
from magicgui import magic_factory
|
|
35
|
+
from magicgui.widgets import CheckBox, Container, create_widget
|
|
36
|
+
from qtpy.QtWidgets import QHBoxLayout, QPushButton, QWidget
|
|
37
|
+
from skimage.util import img_as_float
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
import napari
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Uses the `autogenerate: true` flag in the plugin manifest
|
|
44
|
+
# to indicate it should be wrapped as a magicgui to autogenerate
|
|
45
|
+
# a widget.
|
|
46
|
+
def threshold_autogenerate_widget(
|
|
47
|
+
img: "napari.types.ImageData",
|
|
48
|
+
threshold: "float",
|
|
49
|
+
) -> "napari.types.LabelsData":
|
|
50
|
+
return img_as_float(img) > threshold
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# the magic_factory decorator lets us customize aspects of our widget
|
|
54
|
+
# we specify a widget type for the threshold parameter
|
|
55
|
+
# and use auto_call=True so the function is called whenever
|
|
56
|
+
# the value of a parameter changes
|
|
57
|
+
@magic_factory(
|
|
58
|
+
threshold={"widget_type": "FloatSlider", "max": 1}, auto_call=True
|
|
59
|
+
)
|
|
60
|
+
def threshold_magic_widget(
|
|
61
|
+
img_layer: "napari.layers.Image", threshold: "float"
|
|
62
|
+
) -> "napari.types.LabelsData":
|
|
63
|
+
return img_as_float(img_layer.data) > threshold
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# if we want even more control over our widget, we can use
|
|
67
|
+
# magicgui `Container`
|
|
68
|
+
class ImageThreshold(Container):
|
|
69
|
+
def __init__(self, viewer: "napari.viewer.Viewer"):
|
|
70
|
+
super().__init__()
|
|
71
|
+
self._viewer = viewer
|
|
72
|
+
# use create_widget to generate widgets from type annotations
|
|
73
|
+
self._image_layer_combo = create_widget(
|
|
74
|
+
label="Image", annotation="napari.layers.Image"
|
|
75
|
+
)
|
|
76
|
+
self._threshold_slider = create_widget(
|
|
77
|
+
label="Threshold", annotation=float, widget_type="FloatSlider"
|
|
78
|
+
)
|
|
79
|
+
self._threshold_slider.min = 0
|
|
80
|
+
self._threshold_slider.max = 1
|
|
81
|
+
# use magicgui widgets directly
|
|
82
|
+
self._invert_checkbox = CheckBox(text="Keep pixels below threshold")
|
|
83
|
+
|
|
84
|
+
# connect your own callbacks
|
|
85
|
+
self._threshold_slider.changed.connect(self._threshold_im)
|
|
86
|
+
self._invert_checkbox.changed.connect(self._threshold_im)
|
|
87
|
+
|
|
88
|
+
# append into/extend the container with your widgets
|
|
89
|
+
self.extend(
|
|
90
|
+
[
|
|
91
|
+
self._image_layer_combo,
|
|
92
|
+
self._threshold_slider,
|
|
93
|
+
self._invert_checkbox,
|
|
94
|
+
]
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def _threshold_im(self):
|
|
98
|
+
image_layer = self._image_layer_combo.value
|
|
99
|
+
if image_layer is None:
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
image = img_as_float(image_layer.data)
|
|
103
|
+
name = image_layer.name + "_thresholded"
|
|
104
|
+
threshold = self._threshold_slider.value
|
|
105
|
+
if self._invert_checkbox.value:
|
|
106
|
+
thresholded = image < threshold
|
|
107
|
+
else:
|
|
108
|
+
thresholded = image > threshold
|
|
109
|
+
if name in self._viewer.layers:
|
|
110
|
+
self._viewer.layers[name].data = thresholded
|
|
111
|
+
else:
|
|
112
|
+
self._viewer.add_labels(thresholded, name=name)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class ExampleQWidget(QWidget):
|
|
116
|
+
# your QWidget.__init__ can optionally request the napari viewer instance
|
|
117
|
+
# use a type annotation of 'napari.viewer.Viewer' for any parameter
|
|
118
|
+
def __init__(self, viewer: "napari.viewer.Viewer"):
|
|
119
|
+
super().__init__()
|
|
120
|
+
self.viewer = viewer
|
|
121
|
+
|
|
122
|
+
btn = QPushButton("Click me!")
|
|
123
|
+
btn.clicked.connect(self._on_click)
|
|
124
|
+
|
|
125
|
+
self.setLayout(QHBoxLayout())
|
|
126
|
+
self.layout().addWidget(btn)
|
|
127
|
+
|
|
128
|
+
def _on_click(self):
|
|
129
|
+
print("napari has", len(self.viewer.layers), "layers")
|
napari_tmidas/_writer.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
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/guides.html?#writers
|
|
6
|
+
|
|
7
|
+
Replace code below according to your needs.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Union
|
|
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
|
+
|
|
38
|
+
# implement your writer logic here ...
|
|
39
|
+
|
|
40
|
+
# return path to any file(s) that were successfully written
|
|
41
|
+
return [path]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def write_multiple(path: str, data: list[FullLayerData]) -> list[str]:
|
|
45
|
+
"""Writes multiple layers of different types.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
path : str
|
|
50
|
+
A string path indicating where to save the data file(s).
|
|
51
|
+
data : A list of layer tuples.
|
|
52
|
+
Tuples contain three elements: (data, meta, layer_type)
|
|
53
|
+
`data` is the layer data
|
|
54
|
+
`meta` is a dictionary containing all other metadata attributes
|
|
55
|
+
from the napari layer (excluding the `.data` layer attribute).
|
|
56
|
+
`layer_type` is a string, eg: "image", "labels", "surface", etc.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
[path] : A list containing (potentially multiple) string paths to the saved file(s).
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# implement your writer logic here ...
|
|
64
|
+
|
|
65
|
+
# return path to any file(s) that were successfully written
|
|
66
|
+
return [path]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: napari-tmidas
|
|
2
|
+
display_name: T-MIDAS
|
|
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: ["Annotation", "Segmentation", "Acquisition"]
|
|
7
|
+
contributions:
|
|
8
|
+
commands:
|
|
9
|
+
- id: napari-tmidas.get_reader
|
|
10
|
+
python_name: napari_tmidas._reader:napari_get_reader
|
|
11
|
+
title: Open data with T-MIDAS
|
|
12
|
+
- id: napari-tmidas.write_multiple
|
|
13
|
+
python_name: napari_tmidas._writer:write_multiple
|
|
14
|
+
title: Save multi-layer data with T-MIDAS
|
|
15
|
+
- id: napari-tmidas.write_single_image
|
|
16
|
+
python_name: napari_tmidas._writer:write_single_image
|
|
17
|
+
title: Save image data with T-MIDAS
|
|
18
|
+
- id: napari-tmidas.make_sample_data
|
|
19
|
+
python_name: napari_tmidas._sample_data:make_sample_data
|
|
20
|
+
title: Load sample data from T-MIDAS
|
|
21
|
+
- id: napari-tmidas.make_container_widget
|
|
22
|
+
python_name: napari_tmidas:ImageThreshold
|
|
23
|
+
title: Make threshold Container widget
|
|
24
|
+
- id: napari-tmidas.make_magic_widget
|
|
25
|
+
python_name: napari_tmidas:threshold_magic_widget
|
|
26
|
+
title: Make threshold magic widget
|
|
27
|
+
- id: napari-tmidas.make_function_widget
|
|
28
|
+
python_name: napari_tmidas:threshold_autogenerate_widget
|
|
29
|
+
title: Make threshold function widget
|
|
30
|
+
- id: napari-tmidas.make_qwidget
|
|
31
|
+
python_name: napari_tmidas:ExampleQWidget
|
|
32
|
+
title: Make example QWidget
|
|
33
|
+
readers:
|
|
34
|
+
- command: napari-tmidas.get_reader
|
|
35
|
+
accepts_directories: false
|
|
36
|
+
filename_patterns: ['*.npy']
|
|
37
|
+
writers:
|
|
38
|
+
- command: napari-tmidas.write_multiple
|
|
39
|
+
layer_types: ['image*','labels*']
|
|
40
|
+
filename_extensions: []
|
|
41
|
+
- command: napari-tmidas.write_single_image
|
|
42
|
+
layer_types: ['image']
|
|
43
|
+
filename_extensions: ['.npy']
|
|
44
|
+
sample_data:
|
|
45
|
+
- command: napari-tmidas.make_sample_data
|
|
46
|
+
display_name: T-MIDAS
|
|
47
|
+
key: unique_id.1
|
|
48
|
+
widgets:
|
|
49
|
+
- command: napari-tmidas.make_container_widget
|
|
50
|
+
display_name: Container Threshold
|
|
51
|
+
- command: napari-tmidas.make_magic_widget
|
|
52
|
+
display_name: Magic Threshold
|
|
53
|
+
- command: napari-tmidas.make_function_widget
|
|
54
|
+
autogenerate: true
|
|
55
|
+
display_name: Autogenerate Threshold
|
|
56
|
+
- command: napari-tmidas.make_qwidget
|
|
57
|
+
display_name: Example QWidget
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
Copyright (c) 2025, Marco Meer
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
* Neither the name of copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: napari-tmidas
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Tissue Microscopy Image Data Analysis Suite
|
|
5
|
+
Author: Marco Meer
|
|
6
|
+
Author-email: marco.meer@pm.me
|
|
7
|
+
License:
|
|
8
|
+
Copyright (c) 2025, Marco Meer
|
|
9
|
+
All rights reserved.
|
|
10
|
+
|
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
|
13
|
+
|
|
14
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
15
|
+
list of conditions and the following disclaimer.
|
|
16
|
+
|
|
17
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
18
|
+
this list of conditions and the following disclaimer in the documentation
|
|
19
|
+
and/or other materials provided with the distribution.
|
|
20
|
+
|
|
21
|
+
* Neither the name of copyright holder nor the names of its
|
|
22
|
+
contributors may be used to endorse or promote products derived from
|
|
23
|
+
this software without specific prior written permission.
|
|
24
|
+
|
|
25
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
26
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
27
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
28
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
29
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
30
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
31
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
32
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
33
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
34
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
+
|
|
36
|
+
Project-URL: Bug Tracker, https://github.com/macromeer/napari-tmidas/issues
|
|
37
|
+
Project-URL: Documentation, https://github.com/macromeer/napari-tmidas#README.md
|
|
38
|
+
Project-URL: Source Code, https://github.com/macromeer/napari-tmidas
|
|
39
|
+
Project-URL: User Support, https://github.com/macromeer/napari-tmidas/issues
|
|
40
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
41
|
+
Classifier: Framework :: napari
|
|
42
|
+
Classifier: Intended Audience :: Developers
|
|
43
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
44
|
+
Classifier: Operating System :: OS Independent
|
|
45
|
+
Classifier: Programming Language :: Python
|
|
46
|
+
Classifier: Programming Language :: Python :: 3
|
|
47
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
50
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
51
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
52
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
53
|
+
Requires-Python: >=3.9
|
|
54
|
+
Description-Content-Type: text/markdown
|
|
55
|
+
License-File: LICENSE
|
|
56
|
+
Requires-Dist: numpy
|
|
57
|
+
Requires-Dist: magicgui
|
|
58
|
+
Requires-Dist: qtpy
|
|
59
|
+
Requires-Dist: scikit-image
|
|
60
|
+
Provides-Extra: testing
|
|
61
|
+
Requires-Dist: tox; extra == "testing"
|
|
62
|
+
Requires-Dist: pytest; extra == "testing"
|
|
63
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
64
|
+
Requires-Dist: pytest-qt; extra == "testing"
|
|
65
|
+
Requires-Dist: napari; extra == "testing"
|
|
66
|
+
Requires-Dist: pyqt5; extra == "testing"
|
|
67
|
+
|
|
68
|
+
# napari-tmidas
|
|
69
|
+
|
|
70
|
+
[](https://github.com/macromeer/napari-tmidas/raw/main/LICENSE)
|
|
71
|
+
[](https://pypi.org/project/napari-tmidas)
|
|
72
|
+
[](https://python.org)
|
|
73
|
+
[](https://github.com/macromeer/napari-tmidas/actions)
|
|
74
|
+
[](https://codecov.io/gh/macromeer/napari-tmidas)
|
|
75
|
+
[](https://napari-hub.org/plugins/napari-tmidas)
|
|
76
|
+
|
|
77
|
+
Tissue Microscopy Image Data Analysis Suite
|
|
78
|
+
|
|
79
|
+
----------------------------------
|
|
80
|
+
|
|
81
|
+
This [napari] plugin was generated with [copier] using the [napari-plugin-template].
|
|
82
|
+
|
|
83
|
+
<!--
|
|
84
|
+
Don't miss the full getting started guide to set up your new package:
|
|
85
|
+
https://github.com/napari/napari-plugin-template#getting-started
|
|
86
|
+
|
|
87
|
+
and review the napari docs for plugin developers:
|
|
88
|
+
https://napari.org/stable/plugins/index.html
|
|
89
|
+
-->
|
|
90
|
+
|
|
91
|
+
## Installation
|
|
92
|
+
|
|
93
|
+
You can install `napari-tmidas` via [pip]:
|
|
94
|
+
|
|
95
|
+
pip install napari-tmidas
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
To install latest development version :
|
|
100
|
+
|
|
101
|
+
pip install git+https://github.com/macromeer/napari-tmidas.git
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
## Contributing
|
|
105
|
+
|
|
106
|
+
Contributions are very welcome. Tests can be run with [tox], please ensure
|
|
107
|
+
the coverage at least stays the same before you submit a pull request.
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
Distributed under the terms of the [BSD-3] license,
|
|
112
|
+
"napari-tmidas" is free and open source software
|
|
113
|
+
|
|
114
|
+
## Issues
|
|
115
|
+
|
|
116
|
+
If you encounter any problems, please [file an issue] along with a detailed description.
|
|
117
|
+
|
|
118
|
+
[napari]: https://github.com/napari/napari
|
|
119
|
+
[copier]: https://copier.readthedocs.io/en/stable/
|
|
120
|
+
[@napari]: https://github.com/napari
|
|
121
|
+
[MIT]: http://opensource.org/licenses/MIT
|
|
122
|
+
[BSD-3]: http://opensource.org/licenses/BSD-3-Clause
|
|
123
|
+
[GNU GPL v3.0]: http://www.gnu.org/licenses/gpl-3.0.txt
|
|
124
|
+
[GNU LGPL v3.0]: http://www.gnu.org/licenses/lgpl-3.0.txt
|
|
125
|
+
[Apache Software License 2.0]: http://www.apache.org/licenses/LICENSE-2.0
|
|
126
|
+
[Mozilla Public License 2.0]: https://www.mozilla.org/media/MPL/2.0/index.txt
|
|
127
|
+
[napari-plugin-template]: https://github.com/napari/napari-plugin-template
|
|
128
|
+
|
|
129
|
+
[file an issue]: https://github.com/macromeer/napari-tmidas/issues
|
|
130
|
+
|
|
131
|
+
[napari]: https://github.com/napari/napari
|
|
132
|
+
[tox]: https://tox.readthedocs.io/en/latest/
|
|
133
|
+
[pip]: https://pypi.org/project/pip/
|
|
134
|
+
[PyPI]: https://pypi.org/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
napari_tmidas/__init__.py,sha256=cVpVT4zJ5I9N6YFige0iySIMW3JzE35KKnEy-PFpFx0,592
|
|
2
|
+
napari_tmidas/_reader.py,sha256=A9_hdDxtVkVGmbOsbqgnARCSvpEh7GGPo7ylzmbnu8o,2485
|
|
3
|
+
napari_tmidas/_sample_data.py,sha256=khuv1jemz_fCjqNwEKMFf83Ju0EN4S89IKydsUMmUxw,645
|
|
4
|
+
napari_tmidas/_version.py,sha256=Mmxse1R0ki5tjz9qzU8AQyqUsLt8nTyCAbYQp8R87PU,511
|
|
5
|
+
napari_tmidas/_widget.py,sha256=u9uf9WILAwZg_InhFyjWInY4ej1TV1a59dR8Fe3vNF8,4794
|
|
6
|
+
napari_tmidas/_writer.py,sha256=wbVfHFjjHdybSg37VR4lVmL-kdCkDZsUPDJ66AVLaFQ,1941
|
|
7
|
+
napari_tmidas/napari.yaml,sha256=XRz2siVLEciSqUHv1tlLjX9BB0Sc1jBRB3KyAN2ISgA,2276
|
|
8
|
+
napari_tmidas/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
napari_tmidas/_tests/test_reader.py,sha256=gN_2StATLZYUL56X27ImJTVru_qSoFiY4vtgajcx3H0,975
|
|
10
|
+
napari_tmidas/_tests/test_sample_data.py,sha256=D1HU_C3hWpO3mlSW_7Z94xaYHDtxz0XUrMjQoYop9Ag,104
|
|
11
|
+
napari_tmidas/_tests/test_widget.py,sha256=I_d-Cra_CTcS0QdMItg_HMphvhj0XCx81JnFyCHk9lg,2204
|
|
12
|
+
napari_tmidas/_tests/test_writer.py,sha256=4_MlZM9a5So74J16_4tIOJc6pwTOw9R0-oAE_YioIx4,122
|
|
13
|
+
napari_tmidas-0.1.1.dist-info/LICENSE,sha256=tSjiOqj57exmEIfP2YVPCEeQf0cH49S6HheQR8IiY3g,1485
|
|
14
|
+
napari_tmidas-0.1.1.dist-info/METADATA,sha256=TuiFctic_XaF8TxYPQYuLJOlVTKiF_Qxl0Lh6SiYBb4,5850
|
|
15
|
+
napari_tmidas-0.1.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
16
|
+
napari_tmidas-0.1.1.dist-info/entry_points.txt,sha256=fbVjzbJTm4aDMIBtel1Lyqvq-CwXY7wmCOo_zJ-jtRY,60
|
|
17
|
+
napari_tmidas-0.1.1.dist-info/top_level.txt,sha256=63ybdxCZ4SeT13f_Ou4TsivGV_2Gtm_pJOXToAt30_E,14
|
|
18
|
+
napari_tmidas-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
napari_tmidas
|