Cruicis commited on
Commit
679a1a2
·
verified ·
1 Parent(s): 2b2c8bb

Upload 879 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. skimage/__init__.py +182 -0
  3. skimage/__init__.pyi +41 -0
  4. skimage/__pycache__/__init__.cpython-310.pyc +0 -0
  5. skimage/__pycache__/conftest.cpython-310.pyc +0 -0
  6. skimage/_shared/__init__.py +0 -0
  7. skimage/_shared/__pycache__/__init__.cpython-310.pyc +0 -0
  8. skimage/_shared/__pycache__/_dependency_checks.cpython-310.pyc +0 -0
  9. skimage/_shared/__pycache__/_geometry.cpython-310.pyc +0 -0
  10. skimage/_shared/__pycache__/_tempfile.cpython-310.pyc +0 -0
  11. skimage/_shared/__pycache__/_warnings.cpython-310.pyc +0 -0
  12. skimage/_shared/__pycache__/compat.cpython-310.pyc +0 -0
  13. skimage/_shared/__pycache__/coord.cpython-310.pyc +0 -0
  14. skimage/_shared/__pycache__/dtype.cpython-310.pyc +0 -0
  15. skimage/_shared/__pycache__/filters.cpython-310.pyc +0 -0
  16. skimage/_shared/__pycache__/tester.cpython-310.pyc +0 -0
  17. skimage/_shared/__pycache__/testing.cpython-310.pyc +0 -0
  18. skimage/_shared/__pycache__/utils.cpython-310.pyc +0 -0
  19. skimage/_shared/__pycache__/version_requirements.cpython-310.pyc +0 -0
  20. skimage/_shared/_dependency_checks.py +3 -0
  21. skimage/_shared/_geometry.py +54 -0
  22. skimage/_shared/_tempfile.py +28 -0
  23. skimage/_shared/_warnings.py +149 -0
  24. skimage/_shared/compat.py +30 -0
  25. skimage/_shared/coord.py +125 -0
  26. skimage/_shared/dtype.py +73 -0
  27. skimage/_shared/fast_exp.cp310-win_amd64.lib +0 -0
  28. skimage/_shared/fast_exp.cp310-win_amd64.pyd +0 -0
  29. skimage/_shared/fast_exp.h +47 -0
  30. skimage/_shared/filters.py +142 -0
  31. skimage/_shared/geometry.cp310-win_amd64.lib +0 -0
  32. skimage/_shared/geometry.cp310-win_amd64.pyd +0 -0
  33. skimage/_shared/interpolation.cp310-win_amd64.lib +0 -0
  34. skimage/_shared/interpolation.cp310-win_amd64.pyd +0 -0
  35. skimage/_shared/tester.py +131 -0
  36. skimage/_shared/testing.py +291 -0
  37. skimage/_shared/tests/__init__.py +0 -0
  38. skimage/_shared/tests/__pycache__/__init__.cpython-310.pyc +0 -0
  39. skimage/_shared/tests/__pycache__/test_coord.cpython-310.pyc +0 -0
  40. skimage/_shared/tests/__pycache__/test_dtype.cpython-310.pyc +0 -0
  41. skimage/_shared/tests/__pycache__/test_fast_exp.cpython-310.pyc +0 -0
  42. skimage/_shared/tests/__pycache__/test_geometry.cpython-310.pyc +0 -0
  43. skimage/_shared/tests/__pycache__/test_interpolation.cpython-310.pyc +0 -0
  44. skimage/_shared/tests/__pycache__/test_safe_as_int.cpython-310.pyc +0 -0
  45. skimage/_shared/tests/__pycache__/test_testing.cpython-310.pyc +0 -0
  46. skimage/_shared/tests/__pycache__/test_utils.cpython-310.pyc +0 -0
  47. skimage/_shared/tests/__pycache__/test_version_requirements.cpython-310.pyc +0 -0
  48. skimage/_shared/tests/__pycache__/test_warnings.cpython-310.pyc +0 -0
  49. skimage/_shared/tests/test_coord.py +91 -0
  50. skimage/_shared/tests/test_dtype.py +14 -0
.gitattributes CHANGED
@@ -35,3 +35,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  color_features.json filter=lfs diff=lfs merge=lfs -text
37
  image_subset.json filter=lfs diff=lfs merge=lfs -text
 
 
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  color_features.json filter=lfs diff=lfs merge=lfs -text
37
  image_subset.json filter=lfs diff=lfs merge=lfs -text
