Add files using upload-large-folder tool
Browse files- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/__init__.py +173 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_ni_support.py +143 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_rank_filter_1d.cp310-win_amd64.dll.a +0 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/_support_alternative_backends.py +72 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/__init__.py +12 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_inputs.txt +21 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_results.txt +294 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/data/label_strels.txt +42 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/dots.png +0 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_c_api.py +102 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_datatypes.py +67 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_filters.py +0 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_fourier.py +189 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_interpolation.py +1484 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_measurements.py +1609 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_morphology.py +0 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_ni_support.py +78 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/ndimage/tests/test_splines.py +72 -0
- external/alphageometry/.venv-ag/Lib/site-packages/scipy/odr/models.py +20 -0
- 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)
|