ZAIDX11 commited on
Commit
2c35c5c
·
verified ·
1 Parent(s): edd92ae

Add files using upload-large-folder tool

Browse files
Files changed (20) hide show
  1. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/__init__.py +173 -0
  2. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_ni_support.py +143 -0
  3. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_rank_filter_1d.cp310-win_amd64.dll.a +0 -0
  4. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_support_alternative_backends.py +72 -0
  5. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/__init__.py +12 -0
  6. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_inputs.txt +21 -0
  7. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_results.txt +294 -0
  8. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_strels.txt +42 -0
  9. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/dots.png +0 -0
  10. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_c_api.py +102 -0
  11. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_datatypes.py +67 -0
  12. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_filters.py +0 -0
  13. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_fourier.py +189 -0
  14. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_interpolation.py +1484 -0
  15. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_measurements.py +1609 -0
  16. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_morphology.py +0 -0
  17. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_ni_support.py +78 -0
  18. external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_splines.py +72 -0
  19. external/alphageometry/.venv-ag/Lib/site-packages/scipy/odr/models.py +20 -0
  20. external/alphageometry/.venv-ag/Lib/site-packages/scipy/odr/odrpack.py +21 -0
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/__init__.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ =========================================================
3
+ Multidimensional image processing (:mod:`scipy.ndimage`)
4
+ =========================================================
5
+
6
+ .. currentmodule:: scipy.ndimage
7
+
8
+ This package contains various functions for multidimensional image
9
+ processing.
10
+
11
+
12
+ Filters
13
+ =======
14
+
15
+ .. autosummary::
16
+ :toctree: generated/
17
+
18
+ convolve - Multidimensional convolution
19
+ convolve1d - 1-D convolution along the given axis
20
+ correlate - Multidimensional correlation
21
+ correlate1d - 1-D correlation along the given axis
22
+ gaussian_filter
23
+ gaussian_filter1d
24
+ gaussian_gradient_magnitude
25
+ gaussian_laplace
26
+ generic_filter - Multidimensional filter using a given function
27
+ generic_filter1d - 1-D generic filter along the given axis
28
+ generic_gradient_magnitude
29
+ generic_laplace
30
+ laplace - N-D Laplace filter based on approximate second derivatives
31
+ maximum_filter
32
+ maximum_filter1d
33
+ median_filter - Calculates a multidimensional median filter
34
+ minimum_filter
35
+ minimum_filter1d
36
+ percentile_filter - Calculates a multidimensional percentile filter
37
+ prewitt
38
+ rank_filter - Calculates a multidimensional rank filter
39
+ sobel
40
+ uniform_filter - Multidimensional uniform filter
41
+ uniform_filter1d - 1-D uniform filter along the given axis
42
+
43
+ Fourier filters
44
+ ===============
45
+
46
+ .. autosummary::
47
+ :toctree: generated/
48
+
49
+ fourier_ellipsoid
50
+ fourier_gaussian
51
+ fourier_shift
52
+ fourier_uniform
53
+
54
+ Interpolation
55
+ =============
56
+
57
+ .. autosummary::
58
+ :toctree: generated/
59
+
60
+ affine_transform - Apply an affine transformation
61
+ geometric_transform - Apply an arbitrary geometric transform
62
+ map_coordinates - Map input array to new coordinates by interpolation
63
+ rotate - Rotate an array
64
+ shift - Shift an array
65
+ spline_filter
66
+ spline_filter1d
67
+ zoom - Zoom an array
68
+
69
+ Measurements
70
+ ============
71
+
72
+ .. autosummary::
73
+ :toctree: generated/
74
+
75
+ center_of_mass - The center of mass of the values of an array at labels
76
+ extrema - Min's and max's of an array at labels, with their positions
77
+ find_objects - Find objects in a labeled array
78
+ histogram - Histogram of the values of an array, optionally at labels
79
+ label - Label features in an array
80
+ labeled_comprehension
81
+ maximum
82
+ maximum_position
83
+ mean - Mean of the values of an array at labels
84
+ median
85
+ minimum
86
+ minimum_position
87
+ standard_deviation - Standard deviation of an N-D image array
88
+ sum_labels - Sum of the values of the array
89
+ value_indices - Find indices of each distinct value in given array
90
+ variance - Variance of the values of an N-D image array
91
+ watershed_ift
92
+
93
+ Morphology
94
+ ==========
95
+
96
+ .. autosummary::
97
+ :toctree: generated/
98
+
99
+ binary_closing
100
+ binary_dilation
101
+ binary_erosion
102
+ binary_fill_holes
103
+ binary_hit_or_miss
104
+ binary_opening
105
+ binary_propagation
106
+ black_tophat
107
+ distance_transform_bf
108
+ distance_transform_cdt
109
+ distance_transform_edt
110
+ generate_binary_structure
111
+ grey_closing
112
+ grey_dilation
113
+ grey_erosion
114
+ grey_opening
115
+ iterate_structure
116
+ morphological_gradient
117
+ morphological_laplace
118
+ white_tophat
119
+
120
+ """
121
+
122
+ # Copyright (C) 2003-2005 Peter J. Verveer
123
+ #
124
+ # Redistribution and use in source and binary forms, with or without
125
+ # modification, are permitted provided that the following conditions
126
+ # are met:
127
+ #
128
+ # 1. Redistributions of source code must retain the above copyright
129
+ # notice, this list of conditions and the following disclaimer.
130
+ #
131
+ # 2. Redistributions in binary form must reproduce the above
132
+ # copyright notice, this list of conditions and the following
133
+ # disclaimer in the documentation and/or other materials provided
134
+ # with the distribution.
135
+ #
136
+ # 3. The name of the author may not be used to endorse or promote
137
+ # products derived from this software without specific prior
138
+ # written permission.
139
+ #
140
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
141
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
142
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
143
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
144
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
145
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
146
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
147
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
148
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
149
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
150
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
151
+
152
+ # bring in the public functionality from private namespaces
153
+
154
+ # mypy: ignore-errors
155
+
156
+ from ._support_alternative_backends import *
157
+
158
+ # adjust __all__ and do not leak implementation details
159
+ from . import _support_alternative_backends
160
+ __all__ = _support_alternative_backends.__all__
161
+ del _support_alternative_backends, _ndimage_api, _delegators # noqa: F821
162
+
163
+
164
+ # Deprecated namespaces, to be removed in v2.0.0
165
+ from . import filters
166
+ from . import fourier
167
+ from . import interpolation
168
+ from . import measurements
169
+ from . import morphology
170
+
171
+ from scipy._lib._testutils import PytestTester
172
+ test = PytestTester(__name__)
173
+ del PytestTester
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_ni_support.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2003-2005 Peter J. Verveer
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
6
+ #
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ #
10
+ # 2. Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following
12
+ # disclaimer in the documentation and/or other materials provided
13
+ # with the distribution.
14
+ #
15
+ # 3. The name of the author may not be used to endorse or promote
16
+ # products derived from this software without specific prior
17
+ # written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ from collections.abc import Iterable
32
+ import operator
33
+ import warnings
34
+ import numpy as np
35
+
36
+
37
+ def _extend_mode_to_code(mode, is_filter=False):
38
+ """Convert an extension mode to the corresponding integer code.
39
+ """
40
+ if mode == 'nearest':
41
+ return 0
42
+ elif mode == 'wrap':
43
+ return 1
44
+ elif mode in ['reflect', 'grid-mirror']:
45
+ return 2
46
+ elif mode == 'mirror':
47
+ return 3
48
+ elif mode == 'constant':
49
+ return 4
50
+ elif mode == 'grid-wrap' and is_filter:
51
+ return 1
52
+ elif mode == 'grid-wrap':
53
+ return 5
54
+ elif mode == 'grid-constant' and is_filter:
55
+ return 4
56
+ elif mode == 'grid-constant':
57
+ return 6
58
+ else:
59
+ raise RuntimeError('boundary mode not supported')
60
+
61
+
62
+ def _normalize_sequence(input, rank):
63
+ """If input is a scalar, create a sequence of length equal to the
64
+ rank by duplicating the input. If input is a sequence,
65
+ check if its length is equal to the length of array.
66
+ """
67
+ is_str = isinstance(input, str)
68
+ if not is_str and np.iterable(input):
69
+ normalized = list(input)
70
+ if len(normalized) != rank:
71
+ err = "sequence argument must have length equal to input rank"
72
+ raise RuntimeError(err)
73
+ else:
74
+ normalized = [input] * rank
75
+ return normalized
76
+
77
+
78
+ def _get_output(output, input, shape=None, complex_output=False):
79
+ if shape is None:
80
+ shape = input.shape
81
+ if output is None:
82
+ if not complex_output:
83
+ output = np.zeros(shape, dtype=input.dtype.name)
84
+ else:
85
+ complex_type = np.promote_types(input.dtype, np.complex64)
86
+ output = np.zeros(shape, dtype=complex_type)
87
+ elif isinstance(output, (type, np.dtype)):
88
+ # Classes (like `np.float32`) and dtypes are interpreted as dtype
89
+ if complex_output and np.dtype(output).kind != 'c':
90
+ warnings.warn("promoting specified output dtype to complex", stacklevel=3)
91
+ output = np.promote_types(output, np.complex64)
92
+ output = np.zeros(shape, dtype=output)
93
+ elif isinstance(output, str):
94
+ output = np.dtype(output)
95
+ if complex_output and output.kind != 'c':
96
+ raise RuntimeError("output must have complex dtype")
97
+ elif not issubclass(output.type, np.number):
98
+ raise RuntimeError("output must have numeric dtype")
99
+ output = np.zeros(shape, dtype=output)
100
+ else:
101
+ # output was supplied as an array
102
+ output = np.asarray(output)
103
+ if output.shape != shape:
104
+ raise RuntimeError("output shape not correct")
105
+ elif complex_output and output.dtype.kind != 'c':
106
+ raise RuntimeError("output must have complex dtype")
107
+ return output
108
+
109
+
110
+ def _check_axes(axes, ndim):
111
+ if axes is None:
112
+ return tuple(range(ndim))
113
+ elif np.isscalar(axes):
114
+ axes = (operator.index(axes),)
115
+ elif isinstance(axes, Iterable):
116
+ for ax in axes:
117
+ axes = tuple(operator.index(ax) for ax in axes)
118
+ if ax < -ndim or ax > ndim - 1:
119
+ raise ValueError(f"specified axis: {ax} is out of range")
120
+ axes = tuple(ax % ndim if ax < 0 else ax for ax in axes)
121
+ else:
122
+ message = "axes must be an integer, iterable of integers, or None"
123
+ raise ValueError(message)
124
+ if len(tuple(set(axes))) != len(axes):
125
+ raise ValueError("axes must be unique")
126
+ return axes
127
+
128
+ def _skip_if_dtype(arg):
129
+ """'array or dtype' polymorphism.
130
+
131
+ Return None for np.int8, dtype('float32') or 'f' etc
132
+ arg for np.empty(3) etc
133
+ """
134
+ if isinstance(arg, str):
135
+ return None
136
+ if type(arg) is type:
137
+ return None if issubclass(arg, np.generic) else arg
138
+ else:
139
+ return None if isinstance(arg, np.dtype) else arg
140
+
141
+
142
+ def _skip_if_int(arg):
143
+ return None if (arg is None or isinstance(arg, int)) else arg
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_rank_filter_1d.cp310-win_amd64.dll.a ADDED
Binary file (1.64 kB). View file
 
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_support_alternative_backends.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ from scipy._lib._array_api import (
3
+ is_cupy, is_jax, scipy_namespace_for, SCIPY_ARRAY_API
4
+ )
5
+
6
+ import numpy as np
7
+ from ._ndimage_api import * # noqa: F403
8
+ from . import _ndimage_api
9
+ from . import _delegators
10
+ __all__ = _ndimage_api.__all__
11
+
12
+
13
+ MODULE_NAME = 'ndimage'
14
+
15
+
16
+ def delegate_xp(delegator, module_name):
17
+ def inner(func):
18
+ @functools.wraps(func)
19
+ def wrapper(*args, **kwds):
20
+ xp = delegator(*args, **kwds)
21
+
22
+ # try delegating to a cupyx/jax namesake
23
+ if is_cupy(xp):
24
+ # https://github.com/cupy/cupy/issues/8336
25
+ import importlib
26
+ cupyx_module = importlib.import_module(f"cupyx.scipy.{module_name}")
27
+ cupyx_func = getattr(cupyx_module, func.__name__)
28
+ return cupyx_func(*args, **kwds)
29
+ elif is_jax(xp) and func.__name__ == "map_coordinates":
30
+ spx = scipy_namespace_for(xp)
31
+ jax_module = getattr(spx, module_name)
32
+ jax_func = getattr(jax_module, func.__name__)
33
+ return jax_func(*args, **kwds)
34
+ else:
35
+ # the original function (does all np.asarray internally)
36
+ # XXX: output arrays
37
+ result = func(*args, **kwds)
38
+
39
+ if isinstance(result, (np.ndarray, np.generic)):
40
+ # XXX: np.int32->np.array_0D
41
+ return xp.asarray(result)
42
+ elif isinstance(result, int):
43
+ return result
44
+ elif isinstance(result, dict):
45
+ # value_indices: result is {np.int64(1): (array(0), array(1))} etc
46
+ return {
47
+ k.item(): tuple(xp.asarray(vv) for vv in v)
48
+ for k,v in result.items()
49
+ }
50
+ elif result is None:
51
+ # inplace operations
52
+ return result
53
+ else:
54
+ # lists/tuples
55
+ return type(result)(
56
+ xp.asarray(x) if isinstance(x, np.ndarray) else x
57
+ for x in result
58
+ )
59
+ return wrapper
60
+ return inner
61
+
62
+ # ### decorate ###
63
+ for func_name in _ndimage_api.__all__:
64
+ bare_func = getattr(_ndimage_api, func_name)
65
+ delegator = getattr(_delegators, func_name + "_signature")
66
+
67
+ f = (delegate_xp(delegator, MODULE_NAME)(bare_func)
68
+ if SCIPY_ARRAY_API
69
+ else bare_func)
70
+
71
+ # add the decorated function to the namespace, to be imported in __init__.py
72
+ vars()[func_name] = f
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # list of numarray data types
4
+ integer_types: list[str] = [
5
+ "int8", "uint8", "int16", "uint16",
6
+ "int32", "uint32", "int64", "uint64"]
7
+
8
+ float_types: list[str] = ["float32", "float64"]
9
+
10
+ complex_types: list[str] = ["complex64", "complex128"]
11
+
12
+ types: list[str] = integer_types + float_types
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_inputs.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1 1 1 1 1 1 1
2
+ 1 1 1 1 1 1 1
3
+ 1 1 1 1 1 1 1
4
+ 1 1 1 1 1 1 1
5
+ 1 1 1 1 1 1 1
6
+ 1 1 1 1 1 1 1
7
+ 1 1 1 1 1 1 1
8
+ 1 1 1 0 1 1 1
9
+ 1 1 0 0 0 1 1
10
+ 1 0 1 0 1 0 1
11
+ 0 0 0 1 0 0 0
12
+ 1 0 1 0 1 0 1
13
+ 1 1 0 0 0 1 1
14
+ 1 1 1 0 1 1 1
15
+ 1 0 1 1 1 0 1
16
+ 0 0 0 1 0 0 0
17
+ 1 0 0 1 0 0 1
18
+ 1 1 1 1 1 1 1
19
+ 1 0 0 1 0 0 1
20
+ 0 0 0 1 0 0 0
21
+ 1 0 1 1 1 0 1
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_results.txt ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1 1 1 1 1 1 1
2
+ 1 1 1 1 1 1 1
3
+ 1 1 1 1 1 1 1
4
+ 1 1 1 1 1 1 1
5
+ 1 1 1 1 1 1 1
6
+ 1 1 1 1 1 1 1
7
+ 1 1 1 1 1 1 1
8
+ 1 1 1 1 1 1 1
9
+ 1 1 1 1 1 1 1
10
+ 1 1 1 1 1 1 1
11
+ 1 1 1 1 1 1 1
12
+ 1 1 1 1 1 1 1
13
+ 1 1 1 1 1 1 1
14
+ 1 1 1 1 1 1 1
15
+ 1 1 1 1 1 1 1
16
+ 2 2 2 2 2 2 2
17
+ 3 3 3 3 3 3 3
18
+ 4 4 4 4 4 4 4
19
+ 5 5 5 5 5 5 5
20
+ 6 6 6 6 6 6 6
21
+ 7 7 7 7 7 7 7
22
+ 1 1 1 1 1 1 1
23
+ 1 1 1 1 1 1 1
24
+ 1 1 1 1 1 1 1
25
+ 1 1 1 1 1 1 1
26
+ 1 1 1 1 1 1 1
27
+ 1 1 1 1 1 1 1
28
+ 1 1 1 1 1 1 1
29
+ 1 2 3 4 5 6 7
30
+ 8 9 10 11 12 13 14
31
+ 15 16 17 18 19 20 21
32
+ 22 23 24 25 26 27 28
33
+ 29 30 31 32 33 34 35
34
+ 36 37 38 39 40 41 42
35
+ 43 44 45 46 47 48 49
36
+ 1 1 1 1 1 1 1
37
+ 1 1 1 1 1 1 1
38
+ 1 1 1 1 1 1 1
39
+ 1 1 1 1 1 1 1
40
+ 1 1 1 1 1 1 1
41
+ 1 1 1 1 1 1 1
42
+ 1 1 1 1 1 1 1
43
+ 1 1 1 1 1 1 1
44
+ 1 1 1 1 1 1 1
45
+ 1 1 1 1 1 1 1
46
+ 1 1 1 1 1 1 1
47
+ 1 1 1 1 1 1 1
48
+ 1 1 1 1 1 1 1
49
+ 1 1 1 1 1 1 1
50
+ 1 2 3 4 5 6 7
51
+ 8 1 2 3 4 5 6
52
+ 9 8 1 2 3 4 5
53
+ 10 9 8 1 2 3 4
54
+ 11 10 9 8 1 2 3
55
+ 12 11 10 9 8 1 2
56
+ 13 12 11 10 9 8 1
57
+ 1 2 3 4 5 6 7
58
+ 1 2 3 4 5 6 7
59
+ 1 2 3 4 5 6 7
60
+ 1 2 3 4 5 6 7
61
+ 1 2 3 4 5 6 7
62
+ 1 2 3 4 5 6 7
63
+ 1 2 3 4 5 6 7
64
+ 1 1 1 1 1 1 1
65
+ 1 1 1 1 1 1 1
66
+ 1 1 1 1 1 1 1
67
+ 1 1 1 1 1 1 1
68
+ 1 1 1 1 1 1 1
69
+ 1 1 1 1 1 1 1
70
+ 1 1 1 1 1 1 1
71
+ 1 1 1 1 1 1 1
72
+ 1 1 1 1 1 1 1
73
+ 1 1 1 1 1 1 1
74
+ 1 1 1 1 1 1 1
75
+ 1 1 1 1 1 1 1
76
+ 1 1 1 1 1 1 1
77
+ 1 1 1 1 1 1 1
78
+ 1 2 1 2 1 2 1
79
+ 2 1 2 1 2 1 2
80
+ 1 2 1 2 1 2 1
81
+ 2 1 2 1 2 1 2
82
+ 1 2 1 2 1 2 1
83
+ 2 1 2 1 2 1 2
84
+ 1 2 1 2 1 2 1
85
+ 1 2 3 4 5 6 7
86
+ 2 3 4 5 6 7 8
87
+ 3 4 5 6 7 8 9
88
+ 4 5 6 7 8 9 10
89
+ 5 6 7 8 9 10 11
90
+ 6 7 8 9 10 11 12
91
+ 7 8 9 10 11 12 13
92
+ 1 1 1 1 1 1 1
93
+ 1 1 1 1 1 1 1
94
+ 1 1 1 1 1 1 1
95
+ 1 1 1 1 1 1 1
96
+ 1 1 1 1 1 1 1
97
+ 1 1 1 1 1 1 1
98
+ 1 1 1 1 1 1 1
99
+ 1 1 1 0 2 2 2
100
+ 1 1 0 0 0 2 2
101
+ 1 0 3 0 2 0 4
102
+ 0 0 0 2 0 0 0
103
+ 5 0 2 0 6 0 7
104
+ 2 2 0 0 0 7 7
105
+ 2 2 2 0 7 7 7
106
+ 1 1 1 0 2 2 2
107
+ 1 1 0 0 0 2 2
108
+ 3 0 1 0 4 0 2
109
+ 0 0 0 1 0 0 0
110
+ 5 0 6 0 1 0 7
111
+ 5 5 0 0 0 1 1
112
+ 5 5 5 0 1 1 1
113
+ 1 1 1 0 2 2 2
114
+ 3 3 0 0 0 4 4
115
+ 5 0 6 0 7 0 8
116
+ 0 0 0 9 0 0 0
117
+ 10 0 11 0 12 0 13
118
+ 14 14 0 0 0 15 15
119
+ 16 16 16 0 17 17 17
120
+ 1 1 1 0 2 3 3
121
+ 1 1 0 0 0 3 3
122
+ 1 0 4 0 3 0 3
123
+ 0 0 0 3 0 0 0
124
+ 3 0 3 0 5 0 6
125
+ 3 3 0 0 0 6 6
126
+ 3 3 7 0 6 6 6
127
+ 1 2 3 0 4 5 6
128
+ 7 8 0 0 0 9 10
129
+ 11 0 12 0 13 0 14
130
+ 0 0 0 15 0 0 0
131
+ 16 0 17 0 18 0 19
132
+ 20 21 0 0 0 22 23
133
+ 24 25 26 0 27 28 29
134
+ 1 1 1 0 2 2 2
135
+ 1 1 0 0 0 2 2
136
+ 1 0 3 0 2 0 2
137
+ 0 0 0 2 0 0 0
138
+ 2 0 2 0 4 0 5
139
+ 2 2 0 0 0 5 5
140
+ 2 2 2 0 5 5 5
141
+ 1 1 1 0 2 2 2
142
+ 1 1 0 0 0 2 2
143
+ 1 0 3 0 4 0 2
144
+ 0 0 0 5 0 0 0
145
+ 6 0 7 0 8 0 9
146
+ 6 6 0 0 0 9 9
147
+ 6 6 6 0 9 9 9
148
+ 1 2 3 0 4 5 6
149
+ 7 1 0 0 0 4 5
150
+ 8 0 1 0 9 0 4
151
+ 0 0 0 1 0 0 0
152
+ 10 0 11 0 1 0 12
153
+ 13 10 0 0 0 1 14
154
+ 15 13 10 0 16 17 1
155
+ 1 2 3 0 4 5 6
156
+ 1 2 0 0 0 5 6
157
+ 1 0 7 0 8 0 6
158
+ 0 0 0 9 0 0 0
159
+ 10 0 11 0 12 0 13
160
+ 10 14 0 0 0 15 13
161
+ 10 14 16 0 17 15 13
162
+ 1 1 1 0 1 1 1
163
+ 1 1 0 0 0 1 1
164
+ 1 0 1 0 1 0 1
165
+ 0 0 0 1 0 0 0
166
+ 1 0 1 0 1 0 1
167
+ 1 1 0 0 0 1 1
168
+ 1 1 1 0 1 1 1
169
+ 1 1 2 0 3 3 3
170
+ 1 1 0 0 0 3 3
171
+ 1 0 1 0 4 0 3
172
+ 0 0 0 1 0 0 0
173
+ 5 0 6 0 1 0 1
174
+ 5 5 0 0 0 1 1
175
+ 5 5 5 0 7 1 1
176
+ 1 2 1 0 1 3 1
177
+ 2 1 0 0 0 1 3
178
+ 1 0 1 0 1 0 1
179
+ 0 0 0 1 0 0 0
180
+ 1 0 1 0 1 0 1
181
+ 4 1 0 0 0 1 5
182
+ 1 4 1 0 1 5 1
183
+ 1 2 3 0 4 5 6
184
+ 2 3 0 0 0 6 7
185
+ 3 0 8 0 6 0 9
186
+ 0 0 0 6 0 0 0
187
+ 10 0 6 0 11 0 12
188
+ 13 6 0 0 0 12 14
189
+ 6 15 16 0 12 14 17
190
+ 1 1 1 0 2 2 2
191
+ 1 1 0 0 0 2 2
192
+ 1 0 1 0 3 0 2
193
+ 0 0 0 1 0 0 0
194
+ 4 0 5 0 1 0 1
195
+ 4 4 0 0 0 1 1
196
+ 4 4 4 0 1 1 1
197
+ 1 0 2 2 2 0 3
198
+ 0 0 0 2 0 0 0
199
+ 4 0 0 5 0 0 5
200
+ 5 5 5 5 5 5 5
201
+ 5 0 0 5 0 0 6
202
+ 0 0 0 7 0 0 0
203
+ 8 0 7 7 7 0 9
204
+ 1 0 2 2 2 0 3
205
+ 0 0 0 2 0 0 0
206
+ 4 0 0 4 0 0 5
207
+ 4 4 4 4 4 4 4
208
+ 6 0 0 4 0 0 4
209
+ 0 0 0 7 0 0 0
210
+ 8 0 7 7 7 0 9
211
+ 1 0 2 2 2 0 3
212
+ 0 0 0 4 0 0 0
213
+ 5 0 0 6 0 0 7
214
+ 8 8 8 8 8 8 8
215
+ 9 0 0 10 0 0 11
216
+ 0 0 0 12 0 0 0
217
+ 13 0 14 14 14 0 15
218
+ 1 0 2 3 3 0 4
219
+ 0 0 0 3 0 0 0
220
+ 5 0 0 3 0 0 6
221
+ 5 5 3 3 3 6 6
222
+ 5 0 0 3 0 0 6
223
+ 0 0 0 3 0 0 0
224
+ 7 0 3 3 8 0 9
225
+ 1 0 2 3 4 0 5
226
+ 0 0 0 6 0 0 0
227
+ 7 0 0 8 0 0 9
228
+ 10 11 12 13 14 15 16
229
+ 17 0 0 18 0 0 19
230
+ 0 0 0 20 0 0 0
231
+ 21 0 22 23 24 0 25
232
+ 1 0 2 2 2 0 3
233
+ 0 0 0 2 0 0 0
234
+ 2 0 0 2 0 0 2
235
+ 2 2 2 2 2 2 2
236
+ 2 0 0 2 0 0 2
237
+ 0 0 0 2 0 0 0
238
+ 4 0 2 2 2 0 5
239
+ 1 0 2 2 2 0 3
240
+ 0 0 0 2 0 0 0
241
+ 2 0 0 2 0 0 2
242
+ 2 2 2 2 2 2 2
243
+ 2 0 0 2 0 0 2
244
+ 0 0 0 2 0 0 0
245
+ 4 0 2 2 2 0 5
246
+ 1 0 2 3 4 0 5
247
+ 0 0 0 2 0 0 0
248
+ 6 0 0 7 0 0 8
249
+ 9 6 10 11 7 12 13
250
+ 14 0 0 10 0 0 12
251
+ 0 0 0 15 0 0 0
252
+ 16 0 17 18 15 0 19
253
+ 1 0 2 3 4 0 5
254
+ 0 0 0 3 0 0 0
255
+ 6 0 0 3 0 0 7
256
+ 6 8 9 3 10 11 7
257
+ 6 0 0 3 0 0 7
258
+ 0 0 0 3 0 0 0
259
+ 12 0 13 3 14 0 15
260
+ 1 0 2 2 2 0 3
261
+ 0 0 0 2 0 0 0
262
+ 2 0 0 2 0 0 2
263
+ 2 2 2 2 2 2 2
264
+ 2 0 0 2 0 0 2
265
+ 0 0 0 2 0 0 0
266
+ 4 0 2 2 2 0 5
267
+ 1 0 2 2 3 0 4
268
+ 0 0 0 2 0 0 0
269
+ 5 0 0 2 0 0 6
270
+ 5 5 2 2 2 6 6
271
+ 5 0 0 2 0 0 6
272
+ 0 0 0 2 0 0 0
273
+ 7 0 8 2 2 0 9
274
+ 1 0 2 3 2 0 4
275
+ 0 0 0 2 0 0 0
276
+ 5 0 0 6 0 0 7
277
+ 8 5 6 9 6 7 10
278
+ 5 0 0 6 0 0 7
279
+ 0 0 0 11 0 0 0
280
+ 12 0 11 13 11 0 14
281
+ 1 0 2 3 4 0 5
282
+ 0 0 0 4 0 0 0
283
+ 6 0 0 7 0 0 8
284
+ 9 10 7 11 12 8 13
285
+ 10 0 0 12 0 0 14
286
+ 0 0 0 15 0 0 0
287
+ 16 0 15 17 18 0 19
288
+ 1 0 2 2 2 0 3
289
+ 0 0 0 2 0 0 0
290
+ 2 0 0 2 0 0 2
291
+ 2 2 2 2 2 2 2
292
+ 2 0 0 2 0 0 2
293
+ 0 0 0 2 0 0 0
294
+ 4 0 2 2 2 0 5
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_strels.txt ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 0 0 1
2
+ 1 1 1
3
+ 1 0 0
4
+ 1 0 0
5
+ 1 1 1
6
+ 0 0 1
7
+ 0 0 0
8
+ 1 1 1
9
+ 0 0 0
10
+ 0 1 1
11
+ 0 1 0
12
+ 1 1 0
13
+ 0 0 0
14
+ 0 0 0
15
+ 0 0 0
16
+ 0 1 1
17
+ 1 1 1
18
+ 1 1 0
19
+ 0 1 0
20
+ 1 1 1
21
+ 0 1 0
22
+ 1 0 0
23
+ 0 1 0
24
+ 0 0 1
25
+ 0 1 0
26
+ 0 1 0
27
+ 0 1 0
28
+ 1 1 1
29
+ 1 1 1
30
+ 1 1 1
31
+ 1 1 0
32
+ 0 1 0
33
+ 0 1 1
34
+ 1 0 1
35
+ 0 1 0
36
+ 1 0 1
37
+ 0 0 1
38
+ 0 1 0
39
+ 1 0 0
40
+ 1 1 0
41
+ 1 1 1
42
+ 0 1 1
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/dots.png ADDED
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_c_api.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from scipy._lib._array_api import xp_assert_close
3
+
4
+ from scipy import ndimage
5
+ from scipy.ndimage import _ctest
6
+ from scipy.ndimage import _cytest
7
+ from scipy._lib._ccallback import LowLevelCallable
8
+
9
+ FILTER1D_FUNCTIONS = [
10
+ lambda filter_size: _ctest.filter1d(filter_size),
11
+ lambda filter_size: _cytest.filter1d(filter_size, with_signature=False),
12
+ lambda filter_size: LowLevelCallable(
13
+ _cytest.filter1d(filter_size, with_signature=True)
14
+ ),
15
+ lambda filter_size: LowLevelCallable.from_cython(
16
+ _cytest, "_filter1d",
17
+ _cytest.filter1d_capsule(filter_size),
18
+ ),
19
+ ]
20
+
21
+ FILTER2D_FUNCTIONS = [
22
+ lambda weights: _ctest.filter2d(weights),
23
+ lambda weights: _cytest.filter2d(weights, with_signature=False),
24
+ lambda weights: LowLevelCallable(_cytest.filter2d(weights, with_signature=True)),
25
+ lambda weights: LowLevelCallable.from_cython(_cytest,
26
+ "_filter2d",
27
+ _cytest.filter2d_capsule(weights),),
28
+ ]
29
+
30
+ TRANSFORM_FUNCTIONS = [
31
+ lambda shift: _ctest.transform(shift),
32
+ lambda shift: _cytest.transform(shift, with_signature=False),
33
+ lambda shift: LowLevelCallable(_cytest.transform(shift, with_signature=True)),
34
+ lambda shift: LowLevelCallable.from_cython(_cytest,
35
+ "_transform",
36
+ _cytest.transform_capsule(shift),),
37
+ ]
38
+
39
+
40
+ def test_generic_filter():
41
+ def filter2d(footprint_elements, weights):
42
+ return (weights*footprint_elements).sum()
43
+
44
+ def check(j):
45
+ func = FILTER2D_FUNCTIONS[j]
46
+
47
+ im = np.ones((20, 20))
48
+ im[:10,:10] = 0
49
+ footprint = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
50
+ footprint_size = np.count_nonzero(footprint)
51
+ weights = np.ones(footprint_size)/footprint_size
52
+
53
+ res = ndimage.generic_filter(im, func(weights),
54
+ footprint=footprint)
55
+ std = ndimage.generic_filter(im, filter2d, footprint=footprint,
56
+ extra_arguments=(weights,))
57
+ xp_assert_close(res, std, err_msg=f"#{j} failed")
58
+
59
+ for j, func in enumerate(FILTER2D_FUNCTIONS):
60
+ check(j)
61
+
62
+
63
+ def test_generic_filter1d():
64
+ def filter1d(input_line, output_line, filter_size):
65
+ for i in range(output_line.size):
66
+ output_line[i] = 0
67
+ for j in range(filter_size):
68
+ output_line[i] += input_line[i+j]
69
+ output_line /= filter_size
70
+
71
+ def check(j):
72
+ func = FILTER1D_FUNCTIONS[j]
73
+
74
+ im = np.tile(np.hstack((np.zeros(10), np.ones(10))), (10, 1))
75
+ filter_size = 3
76
+
77
+ res = ndimage.generic_filter1d(im, func(filter_size),
78
+ filter_size)
79
+ std = ndimage.generic_filter1d(im, filter1d, filter_size,
80
+ extra_arguments=(filter_size,))
81
+ xp_assert_close(res, std, err_msg=f"#{j} failed")
82
+
83
+ for j, func in enumerate(FILTER1D_FUNCTIONS):
84
+ check(j)
85
+
86
+
87
+ def test_geometric_transform():
88
+ def transform(output_coordinates, shift):
89
+ return output_coordinates[0] - shift, output_coordinates[1] - shift
90
+
91
+ def check(j):
92
+ func = TRANSFORM_FUNCTIONS[j]
93
+
94
+ im = np.arange(12).reshape(4, 3).astype(np.float64)
95
+ shift = 0.5
96
+
97
+ res = ndimage.geometric_transform(im, func(shift))
98
+ std = ndimage.geometric_transform(im, transform, extra_arguments=(shift,))
99
+ xp_assert_close(res, std, err_msg=f"#{j} failed")
100
+
101
+ for j, func in enumerate(TRANSFORM_FUNCTIONS):
102
+ check(j)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_datatypes.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Testing data types for ndimage calls
2
+ """
3
+ import numpy as np
4
+
5
+ from scipy._lib._array_api import assert_array_almost_equal
6
+ import pytest
7
+
8
+ from scipy import ndimage
9
+
10
+
11
+ def test_map_coordinates_dts():
12
+ # check that ndimage accepts different data types for interpolation
13
+ data = np.array([[4, 1, 3, 2],
14
+ [7, 6, 8, 5],
15
+ [3, 5, 3, 6]])
16
+ shifted_data = np.array([[0, 0, 0, 0],
17
+ [0, 4, 1, 3],
18
+ [0, 7, 6, 8]])
19
+ idx = np.indices(data.shape)
20
+ dts = (np.uint8, np.uint16, np.uint32, np.uint64,
21
+ np.int8, np.int16, np.int32, np.int64,
22
+ np.intp, np.uintp, np.float32, np.float64)
23
+ for order in range(0, 6):
24
+ for data_dt in dts:
25
+ these_data = data.astype(data_dt)
26
+ for coord_dt in dts:
27
+ # affine mapping
28
+ mat = np.eye(2, dtype=coord_dt)
29
+ off = np.zeros((2,), dtype=coord_dt)
30
+ out = ndimage.affine_transform(these_data, mat, off)
31
+ assert_array_almost_equal(these_data, out)
32
+ # map coordinates
33
+ coords_m1 = idx.astype(coord_dt) - 1
34
+ coords_p10 = idx.astype(coord_dt) + 10
35
+ out = ndimage.map_coordinates(these_data, coords_m1, order=order)
36
+ assert_array_almost_equal(out, shifted_data)
37
+ # check constant fill works
38
+ out = ndimage.map_coordinates(these_data, coords_p10, order=order)
39
+ assert_array_almost_equal(out, np.zeros((3,4)))
40
+ # check shift and zoom
41
+ out = ndimage.shift(these_data, 1)
42
+ assert_array_almost_equal(out, shifted_data)
43
+ out = ndimage.zoom(these_data, 1)
44
+ assert_array_almost_equal(these_data, out)
45
+
46
+
47
+ @pytest.mark.xfail(True, reason="Broken on many platforms")
48
+ def test_uint64_max():
49
+ # Test interpolation respects uint64 max. Reported to fail at least on
50
+ # win32 (due to the 32 bit visual C compiler using signed int64 when
51
+ # converting between uint64 to double) and Debian on s390x.
52
+ # Interpolation is always done in double precision floating point, so
53
+ # we use the largest uint64 value for which int(float(big)) still fits
54
+ # in a uint64.
55
+ # This test was last enabled on macOS only, and there it started failing
56
+ # on arm64 as well (see gh-19117).
57
+ big = 2**64 - 1025
58
+ arr = np.array([big, big, big], dtype=np.uint64)
59
+ # Tests geometric transform (map_coordinates, affine_transform)
60
+ inds = np.indices(arr.shape) - 0.1
61
+ x = ndimage.map_coordinates(arr, inds)
62
+ assert x[1] == int(float(big))
63
+ assert x[2] == int(float(big))
64
+ # Tests zoom / shift
65
+ x = ndimage.shift(arr, 0.1)
66
+ assert x[1] == int(float(big))
67
+ assert x[2] == int(float(big))
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_filters.py ADDED
The diff for this file is too large to render. See raw diff
 
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_fourier.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import numpy as np
3
+
4
+ from scipy._lib._array_api import (
5
+ xp_assert_equal,
6
+ assert_array_almost_equal,
7
+ assert_almost_equal,
8
+ is_cupy,
9
+ )
10
+
11
+ import pytest
12
+
13
+ from scipy import ndimage
14
+
15
+ from scipy.conftest import array_api_compatible
16
+ skip_xp_backends = pytest.mark.skip_xp_backends
17
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends"),
18
+ skip_xp_backends(cpu_only=True, exceptions=['cupy', 'jax.numpy'],)]
19
+
20
+
21
+ @skip_xp_backends('jax.numpy', reason="jax-ml/jax#23827")
22
+ class TestNdimageFourier:
23
+
24
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15), (1, 10)])
25
+ @pytest.mark.parametrize('dtype, dec', [("float32", 6), ("float64", 14)])
26
+ def test_fourier_gaussian_real01(self, shape, dtype, dec, xp):
27
+ fft = getattr(xp, 'fft')
28
+
29
+ a = np.zeros(shape, dtype=dtype)
30
+ a[0, 0] = 1.0
31
+ a = xp.asarray(a)
32
+
33
+ a = fft.rfft(a, n=shape[0], axis=0)
34
+ a = fft.fft(a, n=shape[1], axis=1)
35
+ a = ndimage.fourier_gaussian(a, [5.0, 2.5], shape[0], 0)
36
+ a = fft.ifft(a, n=shape[1], axis=1)
37
+ a = fft.irfft(a, n=shape[0], axis=0)
38
+ assert_almost_equal(ndimage.sum(a), xp.asarray(1), decimal=dec,
39
+ check_0d=False)
40
+
41
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15)])
42
+ @pytest.mark.parametrize('dtype, dec', [("complex64", 6), ("complex128", 14)])
43
+ def test_fourier_gaussian_complex01(self, shape, dtype, dec, xp):
44
+ fft = getattr(xp, 'fft')
45
+
46
+ a = np.zeros(shape, dtype=dtype)
47
+ a[0, 0] = 1.0
48
+ a = xp.asarray(a)
49
+
50
+ a = fft.fft(a, n=shape[0], axis=0)
51
+ a = fft.fft(a, n=shape[1], axis=1)
52
+ a = ndimage.fourier_gaussian(a, [5.0, 2.5], -1, 0)
53
+ a = fft.ifft(a, n=shape[1], axis=1)
54
+ a = fft.ifft(a, n=shape[0], axis=0)
55
+ assert_almost_equal(ndimage.sum(xp.real(a)), xp.asarray(1.0), decimal=dec,
56
+ check_0d=False)
57
+
58
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15), (1, 10)])
59
+ @pytest.mark.parametrize('dtype, dec', [("float32", 6), ("float64", 14)])
60
+ def test_fourier_uniform_real01(self, shape, dtype, dec, xp):
61
+ fft = getattr(xp, 'fft')
62
+
63
+ a = np.zeros(shape, dtype=dtype)
64
+ a[0, 0] = 1.0
65
+ a = xp.asarray(a)
66
+
67
+ a = fft.rfft(a, n=shape[0], axis=0)
68
+ a = fft.fft(a, n=shape[1], axis=1)
69
+ a = ndimage.fourier_uniform(a, [5.0, 2.5], shape[0], 0)
70
+ a = fft.ifft(a, n=shape[1], axis=1)
71
+ a = fft.irfft(a, n=shape[0], axis=0)
72
+ assert_almost_equal(ndimage.sum(a), xp.asarray(1.0), decimal=dec,
73
+ check_0d=False)
74
+
75
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15)])
76
+ @pytest.mark.parametrize('dtype, dec', [("complex64", 6), ("complex128", 14)])
77
+ def test_fourier_uniform_complex01(self, shape, dtype, dec, xp):
78
+ fft = getattr(xp, 'fft')
79
+
80
+ a = np.zeros(shape, dtype=dtype)
81
+ a[0, 0] = 1.0
82
+ a = xp.asarray(a)
83
+
84
+ a = fft.fft(a, n=shape[0], axis=0)
85
+ a = fft.fft(a, n=shape[1], axis=1)
86
+ a = ndimage.fourier_uniform(a, [5.0, 2.5], -1, 0)
87
+ a = fft.ifft(a, n=shape[1], axis=1)
88
+ a = fft.ifft(a, n=shape[0], axis=0)
89
+ assert_almost_equal(ndimage.sum(xp.real(a)), xp.asarray(1.0), decimal=dec,
90
+ check_0d=False)
91
+
92
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15)])
93
+ @pytest.mark.parametrize('dtype, dec', [("float32", 4), ("float64", 11)])
94
+ def test_fourier_shift_real01(self, shape, dtype, dec, xp):
95
+ fft = getattr(xp, 'fft')
96
+
97
+ expected = np.arange(shape[0] * shape[1], dtype=dtype).reshape(shape)
98
+ expected = xp.asarray(expected)
99
+
100
+ a = fft.rfft(expected, n=shape[0], axis=0)
101
+ a = fft.fft(a, n=shape[1], axis=1)
102
+ a = ndimage.fourier_shift(a, [1, 1], shape[0], 0)
103
+ a = fft.ifft(a, n=shape[1], axis=1)
104
+ a = fft.irfft(a, n=shape[0], axis=0)
105
+ assert_array_almost_equal(a[1:, 1:], expected[:-1, :-1], decimal=dec)
106
+
107
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15)])
108
+ @pytest.mark.parametrize('dtype, dec', [("complex64", 4), ("complex128", 11)])
109
+ def test_fourier_shift_complex01(self, shape, dtype, dec, xp):
110
+ fft = getattr(xp, 'fft')
111
+
112
+ expected = np.arange(shape[0] * shape[1], dtype=dtype).reshape(shape)
113
+ expected = xp.asarray(expected)
114
+
115
+ a = fft.fft(expected, n=shape[0], axis=0)
116
+ a = fft.fft(a, n=shape[1], axis=1)
117
+ a = ndimage.fourier_shift(a, [1, 1], -1, 0)
118
+ a = fft.ifft(a, n=shape[1], axis=1)
119
+ a = fft.ifft(a, n=shape[0], axis=0)
120
+ assert_array_almost_equal(xp.real(a)[1:, 1:], expected[:-1, :-1], decimal=dec)
121
+ assert_array_almost_equal(xp.imag(a), xp.zeros(shape), decimal=dec)
122
+
123
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15), (1, 10)])
124
+ @pytest.mark.parametrize('dtype, dec', [("float32", 5), ("float64", 14)])
125
+ def test_fourier_ellipsoid_real01(self, shape, dtype, dec, xp):
126
+ fft = getattr(xp, 'fft')
127
+
128
+ a = np.zeros(shape, dtype=dtype)
129
+ a[0, 0] = 1.0
130
+ a = xp.asarray(a)
131
+
132
+ a = fft.rfft(a, n=shape[0], axis=0)
133
+ a = fft.fft(a, n=shape[1], axis=1)
134
+ a = ndimage.fourier_ellipsoid(a, [5.0, 2.5], shape[0], 0)
135
+ a = fft.ifft(a, n=shape[1], axis=1)
136
+ a = fft.irfft(a, n=shape[0], axis=0)
137
+ assert_almost_equal(ndimage.sum(a), xp.asarray(1.0), decimal=dec,
138
+ check_0d=False)
139
+
140
+ @pytest.mark.parametrize('shape', [(32, 16), (31, 15)])
141
+ @pytest.mark.parametrize('dtype, dec', [("complex64", 5), ("complex128", 14)])
142
+ def test_fourier_ellipsoid_complex01(self, shape, dtype, dec, xp):
143
+ fft = getattr(xp, 'fft')
144
+
145
+ a = np.zeros(shape, dtype=dtype)
146
+ a[0, 0] = 1.0
147
+ a = xp.asarray(a)
148
+
149
+ a = fft.fft(a, n=shape[0], axis=0)
150
+ a = fft.fft(a, n=shape[1], axis=1)
151
+ a = ndimage.fourier_ellipsoid(a, [5.0, 2.5], -1, 0)
152
+ a = fft.ifft(a, n=shape[1], axis=1)
153
+ a = fft.ifft(a, n=shape[0], axis=0)
154
+ assert_almost_equal(ndimage.sum(xp.real(a)), xp.asarray(1.0), decimal=dec,
155
+ check_0d=False)
156
+
157
+ def test_fourier_ellipsoid_unimplemented_ndim(self, xp):
158
+ # arrays with ndim > 3 raise NotImplementedError
159
+ x = xp.ones((4, 6, 8, 10), dtype=xp.complex128)
160
+ with pytest.raises(NotImplementedError):
161
+ ndimage.fourier_ellipsoid(x, 3)
162
+
163
+ def test_fourier_ellipsoid_1d_complex(self, xp):
164
+ # expected result of 1d ellipsoid is the same as for fourier_uniform
165
+ for shape in [(32, ), (31, )]:
166
+ for type_, dec in zip([xp.complex64, xp.complex128], [5, 14]):
167
+ x = xp.ones(shape, dtype=type_)
168
+ a = ndimage.fourier_ellipsoid(x, 5, -1, 0)
169
+ b = ndimage.fourier_uniform(x, 5, -1, 0)
170
+ assert_array_almost_equal(a, b, decimal=dec)
171
+
172
+ @pytest.mark.parametrize('shape', [(0, ), (0, 10), (10, 0)])
173
+ @pytest.mark.parametrize('dtype', ["float32", "float64",
174
+ "complex64", "complex128"])
175
+ @pytest.mark.parametrize('test_func',
176
+ [ndimage.fourier_ellipsoid,
177
+ ndimage.fourier_gaussian,
178
+ ndimage.fourier_uniform])
179
+ def test_fourier_zero_length_dims(self, shape, dtype, test_func, xp):
180
+ if is_cupy(xp):
181
+ if (test_func.__name__ == "fourier_ellipsoid" and
182
+ math.prod(shape) == 0):
183
+ pytest.xfail(
184
+ "CuPy's fourier_ellipsoid does not accept size==0 arrays"
185
+ )
186
+ dtype = getattr(xp, dtype)
187
+ a = xp.ones(shape, dtype=dtype)
188
+ b = test_func(a, 3)
189
+ xp_assert_equal(a, b)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_interpolation.py ADDED
@@ -0,0 +1,1484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ import numpy as np
4
+ from numpy.testing import suppress_warnings
5
+ from scipy._lib._array_api import (
6
+ xp_assert_equal, xp_assert_close,
7
+ assert_array_almost_equal,
8
+ )
9
+ from scipy._lib._array_api import is_cupy, is_jax, _asarray, array_namespace
10
+
11
+ import pytest
12
+ from pytest import raises as assert_raises
13
+ import scipy.ndimage as ndimage
14
+
15
+ from . import types
16
+
17
+ from scipy.conftest import array_api_compatible
18
+ skip_xp_backends = pytest.mark.skip_xp_backends
19
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends"),
20
+ skip_xp_backends(cpu_only=True, exceptions=['cupy', 'jax.numpy'],)]
21
+
22
+
23
+ eps = 1e-12
24
+
25
+ ndimage_to_numpy_mode = {
26
+ 'mirror': 'reflect',
27
+ 'reflect': 'symmetric',
28
+ 'grid-mirror': 'symmetric',
29
+ 'grid-wrap': 'wrap',
30
+ 'nearest': 'edge',
31
+ 'grid-constant': 'constant',
32
+ }
33
+
34
+
35
+ class TestBoundaries:
36
+
37
+ @skip_xp_backends("cupy", reason="CuPy does not have geometric_transform")
38
+ @pytest.mark.parametrize(
39
+ 'mode, expected_value',
40
+ [('nearest', [1.5, 2.5, 3.5, 4, 4, 4, 4]),
41
+ ('wrap', [1.5, 2.5, 3.5, 1.5, 2.5, 3.5, 1.5]),
42
+ ('grid-wrap', [1.5, 2.5, 3.5, 2.5, 1.5, 2.5, 3.5]),
43
+ ('mirror', [1.5, 2.5, 3.5, 3.5, 2.5, 1.5, 1.5]),
44
+ ('reflect', [1.5, 2.5, 3.5, 4, 3.5, 2.5, 1.5]),
45
+ ('constant', [1.5, 2.5, 3.5, -1, -1, -1, -1]),
46
+ ('grid-constant', [1.5, 2.5, 3.5, 1.5, -1, -1, -1])]
47
+ )
48
+ def test_boundaries(self, mode, expected_value, xp):
49
+ def shift(x):
50
+ return (x[0] + 0.5,)
51
+
52
+ data = xp.asarray([1, 2, 3, 4.])
53
+ xp_assert_equal(
54
+ ndimage.geometric_transform(data, shift, cval=-1, mode=mode,
55
+ output_shape=(7,), order=1),
56
+ xp.asarray(expected_value))
57
+
58
+ @skip_xp_backends("cupy", reason="CuPy does not have geometric_transform")
59
+ @pytest.mark.parametrize(
60
+ 'mode, expected_value',
61
+ [('nearest', [1, 1, 2, 3]),
62
+ ('wrap', [3, 1, 2, 3]),
63
+ ('grid-wrap', [4, 1, 2, 3]),
64
+ ('mirror', [2, 1, 2, 3]),
65
+ ('reflect', [1, 1, 2, 3]),
66
+ ('constant', [-1, 1, 2, 3]),
67
+ ('grid-constant', [-1, 1, 2, 3])]
68
+ )
69
+ def test_boundaries2(self, mode, expected_value, xp):
70
+ def shift(x):
71
+ return (x[0] - 0.9,)
72
+
73
+ data = xp.asarray([1, 2, 3, 4])
74
+ xp_assert_equal(
75
+ ndimage.geometric_transform(data, shift, cval=-1, mode=mode,
76
+ output_shape=(4,)),
77
+ xp.asarray(expected_value))
78
+
79
+ @pytest.mark.parametrize('mode', ['mirror', 'reflect', 'grid-mirror',
80
+ 'grid-wrap', 'grid-constant',
81
+ 'nearest'])
82
+ @pytest.mark.parametrize('order', range(6))
83
+ def test_boundary_spline_accuracy(self, mode, order, xp):
84
+ """Tests based on examples from gh-2640"""
85
+ if (is_jax(xp) and
86
+ (mode not in ['mirror', 'reflect', 'constant', 'wrap', 'nearest']
87
+ or order > 1)
88
+ ):
89
+ pytest.xfail("Jax does not support grid- modes or order > 1")
90
+
91
+ np_data = np.arange(-6, 7, dtype=np.float64)
92
+ data = xp.asarray(np_data)
93
+ x = xp.asarray(np.linspace(-8, 15, num=1000))
94
+ newaxis = array_namespace(x).newaxis
95
+ y = ndimage.map_coordinates(data, x[newaxis, ...], order=order, mode=mode)
96
+
97
+ # compute expected value using explicit padding via np.pad
98
+ npad = 32
99
+ pad_mode = ndimage_to_numpy_mode.get(mode)
100
+ padded = xp.asarray(np.pad(np_data, npad, mode=pad_mode))
101
+ coords = xp.asarray(npad + x)[newaxis, ...]
102
+ expected = ndimage.map_coordinates(padded, coords, order=order, mode=mode)
103
+
104
+ atol = 1e-5 if mode == 'grid-constant' else 1e-12
105
+ xp_assert_close(y, expected, rtol=1e-7, atol=atol)
106
+
107
+
108
+ @pytest.mark.parametrize('order', range(2, 6))
109
+ @pytest.mark.parametrize('dtype', types)
110
+ class TestSpline:
111
+
112
+ def test_spline01(self, dtype, order, xp):
113
+ dtype = getattr(xp, dtype)
114
+ data = xp.ones([], dtype=dtype)
115
+ out = ndimage.spline_filter(data, order=order)
116
+ assert out == xp.asarray(1, dtype=out.dtype)
117
+
118
+ def test_spline02(self, dtype, order, xp):
119
+ dtype = getattr(xp, dtype)
120
+ data = xp.asarray([1], dtype=dtype)
121
+ out = ndimage.spline_filter(data, order=order)
122
+ assert_array_almost_equal(out, xp.asarray([1]))
123
+
124
+ @skip_xp_backends(np_only=True, reason='output=dtype is numpy-specific')
125
+ def test_spline03(self, dtype, order, xp):
126
+ dtype = getattr(xp, dtype)
127
+ data = xp.ones([], dtype=dtype)
128
+ out = ndimage.spline_filter(data, order, output=dtype)
129
+ assert out == xp.asarray(1, dtype=out.dtype)
130
+
131
+ def test_spline04(self, dtype, order, xp):
132
+ dtype = getattr(xp, dtype)
133
+ data = xp.ones([4], dtype=dtype)
134
+ out = ndimage.spline_filter(data, order)
135
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 1]))
136
+
137
+ def test_spline05(self, dtype, order, xp):
138
+ dtype = getattr(xp, dtype)
139
+ data = xp.ones([4, 4], dtype=dtype)
140
+ out = ndimage.spline_filter(data, order=order)
141
+ expected = xp.asarray([[1, 1, 1, 1],
142
+ [1, 1, 1, 1],
143
+ [1, 1, 1, 1],
144
+ [1, 1, 1, 1]])
145
+ assert_array_almost_equal(out, expected)
146
+
147
+
148
+ @skip_xp_backends("cupy", reason="CuPy does not have geometric_transform")
149
+ @pytest.mark.parametrize('order', range(0, 6))
150
+ class TestGeometricTransform:
151
+
152
+ def test_geometric_transform01(self, order, xp):
153
+ data = xp.asarray([1])
154
+
155
+ def mapping(x):
156
+ return x
157
+
158
+ out = ndimage.geometric_transform(data, mapping, data.shape,
159
+ order=order)
160
+ assert_array_almost_equal(out, xp.asarray([1], dtype=out.dtype))
161
+
162
+ def test_geometric_transform02(self, order, xp):
163
+ data = xp.ones([4])
164
+
165
+ def mapping(x):
166
+ return x
167
+
168
+ out = ndimage.geometric_transform(data, mapping, data.shape,
169
+ order=order)
170
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 1], dtype=out.dtype))
171
+
172
+ def test_geometric_transform03(self, order, xp):
173
+ data = xp.ones([4])
174
+
175
+ def mapping(x):
176
+ return (x[0] - 1,)
177
+
178
+ out = ndimage.geometric_transform(data, mapping, data.shape,
179
+ order=order)
180
+ assert_array_almost_equal(out, xp.asarray([0, 1, 1, 1], dtype=out.dtype))
181
+
182
+ def test_geometric_transform04(self, order, xp):
183
+ data = xp.asarray([4, 1, 3, 2])
184
+
185
+ def mapping(x):
186
+ return (x[0] - 1,)
187
+
188
+ out = ndimage.geometric_transform(data, mapping, data.shape,
189
+ order=order)
190
+ assert_array_almost_equal(out, xp.asarray([0, 4, 1, 3], dtype=out.dtype))
191
+
192
+ @pytest.mark.parametrize('dtype', ["float64", "complex128"])
193
+ def test_geometric_transform05(self, order, dtype, xp):
194
+ dtype = getattr(xp, dtype)
195
+ data = xp.asarray([[1, 1, 1, 1],
196
+ [1, 1, 1, 1],
197
+ [1, 1, 1, 1]], dtype=dtype)
198
+ expected = xp.asarray([[0, 1, 1, 1],
199
+ [0, 1, 1, 1],
200
+ [0, 1, 1, 1]], dtype=dtype)
201
+
202
+ isdtype = array_namespace(data).isdtype
203
+ if isdtype(data.dtype, 'complex floating'):
204
+ data -= 1j * data
205
+ expected -= 1j * expected
206
+
207
+ def mapping(x):
208
+ return (x[0], x[1] - 1)
209
+
210
+ out = ndimage.geometric_transform(data, mapping, data.shape,
211
+ order=order)
212
+ assert_array_almost_equal(out, expected)
213
+
214
+ def test_geometric_transform06(self, order, xp):
215
+ data = xp.asarray([[4, 1, 3, 2],
216
+ [7, 6, 8, 5],
217
+ [3, 5, 3, 6]])
218
+
219
+ def mapping(x):
220
+ return (x[0], x[1] - 1)
221
+
222
+ out = ndimage.geometric_transform(data, mapping, data.shape,
223
+ order=order)
224
+ expected = xp.asarray([[0, 4, 1, 3],
225
+ [0, 7, 6, 8],
226
+ [0, 3, 5, 3]], dtype=out.dtype)
227
+ assert_array_almost_equal(out, expected)
228
+
229
+ def test_geometric_transform07(self, order, xp):
230
+ data = xp.asarray([[4, 1, 3, 2],
231
+ [7, 6, 8, 5],
232
+ [3, 5, 3, 6]])
233
+
234
+ def mapping(x):
235
+ return (x[0] - 1, x[1])
236
+
237
+ out = ndimage.geometric_transform(data, mapping, data.shape,
238
+ order=order)
239
+ expected = xp.asarray([[0, 0, 0, 0],
240
+ [4, 1, 3, 2],
241
+ [7, 6, 8, 5]], dtype=out.dtype)
242
+ assert_array_almost_equal(out, expected)
243
+
244
+ def test_geometric_transform08(self, order, xp):
245
+ data = xp.asarray([[4, 1, 3, 2],
246
+ [7, 6, 8, 5],
247
+ [3, 5, 3, 6]])
248
+
249
+ def mapping(x):
250
+ return (x[0] - 1, x[1] - 1)
251
+
252
+ out = ndimage.geometric_transform(data, mapping, data.shape,
253
+ order=order)
254
+ expected = xp.asarray([[0, 0, 0, 0],
255
+ [0, 4, 1, 3],
256
+ [0, 7, 6, 8]], dtype=out.dtype)
257
+ assert_array_almost_equal(out, expected)
258
+
259
+ def test_geometric_transform10(self, order, xp):
260
+ data = xp.asarray([[4, 1, 3, 2],
261
+ [7, 6, 8, 5],
262
+ [3, 5, 3, 6]])
263
+
264
+ def mapping(x):
265
+ return (x[0] - 1, x[1] - 1)
266
+
267
+ if (order > 1):
268
+ filtered = ndimage.spline_filter(data, order=order)
269
+ else:
270
+ filtered = data
271
+ out = ndimage.geometric_transform(filtered, mapping, data.shape,
272
+ order=order, prefilter=False)
273
+ expected = xp.asarray([[0, 0, 0, 0],
274
+ [0, 4, 1, 3],
275
+ [0, 7, 6, 8]], dtype=out.dtype)
276
+ assert_array_almost_equal(out, expected)
277
+
278
+ def test_geometric_transform13(self, order, xp):
279
+ data = xp.ones([2], dtype=xp.float64)
280
+
281
+ def mapping(x):
282
+ return (x[0] // 2,)
283
+
284
+ out = ndimage.geometric_transform(data, mapping, [4], order=order)
285
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 1], dtype=out.dtype))
286
+
287
+ def test_geometric_transform14(self, order, xp):
288
+ data = xp.asarray([1, 5, 2, 6, 3, 7, 4, 4])
289
+
290
+ def mapping(x):
291
+ return (2 * x[0],)
292
+
293
+ out = ndimage.geometric_transform(data, mapping, [4], order=order)
294
+ assert_array_almost_equal(out, xp.asarray([1, 2, 3, 4], dtype=out.dtype))
295
+
296
+ def test_geometric_transform15(self, order, xp):
297
+ data = [1, 2, 3, 4]
298
+
299
+ def mapping(x):
300
+ return (x[0] / 2,)
301
+
302
+ out = ndimage.geometric_transform(data, mapping, [8], order=order)
303
+ assert_array_almost_equal(out[::2], [1, 2, 3, 4])
304
+
305
+ def test_geometric_transform16(self, order, xp):
306
+ data = [[1, 2, 3, 4],
307
+ [5, 6, 7, 8],
308
+ [9.0, 10, 11, 12]]
309
+
310
+ def mapping(x):
311
+ return (x[0], x[1] * 2)
312
+
313
+ out = ndimage.geometric_transform(data, mapping, (3, 2),
314
+ order=order)
315
+ assert_array_almost_equal(out, [[1, 3], [5, 7], [9, 11]])
316
+
317
+ def test_geometric_transform17(self, order, xp):
318
+ data = [[1, 2, 3, 4],
319
+ [5, 6, 7, 8],
320
+ [9, 10, 11, 12]]
321
+
322
+ def mapping(x):
323
+ return (x[0] * 2, x[1])
324
+
325
+ out = ndimage.geometric_transform(data, mapping, (1, 4),
326
+ order=order)
327
+ assert_array_almost_equal(out, [[1, 2, 3, 4]])
328
+
329
+ def test_geometric_transform18(self, order, xp):
330
+ data = [[1, 2, 3, 4],
331
+ [5, 6, 7, 8],
332
+ [9, 10, 11, 12]]
333
+
334
+ def mapping(x):
335
+ return (x[0] * 2, x[1] * 2)
336
+
337
+ out = ndimage.geometric_transform(data, mapping, (1, 2),
338
+ order=order)
339
+ assert_array_almost_equal(out, [[1, 3]])
340
+
341
+ def test_geometric_transform19(self, order, xp):
342
+ data = [[1, 2, 3, 4],
343
+ [5, 6, 7, 8],
344
+ [9, 10, 11, 12]]
345
+
346
+ def mapping(x):
347
+ return (x[0], x[1] / 2)
348
+
349
+ out = ndimage.geometric_transform(data, mapping, (3, 8),
350
+ order=order)
351
+ assert_array_almost_equal(out[..., ::2], data)
352
+
353
+ def test_geometric_transform20(self, order, xp):
354
+ data = [[1, 2, 3, 4],
355
+ [5, 6, 7, 8],
356
+ [9, 10, 11, 12]]
357
+
358
+ def mapping(x):
359
+ return (x[0] / 2, x[1])
360
+
361
+ out = ndimage.geometric_transform(data, mapping, (6, 4),
362
+ order=order)
363
+ assert_array_almost_equal(out[::2, ...], data)
364
+
365
+ def test_geometric_transform21(self, order, xp):
366
+ data = [[1, 2, 3, 4],
367
+ [5, 6, 7, 8],
368
+ [9, 10, 11, 12]]
369
+
370
+ def mapping(x):
371
+ return (x[0] / 2, x[1] / 2)
372
+
373
+ out = ndimage.geometric_transform(data, mapping, (6, 8),
374
+ order=order)
375
+ assert_array_almost_equal(out[::2, ::2], data)
376
+
377
+ def test_geometric_transform22(self, order, xp):
378
+ data = xp.asarray([[1, 2, 3, 4],
379
+ [5, 6, 7, 8],
380
+ [9, 10, 11, 12]], dtype=xp.float64)
381
+
382
+ def mapping1(x):
383
+ return (x[0] / 2, x[1] / 2)
384
+
385
+ def mapping2(x):
386
+ return (x[0] * 2, x[1] * 2)
387
+
388
+ out = ndimage.geometric_transform(data, mapping1,
389
+ (6, 8), order=order)
390
+ out = ndimage.geometric_transform(out, mapping2,
391
+ (3, 4), order=order)
392
+ assert_array_almost_equal(out, data)
393
+
394
+ def test_geometric_transform23(self, order, xp):
395
+ data = [[1, 2, 3, 4],
396
+ [5, 6, 7, 8],
397
+ [9, 10, 11, 12]]
398
+
399
+ def mapping(x):
400
+ return (1, x[0] * 2)
401
+
402
+ out = ndimage.geometric_transform(data, mapping, (2,), order=order)
403
+ out = out.astype(np.int32)
404
+ assert_array_almost_equal(out, [5, 7])
405
+
406
+ def test_geometric_transform24(self, order, xp):
407
+ data = [[1, 2, 3, 4],
408
+ [5, 6, 7, 8],
409
+ [9, 10, 11, 12]]
410
+
411
+ def mapping(x, a, b):
412
+ return (a, x[0] * b)
413
+
414
+ out = ndimage.geometric_transform(
415
+ data, mapping, (2,), order=order, extra_arguments=(1,),
416
+ extra_keywords={'b': 2})
417
+ assert_array_almost_equal(out, [5, 7])
418
+
419
+
420
+ @skip_xp_backends("cupy", reason="CuPy does not have geometric_transform")
421
+ class TestGeometricTransformExtra:
422
+
423
+ def test_geometric_transform_grid_constant_order1(self, xp):
424
+
425
+ # verify interpolation outside the original bounds
426
+ x = xp.asarray([[1, 2, 3],
427
+ [4, 5, 6]], dtype=xp.float64)
428
+
429
+ def mapping(x):
430
+ return (x[0] - 0.5), (x[1] - 0.5)
431
+
432
+ expected_result = xp.asarray([[0.25, 0.75, 1.25],
433
+ [1.25, 3.00, 4.00]])
434
+ assert_array_almost_equal(
435
+ ndimage.geometric_transform(x, mapping, mode='grid-constant',
436
+ order=1),
437
+ expected_result,
438
+ )
439
+
440
+ @pytest.mark.parametrize('mode', ['grid-constant', 'grid-wrap', 'nearest',
441
+ 'mirror', 'reflect'])
442
+ @pytest.mark.parametrize('order', range(6))
443
+ def test_geometric_transform_vs_padded(self, order, mode, xp):
444
+
445
+ def mapping(x):
446
+ return (x[0] - 0.4), (x[1] + 2.3)
447
+
448
+ # Manually pad and then extract center after the transform to get the
449
+ # expected result.
450
+ x = np.arange(144, dtype=float).reshape(12, 12)
451
+ npad = 24
452
+ pad_mode = ndimage_to_numpy_mode.get(mode)
453
+ x_padded = np.pad(x, npad, mode=pad_mode)
454
+
455
+ x = xp.asarray(x)
456
+ x_padded = xp.asarray(x_padded)
457
+
458
+ center_slice = tuple([slice(npad, -npad)] * x.ndim)
459
+ expected_result = ndimage.geometric_transform(
460
+ x_padded, mapping, mode=mode, order=order)[center_slice]
461
+
462
+ xp_assert_close(
463
+ ndimage.geometric_transform(x, mapping, mode=mode,
464
+ order=order),
465
+ expected_result,
466
+ rtol=1e-7,
467
+ )
468
+
469
+ @skip_xp_backends(np_only=True, reason='endianness is numpy-specific')
470
+ def test_geometric_transform_endianness_with_output_parameter(self, xp):
471
+ # geometric transform given output ndarray or dtype with
472
+ # non-native endianness. see issue #4127
473
+ data = np.asarray([1])
474
+
475
+ def mapping(x):
476
+ return x
477
+
478
+ for out in [data.dtype, data.dtype.newbyteorder(),
479
+ np.empty_like(data),
480
+ np.empty_like(data).astype(data.dtype.newbyteorder())]:
481
+ returned = ndimage.geometric_transform(data, mapping, data.shape,
482
+ output=out)
483
+ result = out if returned is None else returned
484
+ assert_array_almost_equal(result, [1])
485
+
486
+ @skip_xp_backends(np_only=True, reason='string `output` is numpy-specific')
487
+ def test_geometric_transform_with_string_output(self, xp):
488
+ data = xp.asarray([1])
489
+
490
+ def mapping(x):
491
+ return x
492
+
493
+ out = ndimage.geometric_transform(data, mapping, output='f')
494
+ assert out.dtype is np.dtype('f')
495
+ assert_array_almost_equal(out, [1])
496
+
497
+
498
+ class TestMapCoordinates:
499
+
500
+ @pytest.mark.parametrize('order', range(0, 6))
501
+ @pytest.mark.parametrize('dtype', [np.float64, np.complex128])
502
+ def test_map_coordinates01(self, order, dtype, xp):
503
+ if is_jax(xp) and order > 1:
504
+ pytest.xfail("jax map_coordinates requires order <= 1")
505
+
506
+ data = xp.asarray([[4, 1, 3, 2],
507
+ [7, 6, 8, 5],
508
+ [3, 5, 3, 6]])
509
+ expected = xp.asarray([[0, 0, 0, 0],
510
+ [0, 4, 1, 3],
511
+ [0, 7, 6, 8]])
512
+ isdtype = array_namespace(data).isdtype
513
+ if isdtype(data.dtype, 'complex floating'):
514
+ data = data - 1j * data
515
+ expected = expected - 1j * expected
516
+
517
+ idx = np.indices(data.shape)
518
+ idx -= 1
519
+ idx = xp.asarray(idx)
520
+
521
+ out = ndimage.map_coordinates(data, idx, order=order)
522
+ assert_array_almost_equal(out, expected)
523
+
524
+ @pytest.mark.parametrize('order', range(0, 6))
525
+ def test_map_coordinates02(self, order, xp):
526
+ if is_jax(xp):
527
+ if order > 1:
528
+ pytest.xfail("jax map_coordinates requires order <= 1")
529
+ if order == 1:
530
+ pytest.xfail("output differs. jax bug?")
531
+
532
+ data = xp.asarray([[4, 1, 3, 2],
533
+ [7, 6, 8, 5],
534
+ [3, 5, 3, 6]])
535
+ idx = np.indices(data.shape, np.float64)
536
+ idx -= 0.5
537
+ idx = xp.asarray(idx)
538
+
539
+ out1 = ndimage.shift(data, 0.5, order=order)
540
+ out2 = ndimage.map_coordinates(data, idx, order=order)
541
+ assert_array_almost_equal(out1, out2)
542
+
543
+ @skip_xp_backends("jax.numpy", reason="`order` is required in jax")
544
+ def test_map_coordinates03(self, xp):
545
+ data = _asarray([[4, 1, 3, 2],
546
+ [7, 6, 8, 5],
547
+ [3, 5, 3, 6]], order='F', xp=xp)
548
+ idx = np.indices(data.shape) - 1
549
+ idx = xp.asarray(idx)
550
+ out = ndimage.map_coordinates(data, idx)
551
+ expected = xp.asarray([[0, 0, 0, 0],
552
+ [0, 4, 1, 3],
553
+ [0, 7, 6, 8]])
554
+ assert_array_almost_equal(out, expected)
555
+ assert_array_almost_equal(out, ndimage.shift(data, (1, 1)))
556
+
557
+ idx = np.indices(data[::2, ...].shape) - 1
558
+ idx = xp.asarray(idx)
559
+ out = ndimage.map_coordinates(data[::2, ...], idx)
560
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
561
+ [0, 4, 1, 3]]))
562
+ assert_array_almost_equal(out, ndimage.shift(data[::2, ...], (1, 1)))
563
+
564
+ idx = np.indices(data[:, ::2].shape) - 1
565
+ idx = xp.asarray(idx)
566
+ out = ndimage.map_coordinates(data[:, ::2], idx)
567
+ assert_array_almost_equal(out, xp.asarray([[0, 0], [0, 4], [0, 7]]))
568
+ assert_array_almost_equal(out, ndimage.shift(data[:, ::2], (1, 1)))
569
+
570
+ @skip_xp_backends(np_only=True)
571
+ def test_map_coordinates_endianness_with_output_parameter(self, xp):
572
+ # output parameter given as array or dtype with either endianness
573
+ # see issue #4127
574
+ # NB: NumPy-only
575
+
576
+ data = np.asarray([[1, 2], [7, 6]])
577
+ expected = np.asarray([[0, 0], [0, 1]])
578
+ idx = np.indices(data.shape)
579
+ idx -= 1
580
+ for out in [
581
+ data.dtype,
582
+ data.dtype.newbyteorder(),
583
+ np.empty_like(expected),
584
+ np.empty_like(expected).astype(expected.dtype.newbyteorder())
585
+ ]:
586
+ returned = ndimage.map_coordinates(data, idx, output=out)
587
+ result = out if returned is None else returned
588
+ assert_array_almost_equal(result, expected)
589
+
590
+ @skip_xp_backends(np_only=True, reason='string `output` is numpy-specific')
591
+ def test_map_coordinates_with_string_output(self, xp):
592
+ data = xp.asarray([[1]])
593
+ idx = np.indices(data.shape)
594
+ idx = xp.asarray(idx)
595
+ out = ndimage.map_coordinates(data, idx, output='f')
596
+ assert out.dtype is np.dtype('f')
597
+ assert_array_almost_equal(out, xp.asarray([[1]]))
598
+
599
+ @pytest.mark.skipif('win32' in sys.platform or np.intp(0).itemsize < 8,
600
+ reason='do not run on 32 bit or windows '
601
+ '(no sparse memory)')
602
+ def test_map_coordinates_large_data(self, xp):
603
+ # check crash on large data
604
+ try:
605
+ n = 30000
606
+ # a = xp.reshape(xp.empty(n**2, dtype=xp.float32), (n, n))
607
+ a = np.empty(n**2, dtype=np.float32).reshape(n, n)
608
+ # fill the part we might read
609
+ a[n - 3:, n - 3:] = 0
610
+ ndimage.map_coordinates(
611
+ xp.asarray(a), xp.asarray([[n - 1.5], [n - 1.5]]), order=1
612
+ )
613
+ except MemoryError as e:
614
+ raise pytest.skip('Not enough memory available') from e
615
+
616
+
617
+ class TestAffineTransform:
618
+
619
+ @pytest.mark.parametrize('order', range(0, 6))
620
+ def test_affine_transform01(self, order, xp):
621
+ data = xp.asarray([1])
622
+ out = ndimage.affine_transform(data, xp.asarray([[1]]), order=order)
623
+ assert_array_almost_equal(out, xp.asarray([1]))
624
+
625
+ @pytest.mark.parametrize('order', range(0, 6))
626
+ def test_affine_transform02(self, order, xp):
627
+ data = xp.ones([4])
628
+ out = ndimage.affine_transform(data, xp.asarray([[1]]), order=order)
629
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 1]))
630
+
631
+ @pytest.mark.parametrize('order', range(0, 6))
632
+ def test_affine_transform03(self, order, xp):
633
+ data = xp.ones([4])
634
+ out = ndimage.affine_transform(data, xp.asarray([[1]]), -1, order=order)
635
+ assert_array_almost_equal(out, xp.asarray([0, 1, 1, 1]))
636
+
637
+ @pytest.mark.parametrize('order', range(0, 6))
638
+ def test_affine_transform04(self, order, xp):
639
+ data = xp.asarray([4, 1, 3, 2])
640
+ out = ndimage.affine_transform(data, xp.asarray([[1]]), -1, order=order)
641
+ assert_array_almost_equal(out, xp.asarray([0, 4, 1, 3]))
642
+
643
+ @pytest.mark.parametrize('order', range(0, 6))
644
+ @pytest.mark.parametrize('dtype', ["float64", "complex128"])
645
+ def test_affine_transform05(self, order, dtype, xp):
646
+ dtype = getattr(xp, dtype)
647
+ data = xp.asarray([[1, 1, 1, 1],
648
+ [1, 1, 1, 1],
649
+ [1, 1, 1, 1]], dtype=dtype)
650
+ expected = xp.asarray([[0, 1, 1, 1],
651
+ [0, 1, 1, 1],
652
+ [0, 1, 1, 1]], dtype=dtype)
653
+ isdtype = array_namespace(data).isdtype
654
+ if isdtype(data.dtype, 'complex floating'):
655
+ data -= 1j * data
656
+ expected -= 1j * expected
657
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0], [0, 1]]),
658
+ [0, -1], order=order)
659
+ assert_array_almost_equal(out, expected)
660
+
661
+ @pytest.mark.parametrize('order', range(0, 6))
662
+ def test_affine_transform06(self, order, xp):
663
+ data = xp.asarray([[4, 1, 3, 2],
664
+ [7, 6, 8, 5],
665
+ [3, 5, 3, 6]])
666
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0], [0, 1]]),
667
+ [0, -1], order=order)
668
+ assert_array_almost_equal(out, xp.asarray([[0, 4, 1, 3],
669
+ [0, 7, 6, 8],
670
+ [0, 3, 5, 3]]))
671
+
672
+ @pytest.mark.parametrize('order', range(0, 6))
673
+ def test_affine_transform07(self, order, xp):
674
+ data = xp.asarray([[4, 1, 3, 2],
675
+ [7, 6, 8, 5],
676
+ [3, 5, 3, 6]])
677
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0], [0, 1]]),
678
+ [-1, 0], order=order)
679
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
680
+ [4, 1, 3, 2],
681
+ [7, 6, 8, 5]]))
682
+
683
+ @pytest.mark.parametrize('order', range(0, 6))
684
+ def test_affine_transform08(self, order, xp):
685
+ data = xp.asarray([[4, 1, 3, 2],
686
+ [7, 6, 8, 5],
687
+ [3, 5, 3, 6]])
688
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0], [0, 1]]),
689
+ [-1, -1], order=order)
690
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
691
+ [0, 4, 1, 3],
692
+ [0, 7, 6, 8]]))
693
+
694
+ @pytest.mark.parametrize('order', range(0, 6))
695
+ def test_affine_transform09(self, order, xp):
696
+ data = xp.asarray([[4, 1, 3, 2],
697
+ [7, 6, 8, 5],
698
+ [3, 5, 3, 6]])
699
+ if (order > 1):
700
+ filtered = ndimage.spline_filter(data, order=order)
701
+ else:
702
+ filtered = data
703
+ out = ndimage.affine_transform(filtered, xp.asarray([[1, 0], [0, 1]]),
704
+ [-1, -1], order=order,
705
+ prefilter=False)
706
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
707
+ [0, 4, 1, 3],
708
+ [0, 7, 6, 8]]))
709
+
710
+ @pytest.mark.parametrize('order', range(0, 6))
711
+ def test_affine_transform10(self, order, xp):
712
+ data = xp.ones([2], dtype=xp.float64)
713
+ out = ndimage.affine_transform(data, xp.asarray([[0.5]]), output_shape=(4,),
714
+ order=order)
715
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 0]))
716
+
717
+ @pytest.mark.parametrize('order', range(0, 6))
718
+ def test_affine_transform11(self, order, xp):
719
+ data = xp.asarray([1, 5, 2, 6, 3, 7, 4, 4])
720
+ out = ndimage.affine_transform(data, xp.asarray([[2]]), 0, (4,), order=order)
721
+ assert_array_almost_equal(out, xp.asarray([1, 2, 3, 4]))
722
+
723
+ @pytest.mark.parametrize('order', range(0, 6))
724
+ def test_affine_transform12(self, order, xp):
725
+ data = xp.asarray([1, 2, 3, 4])
726
+ out = ndimage.affine_transform(data, xp.asarray([[0.5]]), 0, (8,), order=order)
727
+ assert_array_almost_equal(out[::2], xp.asarray([1, 2, 3, 4]))
728
+
729
+ @pytest.mark.parametrize('order', range(0, 6))
730
+ def test_affine_transform13(self, order, xp):
731
+ data = [[1, 2, 3, 4],
732
+ [5, 6, 7, 8],
733
+ [9.0, 10, 11, 12]]
734
+ data = xp.asarray(data)
735
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0], [0, 2]]), 0, (3, 2),
736
+ order=order)
737
+ assert_array_almost_equal(out, xp.asarray([[1, 3], [5, 7], [9, 11]]))
738
+
739
+ @pytest.mark.parametrize('order', range(0, 6))
740
+ def test_affine_transform14(self, order, xp):
741
+ data = [[1, 2, 3, 4],
742
+ [5, 6, 7, 8],
743
+ [9, 10, 11, 12]]
744
+ data = xp.asarray(data)
745
+ out = ndimage.affine_transform(data, xp.asarray([[2, 0], [0, 1]]), 0, (1, 4),
746
+ order=order)
747
+ assert_array_almost_equal(out, xp.asarray([[1, 2, 3, 4]]))
748
+
749
+ @pytest.mark.parametrize('order', range(0, 6))
750
+ def test_affine_transform15(self, order, xp):
751
+ data = [[1, 2, 3, 4],
752
+ [5, 6, 7, 8],
753
+ [9, 10, 11, 12]]
754
+ data = xp.asarray(data)
755
+ out = ndimage.affine_transform(data, xp.asarray([[2, 0], [0, 2]]), 0, (1, 2),
756
+ order=order)
757
+ assert_array_almost_equal(out, xp.asarray([[1, 3]]))
758
+
759
+ @pytest.mark.parametrize('order', range(0, 6))
760
+ def test_affine_transform16(self, order, xp):
761
+ data = [[1, 2, 3, 4],
762
+ [5, 6, 7, 8],
763
+ [9, 10, 11, 12]]
764
+ data = xp.asarray(data)
765
+ out = ndimage.affine_transform(data, xp.asarray([[1, 0.0], [0, 0.5]]), 0,
766
+ (3, 8), order=order)
767
+ assert_array_almost_equal(out[..., ::2], data)
768
+
769
+ @pytest.mark.parametrize('order', range(0, 6))
770
+ def test_affine_transform17(self, order, xp):
771
+ data = [[1, 2, 3, 4],
772
+ [5, 6, 7, 8],
773
+ [9, 10, 11, 12]]
774
+ data = xp.asarray(data)
775
+ out = ndimage.affine_transform(data, xp.asarray([[0.5, 0], [0, 1]]), 0,
776
+ (6, 4), order=order)
777
+ assert_array_almost_equal(out[::2, ...], data)
778
+
779
+ @pytest.mark.parametrize('order', range(0, 6))
780
+ def test_affine_transform18(self, order, xp):
781
+ data = xp.asarray([[1, 2, 3, 4],
782
+ [5, 6, 7, 8],
783
+ [9, 10, 11, 12]])
784
+ out = ndimage.affine_transform(data, xp.asarray([[0.5, 0], [0, 0.5]]), 0,
785
+ (6, 8), order=order)
786
+ assert_array_almost_equal(out[::2, ::2], data)
787
+
788
+ @pytest.mark.parametrize('order', range(0, 6))
789
+ def test_affine_transform19(self, order, xp):
790
+ data = xp.asarray([[1, 2, 3, 4],
791
+ [5, 6, 7, 8],
792
+ [9, 10, 11, 12]], dtype=xp.float64)
793
+ out = ndimage.affine_transform(data, xp.asarray([[0.5, 0], [0, 0.5]]), 0,
794
+ (6, 8), order=order)
795
+ out = ndimage.affine_transform(out, xp.asarray([[2.0, 0], [0, 2.0]]), 0,
796
+ (3, 4), order=order)
797
+ assert_array_almost_equal(out, data)
798
+
799
+ @pytest.mark.parametrize('order', range(0, 6))
800
+ def test_affine_transform20(self, order, xp):
801
+ if is_cupy(xp):
802
+ pytest.xfail("https://github.com/cupy/cupy/issues/8394")
803
+
804
+ data = [[1, 2, 3, 4],
805
+ [5, 6, 7, 8],
806
+ [9, 10, 11, 12]]
807
+ data = xp.asarray(data)
808
+ out = ndimage.affine_transform(data, xp.asarray([[0], [2]]), 0, (2,),
809
+ order=order)
810
+ assert_array_almost_equal(out, xp.asarray([1, 3]))
811
+
812
+ @pytest.mark.parametrize('order', range(0, 6))
813
+ def test_affine_transform21(self, order, xp):
814
+ if is_cupy(xp):
815
+ pytest.xfail("https://github.com/cupy/cupy/issues/8394")
816
+
817
+ data = [[1, 2, 3, 4],
818
+ [5, 6, 7, 8],
819
+ [9, 10, 11, 12]]
820
+ data = xp.asarray(data)
821
+ out = ndimage.affine_transform(data, xp.asarray([[2], [0]]), 0, (2,),
822
+ order=order)
823
+ assert_array_almost_equal(out, xp.asarray([1, 9]))
824
+
825
+ @pytest.mark.parametrize('order', range(0, 6))
826
+ def test_affine_transform22(self, order, xp):
827
+ # shift and offset interaction; see issue #1547
828
+ data = xp.asarray([4, 1, 3, 2])
829
+ out = ndimage.affine_transform(data, xp.asarray([[2]]), [-1], (3,),
830
+ order=order)
831
+ assert_array_almost_equal(out, xp.asarray([0, 1, 2]))
832
+
833
+ @pytest.mark.parametrize('order', range(0, 6))
834
+ def test_affine_transform23(self, order, xp):
835
+ # shift and offset interaction; see issue #1547
836
+ data = xp.asarray([4, 1, 3, 2])
837
+ out = ndimage.affine_transform(data, xp.asarray([[0.5]]), [-1], (8,),
838
+ order=order)
839
+ assert_array_almost_equal(out[::2], xp.asarray([0, 4, 1, 3]))
840
+
841
+ @pytest.mark.parametrize('order', range(0, 6))
842
+ def test_affine_transform24(self, order, xp):
843
+ # consistency between diagonal and non-diagonal case; see issue #1547
844
+ data = xp.asarray([4, 1, 3, 2])
845
+ with suppress_warnings() as sup:
846
+ sup.filter(UserWarning,
847
+ 'The behavior of affine_transform with a 1-D array .* '
848
+ 'has changed')
849
+ out1 = ndimage.affine_transform(data, xp.asarray([2]), -1, order=order)
850
+ out2 = ndimage.affine_transform(data, xp.asarray([[2]]), -1, order=order)
851
+ assert_array_almost_equal(out1, out2)
852
+
853
+ @pytest.mark.parametrize('order', range(0, 6))
854
+ def test_affine_transform25(self, order, xp):
855
+ # consistency between diagonal and non-diagonal case; see issue #1547
856
+ data = xp.asarray([4, 1, 3, 2])
857
+ with suppress_warnings() as sup:
858
+ sup.filter(UserWarning,
859
+ 'The behavior of affine_transform with a 1-D array .* '
860
+ 'has changed')
861
+ out1 = ndimage.affine_transform(data, xp.asarray([0.5]), -1, order=order)
862
+ out2 = ndimage.affine_transform(data, xp.asarray([[0.5]]), -1, order=order)
863
+ assert_array_almost_equal(out1, out2)
864
+
865
+ @pytest.mark.parametrize('order', range(0, 6))
866
+ def test_affine_transform26(self, order, xp):
867
+ # test homogeneous coordinates
868
+ data = xp.asarray([[4, 1, 3, 2],
869
+ [7, 6, 8, 5],
870
+ [3, 5, 3, 6]])
871
+ if (order > 1):
872
+ filtered = ndimage.spline_filter(data, order=order)
873
+ else:
874
+ filtered = data
875
+ tform_original = xp.eye(2)
876
+ offset_original = -xp.ones((2, 1))
877
+
878
+ concat = array_namespace(tform_original, offset_original).concat
879
+ tform_h1 = concat((tform_original, offset_original), axis=1) # hstack
880
+ tform_h2 = concat( (tform_h1, xp.asarray([[0.0, 0, 1]])), axis=0) # vstack
881
+
882
+ offs = [float(x) for x in xp.reshape(offset_original, (-1,))]
883
+
884
+ out1 = ndimage.affine_transform(filtered, tform_original,
885
+ offs,
886
+ order=order, prefilter=False)
887
+ out2 = ndimage.affine_transform(filtered, tform_h1, order=order,
888
+ prefilter=False)
889
+ out3 = ndimage.affine_transform(filtered, tform_h2, order=order,
890
+ prefilter=False)
891
+ for out in [out1, out2, out3]:
892
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
893
+ [0, 4, 1, 3],
894
+ [0, 7, 6, 8]]))
895
+
896
+ def test_affine_transform27(self, xp):
897
+ if is_cupy(xp):
898
+ pytest.xfail("CuPy does not raise")
899
+
900
+ # test valid homogeneous transformation matrix
901
+ data = xp.asarray([[4, 1, 3, 2],
902
+ [7, 6, 8, 5],
903
+ [3, 5, 3, 6]])
904
+ concat = array_namespace(data).concat
905
+ tform_h1 = concat( (xp.eye(2), -xp.ones((2, 1))) , axis=1) # vstack
906
+ tform_h2 = concat((tform_h1, xp.asarray([[5.0, 2, 1]])), axis=0) # hstack
907
+
908
+ assert_raises(ValueError, ndimage.affine_transform, data, tform_h2)
909
+
910
+ @skip_xp_backends(np_only=True, reason='byteorder is numpy-specific')
911
+ def test_affine_transform_1d_endianness_with_output_parameter(self, xp):
912
+ # 1d affine transform given output ndarray or dtype with
913
+ # either endianness. see issue #7388
914
+ data = xp.ones((2, 2))
915
+ for out in [xp.empty_like(data),
916
+ xp.empty_like(data).astype(data.dtype.newbyteorder()),
917
+ data.dtype, data.dtype.newbyteorder()]:
918
+ with suppress_warnings() as sup:
919
+ sup.filter(UserWarning,
920
+ 'The behavior of affine_transform with a 1-D array '
921
+ '.* has changed')
922
+ matrix = xp.asarray([1, 1])
923
+ returned = ndimage.affine_transform(data, matrix, output=out)
924
+ result = out if returned is None else returned
925
+ assert_array_almost_equal(result, xp.asarray([[1, 1], [1, 1]]))
926
+
927
+ @skip_xp_backends(np_only=True, reason='byteorder is numpy-specific')
928
+ def test_affine_transform_multi_d_endianness_with_output_parameter(self, xp):
929
+ # affine transform given output ndarray or dtype with either endianness
930
+ # see issue #4127
931
+ # NB: byteorder is numpy-specific
932
+ data = np.asarray([1])
933
+ for out in [data.dtype, data.dtype.newbyteorder(),
934
+ np.empty_like(data),
935
+ np.empty_like(data).astype(data.dtype.newbyteorder())]:
936
+ returned = ndimage.affine_transform(data, np.asarray([[1]]), output=out)
937
+ result = out if returned is None else returned
938
+ assert_array_almost_equal(result, np.asarray([1]))
939
+
940
+ @skip_xp_backends(np_only=True,
941
+ reason='`out` of a different size is numpy-specific'
942
+ )
943
+ def test_affine_transform_output_shape(self, xp):
944
+ # don't require output_shape when out of a different size is given
945
+ data = xp.arange(8, dtype=xp.float64)
946
+ out = xp.ones((16,))
947
+
948
+ ndimage.affine_transform(data, xp.asarray([[1]]), output=out)
949
+ assert_array_almost_equal(out[:8], data)
950
+
951
+ # mismatched output shape raises an error
952
+ with pytest.raises(RuntimeError):
953
+ ndimage.affine_transform(
954
+ data, [[1]], output=out, output_shape=(12,))
955
+
956
+ @skip_xp_backends(np_only=True, reason='string `output` is numpy-specific')
957
+ def test_affine_transform_with_string_output(self, xp):
958
+ data = xp.asarray([1])
959
+ out = ndimage.affine_transform(data, xp.asarray([[1]]), output='f')
960
+ assert out.dtype is np.dtype('f')
961
+ assert_array_almost_equal(out, xp.asarray([1]))
962
+
963
+ @pytest.mark.parametrize('shift',
964
+ [(1, 0), (0, 1), (-1, 1), (3, -5), (2, 7)])
965
+ @pytest.mark.parametrize('order', range(0, 6))
966
+ def test_affine_transform_shift_via_grid_wrap(self, shift, order, xp):
967
+ # For mode 'grid-wrap', integer shifts should match np.roll
968
+ x = np.asarray([[0, 1],
969
+ [2, 3]])
970
+ affine = np.zeros((2, 3))
971
+ affine[:2, :2] = np.eye(2)
972
+ affine[:, 2] = np.asarray(shift)
973
+
974
+ expected = np.roll(x, shift, axis=(0, 1))
975
+
976
+ x = xp.asarray(x)
977
+ affine = xp.asarray(affine)
978
+ expected = xp.asarray(expected)
979
+
980
+ assert_array_almost_equal(
981
+ ndimage.affine_transform(x, affine, mode='grid-wrap', order=order),
982
+ expected
983
+ )
984
+
985
+ @pytest.mark.parametrize('order', range(0, 6))
986
+ def test_affine_transform_shift_reflect(self, order, xp):
987
+ # shift by x.shape results in reflection
988
+ x = np.asarray([[0, 1, 2],
989
+ [3, 4, 5]])
990
+ expected = x[::-1, ::-1].copy() # strides >0 for torch
991
+ x = xp.asarray(x)
992
+ expected = xp.asarray(expected)
993
+
994
+ affine = np.zeros([2, 3])
995
+ affine[:2, :2] = np.eye(2)
996
+ affine[:, 2] = np.asarray(x.shape)
997
+ affine = xp.asarray(affine)
998
+
999
+ assert_array_almost_equal(
1000
+ ndimage.affine_transform(x, affine, mode='reflect', order=order),
1001
+ expected,
1002
+ )
1003
+
1004
+
1005
+ class TestShift:
1006
+
1007
+ @pytest.mark.parametrize('order', range(0, 6))
1008
+ def test_shift01(self, order, xp):
1009
+ data = xp.asarray([1])
1010
+ out = ndimage.shift(data, [1], order=order)
1011
+ assert_array_almost_equal(out, xp.asarray([0]))
1012
+
1013
+ @pytest.mark.parametrize('order', range(0, 6))
1014
+ def test_shift02(self, order, xp):
1015
+ data = xp.ones([4])
1016
+ out = ndimage.shift(data, [1], order=order)
1017
+ assert_array_almost_equal(out, xp.asarray([0, 1, 1, 1]))
1018
+
1019
+ @pytest.mark.parametrize('order', range(0, 6))
1020
+ def test_shift03(self, order, xp):
1021
+ data = xp.ones([4])
1022
+ out = ndimage.shift(data, -1, order=order)
1023
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 0]))
1024
+
1025
+ @pytest.mark.parametrize('order', range(0, 6))
1026
+ def test_shift04(self, order, xp):
1027
+ data = xp.asarray([4, 1, 3, 2])
1028
+ out = ndimage.shift(data, 1, order=order)
1029
+ assert_array_almost_equal(out, xp.asarray([0, 4, 1, 3]))
1030
+
1031
+ @pytest.mark.parametrize('order', range(0, 6))
1032
+ @pytest.mark.parametrize('dtype', ["float64", "complex128"])
1033
+ def test_shift05(self, order, dtype, xp):
1034
+ dtype = getattr(xp, dtype)
1035
+ data = xp.asarray([[1, 1, 1, 1],
1036
+ [1, 1, 1, 1],
1037
+ [1, 1, 1, 1]], dtype=dtype)
1038
+ expected = xp.asarray([[0, 1, 1, 1],
1039
+ [0, 1, 1, 1],
1040
+ [0, 1, 1, 1]], dtype=dtype)
1041
+ isdtype = array_namespace(data).isdtype
1042
+ if isdtype(data.dtype, 'complex floating'):
1043
+ data -= 1j * data
1044
+ expected -= 1j * expected
1045
+ out = ndimage.shift(data, [0, 1], order=order)
1046
+ assert_array_almost_equal(out, expected)
1047
+
1048
+ @pytest.mark.parametrize('order', range(0, 6))
1049
+ @pytest.mark.parametrize('mode', ['constant', 'grid-constant'])
1050
+ @pytest.mark.parametrize('dtype', ['float64', 'complex128'])
1051
+ def test_shift_with_nonzero_cval(self, order, mode, dtype, xp):
1052
+ data = np.asarray([[1, 1, 1, 1],
1053
+ [1, 1, 1, 1],
1054
+ [1, 1, 1, 1]], dtype=dtype)
1055
+
1056
+ expected = np.asarray([[0, 1, 1, 1],
1057
+ [0, 1, 1, 1],
1058
+ [0, 1, 1, 1]], dtype=dtype)
1059
+
1060
+ isdtype = array_namespace(data).isdtype
1061
+ if isdtype(data.dtype, 'complex floating'):
1062
+ data -= 1j * data
1063
+ expected -= 1j * expected
1064
+ cval = 5.0
1065
+ expected[:, 0] = cval # specific to shift of [0, 1] used below
1066
+
1067
+ data = xp.asarray(data)
1068
+ expected = xp.asarray(expected)
1069
+ out = ndimage.shift(data, [0, 1], order=order, mode=mode, cval=cval)
1070
+ assert_array_almost_equal(out, expected)
1071
+
1072
+ @pytest.mark.parametrize('order', range(0, 6))
1073
+ def test_shift06(self, order, xp):
1074
+ data = xp.asarray([[4, 1, 3, 2],
1075
+ [7, 6, 8, 5],
1076
+ [3, 5, 3, 6]])
1077
+ out = ndimage.shift(data, [0, 1], order=order)
1078
+ assert_array_almost_equal(out, xp.asarray([[0, 4, 1, 3],
1079
+ [0, 7, 6, 8],
1080
+ [0, 3, 5, 3]]))
1081
+
1082
+ @pytest.mark.parametrize('order', range(0, 6))
1083
+ def test_shift07(self, order, xp):
1084
+ data = xp.asarray([[4, 1, 3, 2],
1085
+ [7, 6, 8, 5],
1086
+ [3, 5, 3, 6]])
1087
+ out = ndimage.shift(data, [1, 0], order=order)
1088
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
1089
+ [4, 1, 3, 2],
1090
+ [7, 6, 8, 5]]))
1091
+
1092
+ @pytest.mark.parametrize('order', range(0, 6))
1093
+ def test_shift08(self, order, xp):
1094
+ data = xp.asarray([[4, 1, 3, 2],
1095
+ [7, 6, 8, 5],
1096
+ [3, 5, 3, 6]])
1097
+ out = ndimage.shift(data, [1, 1], order=order)
1098
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
1099
+ [0, 4, 1, 3],
1100
+ [0, 7, 6, 8]]))
1101
+
1102
+ @pytest.mark.parametrize('order', range(0, 6))
1103
+ def test_shift09(self, order, xp):
1104
+ data = xp.asarray([[4, 1, 3, 2],
1105
+ [7, 6, 8, 5],
1106
+ [3, 5, 3, 6]])
1107
+ if (order > 1):
1108
+ filtered = ndimage.spline_filter(data, order=order)
1109
+ else:
1110
+ filtered = data
1111
+ out = ndimage.shift(filtered, [1, 1], order=order, prefilter=False)
1112
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0],
1113
+ [0, 4, 1, 3],
1114
+ [0, 7, 6, 8]]))
1115
+
1116
+ @pytest.mark.parametrize('shift',
1117
+ [(1, 0), (0, 1), (-1, 1), (3, -5), (2, 7)])
1118
+ @pytest.mark.parametrize('order', range(0, 6))
1119
+ def test_shift_grid_wrap(self, shift, order, xp):
1120
+ # For mode 'grid-wrap', integer shifts should match np.roll
1121
+ x = np.asarray([[0, 1],
1122
+ [2, 3]])
1123
+ expected = np.roll(x, shift, axis=(0,1))
1124
+
1125
+ x = xp.asarray(x)
1126
+ expected = xp.asarray(expected)
1127
+
1128
+ assert_array_almost_equal(
1129
+ ndimage.shift(x, shift, mode='grid-wrap', order=order),
1130
+ expected
1131
+ )
1132
+
1133
+ @pytest.mark.parametrize('shift',
1134
+ [(1, 0), (0, 1), (-1, 1), (3, -5), (2, 7)])
1135
+ @pytest.mark.parametrize('order', range(0, 6))
1136
+ def test_shift_grid_constant1(self, shift, order, xp):
1137
+ # For integer shifts, 'constant' and 'grid-constant' should be equal
1138
+ x = xp.reshape(xp.arange(20), (5, 4))
1139
+ assert_array_almost_equal(
1140
+ ndimage.shift(x, shift, mode='grid-constant', order=order),
1141
+ ndimage.shift(x, shift, mode='constant', order=order),
1142
+ )
1143
+
1144
+ def test_shift_grid_constant_order1(self, xp):
1145
+ x = xp.asarray([[1, 2, 3],
1146
+ [4, 5, 6]], dtype=xp.float64)
1147
+ expected_result = xp.asarray([[0.25, 0.75, 1.25],
1148
+ [1.25, 3.00, 4.00]])
1149
+ assert_array_almost_equal(
1150
+ ndimage.shift(x, (0.5, 0.5), mode='grid-constant', order=1),
1151
+ expected_result,
1152
+ )
1153
+
1154
+ @pytest.mark.parametrize('order', range(0, 6))
1155
+ def test_shift_reflect(self, order, xp):
1156
+ # shift by x.shape results in reflection
1157
+ x = np.asarray([[0, 1, 2],
1158
+ [3, 4, 5]])
1159
+ expected = x[::-1, ::-1].copy() # strides > 0 for torch
1160
+
1161
+ x = xp.asarray(x)
1162
+ expected = xp.asarray(expected)
1163
+ assert_array_almost_equal(
1164
+ ndimage.shift(x, x.shape, mode='reflect', order=order),
1165
+ expected,
1166
+ )
1167
+
1168
+ @pytest.mark.parametrize('order', range(0, 6))
1169
+ @pytest.mark.parametrize('prefilter', [False, True])
1170
+ def test_shift_nearest_boundary(self, order, prefilter, xp):
1171
+ # verify that shifting at least order // 2 beyond the end of the array
1172
+ # gives a value equal to the edge value.
1173
+ x = xp.arange(16)
1174
+ kwargs = dict(mode='nearest', order=order, prefilter=prefilter)
1175
+ assert_array_almost_equal(
1176
+ ndimage.shift(x, order // 2 + 1, **kwargs)[0], x[0],
1177
+ )
1178
+ assert_array_almost_equal(
1179
+ ndimage.shift(x, -order // 2 - 1, **kwargs)[-1], x[-1],
1180
+ )
1181
+
1182
+ @pytest.mark.parametrize('mode', ['grid-constant', 'grid-wrap', 'nearest',
1183
+ 'mirror', 'reflect'])
1184
+ @pytest.mark.parametrize('order', range(6))
1185
+ def test_shift_vs_padded(self, order, mode, xp):
1186
+ x_np = np.arange(144, dtype=float).reshape(12, 12)
1187
+ shift = (0.4, -2.3)
1188
+
1189
+ # manually pad and then extract center to get expected result
1190
+ npad = 32
1191
+ pad_mode = ndimage_to_numpy_mode.get(mode)
1192
+ x_padded = xp.asarray(np.pad(x_np, npad, mode=pad_mode))
1193
+ x = xp.asarray(x_np)
1194
+
1195
+ center_slice = tuple([slice(npad, -npad)] * x.ndim)
1196
+ expected_result = ndimage.shift(
1197
+ x_padded, shift, mode=mode, order=order)[center_slice]
1198
+
1199
+ xp_assert_close(
1200
+ ndimage.shift(x, shift, mode=mode, order=order),
1201
+ expected_result,
1202
+ rtol=1e-7,
1203
+ )
1204
+
1205
+
1206
+ class TestZoom:
1207
+
1208
+ @pytest.mark.parametrize('order', range(0, 6))
1209
+ def test_zoom1(self, order, xp):
1210
+ for z in [2, [2, 2]]:
1211
+ arr = xp.reshape(xp.arange(25, dtype=xp.float64), (5, 5))
1212
+ arr = ndimage.zoom(arr, z, order=order)
1213
+ assert arr.shape == (10, 10)
1214
+ assert xp.all(arr[-1, :] != 0)
1215
+ assert xp.all(arr[-1, :] >= (20 - eps))
1216
+ assert xp.all(arr[0, :] <= (5 + eps))
1217
+ assert xp.all(arr >= (0 - eps))
1218
+ assert xp.all(arr <= (24 + eps))
1219
+
1220
+ def test_zoom2(self, xp):
1221
+ arr = xp.reshape(xp.arange(12), (3, 4))
1222
+ out = ndimage.zoom(ndimage.zoom(arr, 2), 0.5)
1223
+ xp_assert_equal(out, arr)
1224
+
1225
+ def test_zoom3(self, xp):
1226
+ arr = xp.asarray([[1, 2]])
1227
+ out1 = ndimage.zoom(arr, (2, 1))
1228
+ out2 = ndimage.zoom(arr, (1, 2))
1229
+
1230
+ assert_array_almost_equal(out1, xp.asarray([[1, 2], [1, 2]]))
1231
+ assert_array_almost_equal(out2, xp.asarray([[1, 1, 2, 2]]))
1232
+
1233
+ @pytest.mark.parametrize('order', range(0, 6))
1234
+ @pytest.mark.parametrize('dtype', ["float64", "complex128"])
1235
+ def test_zoom_affine01(self, order, dtype, xp):
1236
+ dtype = getattr(xp, dtype)
1237
+ data = xp.asarray([[1, 2, 3, 4],
1238
+ [5, 6, 7, 8],
1239
+ [9, 10, 11, 12]], dtype=dtype)
1240
+ isdtype = array_namespace(data).isdtype
1241
+ if isdtype(data.dtype, 'complex floating'):
1242
+ data -= 1j * data
1243
+ with suppress_warnings() as sup:
1244
+ sup.filter(UserWarning,
1245
+ 'The behavior of affine_transform with a 1-D array .* '
1246
+ 'has changed')
1247
+ out = ndimage.affine_transform(data, xp.asarray([0.5, 0.5]), 0,
1248
+ (6, 8), order=order)
1249
+ assert_array_almost_equal(out[::2, ::2], data)
1250
+
1251
+ def test_zoom_infinity(self, xp):
1252
+ # Ticket #1419 regression test
1253
+ dim = 8
1254
+ ndimage.zoom(xp.zeros((dim, dim)), 1. / dim, mode='nearest')
1255
+
1256
+ def test_zoom_zoomfactor_one(self, xp):
1257
+ # Ticket #1122 regression test
1258
+ arr = xp.zeros((1, 5, 5))
1259
+ zoom = (1.0, 2.0, 2.0)
1260
+
1261
+ out = ndimage.zoom(arr, zoom, cval=7)
1262
+ ref = xp.zeros((1, 10, 10))
1263
+ assert_array_almost_equal(out, ref)
1264
+
1265
+ def test_zoom_output_shape_roundoff(self, xp):
1266
+ arr = xp.zeros((3, 11, 25))
1267
+ zoom = (4.0 / 3, 15.0 / 11, 29.0 / 25)
1268
+ out = ndimage.zoom(arr, zoom)
1269
+ assert out.shape == (4, 15, 29)
1270
+
1271
+ @pytest.mark.parametrize('zoom', [(1, 1), (3, 5), (8, 2), (8, 8)])
1272
+ @pytest.mark.parametrize('mode', ['nearest', 'constant', 'wrap', 'reflect',
1273
+ 'mirror', 'grid-wrap', 'grid-mirror',
1274
+ 'grid-constant'])
1275
+ def test_zoom_by_int_order0(self, zoom, mode, xp):
1276
+ # order 0 zoom should be the same as replication via np.kron
1277
+ # Note: This is not True for general x shapes when grid_mode is False,
1278
+ # but works here for all modes because the size ratio happens to
1279
+ # always be an integer when x.shape = (2, 2).
1280
+ x_np = np.asarray([[0, 1],
1281
+ [2, 3]], dtype=np.float64)
1282
+ expected = np.kron(x_np, np.ones(zoom))
1283
+
1284
+ x = xp.asarray(x_np)
1285
+ expected = xp.asarray(expected)
1286
+
1287
+ assert_array_almost_equal(
1288
+ ndimage.zoom(x, zoom, order=0, mode=mode),
1289
+ expected
1290
+ )
1291
+
1292
+ @pytest.mark.parametrize('shape', [(2, 3), (4, 4)])
1293
+ @pytest.mark.parametrize('zoom', [(1, 1), (3, 5), (8, 2), (8, 8)])
1294
+ @pytest.mark.parametrize('mode', ['nearest', 'reflect', 'mirror',
1295
+ 'grid-wrap', 'grid-constant'])
1296
+ def test_zoom_grid_by_int_order0(self, shape, zoom, mode, xp):
1297
+ # When grid_mode is True, order 0 zoom should be the same as
1298
+ # replication via np.kron. The only exceptions to this are the
1299
+ # non-grid modes 'constant' and 'wrap'.
1300
+ x_np = np.arange(np.prod(shape), dtype=float).reshape(shape)
1301
+
1302
+ x = xp.asarray(x_np)
1303
+ assert_array_almost_equal(
1304
+ ndimage.zoom(x, zoom, order=0, mode=mode, grid_mode=True),
1305
+ xp.asarray(np.kron(x_np, np.ones(zoom)))
1306
+ )
1307
+
1308
+ @pytest.mark.parametrize('mode', ['constant', 'wrap'])
1309
+ @pytest.mark.thread_unsafe
1310
+ def test_zoom_grid_mode_warnings(self, mode, xp):
1311
+ # Warn on use of non-grid modes when grid_mode is True
1312
+ x = xp.reshape(xp.arange(9, dtype=xp.float64), (3, 3))
1313
+ with pytest.warns(UserWarning,
1314
+ match="It is recommended to use mode"):
1315
+ ndimage.zoom(x, 2, mode=mode, grid_mode=True),
1316
+
1317
+ @skip_xp_backends(np_only=True, reason='inplace output= is numpy-specific')
1318
+ def test_zoom_output_shape(self, xp):
1319
+ """Ticket #643"""
1320
+ x = xp.reshape(xp.arange(12), (3, 4))
1321
+ ndimage.zoom(x, 2, output=xp.zeros((6, 8)))
1322
+
1323
+ def test_zoom_0d_array(self, xp):
1324
+ # Ticket #21670 regression test
1325
+ a = xp.arange(10.)
1326
+ factor = 2
1327
+ actual = ndimage.zoom(a, np.array(factor))
1328
+ expected = ndimage.zoom(a, factor)
1329
+ xp_assert_close(actual, expected)
1330
+
1331
+
1332
+ class TestRotate:
1333
+
1334
+ @pytest.mark.parametrize('order', range(0, 6))
1335
+ def test_rotate01(self, order, xp):
1336
+ data = xp.asarray([[0, 0, 0, 0],
1337
+ [0, 1, 1, 0],
1338
+ [0, 0, 0, 0]], dtype=xp.float64)
1339
+ out = ndimage.rotate(data, 0, order=order)
1340
+ assert_array_almost_equal(out, data)
1341
+
1342
+ @pytest.mark.parametrize('order', range(0, 6))
1343
+ def test_rotate02(self, order, xp):
1344
+ data = xp.asarray([[0, 0, 0, 0],
1345
+ [0, 1, 0, 0],
1346
+ [0, 0, 0, 0]], dtype=xp.float64)
1347
+ expected = xp.asarray([[0, 0, 0],
1348
+ [0, 0, 0],
1349
+ [0, 1, 0],
1350
+ [0, 0, 0]], dtype=xp.float64)
1351
+ out = ndimage.rotate(data, 90, order=order)
1352
+ assert_array_almost_equal(out, expected)
1353
+
1354
+ @pytest.mark.parametrize('order', range(0, 6))
1355
+ @pytest.mark.parametrize('dtype', ["float64", "complex128"])
1356
+ def test_rotate03(self, order, dtype, xp):
1357
+ dtype = getattr(xp, dtype)
1358
+ data = xp.asarray([[0, 0, 0, 0, 0],
1359
+ [0, 1, 1, 0, 0],
1360
+ [0, 0, 0, 0, 0]], dtype=dtype)
1361
+ expected = xp.asarray([[0, 0, 0],
1362
+ [0, 0, 0],
1363
+ [0, 1, 0],
1364
+ [0, 1, 0],
1365
+ [0, 0, 0]], dtype=dtype)
1366
+ isdtype = array_namespace(data).isdtype
1367
+ if isdtype(data.dtype, 'complex floating'):
1368
+ data -= 1j * data
1369
+ expected -= 1j * expected
1370
+ out = ndimage.rotate(data, 90, order=order)
1371
+ assert_array_almost_equal(out, expected)
1372
+
1373
+ @pytest.mark.parametrize('order', range(0, 6))
1374
+ def test_rotate04(self, order, xp):
1375
+ data = xp.asarray([[0, 0, 0, 0, 0],
1376
+ [0, 1, 1, 0, 0],
1377
+ [0, 0, 0, 0, 0]], dtype=xp.float64)
1378
+ expected = xp.asarray([[0, 0, 0, 0, 0],
1379
+ [0, 0, 1, 0, 0],
1380
+ [0, 0, 1, 0, 0]], dtype=xp.float64)
1381
+ out = ndimage.rotate(data, 90, reshape=False, order=order)
1382
+ assert_array_almost_equal(out, expected)
1383
+
1384
+ @pytest.mark.parametrize('order', range(0, 6))
1385
+ def test_rotate05(self, order, xp):
1386
+ data = np.empty((4, 3, 3))
1387
+ for i in range(3):
1388
+ data[:, :, i] = np.asarray([[0, 0, 0],
1389
+ [0, 1, 0],
1390
+ [0, 1, 0],
1391
+ [0, 0, 0]], dtype=np.float64)
1392
+ data = xp.asarray(data)
1393
+ expected = xp.asarray([[0, 0, 0, 0],
1394
+ [0, 1, 1, 0],
1395
+ [0, 0, 0, 0]], dtype=xp.float64)
1396
+ out = ndimage.rotate(data, 90, order=order)
1397
+ for i in range(3):
1398
+ assert_array_almost_equal(out[:, :, i], expected)
1399
+
1400
+ @pytest.mark.parametrize('order', range(0, 6))
1401
+ def test_rotate06(self, order, xp):
1402
+ data = np.empty((3, 4, 3))
1403
+ for i in range(3):
1404
+ data[:, :, i] = np.asarray([[0, 0, 0, 0],
1405
+ [0, 1, 1, 0],
1406
+ [0, 0, 0, 0]], dtype=np.float64)
1407
+ data = xp.asarray(data)
1408
+ expected = xp.asarray([[0, 0, 0],
1409
+ [0, 1, 0],
1410
+ [0, 1, 0],
1411
+ [0, 0, 0]], dtype=xp.float64)
1412
+ out = ndimage.rotate(data, 90, order=order)
1413
+ for i in range(3):
1414
+ assert_array_almost_equal(out[:, :, i], expected)
1415
+
1416
+ @pytest.mark.parametrize('order', range(0, 6))
1417
+ def test_rotate07(self, order, xp):
1418
+ data = xp.asarray([[[0, 0, 0, 0, 0],
1419
+ [0, 1, 1, 0, 0],
1420
+ [0, 0, 0, 0, 0]]] * 2, dtype=xp.float64)
1421
+ permute_dims = array_namespace(data).permute_dims
1422
+ data = permute_dims(data, (2, 1, 0))
1423
+ expected = xp.asarray([[[0, 0, 0],
1424
+ [0, 1, 0],
1425
+ [0, 1, 0],
1426
+ [0, 0, 0],
1427
+ [0, 0, 0]]] * 2, dtype=xp.float64)
1428
+ expected = permute_dims(expected, (2, 1, 0))
1429
+ out = ndimage.rotate(data, 90, axes=(0, 1), order=order)
1430
+ assert_array_almost_equal(out, expected)
1431
+
1432
+ @pytest.mark.parametrize('order', range(0, 6))
1433
+ def test_rotate08(self, order, xp):
1434
+ data = xp.asarray([[[0, 0, 0, 0, 0],
1435
+ [0, 1, 1, 0, 0],
1436
+ [0, 0, 0, 0, 0]]] * 2, dtype=xp.float64)
1437
+ permute_dims = array_namespace(data).permute_dims
1438
+ data = permute_dims(data, (2, 1, 0)) # == np.transpose
1439
+ expected = xp.asarray([[[0, 0, 1, 0, 0],
1440
+ [0, 0, 1, 0, 0],
1441
+ [0, 0, 0, 0, 0]]] * 2, dtype=xp.float64)
1442
+ permute_dims = array_namespace(data).permute_dims
1443
+ expected = permute_dims(expected, (2, 1, 0))
1444
+ out = ndimage.rotate(data, 90, axes=(0, 1), reshape=False, order=order)
1445
+ assert_array_almost_equal(out, expected)
1446
+
1447
+ def test_rotate09(self, xp):
1448
+ data = xp.asarray([[0, 0, 0, 0, 0],
1449
+ [0, 1, 1, 0, 0],
1450
+ [0, 0, 0, 0, 0]] * 2, dtype=xp.float64)
1451
+ with assert_raises(ValueError):
1452
+ ndimage.rotate(data, 90, axes=(0, data.ndim))
1453
+
1454
+ def test_rotate10(self, xp):
1455
+ data = xp.reshape(xp.arange(45, dtype=xp.float64), (3, 5, 3))
1456
+
1457
+ # The output of ndimage.rotate before refactoring
1458
+ expected = xp.asarray([[[0.0, 0.0, 0.0],
1459
+ [0.0, 0.0, 0.0],
1460
+ [6.54914793, 7.54914793, 8.54914793],
1461
+ [10.84520162, 11.84520162, 12.84520162],
1462
+ [0.0, 0.0, 0.0]],
1463
+ [[6.19286575, 7.19286575, 8.19286575],
1464
+ [13.4730712, 14.4730712, 15.4730712],
1465
+ [21.0, 22.0, 23.0],
1466
+ [28.5269288, 29.5269288, 30.5269288],
1467
+ [35.80713425, 36.80713425, 37.80713425]],
1468
+ [[0.0, 0.0, 0.0],
1469
+ [31.15479838, 32.15479838, 33.15479838],
1470
+ [35.45085207, 36.45085207, 37.45085207],
1471
+ [0.0, 0.0, 0.0],
1472
+ [0.0, 0.0, 0.0]]], dtype=xp.float64)
1473
+
1474
+ out = ndimage.rotate(data, angle=12, reshape=False)
1475
+ #assert_array_almost_equal(out, expected)
1476
+ xp_assert_close(out, expected, rtol=1e-6, atol=2e-6)
1477
+
1478
+ def test_rotate_exact_180(self, xp):
1479
+ if is_cupy(xp):
1480
+ pytest.xfail("https://github.com/cupy/cupy/issues/8400")
1481
+
1482
+ a = np.tile(xp.arange(5), (5, 1))
1483
+ b = ndimage.rotate(ndimage.rotate(a, 180), -180)
1484
+ xp_assert_equal(a, b)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_measurements.py ADDED
@@ -0,0 +1,1609 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import os.path
3
+
4
+ import numpy as np
5
+ from numpy.testing import suppress_warnings
6
+
7
+ from scipy._lib._array_api import (
8
+ is_jax,
9
+ is_torch,
10
+ array_namespace,
11
+ xp_assert_equal,
12
+ xp_assert_close,
13
+ assert_array_almost_equal,
14
+ assert_almost_equal,
15
+ )
16
+
17
+ import pytest
18
+ from pytest import raises as assert_raises
19
+
20
+ import scipy.ndimage as ndimage
21
+
22
+ from . import types
23
+
24
+ from scipy.conftest import array_api_compatible
25
+ skip_xp_backends = pytest.mark.skip_xp_backends
26
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends"),
27
+ skip_xp_backends(cpu_only=True, exceptions=['cupy', 'jax.numpy'],)]
28
+
29
+ IS_WINDOWS_AND_NP1 = os.name == 'nt' and np.__version__ < '2'
30
+
31
+
32
+ @skip_xp_backends(np_only=True, reason='test internal numpy-only helpers')
33
+ class Test_measurements_stats:
34
+ """ndimage._measurements._stats() is a utility used by other functions.
35
+
36
+ Since internal ndimage/_measurements.py code is NumPy-only,
37
+ so is this this test class.
38
+ """
39
+ def test_a(self, xp):
40
+ x = [0, 1, 2, 6]
41
+ labels = [0, 0, 1, 1]
42
+ index = [0, 1]
43
+ for shp in [(4,), (2, 2)]:
44
+ x = np.array(x).reshape(shp)
45
+ labels = np.array(labels).reshape(shp)
46
+ counts, sums = ndimage._measurements._stats(
47
+ x, labels=labels, index=index)
48
+
49
+ dtype_arg = {'dtype': np.int64} if IS_WINDOWS_AND_NP1 else {}
50
+ xp_assert_equal(counts, np.asarray([2, 2], **dtype_arg))
51
+ xp_assert_equal(sums, np.asarray([1.0, 8.0]))
52
+
53
+ def test_b(self, xp):
54
+ # Same data as test_a, but different labels. The label 9 exceeds the
55
+ # length of 'labels', so this test will follow a different code path.
56
+ x = [0, 1, 2, 6]
57
+ labels = [0, 0, 9, 9]
58
+ index = [0, 9]
59
+ for shp in [(4,), (2, 2)]:
60
+ x = np.array(x).reshape(shp)
61
+ labels = np.array(labels).reshape(shp)
62
+ counts, sums = ndimage._measurements._stats(
63
+ x, labels=labels, index=index)
64
+
65
+ dtype_arg = {'dtype': np.int64} if IS_WINDOWS_AND_NP1 else {}
66
+ xp_assert_equal(counts, np.asarray([2, 2], **dtype_arg))
67
+ xp_assert_equal(sums, np.asarray([1.0, 8.0]))
68
+
69
+ def test_a_centered(self, xp):
70
+ x = [0, 1, 2, 6]
71
+ labels = [0, 0, 1, 1]
72
+ index = [0, 1]
73
+ for shp in [(4,), (2, 2)]:
74
+ x = np.array(x).reshape(shp)
75
+ labels = np.array(labels).reshape(shp)
76
+ counts, sums, centers = ndimage._measurements._stats(
77
+ x, labels=labels, index=index, centered=True)
78
+
79
+ dtype_arg = {'dtype': np.int64} if IS_WINDOWS_AND_NP1 else {}
80
+ xp_assert_equal(counts, np.asarray([2, 2], **dtype_arg))
81
+ xp_assert_equal(sums, np.asarray([1.0, 8.0]))
82
+ xp_assert_equal(centers, np.asarray([0.5, 8.0]))
83
+
84
+ def test_b_centered(self, xp):
85
+ x = [0, 1, 2, 6]
86
+ labels = [0, 0, 9, 9]
87
+ index = [0, 9]
88
+ for shp in [(4,), (2, 2)]:
89
+ x = np.array(x).reshape(shp)
90
+ labels = np.array(labels).reshape(shp)
91
+ counts, sums, centers = ndimage._measurements._stats(
92
+ x, labels=labels, index=index, centered=True)
93
+
94
+ dtype_arg = {'dtype': np.int64} if IS_WINDOWS_AND_NP1 else {}
95
+ xp_assert_equal(counts, np.asarray([2, 2], **dtype_arg))
96
+ xp_assert_equal(sums, np.asarray([1.0, 8.0]))
97
+ xp_assert_equal(centers, np.asarray([0.5, 8.0]))
98
+
99
+ def test_nonint_labels(self, xp):
100
+ x = [0, 1, 2, 6]
101
+ labels = [0.0, 0.0, 9.0, 9.0]
102
+ index = [0.0, 9.0]
103
+ for shp in [(4,), (2, 2)]:
104
+ x = np.array(x).reshape(shp)
105
+ labels = np.array(labels).reshape(shp)
106
+ counts, sums, centers = ndimage._measurements._stats(
107
+ x, labels=labels, index=index, centered=True)
108
+
109
+ dtype_arg = {'dtype': np.int64} if IS_WINDOWS_AND_NP1 else {}
110
+ xp_assert_equal(counts, np.asarray([2, 2], **dtype_arg))
111
+ xp_assert_equal(sums, np.asarray([1.0, 8.0]))
112
+ xp_assert_equal(centers, np.asarray([0.5, 8.0]))
113
+
114
+
115
+ class Test_measurements_select:
116
+ """ndimage._measurements._select() is a utility used by other functions."""
117
+
118
+ def test_basic(self, xp):
119
+ x = [0, 1, 6, 2]
120
+ cases = [
121
+ ([0, 0, 1, 1], [0, 1]), # "Small" integer labels
122
+ ([0, 0, 9, 9], [0, 9]), # A label larger than len(labels)
123
+ ([0.0, 0.0, 7.0, 7.0], [0.0, 7.0]), # Non-integer labels
124
+ ]
125
+ for labels, index in cases:
126
+ result = ndimage._measurements._select(
127
+ x, labels=labels, index=index)
128
+ assert len(result) == 0
129
+ result = ndimage._measurements._select(
130
+ x, labels=labels, index=index, find_max=True)
131
+ assert len(result) == 1
132
+ xp_assert_equal(result[0], [1, 6])
133
+ result = ndimage._measurements._select(
134
+ x, labels=labels, index=index, find_min=True)
135
+ assert len(result) == 1
136
+ xp_assert_equal(result[0], [0, 2])
137
+ result = ndimage._measurements._select(
138
+ x, labels=labels, index=index, find_min=True,
139
+ find_min_positions=True)
140
+ assert len(result) == 2
141
+ xp_assert_equal(result[0], [0, 2])
142
+ xp_assert_equal(result[1], [0, 3])
143
+ assert result[1].dtype.kind == 'i'
144
+ result = ndimage._measurements._select(
145
+ x, labels=labels, index=index, find_max=True,
146
+ find_max_positions=True)
147
+ assert len(result) == 2
148
+ xp_assert_equal(result[0], [1, 6])
149
+ xp_assert_equal(result[1], [1, 2])
150
+ assert result[1].dtype.kind == 'i'
151
+
152
+
153
+ def test_label01(xp):
154
+ data = xp.ones([])
155
+ out, n = ndimage.label(data)
156
+ assert out == 1
157
+ assert n == 1
158
+
159
+
160
+ def test_label02(xp):
161
+ data = xp.zeros([])
162
+ out, n = ndimage.label(data)
163
+ assert out == 0
164
+ assert n == 0
165
+
166
+
167
+ @pytest.mark.thread_unsafe # due to Cython fused types, see cython#6506
168
+ def test_label03(xp):
169
+ data = xp.ones([1])
170
+ out, n = ndimage.label(data)
171
+ assert_array_almost_equal(out, xp.asarray([1]))
172
+ assert n == 1
173
+
174
+
175
+ def test_label04(xp):
176
+ data = xp.zeros([1])
177
+ out, n = ndimage.label(data)
178
+ assert_array_almost_equal(out, xp.asarray([0]))
179
+ assert n == 0
180
+
181
+
182
+ def test_label05(xp):
183
+ data = xp.ones([5])
184
+ out, n = ndimage.label(data)
185
+ assert_array_almost_equal(out, xp.asarray([1, 1, 1, 1, 1]))
186
+ assert n == 1
187
+
188
+
189
+ def test_label06(xp):
190
+ data = xp.asarray([1, 0, 1, 1, 0, 1])
191
+ out, n = ndimage.label(data)
192
+ assert_array_almost_equal(out, xp.asarray([1, 0, 2, 2, 0, 3]))
193
+ assert n == 3
194
+
195
+
196
+ def test_label07(xp):
197
+ data = xp.asarray([[0, 0, 0, 0, 0, 0],
198
+ [0, 0, 0, 0, 0, 0],
199
+ [0, 0, 0, 0, 0, 0],
200
+ [0, 0, 0, 0, 0, 0],
201
+ [0, 0, 0, 0, 0, 0],
202
+ [0, 0, 0, 0, 0, 0]])
203
+ out, n = ndimage.label(data)
204
+ assert_array_almost_equal(out, xp.asarray(
205
+ [[0, 0, 0, 0, 0, 0],
206
+ [0, 0, 0, 0, 0, 0],
207
+ [0, 0, 0, 0, 0, 0],
208
+ [0, 0, 0, 0, 0, 0],
209
+ [0, 0, 0, 0, 0, 0],
210
+ [0, 0, 0, 0, 0, 0]]))
211
+ assert n == 0
212
+
213
+
214
+ def test_label08(xp):
215
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
216
+ [0, 0, 1, 1, 0, 0],
217
+ [0, 0, 1, 1, 1, 0],
218
+ [1, 1, 0, 0, 0, 0],
219
+ [1, 1, 0, 0, 0, 0],
220
+ [0, 0, 0, 1, 1, 0]])
221
+ out, n = ndimage.label(data)
222
+ assert_array_almost_equal(out, xp.asarray([[1, 0, 0, 0, 0, 0],
223
+ [0, 0, 2, 2, 0, 0],
224
+ [0, 0, 2, 2, 2, 0],
225
+ [3, 3, 0, 0, 0, 0],
226
+ [3, 3, 0, 0, 0, 0],
227
+ [0, 0, 0, 4, 4, 0]]))
228
+ assert n == 4
229
+
230
+
231
+ def test_label09(xp):
232
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
233
+ [0, 0, 1, 1, 0, 0],
234
+ [0, 0, 1, 1, 1, 0],
235
+ [1, 1, 0, 0, 0, 0],
236
+ [1, 1, 0, 0, 0, 0],
237
+ [0, 0, 0, 1, 1, 0]])
238
+ struct = ndimage.generate_binary_structure(2, 2)
239
+ struct = xp.asarray(struct)
240
+ out, n = ndimage.label(data, struct)
241
+ assert_array_almost_equal(out, xp.asarray([[1, 0, 0, 0, 0, 0],
242
+ [0, 0, 2, 2, 0, 0],
243
+ [0, 0, 2, 2, 2, 0],
244
+ [2, 2, 0, 0, 0, 0],
245
+ [2, 2, 0, 0, 0, 0],
246
+ [0, 0, 0, 3, 3, 0]]))
247
+ assert n == 3
248
+
249
+
250
+ def test_label10(xp):
251
+ data = xp.asarray([[0, 0, 0, 0, 0, 0],
252
+ [0, 1, 1, 0, 1, 0],
253
+ [0, 1, 1, 1, 1, 0],
254
+ [0, 0, 0, 0, 0, 0]])
255
+ struct = ndimage.generate_binary_structure(2, 2)
256
+ struct = xp.asarray(struct)
257
+ out, n = ndimage.label(data, struct)
258
+ assert_array_almost_equal(out, xp.asarray([[0, 0, 0, 0, 0, 0],
259
+ [0, 1, 1, 0, 1, 0],
260
+ [0, 1, 1, 1, 1, 0],
261
+ [0, 0, 0, 0, 0, 0]]))
262
+ assert n == 1
263
+
264
+
265
+ def test_label11(xp):
266
+ for type in types:
267
+ dtype = getattr(xp, type)
268
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
269
+ [0, 0, 1, 1, 0, 0],
270
+ [0, 0, 1, 1, 1, 0],
271
+ [1, 1, 0, 0, 0, 0],
272
+ [1, 1, 0, 0, 0, 0],
273
+ [0, 0, 0, 1, 1, 0]], dtype=dtype)
274
+ out, n = ndimage.label(data)
275
+ expected = [[1, 0, 0, 0, 0, 0],
276
+ [0, 0, 2, 2, 0, 0],
277
+ [0, 0, 2, 2, 2, 0],
278
+ [3, 3, 0, 0, 0, 0],
279
+ [3, 3, 0, 0, 0, 0],
280
+ [0, 0, 0, 4, 4, 0]]
281
+ expected = xp.asarray(expected)
282
+ assert_array_almost_equal(out, expected)
283
+ assert n == 4
284
+
285
+
286
+ @skip_xp_backends(np_only=True, reason='inplace output is numpy-specific')
287
+ def test_label11_inplace(xp):
288
+ for type in types:
289
+ dtype = getattr(xp, type)
290
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
291
+ [0, 0, 1, 1, 0, 0],
292
+ [0, 0, 1, 1, 1, 0],
293
+ [1, 1, 0, 0, 0, 0],
294
+ [1, 1, 0, 0, 0, 0],
295
+ [0, 0, 0, 1, 1, 0]], dtype=dtype)
296
+ n = ndimage.label(data, output=data)
297
+ expected = [[1, 0, 0, 0, 0, 0],
298
+ [0, 0, 2, 2, 0, 0],
299
+ [0, 0, 2, 2, 2, 0],
300
+ [3, 3, 0, 0, 0, 0],
301
+ [3, 3, 0, 0, 0, 0],
302
+ [0, 0, 0, 4, 4, 0]]
303
+ expected = xp.asarray(expected)
304
+ assert_array_almost_equal(data, expected)
305
+ assert n == 4
306
+
307
+
308
+ def test_label12(xp):
309
+ for type in types:
310
+ dtype = getattr(xp, type)
311
+ data = xp.asarray([[0, 0, 0, 0, 1, 1],
312
+ [0, 0, 0, 0, 0, 1],
313
+ [0, 0, 1, 0, 1, 1],
314
+ [0, 0, 1, 1, 1, 1],
315
+ [0, 0, 0, 1, 1, 0]], dtype=dtype)
316
+ out, n = ndimage.label(data)
317
+ expected = [[0, 0, 0, 0, 1, 1],
318
+ [0, 0, 0, 0, 0, 1],
319
+ [0, 0, 1, 0, 1, 1],
320
+ [0, 0, 1, 1, 1, 1],
321
+ [0, 0, 0, 1, 1, 0]]
322
+ expected = xp.asarray(expected)
323
+ assert_array_almost_equal(out, expected)
324
+ assert n == 1
325
+
326
+
327
+ def test_label13(xp):
328
+ for type in types:
329
+ dtype = getattr(xp, type)
330
+ data = xp.asarray([[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
331
+ [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
332
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
333
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
334
+ dtype=dtype)
335
+ out, n = ndimage.label(data)
336
+ expected = [[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1],
337
+ [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
338
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
339
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
340
+ expected = xp.asarray(expected)
341
+ assert_array_almost_equal(out, expected)
342
+ assert n == 1
343
+
344
+
345
+ @skip_xp_backends(np_only=True, reason='output=dtype is numpy-specific')
346
+ def test_label_output_typed(xp):
347
+ data = xp.ones([5])
348
+ for t in types:
349
+ dtype = getattr(xp, t)
350
+ output = xp.zeros([5], dtype=dtype)
351
+ n = ndimage.label(data, output=output)
352
+ assert_array_almost_equal(output,
353
+ xp.ones(output.shape, dtype=output.dtype))
354
+ assert n == 1
355
+
356
+
357
+ @skip_xp_backends(np_only=True, reason='output=dtype is numpy-specific')
358
+ def test_label_output_dtype(xp):
359
+ data = xp.ones([5])
360
+ for t in types:
361
+ dtype = getattr(xp, t)
362
+ output, n = ndimage.label(data, output=dtype)
363
+ assert_array_almost_equal(output,
364
+ xp.ones(output.shape, dtype=output.dtype))
365
+ assert output.dtype == t
366
+
367
+
368
+ def test_label_output_wrong_size(xp):
369
+ if is_jax(xp):
370
+ pytest.xfail("JAX does not raise")
371
+
372
+ data = xp.ones([5])
373
+ for t in types:
374
+ dtype = getattr(xp, t)
375
+ output = xp.zeros([10], dtype=dtype)
376
+ # TypeError is from non-numpy arrays as output
377
+ assert_raises((ValueError, TypeError),
378
+ ndimage.label, data, output=output)
379
+
380
+
381
+ def test_label_structuring_elements(xp):
382
+ data = np.loadtxt(os.path.join(os.path.dirname(
383
+ __file__), "data", "label_inputs.txt"))
384
+ strels = np.loadtxt(os.path.join(
385
+ os.path.dirname(__file__), "data", "label_strels.txt"))
386
+ results = np.loadtxt(os.path.join(
387
+ os.path.dirname(__file__), "data", "label_results.txt"))
388
+ data = data.reshape((-1, 7, 7))
389
+ strels = strels.reshape((-1, 3, 3))
390
+ results = results.reshape((-1, 7, 7))
391
+
392
+ data = xp.asarray(data)
393
+ strels = xp.asarray(strels)
394
+ results = xp.asarray(results)
395
+ r = 0
396
+ for i in range(data.shape[0]):
397
+ d = data[i, :, :]
398
+ for j in range(strels.shape[0]):
399
+ s = strels[j, :, :]
400
+ xp_assert_equal(ndimage.label(d, s)[0], results[r, :, :], check_dtype=False)
401
+ r += 1
402
+
403
+ @skip_xp_backends("cupy",
404
+ reason="`cupyx.scipy.ndimage` does not have `find_objects`"
405
+ )
406
+ def test_ticket_742(xp):
407
+ def SE(img, thresh=.7, size=4):
408
+ mask = img > thresh
409
+ rank = len(mask.shape)
410
+ struct = ndimage.generate_binary_structure(rank, rank)
411
+ struct = xp.asarray(struct)
412
+ la, co = ndimage.label(mask,
413
+ struct)
414
+ _ = ndimage.find_objects(la)
415
+
416
+ if np.dtype(np.intp) != np.dtype('i'):
417
+ shape = (3, 1240, 1240)
418
+ a = np.random.rand(np.prod(shape)).reshape(shape)
419
+ a = xp.asarray(a)
420
+ # shouldn't crash
421
+ SE(a)
422
+
423
+
424
+ def test_gh_issue_3025(xp):
425
+ """Github issue #3025 - improper merging of labels"""
426
+ d = np.zeros((60, 320))
427
+ d[:, :257] = 1
428
+ d[:, 260:] = 1
429
+ d[36, 257] = 1
430
+ d[35, 258] = 1
431
+ d[35, 259] = 1
432
+ d = xp.asarray(d)
433
+ assert ndimage.label(d, xp.ones((3, 3)))[1] == 1
434
+
435
+
436
+ @skip_xp_backends("cupy", reason="cupyx.scipy.ndimage does not have find_object")
437
+ class TestFindObjects:
438
+ def test_label_default_dtype(self, xp):
439
+ test_array = np.random.rand(10, 10)
440
+ test_array = xp.asarray(test_array)
441
+ label, no_features = ndimage.label(test_array > 0.5)
442
+ assert label.dtype in (xp.int32, xp.int64)
443
+ # Shouldn't raise an exception
444
+ ndimage.find_objects(label)
445
+
446
+
447
+ def test_find_objects01(self, xp):
448
+ data = xp.ones([], dtype=xp.int64)
449
+ out = ndimage.find_objects(data)
450
+ assert out == [()]
451
+
452
+
453
+ def test_find_objects02(self, xp):
454
+ data = xp.zeros([], dtype=xp.int64)
455
+ out = ndimage.find_objects(data)
456
+ assert out == []
457
+
458
+
459
+ def test_find_objects03(self, xp):
460
+ data = xp.ones([1], dtype=xp.int64)
461
+ out = ndimage.find_objects(data)
462
+ assert out == [(slice(0, 1, None),)]
463
+
464
+
465
+ def test_find_objects04(self, xp):
466
+ data = xp.zeros([1], dtype=xp.int64)
467
+ out = ndimage.find_objects(data)
468
+ assert out == []
469
+
470
+
471
+ def test_find_objects05(self, xp):
472
+ data = xp.ones([5], dtype=xp.int64)
473
+ out = ndimage.find_objects(data)
474
+ assert out == [(slice(0, 5, None),)]
475
+
476
+
477
+ def test_find_objects06(self, xp):
478
+ data = xp.asarray([1, 0, 2, 2, 0, 3])
479
+ out = ndimage.find_objects(data)
480
+ assert out == [(slice(0, 1, None),),
481
+ (slice(2, 4, None),),
482
+ (slice(5, 6, None),)]
483
+
484
+
485
+ def test_find_objects07(self, xp):
486
+ data = xp.asarray([[0, 0, 0, 0, 0, 0],
487
+ [0, 0, 0, 0, 0, 0],
488
+ [0, 0, 0, 0, 0, 0],
489
+ [0, 0, 0, 0, 0, 0],
490
+ [0, 0, 0, 0, 0, 0],
491
+ [0, 0, 0, 0, 0, 0]])
492
+ out = ndimage.find_objects(data)
493
+ assert out == []
494
+
495
+
496
+ def test_find_objects08(self, xp):
497
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
498
+ [0, 0, 2, 2, 0, 0],
499
+ [0, 0, 2, 2, 2, 0],
500
+ [3, 3, 0, 0, 0, 0],
501
+ [3, 3, 0, 0, 0, 0],
502
+ [0, 0, 0, 4, 4, 0]])
503
+ out = ndimage.find_objects(data)
504
+ assert out == [(slice(0, 1, None), slice(0, 1, None)),
505
+ (slice(1, 3, None), slice(2, 5, None)),
506
+ (slice(3, 5, None), slice(0, 2, None)),
507
+ (slice(5, 6, None), slice(3, 5, None))]
508
+
509
+
510
+ def test_find_objects09(self, xp):
511
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
512
+ [0, 0, 2, 2, 0, 0],
513
+ [0, 0, 2, 2, 2, 0],
514
+ [0, 0, 0, 0, 0, 0],
515
+ [0, 0, 0, 0, 0, 0],
516
+ [0, 0, 0, 4, 4, 0]])
517
+ out = ndimage.find_objects(data)
518
+ assert out == [(slice(0, 1, None), slice(0, 1, None)),
519
+ (slice(1, 3, None), slice(2, 5, None)),
520
+ None,
521
+ (slice(5, 6, None), slice(3, 5, None))]
522
+
523
+
524
+ def test_value_indices01(xp):
525
+ "Test dictionary keys and entries"
526
+ data = xp.asarray([[1, 0, 0, 0, 0, 0],
527
+ [0, 0, 2, 2, 0, 0],
528
+ [0, 0, 2, 2, 2, 0],
529
+ [0, 0, 0, 0, 0, 0],
530
+ [0, 0, 0, 0, 0, 0],
531
+ [0, 0, 0, 4, 4, 0]])
532
+ vi = ndimage.value_indices(data, ignore_value=0)
533
+ true_keys = [1, 2, 4]
534
+ assert list(vi.keys()) == true_keys
535
+
536
+ nnz_kwd = {'as_tuple': True} if is_torch(xp) else {}
537
+
538
+ truevi = {}
539
+ for k in true_keys:
540
+ truevi[k] = xp.nonzero(data == k, **nnz_kwd)
541
+
542
+ vi = ndimage.value_indices(data, ignore_value=0)
543
+ assert vi.keys() == truevi.keys()
544
+ for key in vi.keys():
545
+ assert len(vi[key]) == len(truevi[key])
546
+ for v, true_v in zip(vi[key], truevi[key]):
547
+ xp_assert_equal(v, true_v)
548
+
549
+
550
+ def test_value_indices02(xp):
551
+ "Test input checking"
552
+ data = xp.zeros((5, 4), dtype=xp.float32)
553
+ msg = "Parameter 'arr' must be an integer array"
554
+ with assert_raises(ValueError, match=msg):
555
+ ndimage.value_indices(data)
556
+
557
+
558
+ def test_value_indices03(xp):
559
+ "Test different input array shapes, from 1-D to 4-D"
560
+ for shape in [(36,), (18, 2), (3, 3, 4), (3, 3, 2, 2)]:
561
+ a = xp.asarray((12*[1]+12*[2]+12*[3]), dtype=xp.int32)
562
+ a = xp.reshape(a, shape)
563
+
564
+ nnz_kwd = {'as_tuple': True} if is_torch(xp) else {}
565
+
566
+ unique_values = array_namespace(a).unique_values
567
+ trueKeys = unique_values(a)
568
+ vi = ndimage.value_indices(a)
569
+ assert list(vi.keys()) == list(trueKeys)
570
+ for k in [int(x) for x in trueKeys]:
571
+ trueNdx = xp.nonzero(a == k, **nnz_kwd)
572
+ assert len(vi[k]) == len(trueNdx)
573
+ for vik, true_vik in zip(vi[k], trueNdx):
574
+ xp_assert_equal(vik, true_vik)
575
+
576
+
577
+ def test_sum01(xp):
578
+ for type in types:
579
+ dtype = getattr(xp, type)
580
+ input = xp.asarray([], dtype=dtype)
581
+ output = ndimage.sum(input)
582
+ assert output == 0
583
+
584
+
585
+ def test_sum02(xp):
586
+ for type in types:
587
+ dtype = getattr(xp, type)
588
+ input = xp.zeros([0, 4], dtype=dtype)
589
+ output = ndimage.sum(input)
590
+ assert output == 0
591
+
592
+
593
+ def test_sum03(xp):
594
+ for type in types:
595
+ dtype = getattr(xp, type)
596
+ input = xp.ones([], dtype=dtype)
597
+ output = ndimage.sum(input)
598
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
599
+
600
+
601
+ def test_sum04(xp):
602
+ for type in types:
603
+ dtype = getattr(xp, type)
604
+ input = xp.asarray([1, 2], dtype=dtype)
605
+ output = ndimage.sum(input)
606
+ assert_almost_equal(output, xp.asarray(3.0), check_0d=False)
607
+
608
+
609
+ def test_sum05(xp):
610
+ for type in types:
611
+ dtype = getattr(xp, type)
612
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
613
+ output = ndimage.sum(input)
614
+ assert_almost_equal(output, xp.asarray(10.0), check_0d=False)
615
+
616
+
617
+ def test_sum06(xp):
618
+ labels = np.asarray([], dtype=bool)
619
+ labels = xp.asarray(labels)
620
+ for type in types:
621
+ dtype = getattr(xp, type)
622
+ input = xp.asarray([], dtype=dtype)
623
+ output = ndimage.sum(input, labels=labels)
624
+ assert output == 0
625
+
626
+
627
+ def test_sum07(xp):
628
+ labels = np.ones([0, 4], dtype=bool)
629
+ labels = xp.asarray(labels)
630
+ for type in types:
631
+ dtype = getattr(xp, type)
632
+ input = xp.zeros([0, 4], dtype=dtype)
633
+ output = ndimage.sum(input, labels=labels)
634
+ assert output == 0
635
+
636
+
637
+ def test_sum08(xp):
638
+ labels = np.asarray([1, 0], dtype=bool)
639
+ labels = xp.asarray(labels)
640
+ for type in types:
641
+ dtype = getattr(xp, type)
642
+ input = xp.asarray([1, 2], dtype=dtype)
643
+ output = ndimage.sum(input, labels=labels)
644
+ assert output == 1
645
+
646
+
647
+ def test_sum09(xp):
648
+ labels = np.asarray([1, 0], dtype=bool)
649
+ labels = xp.asarray(labels)
650
+ for type in types:
651
+ dtype = getattr(xp, type)
652
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
653
+ output = ndimage.sum(input, labels=labels)
654
+ assert_almost_equal(output, xp.asarray(4.0), check_0d=False)
655
+
656
+
657
+ def test_sum10(xp):
658
+ labels = np.asarray([1, 0], dtype=bool)
659
+ input = np.asarray([[1, 2], [3, 4]], dtype=bool)
660
+
661
+ labels = xp.asarray(labels)
662
+ input = xp.asarray(input)
663
+ output = ndimage.sum(input, labels=labels)
664
+ assert_almost_equal(output, xp.asarray(2.0), check_0d=False)
665
+
666
+
667
+ def test_sum11(xp):
668
+ labels = xp.asarray([1, 2], dtype=xp.int8)
669
+ for type in types:
670
+ dtype = getattr(xp, type)
671
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
672
+ output = ndimage.sum(input, labels=labels,
673
+ index=2)
674
+ assert_almost_equal(output, xp.asarray(6.0), check_0d=False)
675
+
676
+
677
+ def test_sum12(xp):
678
+ labels = xp.asarray([[1, 2], [2, 4]], dtype=xp.int8)
679
+ for type in types:
680
+ dtype = getattr(xp, type)
681
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
682
+ output = ndimage.sum(input, labels=labels, index=xp.asarray([4, 8, 2]))
683
+ assert_array_almost_equal(output, xp.asarray([4.0, 0.0, 5.0]))
684
+
685
+
686
+ def test_sum_labels(xp):
687
+ labels = xp.asarray([[1, 2], [2, 4]], dtype=xp.int8)
688
+ for type in types:
689
+ dtype = getattr(xp, type)
690
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
691
+ output_sum = ndimage.sum(input, labels=labels, index=xp.asarray([4, 8, 2]))
692
+ output_labels = ndimage.sum_labels(
693
+ input, labels=labels, index=xp.asarray([4, 8, 2]))
694
+
695
+ assert xp.all(output_sum == output_labels)
696
+ assert_array_almost_equal(output_labels, xp.asarray([4.0, 0.0, 5.0]))
697
+
698
+
699
+ def test_mean01(xp):
700
+ labels = np.asarray([1, 0], dtype=bool)
701
+ labels = xp.asarray(labels)
702
+ for type in types:
703
+ dtype = getattr(xp, type)
704
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
705
+ output = ndimage.mean(input, labels=labels)
706
+ assert_almost_equal(output, xp.asarray(2.0), check_0d=False)
707
+
708
+
709
+ def test_mean02(xp):
710
+ labels = np.asarray([1, 0], dtype=bool)
711
+ input = np.asarray([[1, 2], [3, 4]], dtype=bool)
712
+
713
+ labels = xp.asarray(labels)
714
+ input = xp.asarray(input)
715
+ output = ndimage.mean(input, labels=labels)
716
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
717
+
718
+
719
+ def test_mean03(xp):
720
+ labels = xp.asarray([1, 2])
721
+ for type in types:
722
+ dtype = getattr(xp, type)
723
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
724
+ output = ndimage.mean(input, labels=labels,
725
+ index=2)
726
+ assert_almost_equal(output, xp.asarray(3.0), check_0d=False)
727
+
728
+
729
+ def test_mean04(xp):
730
+ labels = xp.asarray([[1, 2], [2, 4]], dtype=xp.int8)
731
+ with np.errstate(all='ignore'):
732
+ for type in types:
733
+ dtype = getattr(xp, type)
734
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
735
+ output = ndimage.mean(input, labels=labels,
736
+ index=xp.asarray([4, 8, 2]))
737
+ # XXX: output[[0, 2]] does not work in array-api-strict; annoying
738
+ # assert_array_almost_equal(output[[0, 2]], xp.asarray([4.0, 2.5]))
739
+ assert output[0] == 4.0
740
+ assert output[2] == 2.5
741
+ assert xp.isnan(output[1])
742
+
743
+
744
+ def test_minimum01(xp):
745
+ labels = np.asarray([1, 0], dtype=bool)
746
+ labels = xp.asarray(labels)
747
+ for type in types:
748
+ dtype = getattr(xp, type)
749
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
750
+ output = ndimage.minimum(input, labels=labels)
751
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
752
+
753
+
754
+ def test_minimum02(xp):
755
+ labels = np.asarray([1, 0], dtype=bool)
756
+ input = np.asarray([[2, 2], [2, 4]], dtype=bool)
757
+
758
+ labels = xp.asarray(labels)
759
+ input = xp.asarray(input)
760
+ output = ndimage.minimum(input, labels=labels)
761
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
762
+
763
+
764
+ def test_minimum03(xp):
765
+ labels = xp.asarray([1, 2])
766
+ for type in types:
767
+ dtype = getattr(xp, type)
768
+
769
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
770
+ output = ndimage.minimum(input, labels=labels,
771
+ index=2)
772
+ assert_almost_equal(output, xp.asarray(2.0), check_0d=False)
773
+
774
+
775
+ def test_minimum04(xp):
776
+ labels = xp.asarray([[1, 2], [2, 3]])
777
+ for type in types:
778
+ dtype = getattr(xp, type)
779
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
780
+ output = ndimage.minimum(input, labels=labels,
781
+ index=xp.asarray([2, 3, 8]))
782
+ assert_array_almost_equal(output, xp.asarray([2.0, 4.0, 0.0]))
783
+
784
+
785
+ def test_maximum01(xp):
786
+ labels = np.asarray([1, 0], dtype=bool)
787
+ labels = xp.asarray(labels)
788
+ for type in types:
789
+ dtype = getattr(xp, type)
790
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
791
+ output = ndimage.maximum(input, labels=labels)
792
+ assert_almost_equal(output, xp.asarray(3.0), check_0d=False)
793
+
794
+
795
+ def test_maximum02(xp):
796
+ labels = np.asarray([1, 0], dtype=bool)
797
+ input = np.asarray([[2, 2], [2, 4]], dtype=bool)
798
+ labels = xp.asarray(labels)
799
+ input = xp.asarray(input)
800
+ output = ndimage.maximum(input, labels=labels)
801
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
802
+
803
+
804
+ def test_maximum03(xp):
805
+ labels = xp.asarray([1, 2])
806
+ for type in types:
807
+ dtype = getattr(xp, type)
808
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
809
+ output = ndimage.maximum(input, labels=labels,
810
+ index=2)
811
+ assert_almost_equal(output, xp.asarray(4.0), check_0d=False)
812
+
813
+
814
+ def test_maximum04(xp):
815
+ labels = xp.asarray([[1, 2], [2, 3]])
816
+ for type in types:
817
+ dtype = getattr(xp, type)
818
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
819
+ output = ndimage.maximum(input, labels=labels,
820
+ index=xp.asarray([2, 3, 8]))
821
+ assert_array_almost_equal(output, xp.asarray([3.0, 4.0, 0.0]))
822
+
823
+
824
+ def test_maximum05(xp):
825
+ # Regression test for ticket #501 (Trac)
826
+ x = xp.asarray([-3, -2, -1])
827
+ assert ndimage.maximum(x) == -1
828
+
829
+
830
+ def test_median01(xp):
831
+ a = xp.asarray([[1, 2, 0, 1],
832
+ [5, 3, 0, 4],
833
+ [0, 0, 0, 7],
834
+ [9, 3, 0, 0]])
835
+ labels = xp.asarray([[1, 1, 0, 2],
836
+ [1, 1, 0, 2],
837
+ [0, 0, 0, 2],
838
+ [3, 3, 0, 0]])
839
+ output = ndimage.median(a, labels=labels, index=xp.asarray([1, 2, 3]))
840
+ assert_array_almost_equal(output, xp.asarray([2.5, 4.0, 6.0]))
841
+
842
+
843
+ def test_median02(xp):
844
+ a = xp.asarray([[1, 2, 0, 1],
845
+ [5, 3, 0, 4],
846
+ [0, 0, 0, 7],
847
+ [9, 3, 0, 0]])
848
+ output = ndimage.median(a)
849
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
850
+
851
+
852
+ def test_median03(xp):
853
+ a = xp.asarray([[1, 2, 0, 1],
854
+ [5, 3, 0, 4],
855
+ [0, 0, 0, 7],
856
+ [9, 3, 0, 0]])
857
+ labels = xp.asarray([[1, 1, 0, 2],
858
+ [1, 1, 0, 2],
859
+ [0, 0, 0, 2],
860
+ [3, 3, 0, 0]])
861
+ output = ndimage.median(a, labels=labels)
862
+ assert_almost_equal(output, xp.asarray(3.0), check_0d=False)
863
+
864
+
865
+ def test_median_gh12836_bool(xp):
866
+ # test boolean addition fix on example from gh-12836
867
+ a = np.asarray([1, 1], dtype=bool)
868
+ a = xp.asarray(a)
869
+ output = ndimage.median(a, labels=xp.ones((2,)), index=xp.asarray([1]))
870
+ assert_array_almost_equal(output, xp.asarray([1.0]))
871
+
872
+
873
+ def test_median_no_int_overflow(xp):
874
+ # test integer overflow fix on example from gh-12836
875
+ a = xp.asarray([65, 70], dtype=xp.int8)
876
+ output = ndimage.median(a, labels=xp.ones((2,)), index=xp.asarray([1]))
877
+ assert_array_almost_equal(output, xp.asarray([67.5]))
878
+
879
+
880
+ def test_variance01(xp):
881
+ with np.errstate(all='ignore'):
882
+ for type in types:
883
+ dtype = getattr(xp, type)
884
+ input = xp.asarray([], dtype=dtype)
885
+ with suppress_warnings() as sup:
886
+ sup.filter(RuntimeWarning, "Mean of empty slice")
887
+ output = ndimage.variance(input)
888
+ assert xp.isnan(output)
889
+
890
+
891
+ def test_variance02(xp):
892
+ for type in types:
893
+ dtype = getattr(xp, type)
894
+ input = xp.asarray([1], dtype=dtype)
895
+ output = ndimage.variance(input)
896
+ assert_almost_equal(output, xp.asarray(0.0), check_0d=False)
897
+
898
+
899
+ def test_variance03(xp):
900
+ for type in types:
901
+ dtype = getattr(xp, type)
902
+ input = xp.asarray([1, 3], dtype=dtype)
903
+ output = ndimage.variance(input)
904
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
905
+
906
+
907
+ def test_variance04(xp):
908
+ input = np.asarray([1, 0], dtype=bool)
909
+ input = xp.asarray(input)
910
+ output = ndimage.variance(input)
911
+ assert_almost_equal(output, xp.asarray(0.25), check_0d=False)
912
+
913
+
914
+ def test_variance05(xp):
915
+ labels = xp.asarray([2, 2, 3])
916
+ for type in types:
917
+ dtype = getattr(xp, type)
918
+
919
+ input = xp.asarray([1, 3, 8], dtype=dtype)
920
+ output = ndimage.variance(input, labels, 2)
921
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
922
+
923
+
924
+ def test_variance06(xp):
925
+ labels = xp.asarray([2, 2, 3, 3, 4])
926
+ with np.errstate(all='ignore'):
927
+ for type in types:
928
+ dtype = getattr(xp, type)
929
+ input = xp.asarray([1, 3, 8, 10, 8], dtype=dtype)
930
+ output = ndimage.variance(input, labels, xp.asarray([2, 3, 4]))
931
+ assert_array_almost_equal(output, xp.asarray([1.0, 1.0, 0.0]))
932
+
933
+
934
+ def test_standard_deviation01(xp):
935
+ with np.errstate(all='ignore'):
936
+ for type in types:
937
+ dtype = getattr(xp, type)
938
+ input = xp.asarray([], dtype=dtype)
939
+ with suppress_warnings() as sup:
940
+ sup.filter(RuntimeWarning, "Mean of empty slice")
941
+ output = ndimage.standard_deviation(input)
942
+ assert xp.isnan(output)
943
+
944
+
945
+ def test_standard_deviation02(xp):
946
+ for type in types:
947
+ dtype = getattr(xp, type)
948
+ input = xp.asarray([1], dtype=dtype)
949
+ output = ndimage.standard_deviation(input)
950
+ assert_almost_equal(output, xp.asarray(0.0), check_0d=False)
951
+
952
+
953
+ def test_standard_deviation03(xp):
954
+ for type in types:
955
+ dtype = getattr(xp, type)
956
+ input = xp.asarray([1, 3], dtype=dtype)
957
+ output = ndimage.standard_deviation(input)
958
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
959
+
960
+
961
+ def test_standard_deviation04(xp):
962
+ input = np.asarray([1, 0], dtype=bool)
963
+ input = xp.asarray(input)
964
+ output = ndimage.standard_deviation(input)
965
+ assert_almost_equal(output, xp.asarray(0.5), check_0d=False)
966
+
967
+
968
+ def test_standard_deviation05(xp):
969
+ labels = xp.asarray([2, 2, 3])
970
+ for type in types:
971
+ dtype = getattr(xp, type)
972
+ input = xp.asarray([1, 3, 8], dtype=dtype)
973
+ output = ndimage.standard_deviation(input, labels, 2)
974
+ assert_almost_equal(output, xp.asarray(1.0), check_0d=False)
975
+
976
+
977
+ def test_standard_deviation06(xp):
978
+ labels = xp.asarray([2, 2, 3, 3, 4])
979
+ with np.errstate(all='ignore'):
980
+ for type in types:
981
+ dtype = getattr(xp, type)
982
+ input = xp.asarray([1, 3, 8, 10, 8], dtype=dtype)
983
+ output = ndimage.standard_deviation(
984
+ input, labels, xp.asarray([2, 3, 4])
985
+ )
986
+ assert_array_almost_equal(output, xp.asarray([1.0, 1.0, 0.0]))
987
+
988
+
989
+ def test_standard_deviation07(xp):
990
+ labels = xp.asarray([1])
991
+ with np.errstate(all='ignore'):
992
+ for type in types:
993
+ if is_torch(xp) and type == 'uint8':
994
+ pytest.xfail("value cannot be converted to type uint8 "
995
+ "without overflow")
996
+ dtype = getattr(xp, type)
997
+ input = xp.asarray([-0.00619519], dtype=dtype)
998
+ output = ndimage.standard_deviation(input, labels, xp.asarray([1]))
999
+ assert_array_almost_equal(output, xp.asarray([0]))
1000
+
1001
+
1002
+ def test_minimum_position01(xp):
1003
+ labels = np.asarray([1, 0], dtype=bool)
1004
+ labels = xp.asarray(labels)
1005
+ for type in types:
1006
+ dtype = getattr(xp, type)
1007
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
1008
+ output = ndimage.minimum_position(input, labels=labels)
1009
+ assert output == (0, 0)
1010
+
1011
+
1012
+ def test_minimum_position02(xp):
1013
+ for type in types:
1014
+ dtype = getattr(xp, type)
1015
+ input = xp.asarray([[5, 4, 2, 5],
1016
+ [3, 7, 0, 2],
1017
+ [1, 5, 1, 1]], dtype=dtype)
1018
+ output = ndimage.minimum_position(input)
1019
+ assert output == (1, 2)
1020
+
1021
+
1022
+ def test_minimum_position03(xp):
1023
+ input = np.asarray([[5, 4, 2, 5],
1024
+ [3, 7, 0, 2],
1025
+ [1, 5, 1, 1]], dtype=bool)
1026
+ input = xp.asarray(input)
1027
+ output = ndimage.minimum_position(input)
1028
+ assert output == (1, 2)
1029
+
1030
+
1031
+ def test_minimum_position04(xp):
1032
+ input = np.asarray([[5, 4, 2, 5],
1033
+ [3, 7, 1, 2],
1034
+ [1, 5, 1, 1]], dtype=bool)
1035
+ input = xp.asarray(input)
1036
+ output = ndimage.minimum_position(input)
1037
+ assert output == (0, 0)
1038
+
1039
+
1040
+ def test_minimum_position05(xp):
1041
+ labels = xp.asarray([1, 2, 0, 4])
1042
+ for type in types:
1043
+ dtype = getattr(xp, type)
1044
+ input = xp.asarray([[5, 4, 2, 5],
1045
+ [3, 7, 0, 2],
1046
+ [1, 5, 2, 3]], dtype=dtype)
1047
+ output = ndimage.minimum_position(input, labels)
1048
+ assert output == (2, 0)
1049
+
1050
+
1051
+ def test_minimum_position06(xp):
1052
+ labels = xp.asarray([1, 2, 3, 4])
1053
+ for type in types:
1054
+ dtype = getattr(xp, type)
1055
+ input = xp.asarray([[5, 4, 2, 5],
1056
+ [3, 7, 0, 2],
1057
+ [1, 5, 1, 1]], dtype=dtype)
1058
+ output = ndimage.minimum_position(input, labels, 2)
1059
+ assert output == (0, 1)
1060
+
1061
+
1062
+ def test_minimum_position07(xp):
1063
+ labels = xp.asarray([1, 2, 3, 4])
1064
+ for type in types:
1065
+ dtype = getattr(xp, type)
1066
+ input = xp.asarray([[5, 4, 2, 5],
1067
+ [3, 7, 0, 2],
1068
+ [1, 5, 1, 1]], dtype=dtype)
1069
+ output = ndimage.minimum_position(input, labels,
1070
+ xp.asarray([2, 3]))
1071
+ assert output[0] == (0, 1)
1072
+ assert output[1] == (1, 2)
1073
+
1074
+
1075
+ def test_maximum_position01(xp):
1076
+ labels = np.asarray([1, 0], dtype=bool)
1077
+ labels = xp.asarray(labels)
1078
+ for type in types:
1079
+ dtype = getattr(xp, type)
1080
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
1081
+ output = ndimage.maximum_position(input,
1082
+ labels=labels)
1083
+ assert output == (1, 0)
1084
+
1085
+
1086
+ def test_maximum_position02(xp):
1087
+ for type in types:
1088
+ dtype = getattr(xp, type)
1089
+ input = xp.asarray([[5, 4, 2, 5],
1090
+ [3, 7, 8, 2],
1091
+ [1, 5, 1, 1]], dtype=dtype)
1092
+ output = ndimage.maximum_position(input)
1093
+ assert output == (1, 2)
1094
+
1095
+
1096
+ def test_maximum_position03(xp):
1097
+ input = np.asarray([[5, 4, 2, 5],
1098
+ [3, 7, 8, 2],
1099
+ [1, 5, 1, 1]], dtype=bool)
1100
+ input = xp.asarray(input)
1101
+ output = ndimage.maximum_position(input)
1102
+ assert output == (0, 0)
1103
+
1104
+
1105
+ def test_maximum_position04(xp):
1106
+ labels = xp.asarray([1, 2, 0, 4])
1107
+ for type in types:
1108
+ dtype = getattr(xp, type)
1109
+ input = xp.asarray([[5, 4, 2, 5],
1110
+ [3, 7, 8, 2],
1111
+ [1, 5, 1, 1]], dtype=dtype)
1112
+ output = ndimage.maximum_position(input, labels)
1113
+ assert output == (1, 1)
1114
+
1115
+
1116
+ def test_maximum_position05(xp):
1117
+ labels = xp.asarray([1, 2, 0, 4])
1118
+ for type in types:
1119
+ dtype = getattr(xp, type)
1120
+ input = xp.asarray([[5, 4, 2, 5],
1121
+ [3, 7, 8, 2],
1122
+ [1, 5, 1, 1]], dtype=dtype)
1123
+ output = ndimage.maximum_position(input, labels, 1)
1124
+ assert output == (0, 0)
1125
+
1126
+
1127
+ def test_maximum_position06(xp):
1128
+ labels = xp.asarray([1, 2, 0, 4])
1129
+ for type in types:
1130
+ dtype = getattr(xp, type)
1131
+ input = xp.asarray([[5, 4, 2, 5],
1132
+ [3, 7, 8, 2],
1133
+ [1, 5, 1, 1]], dtype=dtype)
1134
+ output = ndimage.maximum_position(input, labels,
1135
+ xp.asarray([1, 2]))
1136
+ assert output[0] == (0, 0)
1137
+ assert output[1] == (1, 1)
1138
+
1139
+
1140
+ def test_maximum_position07(xp):
1141
+ # Test float labels
1142
+ if is_torch(xp):
1143
+ pytest.xfail("output[1] is wrong on pytorch")
1144
+
1145
+ labels = xp.asarray([1.0, 2.5, 0.0, 4.5])
1146
+ for type in types:
1147
+ dtype = getattr(xp, type)
1148
+ input = xp.asarray([[5, 4, 2, 5],
1149
+ [3, 7, 8, 2],
1150
+ [1, 5, 1, 1]], dtype=dtype)
1151
+ output = ndimage.maximum_position(input, labels,
1152
+ xp.asarray([1.0, 4.5]))
1153
+ assert output[0] == (0, 0)
1154
+ assert output[1] == (0, 3)
1155
+
1156
+
1157
+ def test_extrema01(xp):
1158
+ labels = np.asarray([1, 0], dtype=bool)
1159
+ labels = xp.asarray(labels)
1160
+ for type in types:
1161
+ dtype = getattr(xp, type)
1162
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
1163
+ output1 = ndimage.extrema(input, labels=labels)
1164
+ output2 = ndimage.minimum(input, labels=labels)
1165
+ output3 = ndimage.maximum(input, labels=labels)
1166
+ output4 = ndimage.minimum_position(input,
1167
+ labels=labels)
1168
+ output5 = ndimage.maximum_position(input,
1169
+ labels=labels)
1170
+ assert output1 == (output2, output3, output4, output5)
1171
+
1172
+
1173
+ def test_extrema02(xp):
1174
+ labels = xp.asarray([1, 2])
1175
+ for type in types:
1176
+ dtype = getattr(xp, type)
1177
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
1178
+ output1 = ndimage.extrema(input, labels=labels,
1179
+ index=2)
1180
+ output2 = ndimage.minimum(input, labels=labels,
1181
+ index=2)
1182
+ output3 = ndimage.maximum(input, labels=labels,
1183
+ index=2)
1184
+ output4 = ndimage.minimum_position(input,
1185
+ labels=labels, index=2)
1186
+ output5 = ndimage.maximum_position(input,
1187
+ labels=labels, index=2)
1188
+ assert output1 == (output2, output3, output4, output5)
1189
+
1190
+
1191
+ def test_extrema03(xp):
1192
+ labels = xp.asarray([[1, 2], [2, 3]])
1193
+ for type in types:
1194
+ if is_torch(xp) and type in ("uint16", "uint32", "uint64"):
1195
+ pytest.xfail("https://github.com/pytorch/pytorch/issues/58734")
1196
+
1197
+ dtype = getattr(xp, type)
1198
+ input = xp.asarray([[1, 2], [3, 4]], dtype=dtype)
1199
+ output1 = ndimage.extrema(input,
1200
+ labels=labels,
1201
+ index=xp.asarray([2, 3, 8]))
1202
+ output2 = ndimage.minimum(input,
1203
+ labels=labels,
1204
+ index=xp.asarray([2, 3, 8]))
1205
+ output3 = ndimage.maximum(input, labels=labels,
1206
+ index=xp.asarray([2, 3, 8]))
1207
+ output4 = ndimage.minimum_position(input,
1208
+ labels=labels,
1209
+ index=xp.asarray([2, 3, 8]))
1210
+ output5 = ndimage.maximum_position(input,
1211
+ labels=labels,
1212
+ index=xp.asarray([2, 3, 8]))
1213
+ assert_array_almost_equal(output1[0], output2)
1214
+ assert_array_almost_equal(output1[1], output3)
1215
+ assert output1[2] == output4
1216
+ assert output1[3] == output5
1217
+
1218
+
1219
+ def test_extrema04(xp):
1220
+ labels = xp.asarray([1, 2, 0, 4])
1221
+ for type in types:
1222
+ if is_torch(xp) and type in ("uint16", "uint32", "uint64"):
1223
+ pytest.xfail("https://github.com/pytorch/pytorch/issues/58734")
1224
+
1225
+ dtype = getattr(xp, type)
1226
+ input = xp.asarray([[5, 4, 2, 5],
1227
+ [3, 7, 8, 2],
1228
+ [1, 5, 1, 1]], dtype=dtype)
1229
+ output1 = ndimage.extrema(input, labels, xp.asarray([1, 2]))
1230
+ output2 = ndimage.minimum(input, labels, xp.asarray([1, 2]))
1231
+ output3 = ndimage.maximum(input, labels, xp.asarray([1, 2]))
1232
+ output4 = ndimage.minimum_position(input, labels,
1233
+ xp.asarray([1, 2]))
1234
+ output5 = ndimage.maximum_position(input, labels,
1235
+ xp.asarray([1, 2]))
1236
+ assert_array_almost_equal(output1[0], output2)
1237
+ assert_array_almost_equal(output1[1], output3)
1238
+ assert output1[2] == output4
1239
+ assert output1[3] == output5
1240
+
1241
+
1242
+ def test_center_of_mass01(xp):
1243
+ expected = (0.0, 0.0)
1244
+ for type in types:
1245
+ dtype = getattr(xp, type)
1246
+ input = xp.asarray([[1, 0], [0, 0]], dtype=dtype)
1247
+ output = ndimage.center_of_mass(input)
1248
+ assert output == expected
1249
+
1250
+
1251
+ def test_center_of_mass02(xp):
1252
+ expected = (1, 0)
1253
+ for type in types:
1254
+ dtype = getattr(xp, type)
1255
+ input = xp.asarray([[0, 0], [1, 0]], dtype=dtype)
1256
+ output = ndimage.center_of_mass(input)
1257
+ assert output == expected
1258
+
1259
+
1260
+ def test_center_of_mass03(xp):
1261
+ expected = (0, 1)
1262
+ for type in types:
1263
+ dtype = getattr(xp, type)
1264
+ input = xp.asarray([[0, 1], [0, 0]], dtype=dtype)
1265
+ output = ndimage.center_of_mass(input)
1266
+ assert output == expected
1267
+
1268
+
1269
+ def test_center_of_mass04(xp):
1270
+ expected = (1, 1)
1271
+ for type in types:
1272
+ dtype = getattr(xp, type)
1273
+ input = xp.asarray([[0, 0], [0, 1]], dtype=dtype)
1274
+ output = ndimage.center_of_mass(input)
1275
+ assert output == expected
1276
+
1277
+
1278
+ def test_center_of_mass05(xp):
1279
+ expected = (0.5, 0.5)
1280
+ for type in types:
1281
+ dtype = getattr(xp, type)
1282
+ input = xp.asarray([[1, 1], [1, 1]], dtype=dtype)
1283
+ output = ndimage.center_of_mass(input)
1284
+ assert output == expected
1285
+
1286
+
1287
+ def test_center_of_mass06(xp):
1288
+ expected = (0.5, 0.5)
1289
+ input = np.asarray([[1, 2], [3, 1]], dtype=bool)
1290
+ input = xp.asarray(input)
1291
+ output = ndimage.center_of_mass(input)
1292
+ assert output == expected
1293
+
1294
+
1295
+ def test_center_of_mass07(xp):
1296
+ labels = xp.asarray([1, 0])
1297
+ expected = (0.5, 0.0)
1298
+ input = np.asarray([[1, 2], [3, 1]], dtype=bool)
1299
+ input = xp.asarray(input)
1300
+ output = ndimage.center_of_mass(input, labels)
1301
+ assert output == expected
1302
+
1303
+
1304
+ def test_center_of_mass08(xp):
1305
+ labels = xp.asarray([1, 2])
1306
+ expected = (0.5, 1.0)
1307
+ input = np.asarray([[5, 2], [3, 1]], dtype=bool)
1308
+ input = xp.asarray(input)
1309
+ output = ndimage.center_of_mass(input, labels, 2)
1310
+ assert output == expected
1311
+
1312
+
1313
+ def test_center_of_mass09(xp):
1314
+ labels = xp.asarray((1, 2))
1315
+ expected = xp.asarray([(0.5, 0.0), (0.5, 1.0)], dtype=xp.float64)
1316
+ input = np.asarray([[1, 2], [1, 1]], dtype=bool)
1317
+ input = xp.asarray(input)
1318
+ output = ndimage.center_of_mass(input, labels, xp.asarray([1, 2]))
1319
+ xp_assert_equal(xp.asarray(output), xp.asarray(expected))
1320
+
1321
+
1322
+ def test_histogram01(xp):
1323
+ expected = xp.ones(10)
1324
+ input = xp.arange(10)
1325
+ output = ndimage.histogram(input, 0, 10, 10)
1326
+ assert_array_almost_equal(output, expected)
1327
+
1328
+
1329
+ def test_histogram02(xp):
1330
+ labels = xp.asarray([1, 1, 1, 1, 2, 2, 2, 2])
1331
+ expected = xp.asarray([0, 2, 0, 1, 1])
1332
+ input = xp.asarray([1, 1, 3, 4, 3, 3, 3, 3])
1333
+ output = ndimage.histogram(input, 0, 4, 5, labels, 1)
1334
+ assert_array_almost_equal(output, expected)
1335
+
1336
+
1337
+ @skip_xp_backends(np_only=True, reason='object arrays')
1338
+ def test_histogram03(xp):
1339
+ labels = xp.asarray([1, 0, 1, 1, 2, 2, 2, 2])
1340
+ expected1 = xp.asarray([0, 1, 0, 1, 1])
1341
+ expected2 = xp.asarray([0, 0, 0, 3, 0])
1342
+ input = xp.asarray([1, 1, 3, 4, 3, 5, 3, 3])
1343
+
1344
+ output = ndimage.histogram(input, 0, 4, 5, labels, (1, 2))
1345
+
1346
+ assert_array_almost_equal(output[0], expected1)
1347
+ assert_array_almost_equal(output[1], expected2)
1348
+
1349
+
1350
+ def test_stat_funcs_2d(xp):
1351
+ a = xp.asarray([[5, 6, 0, 0, 0], [8, 9, 0, 0, 0], [0, 0, 0, 3, 5]])
1352
+ lbl = xp.asarray([[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 0, 2, 2]])
1353
+
1354
+ mean = ndimage.mean(a, labels=lbl, index=xp.asarray([1, 2]))
1355
+ xp_assert_equal(mean, xp.asarray([7.0, 4.0], dtype=xp.float64))
1356
+
1357
+ var = ndimage.variance(a, labels=lbl, index=xp.asarray([1, 2]))
1358
+ xp_assert_equal(var, xp.asarray([2.5, 1.0], dtype=xp.float64))
1359
+
1360
+ std = ndimage.standard_deviation(a, labels=lbl, index=xp.asarray([1, 2]))
1361
+ assert_array_almost_equal(std, xp.sqrt(xp.asarray([2.5, 1.0], dtype=xp.float64)))
1362
+
1363
+ med = ndimage.median(a, labels=lbl, index=xp.asarray([1, 2]))
1364
+ xp_assert_equal(med, xp.asarray([7.0, 4.0], dtype=xp.float64))
1365
+
1366
+ min = ndimage.minimum(a, labels=lbl, index=xp.asarray([1, 2]))
1367
+ xp_assert_equal(min, xp.asarray([5, 3]), check_dtype=False)
1368
+
1369
+ max = ndimage.maximum(a, labels=lbl, index=xp.asarray([1, 2]))
1370
+ xp_assert_equal(max, xp.asarray([9, 5]), check_dtype=False)
1371
+
1372
+
1373
+ @skip_xp_backends("cupy", reason="no watershed_ift on CuPy")
1374
+ class TestWatershedIft:
1375
+
1376
+ def test_watershed_ift01(self, xp):
1377
+ data = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1378
+ [0, 1, 1, 1, 1, 1, 0],
1379
+ [0, 1, 0, 0, 0, 1, 0],
1380
+ [0, 1, 0, 0, 0, 1, 0],
1381
+ [0, 1, 0, 0, 0, 1, 0],
1382
+ [0, 1, 1, 1, 1, 1, 0],
1383
+ [0, 0, 0, 0, 0, 0, 0],
1384
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1385
+ markers = xp.asarray([[-1, 0, 0, 0, 0, 0, 0],
1386
+ [0, 0, 0, 0, 0, 0, 0],
1387
+ [0, 0, 0, 0, 0, 0, 0],
1388
+ [0, 0, 0, 1, 0, 0, 0],
1389
+ [0, 0, 0, 0, 0, 0, 0],
1390
+ [0, 0, 0, 0, 0, 0, 0],
1391
+ [0, 0, 0, 0, 0, 0, 0],
1392
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.int8)
1393
+ structure=xp.asarray([[1, 1, 1],
1394
+ [1, 1, 1],
1395
+ [1, 1, 1]])
1396
+ out = ndimage.watershed_ift(data, markers, structure=structure)
1397
+ expected = [[-1, -1, -1, -1, -1, -1, -1],
1398
+ [-1, 1, 1, 1, 1, 1, -1],
1399
+ [-1, 1, 1, 1, 1, 1, -1],
1400
+ [-1, 1, 1, 1, 1, 1, -1],
1401
+ [-1, 1, 1, 1, 1, 1, -1],
1402
+ [-1, 1, 1, 1, 1, 1, -1],
1403
+ [-1, -1, -1, -1, -1, -1, -1],
1404
+ [-1, -1, -1, -1, -1, -1, -1]]
1405
+ assert_array_almost_equal(out, xp.asarray(expected))
1406
+
1407
+ def test_watershed_ift02(self, xp):
1408
+ data = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1409
+ [0, 1, 1, 1, 1, 1, 0],
1410
+ [0, 1, 0, 0, 0, 1, 0],
1411
+ [0, 1, 0, 0, 0, 1, 0],
1412
+ [0, 1, 0, 0, 0, 1, 0],
1413
+ [0, 1, 1, 1, 1, 1, 0],
1414
+ [0, 0, 0, 0, 0, 0, 0],
1415
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1416
+ markers = xp.asarray([[-1, 0, 0, 0, 0, 0, 0],
1417
+ [0, 0, 0, 0, 0, 0, 0],
1418
+ [0, 0, 0, 0, 0, 0, 0],
1419
+ [0, 0, 0, 1, 0, 0, 0],
1420
+ [0, 0, 0, 0, 0, 0, 0],
1421
+ [0, 0, 0, 0, 0, 0, 0],
1422
+ [0, 0, 0, 0, 0, 0, 0],
1423
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.int8)
1424
+ out = ndimage.watershed_ift(data, markers)
1425
+ expected = [[-1, -1, -1, -1, -1, -1, -1],
1426
+ [-1, -1, 1, 1, 1, -1, -1],
1427
+ [-1, 1, 1, 1, 1, 1, -1],
1428
+ [-1, 1, 1, 1, 1, 1, -1],
1429
+ [-1, 1, 1, 1, 1, 1, -1],
1430
+ [-1, -1, 1, 1, 1, -1, -1],
1431
+ [-1, -1, -1, -1, -1, -1, -1],
1432
+ [-1, -1, -1, -1, -1, -1, -1]]
1433
+ assert_array_almost_equal(out, xp.asarray(expected))
1434
+
1435
+ def test_watershed_ift03(self, xp):
1436
+ data = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1437
+ [0, 1, 1, 1, 1, 1, 0],
1438
+ [0, 1, 0, 1, 0, 1, 0],
1439
+ [0, 1, 0, 1, 0, 1, 0],
1440
+ [0, 1, 0, 1, 0, 1, 0],
1441
+ [0, 1, 1, 1, 1, 1, 0],
1442
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1443
+ markers = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1444
+ [0, 0, 0, 0, 0, 0, 0],
1445
+ [0, 0, 0, 0, 0, 0, 0],
1446
+ [0, 0, 2, 0, 3, 0, 0],
1447
+ [0, 0, 0, 0, 0, 0, 0],
1448
+ [0, 0, 0, 0, 0, 0, 0],
1449
+ [0, 0, 0, 0, 0, 0, -1]], dtype=xp.int8)
1450
+ out = ndimage.watershed_ift(data, markers)
1451
+ expected = [[-1, -1, -1, -1, -1, -1, -1],
1452
+ [-1, -1, 2, -1, 3, -1, -1],
1453
+ [-1, 2, 2, 3, 3, 3, -1],
1454
+ [-1, 2, 2, 3, 3, 3, -1],
1455
+ [-1, 2, 2, 3, 3, 3, -1],
1456
+ [-1, -1, 2, -1, 3, -1, -1],
1457
+ [-1, -1, -1, -1, -1, -1, -1]]
1458
+ assert_array_almost_equal(out, xp.asarray(expected))
1459
+
1460
+ def test_watershed_ift04(self, xp):
1461
+ data = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1462
+ [0, 1, 1, 1, 1, 1, 0],
1463
+ [0, 1, 0, 1, 0, 1, 0],
1464
+ [0, 1, 0, 1, 0, 1, 0],
1465
+ [0, 1, 0, 1, 0, 1, 0],
1466
+ [0, 1, 1, 1, 1, 1, 0],
1467
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1468
+ markers = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1469
+ [0, 0, 0, 0, 0, 0, 0],
1470
+ [0, 0, 0, 0, 0, 0, 0],
1471
+ [0, 0, 2, 0, 3, 0, 0],
1472
+ [0, 0, 0, 0, 0, 0, 0],
1473
+ [0, 0, 0, 0, 0, 0, 0],
1474
+ [0, 0, 0, 0, 0, 0, -1]],
1475
+ dtype=xp.int8)
1476
+
1477
+ structure=xp.asarray([[1, 1, 1],
1478
+ [1, 1, 1],
1479
+ [1, 1, 1]])
1480
+ out = ndimage.watershed_ift(data, markers, structure=structure)
1481
+ expected = [[-1, -1, -1, -1, -1, -1, -1],
1482
+ [-1, 2, 2, 3, 3, 3, -1],
1483
+ [-1, 2, 2, 3, 3, 3, -1],
1484
+ [-1, 2, 2, 3, 3, 3, -1],
1485
+ [-1, 2, 2, 3, 3, 3, -1],
1486
+ [-1, 2, 2, 3, 3, 3, -1],
1487
+ [-1, -1, -1, -1, -1, -1, -1]]
1488
+ assert_array_almost_equal(out, xp.asarray(expected))
1489
+
1490
+ def test_watershed_ift05(self, xp):
1491
+ data = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1492
+ [0, 1, 1, 1, 1, 1, 0],
1493
+ [0, 1, 0, 1, 0, 1, 0],
1494
+ [0, 1, 0, 1, 0, 1, 0],
1495
+ [0, 1, 0, 1, 0, 1, 0],
1496
+ [0, 1, 1, 1, 1, 1, 0],
1497
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1498
+ markers = xp.asarray([[0, 0, 0, 0, 0, 0, 0],
1499
+ [0, 0, 0, 0, 0, 0, 0],
1500
+ [0, 0, 0, 0, 0, 0, 0],
1501
+ [0, 0, 3, 0, 2, 0, 0],
1502
+ [0, 0, 0, 0, 0, 0, 0],
1503
+ [0, 0, 0, 0, 0, 0, 0],
1504
+ [0, 0, 0, 0, 0, 0, -1]],
1505
+ dtype=xp.int8)
1506
+ structure = xp.asarray([[1, 1, 1],
1507
+ [1, 1, 1],
1508
+ [1, 1, 1]])
1509
+ out = ndimage.watershed_ift(data, markers, structure=structure)
1510
+ expected = [[-1, -1, -1, -1, -1, -1, -1],
1511
+ [-1, 3, 3, 2, 2, 2, -1],
1512
+ [-1, 3, 3, 2, 2, 2, -1],
1513
+ [-1, 3, 3, 2, 2, 2, -1],
1514
+ [-1, 3, 3, 2, 2, 2, -1],
1515
+ [-1, 3, 3, 2, 2, 2, -1],
1516
+ [-1, -1, -1, -1, -1, -1, -1]]
1517
+ assert_array_almost_equal(out, xp.asarray(expected))
1518
+
1519
+ def test_watershed_ift06(self, xp):
1520
+ data = xp.asarray([[0, 1, 0, 0, 0, 1, 0],
1521
+ [0, 1, 0, 0, 0, 1, 0],
1522
+ [0, 1, 0, 0, 0, 1, 0],
1523
+ [0, 1, 1, 1, 1, 1, 0],
1524
+ [0, 0, 0, 0, 0, 0, 0],
1525
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.uint8)
1526
+ markers = xp.asarray([[-1, 0, 0, 0, 0, 0, 0],
1527
+ [0, 0, 0, 1, 0, 0, 0],
1528
+ [0, 0, 0, 0, 0, 0, 0],
1529
+ [0, 0, 0, 0, 0, 0, 0],
1530
+ [0, 0, 0, 0, 0, 0, 0],
1531
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.int8)
1532
+ structure=xp.asarray([[1, 1, 1],
1533
+ [1, 1, 1],
1534
+ [1, 1, 1]])
1535
+ out = ndimage.watershed_ift(data, markers, structure=structure)
1536
+ expected = [[-1, 1, 1, 1, 1, 1, -1],
1537
+ [-1, 1, 1, 1, 1, 1, -1],
1538
+ [-1, 1, 1, 1, 1, 1, -1],
1539
+ [-1, 1, 1, 1, 1, 1, -1],
1540
+ [-1, -1, -1, -1, -1, -1, -1],
1541
+ [-1, -1, -1, -1, -1, -1, -1]]
1542
+ assert_array_almost_equal(out, xp.asarray(expected))
1543
+
1544
+ @skip_xp_backends(np_only=True, reason="inplace ops are numpy-specific")
1545
+ def test_watershed_ift07(self, xp):
1546
+ shape = (7, 6)
1547
+ data = np.zeros(shape, dtype=np.uint8)
1548
+ data = data.transpose()
1549
+ data[...] = np.asarray([[0, 1, 0, 0, 0, 1, 0],
1550
+ [0, 1, 0, 0, 0, 1, 0],
1551
+ [0, 1, 0, 0, 0, 1, 0],
1552
+ [0, 1, 1, 1, 1, 1, 0],
1553
+ [0, 0, 0, 0, 0, 0, 0],
1554
+ [0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
1555
+ data = xp.asarray(data)
1556
+ markers = xp.asarray([[-1, 0, 0, 0, 0, 0, 0],
1557
+ [0, 0, 0, 1, 0, 0, 0],
1558
+ [0, 0, 0, 0, 0, 0, 0],
1559
+ [0, 0, 0, 0, 0, 0, 0],
1560
+ [0, 0, 0, 0, 0, 0, 0],
1561
+ [0, 0, 0, 0, 0, 0, 0]], dtype=xp.int8)
1562
+ out = xp.zeros(shape, dtype=xp.int16)
1563
+ out = out.T
1564
+ structure=xp.asarray([[1, 1, 1],
1565
+ [1, 1, 1],
1566
+ [1, 1, 1]])
1567
+ ndimage.watershed_ift(data, markers, structure=structure,
1568
+ output=out)
1569
+ expected = [[-1, 1, 1, 1, 1, 1, -1],
1570
+ [-1, 1, 1, 1, 1, 1, -1],
1571
+ [-1, 1, 1, 1, 1, 1, -1],
1572
+ [-1, 1, 1, 1, 1, 1, -1],
1573
+ [-1, -1, -1, -1, -1, -1, -1],
1574
+ [-1, -1, -1, -1, -1, -1, -1]]
1575
+ assert_array_almost_equal(out, xp.asarray(expected))
1576
+
1577
+ @skip_xp_backends("cupy", reason="no watershed_ift on CuPy")
1578
+ def test_watershed_ift08(self, xp):
1579
+ # Test cost larger than uint8. See gh-10069.
1580
+ data = xp.asarray([[256, 0],
1581
+ [0, 0]], dtype=xp.uint16)
1582
+ markers = xp.asarray([[1, 0],
1583
+ [0, 0]], dtype=xp.int8)
1584
+ out = ndimage.watershed_ift(data, markers)
1585
+ expected = [[1, 1],
1586
+ [1, 1]]
1587
+ assert_array_almost_equal(out, xp.asarray(expected))
1588
+
1589
+ @skip_xp_backends("cupy", reason="no watershed_ift on CuPy" )
1590
+ def test_watershed_ift09(self, xp):
1591
+ # Test large cost. See gh-19575
1592
+ data = xp.asarray([[xp.iinfo(xp.uint16).max, 0],
1593
+ [0, 0]], dtype=xp.uint16)
1594
+ markers = xp.asarray([[1, 0],
1595
+ [0, 0]], dtype=xp.int8)
1596
+ out = ndimage.watershed_ift(data, markers)
1597
+ expected = [[1, 1],
1598
+ [1, 1]]
1599
+ xp_assert_close(out, xp.asarray(expected), check_dtype=False)
1600
+
1601
+
1602
+ @skip_xp_backends(np_only=True)
1603
+ @pytest.mark.parametrize("dt", [np.intc, np.uintc])
1604
+ def test_gh_19423(dt, xp):
1605
+ rng = np.random.default_rng(123)
1606
+ max_val = 8
1607
+ image = rng.integers(low=0, high=max_val, size=(10, 12)).astype(dtype=dt)
1608
+ val_idx = ndimage.value_indices(image)
1609
+ assert len(val_idx.keys()) == max_val
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_morphology.py ADDED
The diff for this file is too large to render. See raw diff
 
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_ni_support.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ import numpy as np
4
+ from .._ni_support import _get_output
5
+
6
+
7
+ @pytest.mark.parametrize(
8
+ 'dtype',
9
+ [
10
+ # String specifiers
11
+ 'f4', 'float32', 'complex64', 'complex128',
12
+ # Type and dtype specifiers
13
+ np.float32, float, np.dtype('f4'),
14
+ # Derive from input
15
+ None,
16
+ ],
17
+ )
18
+ def test_get_output_basic(dtype):
19
+ shape = (2, 3)
20
+
21
+ input_ = np.zeros(shape, dtype='float32')
22
+
23
+ # For None, derive dtype from input
24
+ expected_dtype = 'float32' if dtype is None else dtype
25
+
26
+ # Output is dtype-specifier, retrieve shape from input
27
+ result = _get_output(dtype, input_)
28
+ assert result.shape == shape
29
+ assert result.dtype == np.dtype(expected_dtype)
30
+
31
+ # Output is dtype specifier, with explicit shape, overriding input
32
+ result = _get_output(dtype, input_, shape=(3, 2))
33
+ assert result.shape == (3, 2)
34
+ assert result.dtype == np.dtype(expected_dtype)
35
+
36
+ # Output is pre-allocated array, return directly
37
+ output = np.zeros(shape, dtype=dtype)
38
+ result = _get_output(output, input_)
39
+ assert result is output
40
+
41
+
42
+ @pytest.mark.thread_unsafe
43
+ def test_get_output_complex():
44
+ shape = (2, 3)
45
+
46
+ input_ = np.zeros(shape)
47
+
48
+ # None, promote input type to complex
49
+ result = _get_output(None, input_, complex_output=True)
50
+ assert result.shape == shape
51
+ assert result.dtype == np.dtype('complex128')
52
+
53
+ # Explicit type, promote type to complex
54
+ with pytest.warns(UserWarning, match='promoting specified output dtype to complex'):
55
+ result = _get_output(float, input_, complex_output=True)
56
+ assert result.shape == shape
57
+ assert result.dtype == np.dtype('complex128')
58
+
59
+ # String specifier, simply verify complex output
60
+ result = _get_output('complex64', input_, complex_output=True)
61
+ assert result.shape == shape
62
+ assert result.dtype == np.dtype('complex64')
63
+
64
+
65
+ def test_get_output_error_cases():
66
+ input_ = np.zeros((2, 3), 'float32')
67
+
68
+ # Two separate paths can raise the same error
69
+ with pytest.raises(RuntimeError, match='output must have complex dtype'):
70
+ _get_output('float32', input_, complex_output=True)
71
+ with pytest.raises(RuntimeError, match='output must have complex dtype'):
72
+ _get_output(np.zeros((2, 3)), input_, complex_output=True)
73
+
74
+ with pytest.raises(RuntimeError, match='output must have numeric dtype'):
75
+ _get_output('void', input_)
76
+
77
+ with pytest.raises(RuntimeError, match='shape not correct'):
78
+ _get_output(np.zeros((3, 2)), input_)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_splines.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for spline filtering."""
2
+ import pytest
3
+
4
+ import numpy as np
5
+ from scipy._lib._array_api import assert_almost_equal
6
+
7
+ from scipy import ndimage
8
+
9
+ from scipy.conftest import array_api_compatible
10
+ skip_xp_backends = pytest.mark.skip_xp_backends
11
+ pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends"),
12
+ skip_xp_backends(cpu_only=True, exceptions=['cupy', 'jax.numpy'],)]
13
+
14
+
15
+ def get_spline_knot_values(order):
16
+ """Knot values to the right of a B-spline's center."""
17
+ knot_values = {0: [1],
18
+ 1: [1],
19
+ 2: [6, 1],
20
+ 3: [4, 1],
21
+ 4: [230, 76, 1],
22
+ 5: [66, 26, 1]}
23
+
24
+ return knot_values[order]
25
+
26
+
27
+ def make_spline_knot_matrix(xp, n, order, mode='mirror'):
28
+ """Matrix to invert to find the spline coefficients."""
29
+ knot_values = get_spline_knot_values(order)
30
+
31
+ # NB: do computations with numpy, convert to xp as the last step only
32
+
33
+ matrix = np.zeros((n, n))
34
+ for diag, knot_value in enumerate(knot_values):
35
+ indices = np.arange(diag, n)
36
+ if diag == 0:
37
+ matrix[indices, indices] = knot_value
38
+ else:
39
+ matrix[indices, indices - diag] = knot_value
40
+ matrix[indices - diag, indices] = knot_value
41
+
42
+ knot_values_sum = knot_values[0] + 2 * sum(knot_values[1:])
43
+
44
+ if mode == 'mirror':
45
+ start, step = 1, 1
46
+ elif mode == 'reflect':
47
+ start, step = 0, 1
48
+ elif mode == 'grid-wrap':
49
+ start, step = -1, -1
50
+ else:
51
+ raise ValueError(f'unsupported mode {mode}')
52
+
53
+ for row in range(len(knot_values) - 1):
54
+ for idx, knot_value in enumerate(knot_values[row + 1:]):
55
+ matrix[row, start + step*idx] += knot_value
56
+ matrix[-row - 1, -start - 1 - step*idx] += knot_value
57
+
58
+ return xp.asarray(matrix / knot_values_sum)
59
+
60
+
61
+ @pytest.mark.parametrize('order', [0, 1, 2, 3, 4, 5])
62
+ @pytest.mark.parametrize('mode', ['mirror', 'grid-wrap', 'reflect'])
63
+ def test_spline_filter_vs_matrix_solution(order, mode, xp):
64
+ n = 100
65
+ eye = xp.eye(n, dtype=xp.float64)
66
+ spline_filter_axis_0 = ndimage.spline_filter1d(eye, axis=0, order=order,
67
+ mode=mode)
68
+ spline_filter_axis_1 = ndimage.spline_filter1d(eye, axis=1, order=order,
69
+ mode=mode)
70
+ matrix = make_spline_knot_matrix(xp, n, order, mode=mode)
71
+ assert_almost_equal(eye, spline_filter_axis_0 @ matrix)
72
+ assert_almost_equal(eye, spline_filter_axis_1 @ matrix.T)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/odr/models.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.odr` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+ __all__ = [ # noqa: F822
8
+ 'Model', 'exponential', 'multilinear', 'unilinear',
9
+ 'quadratic', 'polynomial'
10
+ ]
11
+
12
+
13
+ def __dir__():
14
+ return __all__
15
+
16
+
17
+ def __getattr__(name):
18
+ return _sub_module_deprecation(sub_package="odr", module="models",
19
+ private_modules=["_models"], all=__all__,
20
+ attribute=name)
external/alphageometry/.venv-ag/Lib/site-packages/scipy/odr/odrpack.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is not meant for public use and will be removed in SciPy v2.0.0.
2
+ # Use the `scipy.odr` namespace for importing the functions
3
+ # included below.
4
+
5
+ from scipy._lib.deprecation import _sub_module_deprecation
6
+
7
+ __all__ = [ # noqa: F822
8
+ 'odr', 'OdrWarning', 'OdrError', 'OdrStop',
9
+ 'Data', 'RealData', 'Model', 'Output', 'ODR',
10
+ 'odr_error', 'odr_stop'
11
+ ]
12
+
13
+
14
+ def __dir__():
15
+ return __all__
16
+
17
+
18
+ def __getattr__(name):
19
+ return _sub_module_deprecation(sub_package="odr", module="odrpack",
20
+ private_modules=["_odrpack"], all=__all__,
21
+ attribute=name)