38
+ skimage/filters/rank/generic_cy.cp310-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
skimage/__init__.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Image Processing for Python
2
+
3
+ ``scikit-image`` (a.k.a. ``skimage``) is a collection of algorithms for image
4
+ processing and computer vision.
5
+
6
+ The main package of ``skimage`` only provides a few utilities for converting
7
+ between image data types; for most features, you need to import one of the
8
+ following subpackages:
9
+
10
+ Subpackages
11
+ -----------
12
+ color
13
+ Color space conversion.
14
+ data
15
+ Test images and example data.
16
+ draw
17
+ Drawing primitives (lines, text, etc.) that operate on NumPy arrays.
18
+ exposure
19
+ Image intensity adjustment, e.g., histogram equalization, etc.
20
+ feature
21
+ Feature detection and extraction, e.g., texture analysis corners, etc.
22
+ filters
23
+ Sharpening, edge finding, rank filters, thresholding, etc.
24
+ graph
25
+ Graph-theoretic operations, e.g., shortest paths.
26
+ io
27
+ Reading, saving, and displaying images and video.
28
+ measure
29
+ Measurement of image properties, e.g., region properties and contours.
30
+ metrics
31
+ Metrics corresponding to images, e.g. distance metrics, similarity, etc.
32
+ morphology
33
+ Morphological operations, e.g., opening or skeletonization.
34
+ restoration
35
+ Restoration algorithms, e.g., deconvolution algorithms, denoising, etc.
36
+ segmentation
37
+ Partitioning an image into multiple regions.
38
+ transform
39
+ Geometric and other transforms, e.g., rotation or the Radon transform.
40
+ util
41
+ Generic utilities.
42
+
43
+ Utility Functions
44
+ -----------------
45
+ img_as_float
46
+ Convert an image to floating point format, with values in [0, 1].
47
+ Is similar to `img_as_float64`, but will not convert lower-precision
48
+ floating point arrays to `float64`.
49
+ img_as_float32
50
+ Convert an image to single-precision (32-bit) floating point format,
51
+ with values in [0, 1].
52
+ img_as_float64
53
+ Convert an image to double-precision (64-bit) floating point format,
54
+ with values in [0, 1].
55
+ img_as_uint
56
+ Convert an image to unsigned integer format, with values in [0, 65535].
57
+ img_as_int
58
+ Convert an image to signed integer format, with values in [-32768, 32767].
59
+ img_as_ubyte
60
+ Convert an image to unsigned byte format, with values in [0, 255].
61
+ img_as_bool
62
+ Convert an image to boolean format, with values either True or False.
63
+ dtype_limits
64
+ Return intensity limits, i.e. (min, max) tuple, of the image's dtype.
65
+
66
+ """
67
+
68
+ __version__ = '0.23.2'
69
+
70
+ import lazy_loader as lazy
71
+
72
+ __getattr__, __lazy_dir__, _ = lazy.attach_stub(__name__, __file__)
73
+
74
+
75
+ def __dir__():
76
+ return __lazy_dir__() + ['__version__']
77
+
78
+
79
+ # Logic for checking for improper install and importing while in the source
80
+ # tree when package has not been installed inplace.
81
+ # Code adapted from scikit-learn's __check_build module.
82
+ _INPLACE_MSG = """
83
+ It appears that you are importing a local scikit-image source tree. For
84
+ this, you need to have an inplace install. Maybe you are in the source
85
+ directory and you need to try from another location."""
86
+
87
+ _STANDARD_MSG = """
88
+ Your install of scikit-image appears to be broken.
89
+ Try re-installing the package following the instructions at:
90
+ https://scikit-image.org/docs/stable/user_guide/install.html"""
91
+
92
+
93
+ def _raise_build_error(e):
94
+ # Raise a comprehensible error
95
+ import os.path as osp
96
+
97
+ local_dir = osp.split(__file__)[0]
98
+ msg = _STANDARD_MSG
99
+ if local_dir == "skimage":
100
+ # Picking up the local install: this will work only if the
101
+ # install is an 'inplace build'
102
+ msg = _INPLACE_MSG
103
+ raise ImportError(
104
+ f"{e}\nIt seems that scikit-image has not been built correctly.\n{msg}"
105
+ )
106
+
107
+
108
+ try:
109
+ # This variable is injected in the __builtins__ by the build
110
+ # process. It used to enable importing subpackages of skimage when
111
+ # the binaries are not built
112
+ __SKIMAGE_SETUP__
113
+ except NameError:
114
+ __SKIMAGE_SETUP__ = False
115
+
116
+ if __SKIMAGE_SETUP__:
117
+ import sys
118
+
119
+ sys.stderr.write('Partial import of skimage during the build process.\n')
120
+ # We are not importing the rest of the scikit during the build
121
+ # process, as it may not be compiled yet
122
+ else:
123
+ try:
124
+ from ._shared import geometry
125
+
126
+ del geometry
127
+ except ImportError as e:
128
+ _raise_build_error(e)
129
+
130
+ # Legacy imports into the root namespace; not advertised in __all__
131
+ from .util.dtype import (
132
+ dtype_limits,
133
+ img_as_float32,
134
+ img_as_float64,
135
+ img_as_float,
136
+ img_as_int,
137
+ img_as_uint,
138
+ img_as_ubyte,
139
+ img_as_bool,
140
+ )
141
+
142
+ from .util.lookfor import lookfor
143
+
144
+ from .data import data_dir
145
+
146
+
147
+ if 'dev' in __version__:
148
+ # Append last commit date and hash to dev version information, if available
149
+
150
+ import subprocess
151
+ import os.path
152
+
153
+ try:
154
+ p = subprocess.Popen(
155
+ ['git', 'log', '-1', '--format="%h %aI"'],
156
+ stdout=subprocess.PIPE,
157
+ stderr=subprocess.PIPE,
158
+ cwd=os.path.dirname(__file__),
159
+ )
160
+ except FileNotFoundError:
161
+ pass
162
+ else:
163
+ out, err = p.communicate()
164
+ if p.returncode == 0:
165
+ git_hash, git_date = (
166
+ out.decode('utf-8')
167
+ .strip()
168
+ .replace('"', '')
169
+ .split('T')[0]
170
+ .replace('-', '')
171
+ .split()
172
+ )
173
+
174
+ __version__ = '+'.join(
175
+ [tag for tag in __version__.split('+') if not tag.startswith('git')]
176
+ )
177
+ __version__ += f'+git{git_date}.{git_hash}'
178
+
179
+ from skimage._shared.tester import PytestTester # noqa
180
+
181
+ test = PytestTester(__name__)
182
+ del PytestTester
skimage/__init__.pyi ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ submodules = [
2
+ 'color',
3
+ 'data',
4
+ 'draw',
5
+ 'exposure',
6
+ 'feature',
7
+ 'filters',
8
+ 'future',
9
+ 'graph',
10
+ 'io',
11
+ 'measure',
12
+ 'metrics',
13
+ 'morphology',
14
+ 'registration',
15
+ 'restoration',
16
+ 'segmentation',
17
+ 'transform',
18
+ 'util',
19
+ ]
20
+
21
+ __all__ = submodules + ['__version__'] # noqa: F822
22
+
23
+ from . import (
24
+ color,
25
+ data,
26
+ draw,
27
+ exposure,
28
+ feature,
29
+ filters,
30
+ future,
31
+ graph,
32
+ io,
33
+ measure,
34
+ metrics,
35
+ morphology,
36
+ registration,
37
+ restoration,
38
+ segmentation,
39
+ transform,
40
+ util,
41
+ )
skimage/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (4.7 kB). View file
 
skimage/__pycache__/conftest.cpython-310.pyc ADDED
Binary file (453 Bytes). View file
 
skimage/_shared/__init__.py ADDED
File without changes
skimage/_shared/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (153 Bytes). View file
 
skimage/_shared/__pycache__/_dependency_checks.cpython-310.pyc ADDED
Binary file (260 Bytes). View file
 
skimage/_shared/__pycache__/_geometry.cpython-310.pyc ADDED
Binary file (1.64 kB). View file
 
skimage/_shared/__pycache__/_tempfile.cpython-310.pyc ADDED
Binary file (995 Bytes). View file
 
skimage/_shared/__pycache__/_warnings.cpython-310.pyc ADDED
Binary file (4.2 kB). View file
 
skimage/_shared/__pycache__/compat.cpython-310.pyc ADDED
Binary file (519 Bytes). View file
 
skimage/_shared/__pycache__/coord.cpython-310.pyc ADDED
Binary file (3.83 kB). View file
 
skimage/_shared/__pycache__/dtype.cpython-310.pyc ADDED
Binary file (2.06 kB). View file
 
skimage/_shared/__pycache__/filters.cpython-310.pyc ADDED
Binary file (4.98 kB). View file
 
skimage/_shared/__pycache__/tester.cpython-310.pyc ADDED
Binary file (3.43 kB). View file
 
skimage/_shared/__pycache__/testing.cpython-310.pyc ADDED
Binary file (8.3 kB). View file
 
skimage/_shared/__pycache__/utils.cpython-310.pyc ADDED
Binary file (25.6 kB). View file
 
skimage/_shared/__pycache__/version_requirements.cpython-310.pyc ADDED
Binary file (4.12 kB). View file
 
