<commit_before>import numpy as np
import itertools
from numpy.testing import (assert_equal,
                           assert_almost_equal,
                           assert_array_equal,
                           assert_array_almost_equal,
                           suppress_warnings)
import pytest
from pytest import raises as assert_raises
from pytest import warns as assert_warns
from scipy.spatial import SphericalVoronoi, distance
from scipy.optimize import linear_sum_assignment
from scipy.constants import golden as phi
from scipy.special import gamma


TOL = 1E-10


def _generate_tetrahedron():
    return np.array([[1, 1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, 1]])


def _generate_cube():
    return np.array(list(itertools.product([-1, 1.], repeat=3)))


def _generate_octahedron():
    return np.array([[-1, 0, 0], [+1, 0, 0], [0, -1, 0],
                     [0, +1, 0], [0, 0, -1], [0, 0, +1]])


def _generate_dodecahedron():

    x1 = _generate_cube()
    x2 = np.array([[0, -phi, -1 / phi],
                   [0, -phi, +1 / phi],
                   [0, +phi, -1 / phi],
                   [0, +phi, +1 / phi]])
    x3 = np.array([[-1 / phi, 0, -phi],
                   [+1 / phi, 0, -phi],
                   [-1 / phi, 0, +phi],
                   [+1 / phi, 0, +phi]])
    x4 = np.array([[-phi, -1 / phi, 0],
                   [-phi, +1 / phi, 0],
                   [+phi, -1 / phi, 0],
                   [+phi, +1 / phi, 0]])
    return np.concatenate((x1, x2, x3, x4))


def _generate_icosahedron():
    x = np.array([[0, -1, -phi],
                  [0, -1, +phi],
                  [0, +1, -phi],
                  [0, +1, +phi]])
    return np.concatenate([np.roll(x, i, axis=1) for i in range(3)])


def _generate_polytope(name):
    polygons = ["triangle", "square", "pentagon", "hexagon", "heptagon",
                "octagon", "nonagon", "decagon", "undecagon", "dodecagon"]
    polyhedra = ["tetrahedron", "cube", "octahedron", "dodecahedron",
                 "icosahedron"]
    if name not in polygons and name not in polyhedra:
        raise ValueError("unrecognized polytope")

    if name in polygons:
        n = polygons.index(name) + 3
        thetas = np.linspace(0, 2 * np.pi, n, endpoint=False)
        p = np.vstack([np.cos(thetas), np.sin(thetas)]).T
    elif name == "tetrahedron":
        p = _generate_tetrahedron()
    elif name == "cube":
        p = _generate_cube()
    elif name == "octahedron":
        p = _generate_octahedron()
    elif name == "dodecahedron":
        p = _generate_dodecahedron()
    elif name == "icosahedron":
        p = _generate_icosahedron()

    return p / np.linalg.norm(p, axis=1, keepdims=True)


def _hypersphere_area(dim, radius):
    # https://en.wikipedia.org/wiki/N-sphere#Closed_forms
    return 2 * np.pi**(dim / 2) / gamma(dim / 2) * radius**(dim - 1)


def _sample_sphere(n, dim, seed=None):
    # Sample points uniformly at random from the hypersphere
    rng = np.random.RandomState(seed=seed)
    points = rng.randn(n, dim)
    points /= np.linalg.norm(points, axis=1, keepdims=True)
    return points