skimage/_shared/_dependency_checks.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .version_requirements import is_installed
2
+
3
+ has_mpl = is_installed("matplotlib", ">=3.3")
skimage/_shared/_geometry.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __all__ = ['polygon_clip', 'polygon_area']
2
+
3
+ import numpy as np
4
+
5
+ from .version_requirements import require
6
+
7
+
8
+ @require("matplotlib", ">=3.3")
9
+ def polygon_clip(rp, cp, r0, c0, r1, c1):
10
+ """Clip a polygon to the given bounding box.
11
+
12
+ Parameters
13
+ ----------
14
+ rp, cp : (K,) ndarray of double
15
+ Row and column coordinates of the polygon.
16
+ (r0, c0), (r1, c1) : double
17
+ Top-left and bottom-right coordinates of the bounding box.
18
+
19
+ Returns
20
+ -------
21
+ r_clipped, c_clipped : (L,) ndarray of double
22
+ Coordinates of clipped polygon.
23
+
24
+ Notes
25
+ -----
26
+ This makes use of Sutherland-Hodgman clipping as implemented in
27
+ AGG 2.4 and exposed in Matplotlib.
28
+
29
+ """
30
+ from matplotlib import path, transforms
31
+
32
+ poly = path.Path(np.vstack((rp, cp)).T, closed=True)
33
+ clip_rect = transforms.Bbox([[r0, c0], [r1, c1]])
34
+ poly_clipped = poly.clip_to_bbox(clip_rect).to_polygons()[0]
35
+
36
+ return poly_clipped[:, 0], poly_clipped[:, 1]
37
+
38
+
39
+ def polygon_area(pr, pc):
40
+ """Compute the area of a polygon.
41
+
42
+ Parameters
43
+ ----------
44
+ pr, pc : (K,) array of float
45
+ Polygon row and column coordinates.
46
+
47
+ Returns
48
+ -------
49
+ a : float
50
+ Area of the polygon.
51
+ """
52
+ pr = np.asarray(pr)
53
+ pc = np.asarray(pc)
54
+ return 0.5 * np.abs(np.sum((pc[:-1] * pr[1:]) - (pc[1:] * pr[:-1])))
skimage/_shared/_tempfile.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tempfile import NamedTemporaryFile
2
+ from contextlib import contextmanager
3
+ import os
4
+
5
+
6
+ @contextmanager
7
+ def temporary_file(suffix=''):
8
+ """Yield a writeable temporary filename that is deleted on context exit.
9
+
10
+ Parameters
11
+ ----------
12
+ suffix : string, optional
13
+ The suffix for the file.
14
+
15
+ Examples
16
+ --------
17
+ >>> import numpy as np
18
+ >>> from skimage import io
19
+ >>> with temporary_file('.tif') as tempfile:
20
+ ... im = np.arange(25, dtype=np.uint8).reshape((5, 5))
21
+ ... io.imsave(tempfile, im)
22
+ ... assert np.all(io.imread(tempfile) == im)
23
+ """
24
+ with NamedTemporaryFile(suffix=suffix, delete=False) as tempfile_stream:
25
+ tempfile = tempfile_stream.name
26
+
27
+ yield tempfile
28
+ os.remove(tempfile)
skimage/_shared/_warnings.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from contextlib import contextmanager
2
+ import sys
3
+ import warnings
4
+ import re
5
+ import functools
6
+ import os
7
+
8
+ __all__ = ['all_warnings', 'expected_warnings', 'warn']
9
+
10
+
11
+ # A version of `warnings.warn` with a default stacklevel of 2.
12
+ # functool is used so as not to increase the call stack accidentally
13
+ warn = functools.partial(warnings.warn, stacklevel=2)
14
+
15
+
16
+ @contextmanager
17
+ def all_warnings():
18
+ """
19
+ Context for use in testing to ensure that all warnings are raised.
20
+
21
+ Examples
22
+ --------
23
+ >>> import warnings
24
+ >>> def foo():
25
+ ... warnings.warn(RuntimeWarning("bar"), stacklevel=2)
26
+
27
+ We raise the warning once, while the warning filter is set to "once".
28
+ Hereafter, the warning is invisible, even with custom filters:
29
+
30
+ >>> with warnings.catch_warnings():
31
+ ... warnings.simplefilter('once')
32
+ ... foo() # doctest: +SKIP
33
+
34
+ We can now run ``foo()`` without a warning being raised:
35
+
36
+ >>> from numpy.testing import assert_warns
37
+ >>> foo() # doctest: +SKIP
38
+
39
+ To catch the warning, we call in the help of ``all_warnings``:
40
+
41
+ >>> with all_warnings():
42
+ ... assert_warns(RuntimeWarning, foo)
43
+ """
44
+ # _warnings.py is on the critical import path.
45
+ # Since this is a testing only function, we lazy import inspect.
46
+ import inspect
47
+
48
+ # Whenever a warning is triggered, Python adds a __warningregistry__
49
+ # member to the *calling* module. The exercise here is to find
50
+ # and eradicate all those breadcrumbs that were left lying around.
51
+ #
52
+ # We proceed by first searching all parent calling frames and explicitly
53
+ # clearing their warning registries (necessary for the doctests above to
54
+ # pass). Then, we search for all submodules of skimage and clear theirs
55
+ # as well (necessary for the skimage test suite to pass).
56
+
57
+ frame = inspect.currentframe()
58
+ if frame:
59
+ for f in inspect.getouterframes(frame):
60
+ f[0].f_locals['__warningregistry__'] = {}
61
+ del frame
62
+
63
+ for mod_name, mod in list(sys.modules.items()):
64
+ try:
65
+ mod.__warningregistry__.clear()
66
+ except AttributeError:
67
+ pass
68
+
69
+ with warnings.catch_warnings(record=True) as w:
70
+ warnings.simplefilter("always")
71
+ yield w
72
+
73
+
74
+ @contextmanager
75
+ def expected_warnings(matching):
76
+ r"""Context for use in testing to catch known warnings matching regexes
77
+
78
+ Parameters
79
+ ----------
80
+ matching : None or a list of strings or compiled regexes
81
+ Regexes for the desired warning to catch
82
+ If matching is None, this behaves as a no-op.
83
+
84
+ Examples
85
+ --------
86
+ >>> import numpy as np
87
+ >>> rng = np.random.default_rng()
88
+ >>> image = rng.integers(0, 2**16, size=(100, 100), dtype=np.uint16)
89
+ >>> # rank filters are slow when bit-depth exceeds 10 bits
90
+ >>> from skimage import filters
91
+ >>> with expected_warnings(['Bad rank filter performance']):
92
+ ... median_filtered = filters.rank.median(image)
93
+
94
+ Notes
95
+ -----
96
+ Uses `all_warnings` to ensure all warnings are raised.
97
+ Upon exiting, it checks the recorded warnings for the desired matching
98
+ pattern(s).
99
+ Raises a ValueError if any match was not found or an unexpected
100
+ warning was raised.
101
+ Allows for three types of behaviors: `and`, `or`, and `optional` matches.
102
+ This is done to accommodate different build environments or loop conditions
103
+ that may produce different warnings. The behaviors can be combined.
104
+ If you pass multiple patterns, you get an orderless `and`, where all of the
105
+ warnings must be raised.
106
+ If you use the `|` operator in a pattern, you can catch one of several
107
+ warnings.
108
+ Finally, you can use `|\A\Z` in a pattern to signify it as optional.
109
+
110
+ """
111
+ if isinstance(matching, str):
112
+ raise ValueError(
113
+ '``matching`` should be a list of strings and not ' 'a string itself.'
114
+ )
115
+
116
+ # Special case for disabling the context manager
117
+ if matching is None:
118
+ yield None
119
+ return
120
+
121
+ strict_warnings = os.environ.get('SKIMAGE_TEST_STRICT_WARNINGS', '1')
122
+ if strict_warnings.lower() == 'true':
123
+ strict_warnings = True
124
+ elif strict_warnings.lower() == 'false':
125
+ strict_warnings = False
126
+ else:
127
+ strict_warnings = bool(int(strict_warnings))
128
+
129
+ with all_warnings() as w:
130
+ # enter context
131
+ yield w
132
+ # exited user context, check the recorded warnings
133
+ # Allow users to provide None
134
+ while None in matching:
135
+ matching.remove(None)
136
+ remaining = [m for m in matching if r'\A\Z' not in m.split('|')]
137
+ for warn in w:
138
+ found = False
139
+ for match in matching:
140
+ if re.search(match, str(warn.message)) is not None:
141
+ found = True
142
+ if match in remaining:
143
+ remaining.remove(match)
144
+ if strict_warnings and not found:
145
+ raise ValueError(f'Unexpected warning: {str(warn.message)}')
146
+ if strict_warnings and (len(remaining) > 0):
147
+ newline = "\n"
148
+ msg = f"No warning raised matching:{newline}{newline.join(remaining)}"
149
+ raise ValueError(msg)
skimage/_shared/compat.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compatibility helpers for dependencies."""
2
+
3
+ from packaging.version import parse
4
+
5
+ import numpy as np
6
+ import scipy as sp
7
+
8
+
9
+ __all__ = [
10
+ "NP_COPY_IF_NEEDED",
11
+ "SCIPY_CG_TOL_PARAM_NAME",
12
+ ]
13
+
14
+
15
+ NUMPY_LT_2_0_0 = parse(np.__version__) < parse('2.0.0.dev0')
16
+
17
+ # With NumPy 2.0.0, `copy=False` now raises a ValueError if the copy cannot be
18
+ # made. The previous behavior to only copy if needed is provided with `copy=None`.
19
+ # During the transition period, use this symbol instead.
20
+ # Remove once NumPy 2.0.0 is the minimal required version.
21
+ # https://numpy.org/devdocs/release/2.0.0-notes.html#new-copy-keyword-meaning-for-array-and-asarray-constructors
22
+ # https://github.com/numpy/numpy/pull/25168
23
+ NP_COPY_IF_NEEDED = False if NUMPY_LT_2_0_0 else None
24
+
25
+
26
+ SCIPY_LT_1_12 = parse(sp.__version__) < parse('1.12')
27
+
28
+ # Starting in SciPy v1.12, 'scipy.sparse.linalg.cg' keyword argument `tol` is
29
+ # deprecated in favor of `rtol`.
30
+ SCIPY_CG_TOL_PARAM_NAME = "tol" if SCIPY_LT_1_12 else "rtol"
skimage/_shared/coord.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from scipy.spatial import cKDTree, distance
3
+
4
+
5
+ def _ensure_spacing(coord, spacing, p_norm, max_out):
6
+ """Returns a subset of coord where a minimum spacing is guaranteed.
7
+
8
+ Parameters
9
+ ----------
10
+ coord : ndarray
11
+ The coordinates of the considered points.
12
+ spacing : float
13
+ the maximum allowed spacing between the points.
14
+ p_norm : float
15
+ Which Minkowski p-norm to use. Should be in the range [1, inf].
16
+ A finite large p may cause a ValueError if overflow can occur.
17
+ ``inf`` corresponds to the Chebyshev distance and 2 to the
18
+ Euclidean distance.
19
+ max_out: int
20
+ If not None, at most the first ``max_out`` candidates are
21
+ returned.
22
+
23
+ Returns
24
+ -------
25
+ output : ndarray
26
+ A subset of coord where a minimum spacing is guaranteed.
27
+
28
+ """
29
+
30
+ # Use KDtree to find the peaks that are too close to each other
31
+ tree = cKDTree(coord)
32
+
33
+ indices = tree.query_ball_point(coord, r=spacing, p=p_norm)
34
+ rejected_peaks_indices = set()
35
+ naccepted = 0
36
+ for idx, candidates in enumerate(indices):
37
+ if idx not in rejected_peaks_indices:
38
+ # keep current point and the points at exactly spacing from it
39
+ candidates.remove(idx)
40
+ dist = distance.cdist(
41
+ [coord[idx]], coord[candidates], distance.minkowski, p=p_norm
42
+ ).reshape(-1)
43
+ candidates = [c for c, d in zip(candidates, dist) if d < spacing]
44
+
45
+ # candidates.remove(keep)
46
+ rejected_peaks_indices.update(candidates)
47
+ naccepted += 1
48
+ if max_out is not None and naccepted >= max_out:
49
+ break
50
+
51
+ # Remove the peaks that are too close to each other
52
+ output = np.delete(coord, tuple(rejected_peaks_indices), axis=0)
53
+ if max_out is not None:
54
+ output = output[:max_out]
55
+
56
+ return output
57
+
58
+
59
+ def ensure_spacing(
60
+ coords,
61
+ spacing=1,
62
+ p_norm=np.inf,
63
+ min_split_size=50,
64
+ max_out=None,
65
+ *,
66
+ max_split_size=2000,
67
+ ):
68
+ """Returns a subset of coord where a minimum spacing is guaranteed.
69
+
70
+ Parameters
71
+ ----------
72
+ coords : array_like
73
+ The coordinates of the considered points.
74
+ spacing : float
75
+ the maximum allowed spacing between the points.
76
+ p_norm : float
77
+ Which Minkowski p-norm to use. Should be in the range [1, inf].
78
+ A finite large p may cause a ValueError if overflow can occur.
79
+ ``inf`` corresponds to the Chebyshev distance and 2 to the
80
+ Euclidean distance.
81
+ min_split_size : int
82
+ Minimum split size used to process ``coords`` by batch to save
83
+ memory. If None, the memory saving strategy is not applied.
84
+ max_out : int
85
+ If not None, only the first ``max_out`` candidates are returned.
86
+ max_split_size : int
87
+ Maximum split size used to process ``coords`` by batch to save
88
+ memory. This number was decided by profiling with a large number
89
+ of points. Too small a number results in too much looping in
90
+ Python instead of C, slowing down the process, while too large
91
+ a number results in large memory allocations, slowdowns, and,
92
+ potentially, in the process being killed -- see gh-6010. See
93
+ benchmark results `here
94
+ <https://github.com/scikit-image/scikit-image/pull/6035#discussion_r751518691>`_.
95
+
96
+ Returns
97
+ -------
98
+ output : array_like
99
+ A subset of coord where a minimum spacing is guaranteed.
100
+
101
+ """
102
+
103
+ output = coords
104
+ if len(coords):
105
+ coords = np.atleast_2d(coords)
106
+ if min_split_size is None:
107
+ batch_list = [coords]
108
+ else:
109
+ coord_count = len(coords)
110
+ split_idx = [min_split_size]
111
+ split_size = min_split_size
112
+ while coord_count - split_idx[-1] > max_split_size:
113
+ split_size *= 2
114
+ split_idx.append(split_idx[-1] + min(split_size, max_split_size))
115
+ batch_list = np.array_split(coords, split_idx)
116
+
117
+ output = np.zeros((0, coords.shape[1]), dtype=coords.dtype)
118
+ for batch in batch_list:
119
+ output = _ensure_spacing(
120
+ np.vstack([output, batch]), spacing, p_norm, max_out
121
+ )
122
+ if max_out is not None and len(output) >= max_out:
123
+ break
124
+
125
+ return output
skimage/_shared/dtype.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # Define classes of supported dtypes and Python scalar types
4
+ # Variables ending in `_dtypes` only contain numpy.dtypes of the respective
5
+ # class; variables ending in `_types` additionally include Python scalar types.
6
+ signed_integer_dtypes = {np.int8, np.int16, np.int32, np.int64}
7
+ signed_integer_types = signed_integer_dtypes | {int}
8
+
9
+ unsigned_integer_dtypes = {np.uint8, np.uint16, np.uint32, np.uint64}
10
+
11
+ integer_dtypes = signed_integer_dtypes | unsigned_integer_dtypes
12
+ integer_types = signed_integer_types | unsigned_integer_dtypes
13
+
14
+ floating_dtypes = {np.float16, np.float32, np.float64}
15
+ floating_types = floating_dtypes | {float}
16
+
17
+ complex_dtypes = {np.complex64, np.complex128}
18
+ complex_types = complex_dtypes | {complex}
19
+
20
+ inexact_dtypes = floating_dtypes | complex_dtypes
21
+ inexact_types = floating_types | complex_types
22
+
23
+ bool_types = {np.dtype(bool), bool}
24
+
25
+ numeric_dtypes = integer_dtypes | inexact_dtypes | {np.bool_}
26
+ numeric_types = integer_types | inexact_types | bool_types
27
+
28
+
29
+ def numeric_dtype_min_max(dtype):
30
+ """Return minimum and maximum representable value for a given dtype.
31
+
32
+ A convenient wrapper around `numpy.finfo` and `numpy.iinfo` that
33
+ additionally supports numpy.bool as well.
34
+
35
+ Parameters
36
+ ----------
37
+ dtype : numpy.dtype
38
+ The dtype. Tries to convert Python "types" such as int or float, to
39
+ the corresponding NumPy dtype.
40
+
41
+ Returns
42
+ -------
43
+ min, max : number
44
+ Minimum and maximum of the given `dtype`. These scalars are themselves
45
+ of the given `dtype`.
46
+
47
+ Examples
48
+ --------
49
+ >>> import numpy as np
50
+ >>> numeric_dtype_min_max(np.uint8)
51
+ (0, 255)
52
+ >>> numeric_dtype_min_max(bool)
53
+ (False, True)
54
+ >>> numeric_dtype_min_max(np.float64)
55
+ (-1.7976931348623157e+308, 1.7976931348623157e+308)
56
+ >>> numeric_dtype_min_max(int)
57
+ (-9223372036854775808, 9223372036854775807)
58
+ """
59
+ dtype = np.dtype(dtype)
60
+ if np.issubdtype(dtype, np.integer):
61
+ info = np.iinfo(dtype)
62
+ min_ = dtype.type(info.min)
63
+ max_ = dtype.type(info.max)
64
+ elif np.issubdtype(dtype, np.inexact):
65
+ info = np.finfo(dtype)
66
+ min_ = info.min
67
+ max_ = info.max
68
+ elif np.issubdtype(dtype, np.dtype(bool)):
69
+ min_ = dtype.type(False)
70
+ max_ = dtype.type(True)
71
+ else:
72
+ raise ValueError(f"unsupported dtype {dtype!r}")
73
+ return min_, max_
skimage/_shared/fast_exp.cp310-win_amd64.lib ADDED
Binary file (1.37 kB). View file
 
skimage/_shared/fast_exp.cp310-win_amd64.pyd ADDED
Binary file (53.8 kB). View file
 
skimage/_shared/fast_exp.h ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* A fast approximation of the exponential function.
2
+ * Reference [1]: https://schraudolph.org/pubs/Schraudolph99.pdf
3
+ * Reference [2]: https://doi.org/10.1162/089976600300015033
4
+ * Additional improvements by Leonid Bloch. */
5
+
6
+ #include <stdint.h>
7
+
8
+ /* use just EXP_A = 1512775 for integer version, to avoid FP calculations */
9
+ #define EXP_A (1512775.3951951856938) /* 2^20/ln2 */
10
+ /* For min. RMS error */
11
+ #define EXP_BC 1072632447 /* 1023*2^20 - 60801 */
12
+ /* For min. max. relative error */
13
+ /* #define EXP_BC 1072647449 */ /* 1023*2^20 - 45799 */
14
+ /* For min. mean relative error */
15
+ /* #define EXP_BC 1072625005 */ /* 1023*2^20 - 68243 */
16
+
17
+ __inline double _fast_exp (double y)
18
+ {
19
+ union
20
+ {
21
+ double d;
22
+ struct { int32_t i, j; } n;
23
+ char t[8];
24
+ } _eco;
25
+
26
+ _eco.n.i = 1;
27
+
28
+ switch(_eco.t[0]) {
29
+ case 1:
30
+ /* Little endian */
31
+ _eco.n.j = (int32_t)(EXP_A*(y)) + EXP_BC;
32
+ _eco.n.i = 0;
33
+ break;
34
+ case 0:
35
+ /* Big endian */
36
+ _eco.n.i = (int32_t)(EXP_A*(y)) + EXP_BC;
37
+ _eco.n.j = 0;
38
+ break;
39
+ }
40
+
41
+ return _eco.d;
42
+ }
43
+
44
+ __inline float _fast_expf (float y)
45
+ {
46
+ return (float)_fast_exp((double)y);
47
+ }
skimage/_shared/filters.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Filters used across multiple skimage submodules.
2
+
3
+ These are defined here to avoid circular imports.
4
+
5
+ The unit tests remain under skimage/filters/tests/
6
+ """
7
+
8
+ from collections.abc import Iterable
9
+
10
+ import numpy as np
11
+ from scipy import ndimage as ndi
12
+
13
+ from .._shared.utils import (
14
+ _supported_float_type,
15
+ convert_to_float,
16
+ deprecate_parameter,
17
+ DEPRECATED,
18
+ )
19
+
20
+
21
+ @deprecate_parameter(
22
+ "output", new_name="out", start_version="0.23", stop_version="0.25"
23
+ )
24
+ def gaussian(
25
+ image,
26
+ sigma=1,
27
+ output=DEPRECATED,
28
+ mode='nearest',
29
+ cval=0,
30
+ preserve_range=False,
31
+ truncate=4.0,
32
+ *,
33
+ channel_axis=None,
34
+ out=None,
35
+ ):
36
+ """Multi-dimensional Gaussian filter.
37
+
38
+ Parameters
39
+ ----------
40
+ image : ndarray
41
+ Input image (grayscale or color) to filter.
42
+ sigma : scalar or sequence of scalars, optional
43
+ Standard deviation for Gaussian kernel. The standard
44
+ deviations of the Gaussian filter are given for each axis as a
45
+ sequence, or as a single number, in which case it is equal for
46
+ all axes.
47
+ mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
48
+ The ``mode`` parameter determines how the array borders are
49
+ handled, where ``cval`` is the value when mode is equal to
50
+ 'constant'. Default is 'nearest'.
51
+ cval : scalar, optional
52
+ Value to fill past edges of input if ``mode`` is 'constant'. Default
53
+ is 0.0
54
+ preserve_range : bool, optional
55
+ If True, keep the original range of values. Otherwise, the input
56
+ ``image`` is converted according to the conventions of ``img_as_float``
57
+ (Normalized first to values [-1.0 ; 1.0] or [0 ; 1.0] depending on
58
+ dtype of input)
59
+
60
+ For more information, see:
61
+ https://scikit-image.org/docs/dev/user_guide/data_types.html
62
+ truncate : float, optional
63
+ Truncate the filter at this many standard deviations.
64
+ channel_axis : int or None, optional
65
+ If None, the image is assumed to be a grayscale (single channel) image.
66
+ Otherwise, this parameter indicates which axis of the array corresponds
67
+ to channels.
68
+
69
+ .. versionadded:: 0.19
70
+ `channel_axis` was added in 0.19.
71
+ out : ndarray, optional
72
+ If given, the filtered image will be stored in this array.
73
+
74
+ .. versionadded:: 0.23
75
+ `out` was added in 0.23.
76
+
77
+ Returns
78
+ -------
79
+ filtered_image : ndarray
80
+ the filtered array
81
+
82
+ Notes
83
+ -----
84
+ This function is a wrapper around :func:`scipy.ndimage.gaussian_filter`.
85
+
86
+ Integer arrays are converted to float.
87
+
88
+ `out` should be of floating-point data type since `gaussian` converts the
89
+ input `image` to float. If `out` is not provided, another array
90
+ will be allocated and returned as the result.
91
+
92
+ The multi-dimensional filter is implemented as a sequence of
93
+ one-dimensional convolution filters. The intermediate arrays are
94
+ stored in the same data type as the output. Therefore, for output
95
+ types with a limited precision, the results may be imprecise
96
+ because intermediate results may be stored with insufficient
97
+ precision.
98
+
99
+ Examples
100
+ --------
101
+ >>> import skimage as ski
102
+ >>> a = np.zeros((3, 3))
103
+ >>> a[1, 1] = 1
104
+ >>> a
105
+ array([[0., 0., 0.],
106
+ [0., 1., 0.],
107
+ [0., 0., 0.]])
108
+ >>> ski.filters.gaussian(a, sigma=0.4) # mild smoothing
109
+ array([[0.00163116, 0.03712502, 0.00163116],
110
+ [0.03712502, 0.84496158, 0.03712502],
111
+ [0.00163116, 0.03712502, 0.00163116]])
112
+ >>> ski.filters.gaussian(a, sigma=1) # more smoothing
113
+ array([[0.05855018, 0.09653293, 0.05855018],
114
+ [0.09653293, 0.15915589, 0.09653293],
115
+ [0.05855018, 0.09653293, 0.05855018]])
116
+ >>> # Several modes are possible for handling boundaries
117
+ >>> ski.filters.gaussian(a, sigma=1, mode='reflect')
118
+ array([[0.08767308, 0.12075024, 0.08767308],
119
+ [0.12075024, 0.16630671, 0.12075024],
120
+ [0.08767308, 0.12075024, 0.08767308]])
121
+ >>> # For RGB images, each is filtered separately
122
+ >>> image = ski.data.astronaut()
123
+ >>> filtered_img = ski.filters.gaussian(image, sigma=1, channel_axis=-1)
124
+
125
+ """
126
+ if np.any(np.asarray(sigma) < 0.0):
127
+ raise ValueError("Sigma values less than zero are not valid")
128
+ if channel_axis is not None:
129
+ # do not filter across channels
130
+ if not isinstance(sigma, Iterable):
131
+ sigma = [sigma] * (image.ndim - 1)
132
+ if len(sigma) == image.ndim - 1:
133
+ sigma = list(sigma)
134
+ sigma.insert(channel_axis % image.ndim, 0)
135
+ image = convert_to_float(image, preserve_range)
136
+ float_dtype = _supported_float_type(image.dtype)
137
+ image = image.astype(float_dtype, copy=False)
138
+ if (out is not None) and (not np.issubdtype(out.dtype, np.floating)):
139
+ raise ValueError(f"dtype of `out` must be float; got {out.dtype!r}.")
140
+ return ndi.gaussian_filter(
141
+ image, sigma, output=out, mode=mode, cval=cval, truncate=truncate
142
+ )
skimage/_shared/geometry.cp310-win_amd64.lib ADDED
Binary file (1.37 kB). View file
 
skimage/_shared/geometry.cp310-win_amd64.pyd ADDED
Binary file (118 kB). View file
 
skimage/_shared/interpolation.cp310-win_amd64.lib ADDED
Binary file (1.42 kB). View file
 
skimage/_shared/interpolation.cp310-win_amd64.pyd ADDED
Binary file (36.9 kB). View file
 
skimage/_shared/tester.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+
5
+ def _show_skimage_info():
6
+ import skimage
7
+
8
+ print(f"skimage version {skimage.__version__}")
9
+
10
+
11
+ class PytestTester:
12
+ """
13
+ Pytest test runner.
14
+
15
+ This class is made available in ``skimage._shared.testing``, and a test
16
+ function is typically added to a package's __init__.py like so::
17
+
18
+ from skimage._shared.testing import PytestTester
19
+ test = PytestTester(__name__)
20
+ del PytestTester
21
+
22
+ Calling this test function finds and runs all tests associated with the
23
+ module and all its sub-modules.
24
+
25
+ Attributes
26
+ ----------
27
+ module_name : str
28
+ Full path to the package to test.
29
+
30
+ Parameters
31
+ ----------
32
+ module_name : module name
33
+ The name of the module to test.
34
+
35
+ """
36
+
37
+ def __init__(self, module_name):
38
+ self.module_name = module_name
39
+
40
+ def __call__(
41
+ self,
42
+ label='fast',
43
+ verbose=1,
44
+ extra_argv=None,
45
+ doctests=False,
46
+ coverage=False,
47
+ durations=-1,
48
+ tests=None,
49
+ ):
50
+ """
51
+ Run tests for module using pytest.
52
+
53
+ Parameters
54
+ ----------
55
+ label : {'fast', 'full'}, optional
56
+ Identifies the tests to run. When set to 'fast', tests decorated
57
+ with `pytest.mark.slow` are skipped, when 'full', the slow marker
58
+ is ignored.
59
+ verbose : int, optional
60
+ Verbosity value for test outputs, in the range 1-3. Default is 1.
61
+ extra_argv : list, optional
62
+ List with any extra arguments to pass to pytests.
63
+ doctests : bool, optional
64
+ .. note:: Not supported
65
+ coverage : bool, optional
66
+ If True, report coverage of scikit-image code. Default is False.
67
+ Requires installation of (pip) pytest-cov.
68
+ durations : int, optional
69
+ If < 0, do nothing, If 0, report time of all tests, if > 0,
70
+ report the time of the slowest `timer` tests. Default is -1.
71
+ tests : test or list of tests
72
+ Tests to be executed with pytest '--pyargs'
73
+
74
+ Returns
75
+ -------
76
+ result : bool
77
+ Return True on success, false otherwise.
78
+ """
79
+ import pytest
80
+
81
+ module = sys.modules[self.module_name]
82
+ module_path = os.path.abspath(module.__path__[0])
83
+
84
+ # setup the pytest arguments
85
+ pytest_args = ["-l"]
86
+
87
+ # offset verbosity. The "-q" cancels a "-v".
88
+ pytest_args += ["-q"]
89
+
90
+ # Filter out annoying import messages. Want these in both develop and
91
+ # release mode.
92
+ pytest_args += [
93
+ "-W ignore:Not importing directory",
94
+ "-W ignore:numpy.dtype size changed",
95
+ "-W ignore:numpy.ufunc size changed",
96
+ ]
97
+
98
+ if doctests:
99
+ raise ValueError("Doctests not supported")
100
+
101
+ if extra_argv:
102
+ pytest_args += list(extra_argv)
103
+
104
+ if verbose > 1:
105
+ pytest_args += ["-" + "v" * (verbose - 1)]
106
+
107
+ if coverage:
108
+ pytest_args += ["--cov=" + module_path]
109
+
110
+ if label == "fast":
111
+ pytest_args += ["-m", "not slow"]
112
+ elif label != "full":
113
+ pytest_args += ["-m", label]
114
+
115
+ if durations >= 0:
116
+ pytest_args += [f"--durations={durations}"]
117
+
118
+ if tests is None:
119
+ tests = [self.module_name]
120
+
121
+ pytest_args += ["--pyargs"] + list(tests)
122
+
123
+ # run tests.
124
+ _show_skimage_info()
125
+
126
+ try:
127
+ code = pytest.main(pytest_args)
128
+ except SystemExit as exc:
129
+ code = exc.code
130
+
131
+ return code == 0
skimage/_shared/testing.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Testing utilities.
3
+ """
4
+
5
+ import os
6
+ import re
7
+ import struct
8
+ import threading
9
+ import functools
10
+ import inspect
11
+ from tempfile import NamedTemporaryFile
12
+
13
+ import numpy as np
14
+ from numpy import testing
15
+ from numpy.testing import (
16
+ TestCase,
17
+ assert_,
18
+ assert_warns,
19
+ assert_no_warnings,
20
+ assert_equal,
21
+ assert_almost_equal,
22
+ assert_array_equal,
23
+ assert_allclose,
24
+ assert_array_almost_equal,
25
+ assert_array_almost_equal_nulp,
26
+ assert_array_less,
27
+ )
28
+
29
+ from .. import data, io
30
+ from ..data._fetchers import _fetch
31
+ from ..util import img_as_uint, img_as_float, img_as_int, img_as_ubyte
32
+ from ._warnings import expected_warnings
33
+
34
+ import pytest
35
+
36
+
37
+ skipif = pytest.mark.skipif
38
+ xfail = pytest.mark.xfail
39
+ parametrize = pytest.mark.parametrize
40
+ raises = pytest.raises
41
+ fixture = pytest.fixture
42
+
43
+ SKIP_RE = re.compile(r"(\s*>>>.*?)(\s*)#\s*skip\s+if\s+(.*)$")
44
+
45
+
46
+ # true if python is running in 32bit mode
47
+ # Calculate the size of a void * pointer in bits
48
+ # https://docs.python.org/3/library/struct.html
49
+ arch32 = struct.calcsize("P") * 8 == 32
50
+
51
+
52
+ def assert_less(a, b, msg=None):
53
+ message = f"{a!r} is not lower than {b!r}"
54
+ if msg is not None:
55
+ message += ": " + msg
56
+ assert a < b, message
57
+
58
+
59
+ def assert_greater(a, b, msg=None):
60
+ message = f"{a!r} is not greater than {b!r}"
61
+ if msg is not None:
62
+ message += ": " + msg
63
+ assert a > b, message
64
+
65
+
66
+ def doctest_skip_parser(func):
67
+ """Decorator replaces custom skip test markup in doctests
68
+
69
+ Say a function has a docstring::
70
+
71
+ >>> something, HAVE_AMODULE, HAVE_BMODULE = 0, False, False
72
+ >>> something # skip if not HAVE_AMODULE
73
+ 0
74
+ >>> something # skip if HAVE_BMODULE
75
+ 0
76
+
77
+ This decorator will evaluate the expression after ``skip if``. If this
78
+ evaluates to True, then the comment is replaced by ``# doctest: +SKIP``. If
79
+ False, then the comment is just removed. The expression is evaluated in the
80
+ ``globals`` scope of `func`.
81
+
82
+ For example, if the module global ``HAVE_AMODULE`` is False, and module
83
+ global ``HAVE_BMODULE`` is False, the returned function will have docstring::
84
+
85
+ >>> something # doctest: +SKIP
86
+ >>> something + else # doctest: +SKIP
87
+ >>> something # doctest: +SKIP
88
+
89
+ """
90
+ lines = func.__doc__.split('\n')
91
+ new_lines = []
92
+ for line in lines:
93
+ match = SKIP_RE.match(line)
94
+ if match is None:
95
+ new_lines.append(line)
96
+ continue
97
+ code, space, expr = match.groups()
98
+
99
+ try:
100
+ # Works as a function decorator
101
+ if eval(expr, func.__globals__):
102
+ code = code + space + "# doctest: +SKIP"
103
+ except AttributeError:
104
+ # Works as a class decorator
105
+ if eval(expr, func.__init__.__globals__):
106
+ code = code + space + "# doctest: +SKIP"
107
+
108
+ new_lines.append(code)
109
+ func.__doc__ = "\n".join(new_lines)
110
+ return func
111
+
112
+
113
+ def roundtrip(image, plugin, suffix):
114
+ """Save and read an image using a specified plugin"""
115
+ if '.' not in suffix:
116
+ suffix = '.' + suffix
117
+ with NamedTemporaryFile(suffix=suffix, delete=False) as temp_file:
118
+ fname = temp_file.name
119
+ io.imsave(fname, image, plugin=plugin)
120
+ new = io.imread(fname, plugin=plugin)
121
+ try:
122
+ os.remove(fname)
123
+ except Exception:
124
+ pass
125
+ return new
126
+
127
+
128
+ def color_check(plugin, fmt='png'):
129
+ """Check roundtrip behavior for color images.
130
+
131
+ All major input types should be handled as ubytes and read
132
+ back correctly.
133
+ """
134
+ img = img_as_ubyte(data.chelsea())
135
+ r1 = roundtrip(img, plugin, fmt)
136
+ testing.assert_allclose(img, r1)
137
+
138
+ img2 = img > 128
139
+ r2 = roundtrip(img2, plugin, fmt)
140
+ testing.assert_allclose(img2, r2.astype(bool))
141
+
142
+ img3 = img_as_float(img)
143
+ r3 = roundtrip(img3, plugin, fmt)
144
+ testing.assert_allclose(r3, img)
145
+
146
+ img4 = img_as_int(img)
147
+ if fmt.lower() in (('tif', 'tiff')):
148
+ img4 -= 100
149
+ r4 = roundtrip(img4, plugin, fmt)
150
+ testing.assert_allclose(r4, img4)
151
+ else:
152
+ r4 = roundtrip(img4, plugin, fmt)
153
+ testing.assert_allclose(r4, img_as_ubyte(img4))
154
+
155
+ img5 = img_as_uint(img)
156
+ r5 = roundtrip(img5, plugin, fmt)
157
+ testing.assert_allclose(r5, img)
158
+
159
+
160
+ def mono_check(plugin, fmt='png'):
161
+ """Check the roundtrip behavior for images that support most types.
162
+
163
+ All major input types should be handled.
164
+ """
165
+
166
+ img = img_as_ubyte(data.moon())
167
+ r1 = roundtrip(img, plugin, fmt)
168
+ testing.assert_allclose(img, r1)
169
+
170
+ img2 = img > 128
171
+ r2 = roundtrip(img2, plugin, fmt)
172
+ testing.assert_allclose(img2, r2.astype(bool))
173
+
174
+ img3 = img_as_float(img)
175
+ r3 = roundtrip(img3, plugin, fmt)
176
+ if r3.dtype.kind == 'f':
177
+ testing.assert_allclose(img3, r3)
178
+ else:
179
+ testing.assert_allclose(r3, img_as_uint(img))
180
+
181
+ img4 = img_as_int(img)
182
+ if fmt.lower() in (('tif', 'tiff')):
183
+ img4 -= 100
184
+ r4 = roundtrip(img4, plugin, fmt)
185
+ testing.assert_allclose(r4, img4)
186
+ else:
187
+ r4 = roundtrip(img4, plugin, fmt)
188
+ testing.assert_allclose(r4, img_as_uint(img4))
189
+
190
+ img5 = img_as_uint(img)
191
+ r5 = roundtrip(img5, plugin, fmt)
192
+ testing.assert_allclose(r5, img5)
193
+
194
+
195
+ def fetch(data_filename):
196
+ """Attempt to fetch data, but if unavailable, skip the tests."""
197
+ try:
198
+ return _fetch(data_filename)
199
+ except (ConnectionError, ModuleNotFoundError):
200
+ pytest.skip(f'Unable to download {data_filename}', allow_module_level=True)
201
+
202
+
203
+ def run_in_parallel(num_threads=2, warnings_matching=None):
204
+ """Decorator to run the same function multiple times in parallel.
205
+
206
+ This decorator is useful to ensure that separate threads execute
207
+ concurrently and correctly while releasing the GIL.
208
+
209
+ Parameters
210
+ ----------
211
+ num_threads : int, optional
212
+ The number of times the function is run in parallel.
213
+
214
+ warnings_matching: list or None
215
+ This parameter is passed on to `expected_warnings` so as not to have
216
+ race conditions with the warnings filters. A single
217
+ `expected_warnings` context manager is used for all threads.
218
+ If None, then no warnings are checked.
219
+
220
+ """
221
+
222
+ assert num_threads > 0
223
+
224
+ def wrapper(func):
225
+ @functools.wraps(func)
226
+ def inner(*args, **kwargs):
227
+ with expected_warnings(warnings_matching):
228
+ threads = []
229
+ for i in range(num_threads - 1):
230
+ thread = threading.Thread(target=func, args=args, kwargs=kwargs)
231
+ threads.append(thread)
232
+ for thread in threads:
233
+ thread.start()
234
+
235
+ func(*args, **kwargs)
236
+
237
+ for thread in threads:
238
+ thread.join()
239
+
240
+ return inner
241
+
242
+ return wrapper
243
+
244
+
245
+ def assert_stacklevel(warnings, *, offset=-1):
246
+ """Assert correct stacklevel of captured warnings.
247
+
248
+ When scikit-image raises warnings, the stacklevel should ideally be set
249
+ so that the origin of the warnings will point to the public function
250
+ that was called by the user and not necessarily the very place where the
251
+ warnings were emitted (which may be inside of some internal function).
252
+ This utility function helps with checking that
253
+ the stacklevel was set correctly on warnings captured by `pytest.warns`.
254
+
255
+ Parameters
256
+ ----------
257
+ warnings : collections.abc.Iterable[warning.WarningMessage]
258
+ Warnings that were captured by `pytest.warns`.
259
+ offset : int, optional
260
+ Offset from the line this function is called to the line were the
261
+ warning is supposed to originate from. For multiline calls, the
262
+ first line is relevant. Defaults to -1 which corresponds to the line
263
+ right above the one where this function is called.
264
+
265
+ Raises
266
+ ------
267
+ AssertionError
268
+ If a warning in `warnings` does not match the expected line number or
269
+ file name.
270
+
271
+ Examples
272
+ --------
273
+ >>> def test_something():
274
+ ... with pytest.warns(UserWarning, match="some message") as record:
275
+ ... something_raising_a_warning()
276
+ ... assert_stacklevel(record)
277
+ ...
278
+ >>> def test_another_thing():
279
+ ... with pytest.warns(UserWarning, match="some message") as record:
280
+ ... iam_raising_many_warnings(
281
+ ... "A long argument that forces the call to wrap."
282
+ ... )
283
+ ... assert_stacklevel(record, offset=-3)
284
+ """
285
+ frame = inspect.stack()[1].frame # 0 is current frame, 1 is outer frame
286
+ line_number = frame.f_lineno + offset
287
+ filename = frame.f_code.co_filename
288
+ expected = f"{filename}:{line_number}"
289
+ for warning in warnings:
290
+ actual = f"{warning.filename}:{warning.lineno}"
291
+ assert actual == expected, f"{actual} != {expected}"
skimage/_shared/tests/__init__.py ADDED
File without changes
skimage/_shared/tests/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (159 Bytes). View file
 
skimage/_shared/tests/__pycache__/test_coord.cpython-310.pyc ADDED
Binary file (2.45 kB). View file
 
skimage/_shared/tests/__pycache__/test_dtype.cpython-310.pyc ADDED
Binary file (761 Bytes). View file
 
skimage/_shared/tests/__pycache__/test_fast_exp.cpython-310.pyc ADDED
Binary file (820 Bytes). View file
 
skimage/_shared/tests/__pycache__/test_geometry.cpython-310.pyc ADDED
Binary file (2.27 kB). View file
 
skimage/_shared/tests/__pycache__/test_interpolation.cpython-310.pyc ADDED
Binary file (1.69 kB). View file
 
skimage/_shared/tests/__pycache__/test_safe_as_int.cpython-310.pyc ADDED
Binary file (1.69 kB). View file
 
skimage/_shared/tests/__pycache__/test_testing.cpython-310.pyc ADDED
Binary file (4.94 kB). View file
 
skimage/_shared/tests/__pycache__/test_utils.cpython-310.pyc ADDED
Binary file (14.5 kB). View file
 
skimage/_shared/tests/__pycache__/test_version_requirements.cpython-310.pyc ADDED
Binary file (1.56 kB). View file
 
skimage/_shared/tests/__pycache__/test_warnings.cpython-310.pyc ADDED
Binary file (1.4 kB). View file
 
skimage/_shared/tests/test_coord.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+
3
+ import numpy as np
4
+ import pytest
5
+ from scipy.spatial.distance import pdist, minkowski
6
+
7
+ from skimage._shared.coord import ensure_spacing
8
+
9
+
10
+ @pytest.mark.parametrize("p", [1, 2, np.inf])
11
+ @pytest.mark.parametrize("size", [30, 50, None])
12
+ def test_ensure_spacing_trivial(p, size):
13
+ # --- Empty input
14
+ assert ensure_spacing([], p_norm=p) == []
15
+
16
+ # --- A unique point
17
+ coord = np.random.randn(1, 2)
18
+ assert np.array_equal(coord, ensure_spacing(coord, p_norm=p, min_split_size=size))
19
+
20
+ # --- Verified spacing
21
+ coord = np.random.randn(100, 2)
22
+
23
+ # --- 0 spacing
24
+ assert np.array_equal(
25
+ coord, ensure_spacing(coord, spacing=0, p_norm=p, min_split_size=size)
26
+ )
27
+
28
+ # Spacing is chosen to be half the minimum distance
29
+ spacing = pdist(coord, metric=minkowski, p=p).min() * 0.5
30
+
31
+ out = ensure_spacing(coord, spacing=spacing, p_norm=p, min_split_size=size)
32
+
33
+ assert np.array_equal(coord, out)
34
+
35
+
36
+ @pytest.mark.parametrize("ndim", [1, 2, 3, 4, 5])
37
+ @pytest.mark.parametrize("size", [2, 10, None])
38
+ def test_ensure_spacing_nD(ndim, size):
39
+ coord = np.ones((5, ndim))
40
+
41
+ expected = np.ones((1, ndim))
42
+
43
+ assert np.array_equal(ensure_spacing(coord, min_split_size=size), expected)
44
+
45
+
46
+ @pytest.mark.parametrize("p", [1, 2, np.inf])
47
+ @pytest.mark.parametrize("size", [50, 100, None])
48
+ def test_ensure_spacing_batch_processing(p, size):
49
+ coord = np.random.randn(100, 2)
50
+
51
+ # --- Consider the average distance btween the point as spacing
52
+ spacing = np.median(pdist(coord, metric=minkowski, p=p))
53
+
54
+ expected = ensure_spacing(coord, spacing=spacing, p_norm=p)
55
+
56
+ assert np.array_equal(
57
+ ensure_spacing(coord, spacing=spacing, p_norm=p, min_split_size=size), expected
58
+ )
59
+
60
+
61
+ def test_max_batch_size():
62
+ """Small batches are slow, large batches -> large allocations -> also slow.
63
+
64
+ https://github.com/scikit-image/scikit-image/pull/6035#discussion_r751518691
65
+ """
66
+ coords = np.random.randint(low=0, high=1848, size=(40000, 2))
67
+ tstart = time.time()
68
+ ensure_spacing(coords, spacing=100, min_split_size=50, max_split_size=2000)
69
+ dur1 = time.time() - tstart
70
+
71
+ tstart = time.time()
72
+ ensure_spacing(coords, spacing=100, min_split_size=50, max_split_size=20000)
73
+ dur2 = time.time() - tstart
74
+
75
+ # Originally checked dur1 < dur2 to assert that the default batch size was
76
+ # faster than a much larger batch size. However, on rare occasion a CI test
77
+ # case would fail with dur1 ~5% larger than dur2. To be more robust to
78
+ # variable load or differences across architectures, we relax this here.
79
+ assert dur1 < 1.33 * dur2
80
+
81
+
82
+ @pytest.mark.parametrize("p", [1, 2, np.inf])
83
+ @pytest.mark.parametrize("size", [30, 50, None])
84
+ def test_ensure_spacing_p_norm(p, size):
85
+ coord = np.random.randn(100, 2)
86
+
87
+ # --- Consider the average distance btween the point as spacing
88
+ spacing = np.median(pdist(coord, metric=minkowski, p=p))
89
+ out = ensure_spacing(coord, spacing=spacing, p_norm=p, min_split_size=size)
90
+
91
+ assert pdist(out, metric=minkowski, p=p).min() > spacing
skimage/_shared/tests/test_dtype.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+
5
+ from ..dtype import numeric_dtype_min_max, numeric_types
6
+
7
+
8
+ class Test_numeric_dtype_min_max:
9
+ @pytest.mark.parametrize("dtype", numeric_types)
10
+ def test_all_numeric_types(self, dtype):
11
+ min_, max_ = numeric_dtype_min_max(dtype)
12
+ assert np.isscalar(min_)
13
+ assert np.isscalar(max_)
14
+ assert min_ < max_