class TestSphericalVoronoi:

    def setup_method(self):
        self.points = np.array([
            [-0.78928481, -0.16341094, 0.59188373],
            [-0.66839141, 0.73309634, 0.12578818],
            [0.32535778, -0.92476944, -0.19734181],
            [-0.90177102, -0.03785291, -0.43055335],
            [0.71781344, 0.68428936, 0.12842096],
            [-0.96064876, 0.23492353, -0.14820556],
            [0.73181537, -0.22025898, -0.6449281],
            [0.79979205, 0.54555747, 0.25039913]]
        )

    def test_constructor(self):
        center = np.array([1, 2, 3])
        radius = 2
        s1 = SphericalVoronoi(self.points)
        # user input checks in SphericalVoronoi now require
        # the radius / center to match the generators so adjust
        # accordingly here
        s2 = SphericalVoronoi(self.points * radius, radius)
        s3 = SphericalVoronoi(self.points + center, center=center)
        s4 = SphericalVoronoi(self.points * radius + center, radius, center)
        assert_array_equal(s1.center, np.array([0, 0, 0]))
        assert_equal(s1.radius, 1)
        assert_array_equal(s2.center, np.array([0, 0, 0]))
        assert_equal(s2.radius, 2)
        assert_array_equal(s3.center, center)
        assert_equal(s3.radius, 1)
        assert_array_equal(s4.center, center)
        assert_equal(s4.radius, radius)

    def test_vertices_regions_translation_invariance(self):
        sv_origin = SphericalVoronoi(self.points)
        center = np.array([1, 1, 1])
        sv_translated = SphericalVoronoi(self.points + center, center=center)
        assert_equal(sv_origin.regions, sv_translated.regions)
        assert_array_almost_equal(sv_origin.vertices + center,
                                  sv_translated.vertices)

    def test_vertices_regions_scaling_invariance(self):
        sv_unit = SphericalVoronoi(self.points)
        sv_scaled = SphericalVoronoi(self.points * 2, 2)
        assert_equal(sv_unit.regions, sv_scaled.regions)
        assert_array_almost_equal(sv_unit.vertices * 2,
                                  sv_scaled.vertices)

    def test_old_radius_api(self):
        sv_unit = SphericalVoronoi(self.points, radius=1)
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "`radius` is `None`")
            sv = SphericalVoronoi(self.points, None)
            assert_array_almost_equal(sv_unit.vertices, sv.vertices)

    def test_old_radius_api_warning(self):
        with assert_warns(DeprecationWarning):
            SphericalVoronoi(self.points, None)
<commit_msg>TST: Add a `SphericalVoronoi` test for a non-sequence-based array-like<commit_after>import numpy as np
import itertools
from numpy.testing import (assert_equal,
                           assert_almost_equal,
                           assert_array_equal,
                           assert_array_almost_equal,
                           suppress_warnings)
import pytest
from pytest import raises as assert_raises
from pytest import warns as assert_warns
from scipy.spatial import SphericalVoronoi, distance
from scipy.optimize import linear_sum_assignment
from scipy.constants import golden as phi
from scipy.special import gamma


TOL = 1E-10


def _generate_tetrahedron():
    return np.array([[1, 1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, 1]])


def _generate_cube():
    return np.array(list(itertools.product([-1, 1.], repeat=3)))


def _generate_octahedron():
    return np.array([[-1, 0, 0], [+1, 0, 0], [0, -1, 0],
                     [0, +1, 0], [0, 0, -1], [0, 0, +1]])


def _generate_dodecahedron():

    x1 = _generate_cube()
    x2 = np.array([[0, -phi, -1 / phi],
                   [0, -phi, +1 / phi],
                   [0, +phi, -1 / phi],
                   [0, +phi, +1 / phi]])
    x3 = np.array([[-1 / phi, 0, -phi],
                   [+1 / phi, 0, -phi],
                   [-1 / phi, 0, +phi],
                   [+1 / phi, 0, +phi]])
    x4 = np.array([[-phi, -1 / phi, 0],
                   [-phi, +1 / phi, 0],
                   [+phi, -1 / phi, 0],
                   [+phi, +1 / phi, 0]])
    return np.concatenate((x1, x2, x3, x4))


def _generate_icosahedron():
    x = np.array([[0, -1, -phi],
                  [0, -1, +phi],
                  [0, +1, -phi],
                  [0, +1, +phi]])
    return np.concatenate([np.roll(x, i, axis=1) for i in range(3)])


def _generate_polytope(name):
    polygons = ["triangle", "square", "pentagon", "hexagon", "heptagon",
                "octagon", "nonagon", "decagon", "undecagon", "dodecagon"]
    polyhedra = ["tetrahedron", "cube", "octahedron", "dodecahedron",
                 "icosahedron"]
    if name not in polygons and name not in polyhedra:
        raise ValueError("unrecognized polytope")

    if name in polygons:
        n = polygons.index(name) + 3
        thetas = np.linspace(0, 2 * np.pi, n, endpoint=False)
        p = np.vstack([np.cos(thetas), np.sin(thetas)]).T
    elif name == "tetrahedron":
        p = _generate_tetrahedron()
    elif name == "cube":
        p = _generate_cube()
    elif name == "octahedron":
        p = _generate_octahedron()
    elif name == "dodecahedron":
        p = _generate_dodecahedron()
    elif name == "icosahedron":
        p = _generate_icosahedron()

    return p / np.linalg.norm(p, axis=1, keepdims=True)


def _hypersphere_area(dim, radius):
    # https://en.wikipedia.org/wiki/N-sphere#Closed_forms
    return 2 * np.pi**(dim / 2) / gamma(dim / 2) * radius**(dim - 1)


def _sample_sphere(n, dim, seed=None):
    # Sample points uniformly at random from the hypersphere
    rng = np.random.RandomState(seed=seed)
    points = rng.randn(n, dim)
    points /= np.linalg.norm(points, axis=1, keepdims=True)
    return points


class TestSphericalVoronoi:

    def setup_method(self):
        self.points = np.array([
            [-0.78928481, -0.16341094, 0.59188373],
            [-0.66839141, 0.73309634, 0.12578818],
            [0.32535778, -0.92476944, -0.19734181],
            [-0.90177102, -0.03785291, -0.43055335],
            [0.71781344, 0.68428936, 0.12842096],
            [-0.96064876, 0.23492353, -0.14820556],
            [0.73181537, -0.22025898, -0.6449281],
            [0.79979205, 0.54555747, 0.25039913]]
        )

    def test_constructor(self):
        center = np.array([1, 2, 3])
        radius = 2
        s1 = SphericalVoronoi(self.points)
        # user input checks in SphericalVoronoi now require
        # the radius / center to match the generators so adjust
        # accordingly here
        s2 = SphericalVoronoi(self.points * radius, radius)
        s3 = SphericalVoronoi(self.points + center, center=center)
        s4 = SphericalVoronoi(self.points * radius + center, radius, center)
        assert_array_equal(s1.center, np.array([0, 0, 0]))
        assert_equal(s1.radius, 1)
        assert_array_equal(s2.center, np.array([0, 0, 0]))
        assert_equal(s2.radius, 2)
        assert_array_equal(s3.center, center)
        assert_equal(s3.radius, 1)
        assert_array_equal(s4.center, center)
        assert_equal(s4.radius, radius)

        # Test a non-sequence/-ndarray based array-like
        s5 = SphericalVoronoi(memoryview(self.points))
        assert_array_equal(s5.center, np.array([0, 0, 0]))
        assert_equal(s5.radius, 1)

    def test_vertices_regions_translation_invariance(self):
        sv_origin = SphericalVoronoi(self.points)
        center = np.array([1, 1, 1])
        sv_translated = SphericalVoronoi(self.points + center, center=center)
        assert_equal(sv_origin.regions, sv_translated.regions)
        assert_array_almost_equal(sv_origin.vertices + center,
                                  sv_translated.vertices)

    def test_vertices_regions_scaling_invariance(self):
        sv_unit = SphericalVoronoi(self.points)
        sv_scaled = SphericalVoronoi(self.points * 2, 2)
        assert_equal(sv_unit.regions, sv_scaled.regions)
        assert_array_almost_equal(sv_unit.vertices * 2,
                                  sv_scaled.vertices)

    def test_old_radius_api(self):
        sv_unit = SphericalVoronoi(self.points, radius=1)
        with suppress_warnings() as sup:
            sup.filter(DeprecationWarning, "`radius` is `None`")
            sv = SphericalVoronoi(self.points, None)
            assert_array_almost_equal(sv_unit.vertices, sv.vertices)

    def test_old_radius_api_warning(self):
        with assert_warns(DeprecationWarning):
            SphericalVoronoi(self.points, None)

{'fraction_non_alphanumeric': 0.1323795570111178, 'fraction_numerical': 0.058174610014651386, 'mean_word_length': 2.2632170978627673, 'pattern_counts': {'":': 10, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3739616', 'n_tokens_mistral': 4529, 'n_tokens_neox': 4021, 'n_words': 887}