text: # std
  import itertools
  
  # third-party
  import pytest
  import numpy as np
  import matplotlib.pyplot as plt
  from scipy.special import lpmv
  
  # local
  from recipes.testing import expected
  from mCV.bfield import (IdealMultipole, MultipoleFieldLines, PhysicalMultipole,
                          PhysicalMultipoleFieldLines, _alf1_zeros, π)
  
  
  # ---------------------------------------------------------------------------- #
  # Module variables
  # ---------------------------------------------------------------------------- #
  _SHELLS = np.arange(1, 5)
  _INIT_PARAMS = {
      PhysicalMultipoleFieldLines: {'radius': 0.25},
      PhysicalMultipole: {'radius': 0.25},
  }
  
  # ---------------------------------------------------------------------------- #
  # Fixtures
  # ---------------------------------------------------------------------------- #
  
  
  @pytest.fixture(scope='module',
                  params=[MultipoleFieldLines,
                          PhysicalMultipoleFieldLines])
  def fieldline_class(request):
      return request.param
  
  
  @pytest.fixture(scope='module',
                  params=[IdealMultipole,
                          PhysicalMultipole])
  def multipole_class(request):
      return request.param
  
  
  @pytest.fixture(scope='module',
                  params=range(1, 8))
  def degree(request):
      return request.param
  
  
  def _init(kls, degree):
      return kls(degree, **_INIT_PARAMS.get(kls, {}))
  
  
  @pytest.fixture(scope='module')
  def fieldlines(fieldline_class, degree):
      return _init(fieldline_class, degree)
  
  
  @pytest.fixture(scope='module')
  def multipole(multipole_class, degree):
      return _init(multipole_class, degree)
  
  
  @pytest.fixture(scope='module',
                  params=[MultipoleFieldLines,
                          PhysicalMultipoleFieldLines,
                          IdealMultipole,
                          PhysicalMultipole])
  def plotable(request, degree):
      return _init(request.param, degree)
  
  
  # ---------------------------------------------------------------------------- #
  # def test_dipole():
  #     return MagneticDipole(theta=30, phi=30).plot3d(rmin=0.1, alpha=1)
  
  
  # def test_ideal_multipole(degree):
  #     IdealMultipole(0, degree)
  
  
  # class TestMultipoleFieldLine:
  #     def test_get_zeros(self):
  #         l = 5
  #         MultipoleFieldLines(l)
  
  
  # class TestMultipoleFieldLines:
  
  # plt.show()
  def test_alf1_zeros():
  
      res = 100
  
      fig, ax = plt.subplots()
  
      for l in range(8, 12):
          x = np.linspace(0, 1, res)
          line, = ax.plot(x, lpmv(1, l, x), ':',)  # color=line.get_color()
          thc = _alf1_zeros(l)
          print(f'l = {l}\nzeros = {thc}\n')
          ax.plot(thc, np.zeros_like(thc), 'x',  color=line.get_color())
  
  
  def test_legendre_zero_angles():
      res = 100
  
      fig, ax = plt.subplots()
  
      for l in range(2, 8):
          θ = np.linspace(π / 2, 0, res)
          sinθ, cosθ = np.cos(θ), np.sin(θ)
          #pl0 = lpmv(0, l, cosθ)
          pl1 = lpmv(1, l, cosθ)
          sl = np.sin(θ) * pl1
          line, = ax.plot(θ, sl, ':',)  # color=line.get_color()
          thc = π / 2 - np.arccos(_alf1_zeros(l))
  
          print(f'l = {l}\nzeros = {thc}\n')
          ax.plot(thc, np.zeros_like(thc), 'x',  color=line.get_color())
  
      ax.grid()
      ax.legend()
      fig
  
  
  def test_get_loop_index(fieldlines):
      for m, i in itertools.product(range(2), range(fieldlines.degree)):
          point = m * π + fieldlines.theta_intervals[i].mean()
          assert fieldlines.get_loop_index(point) == m * fieldlines.degree + i
  
  
  # test_split_interval_ideal =
  @expected(
      kls=MultipoleFieldLines,
      cases={
          # -------------------------------------------------------------------- #
          # dipole
          # -------------------------------------------------------------------- #
          (1, (0, π - 0.1)):
              np.array([[0.0,        3.04159265]]),
          (1, (0, π)):
              np.array([[0.0,        3.14159265]]),
          (1, (0, π + 0.1)):
              np.array([[0.0,        3.14159265],
                        [3.14159265, 3.24159265]]),
          (1, (0, 2 * π - 0.1)):
              np.array([[0.0,        3.14159265],
                        [3.14159265, 6.18318531]]),
          (1, (0, 2 * π)):
              np.array([[0.0,        3.14159265],
                        [3.14159265, 6.28318531]]),
          (1, (0, 2 * π + 0.1)):
              np.array([[0.0,        3.14159265],
                        [3.14159265, 6.28318531],
                        [6.28318531, 6.38318531]]),
  
          # -------------------------------------------------------------------- #
          # quadrupole
          # -------------------------------------------------------------------- #
          (2, (0, π - 0.1)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.04159265]]),
          (2, (0, π)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.14159265]]),
          (2, (0, π + 0.1)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.14159265],
                        [3.14159265, 3.24159265]]),
          (2, (0, 2 * π - 0.1)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.14159265],
                        [3.14159265, 4.71238898],
                        [4.71238898, 6.18318531]]),
          (2, (0, 2 * π)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.14159265],
                        [3.14159265, 4.71238898],
                        [4.71238898, 6.28318531]]),
          (2, (0, 2 * π + 0.1)):
              np.array([[0.0,        1.57079633],
                        [1.57079633, 3.14159265],
                        [3.14159265, 4.71238898],
                        [4.71238898, 6.28318531],
                        [6.28318531, 6.38318531]]),
  
          # -------------------------------------------------------------------- #
          # sextupole
          # -------------------------------------------------------------------- #
          (3, (0, π - 0.1)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.04159265]]),
          (3, (0, π)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.14159265]]),
          (3, (0, π + 0.1)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.14159265],
                        [3.14159265, 3.24159265]]),
          (3, (0, 2 * π - 0.1)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.14159265],
                        [3.14159265, 4.24874137],
                        [4.24874137, 5.17603659],
                        [5.17603659, 6.18318531]]),
          (3, (0, 2 * π)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.14159265],
                        [3.14159265, 4.24874137],
                        [4.24874137, 5.17603659],
                        [5.17603659, 6.28318531]]),
          (3, (0, 2 * π + 0.1)):
              np.array([[0.0,        1.10714872],
                        [1.10714872, 2.03444394],
                        [2.03444394, 3.14159265],
                        [3.14159265, 4.24874137],
                        [4.24874137, 5.17603659],
                        [5.17603659, 6.28318531],
                        [6.28318531, 6.38318531]]),
  
          # -------------------------------------------------------------------- #
          # octupole
          # -------------------------------------------------------------------- #
          (4, (0, π - 0.1)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.04159265]]),
          (4, (0, π)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.14159265]]),
          (4, (0, π + 0.1)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.14159265],
                        [3.14159265, 3.24159265]]),
          (4, (0, 2 * π - 0.1)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.14159265],
                        [3.14159265, 3.9986646],
                        [3.9986646,  4.71238898],
                        [4.71238898, 5.42611336],
                        [5.42611336, 6.18318531]]),
          (4, (0, 2 * π)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.14159265],
                        [3.14159265, 3.9986646],
                        [3.9986646,  4.71238898],
                        [4.71238898, 5.42611336],
                        [5.42611336, 6.28318531]]),
          (4, (0, 2 * π + 0.1)):
              np.array([[0.0,        0.85707195],
                        [0.85707195, 1.57079633],
                        [1.57079633, 2.28452071],
                        [2.28452071, 3.14159265],
                        [3.14159265, 3.9986646],
                        [3.9986646,  4.71238898],
                        [4.71238898, 5.42611336],
                        [5.42611336, 6.28318531],
                        [6.28318531, 6.38318531]]),
  
          # -------------------------------------------------------------------- #
          # decapole
          # -------------------------------------------------------------------- #
          (5, (0, π - 0.1)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.04159265]]),
          (5, (0, π)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.14159265]]),
          (5, (0, π + 0.1)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.14159265],
                        [3.14159265, 3.24159265]]),
          (5, (0, 2 * π - 0.1)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.14159265],
                        [3.14159265, 3.84126174],
                        [3.84126174, 4.42314101],
                        [4.42314101, 5.00163695],
                        [5.00163695, 5.58351622],
                        [5.58351622, 6.18318531]]),
          (5, (0, 2 * π)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.14159265],
                        [3.14159265, 3.84126174],
                        [3.84126174, 4.42314101],
                        [4.42314101, 5.00163695],
                        [5.00163695, 5.58351622],
                        [5.58351622, 6.28318531]]),
          (5, (0, 2 * π + 0.1)):
              np.array([[0.0,        0.69966909],
                        [0.69966909, 1.28154836],
                        [1.28154836, 1.8600443],
                        [1.8600443,  2.44192356],
                        [2.44192356, 3.14159265],
                        [3.14159265, 3.84126174],
                        [3.84126174, 4.42314101],
                        [4.42314101, 5.00163695],
                        [5.00163695, 5.58351622],
                        [5.58351622, 6.28318531],
                        [6.28318531, 6.38318531]]),
  
          # -------------------------------------------------------------------- #
          # didecapole
          # -------------------------------------------------------------------- #
          (6, (0, π - 0.1)):
              np.array([[0.0,        0.5912871],
                        [0.5912871,  1.08280933],
                        [1.08280933, 1.57079633],
                        [1.57079633, 2.05878332],
                        [2.05878332, 2.55030555],
                        [2.55030555, 3.04159265]]),
          (6, (0, π)):
              np.array([[0.0,        0.5912871],
                        [0.5912871,  1.08280933],
                        [1.08280933, 1.57079633],
                        [1.57079633, 2.05878332],
                        [2.05878332, 2.55030555],
                        [2.55030555, 3.14159265]]),
          (6, (0, π + 0.1)):
              np.array([[0.0,        0.5912871],
                        [0.5912871,  1.08280933],
                        [1.08280933, 1.57079633],
                        [1.57079633, 2.05878332],
                        [2.05878332, 2.55030555],
                        [2.55030555, 3.14159265],
                        [3.14159265, 3.24159265]]),
  
          # -------------------------------------------------------------------- #
          # quadecapole
          # -------------------------------------------------------------------- #
  
          (7, (0, π - 0.1)):
              np.array([[0.0,        0.5120536],
                        [0.5120536,  0.93763012],
                        [0.93763012, 1.35993808],
                        [1.35993808, 1.78165458],
                        [1.78165458, 2.20396253],
                        [2.20396253, 2.62953906],
                        [2.62953906, 3.04159265]]),
          (7, (0, π)):
              np.array([[0.0,        0.5120536],
                        [0.5120536,  0.93763012],
                        [0.93763012, 1.35993808],
                        [1.35993808, 1.78165458],
                        [1.78165458, 2.20396253],
                        [2.20396253, 2.62953906],
                        [2.62953906, 3.14159265]]),
          (7, (0, π + 0.1)):
              np.array([[0.0,        0.5120536],
                        [0.5120536,  0.93763012],
                        [0.93763012, 1.35993808],
                        [1.35993808, 1.78165458],
                        [1.78165458, 2.20396253],
                        [2.20396253, 2.62953906],
                        [2.62953906, 3.14159265],
                        [3.14159265, 3.24159265]])
  
          # ------------------------------------------------------------------------ #
      })
  def test_split_interval(degree, interval, kls, expected):
      fieldlines = kls(degree, **_INIT_PARAMS.get(kls, {}))
      _, intervals = fieldlines.split_interval_by_loop(interval)
      assert np.allclose(intervals, expected)
  
  
  # test_split_interval_physical =
  @expected(
      kls=PhysicalMultipoleFieldLines,
      cases={
          # -------------------------------------------------------------------- #
          # dipole
          # -------------------------------------------------------------------- #
          (1, (0, π - 0.1)):
              np.array([[0.52359878, 2.61799388]]),
          (1, (0, π)):
              np.array([[0.52359878, 2.61799388]]),
          (1, (0, π + 0.1)):
              np.array([[0.52359878, 2.61799388]]),
  
          (1, (0.6, π - 0.6,)):
              np.array([[0.6,        2.54159265]]),
          (1, (0.6, π)):
              np.array([[0.6,        2.61799388]]),
          (1, (0.6, π + 0.6,)):
              np.array([[0.6,        2.61799388],
                        [3.66519143, 3.74159265]]),
  
          (1, (0, 2 * π - 0.1)):
              np.array([[0.52359878, 2.61799388],
                        [3.66519143, 5.75958653]]),
          (1, (0, 2 * π)):
              np.array([[0.52359878, 2.61799388],
                        [3.66519143, 5.75958653]]),
          (1, (0, 2 * π + 0.1)):
              np.array([[0.52359878, 2.61799388],
                        [3.66519143, 5.75958653]]),
  
          (1, (0.6, π - 0.6)):
              np.array([[0.6,        2.54159265]]),
          (1, (0.6, π)):
              np.array([[0.6,        2.61799388]]),
          (1, (0.6, π + 0.6)):
              np.array([[0.6,        2.61799388],
                        [3.66519143, 3.74159265]]),
  
          (1, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        2.61799388],
                        [3.66519143, 5.68318531]]),
          (1, (0.6, 2 * π)):
              np.array([[0.6,        2.61799388],
                        [3.66519143, 5.75958653]]),
          (1, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        2.61799388],
                        [3.66519143, 5.75958653],
                        [6.80678408, 6.88318531]]),
  
          # -------------------------------------------------------------------- #
          # quadrupole
          # -------------------------------------------------------------------- #
          (2, (0, π - 0.1)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158]]),
          (2, (0, π)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158]]),
          (2, (0, π + 0.1)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158]]),
          (2, (0, 2 * π - 0.1)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 6.09024423]]),
          (2, (0, 2 * π)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 6.09024423]]),
          (2, (0, 2 * π + 0.1)):
              np.array([[0.19294107, 1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 6.09024423]]),
  
          (2, (0.6, π - 0.6)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.54159265]]),
          (2, (0.6, π)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.94865158]]),
          (2, (0.6, π + 0.6)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 3.74159265]]),
  
          (2, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 5.68318531]]),
          (2, (0.6, 2 * π)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 6.09024423]]),
          (2, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        1.5346569],
                        [1.60693575, 2.94865158],
                        [3.33453373, 4.67624955],
                        [4.74852841, 6.09024423],
                        [6.47612638, 6.88318530]]),
  
          # -------------------------------------------------------------------- #
          # sextupole
          # -------------------------------------------------------------------- #
          (3, (0, π - 0.1)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346, 3.04159265]]),
          (3, (0, π)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562]]),
          (3, (0, π + 0.1)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 3.24159265]]),
          (3, (0, 2 * π - 0.1)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 6.18318531]]),
          (3, (0, 2 * π)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 6.20290828]]),
          (3, (0, 2 * π + 0.1)):
              np.array([[0.08027703, 1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 6.20290828],
                        [6.36346234, 6.38318531]]),
  
          (3, (0.6, π - 0.6)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  2.54159265]]),
          (3, (0.6, π)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562]]),
          (3, (0.6, π + 0.6)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 3.74159265]]),
          (3, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 5.68318531]]),
          (3, (0.6, 2 * π)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 6.20290828]]),
          (3, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        1.09915805],
                        [1.11510758, 2.02648508],
                        [2.0424346,  3.06131562],
                        [3.22186968, 4.24075071],
                        [4.25670023, 5.16807773],
                        [5.18402725, 6.20290828],
                        [6.36346234, 6.88318531]]),
  
  
          # -------------------------------------------------------------------- #
          # octupole
          # -------------------------------------------------------------------- #
          (4, (0, π - 0.1)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.04159265]]),
          (4, (0, π)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999]]),
          (4, (0, π + 0.1)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.24159265]]),
          (4, (0, 2 * π - 0.1)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 6.18318531]]),
          (4, (0, 2 * π)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 6.24798264]]),
          (4, (0, 2 * π + 0.1)):
              np.array([[0.03520266, 0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 6.24798264],
                        [6.31838797, 6.38318531]]),
  
          (4, (0.6, π - 0.6)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 2.54159265]]),
          (4, (0.6, π)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999]]),
          (4, (0.6, π + 0.6)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.74159265]]),
          (4, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 5.68318531]]),
          (4, (0.6, 2 * π)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 6.24798264]]),
          (4, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        0.8551639],
                        [0.85897685, 1.56914929],
                        [1.57244336, 2.2826158],
                        [2.28642876, 3.10638999],
                        [3.17679532, 3.99675655],
                        [4.00056951, 4.71074195],
                        [4.71403602, 5.42420845],
                        [5.42802141, 6.24798264],
                        [6.31838797, 6.88318531]]),
  
          # -------------------------------------------------------------------- #
          # decapole
          # -------------------------------------------------------------------- #
          (5, (0, π - 0.1)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.04159265]]),
          (5, (0, π)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582]]),
          (5, (0, π + 0.1)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.24159265]]),
          (5, (0, 2 * π - 0.1)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 6.18318531]]),
          (5, (0, 2 * π)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 6.26729847]]),
          (5, (0, 2 * π + 0.1)):
              np.array([[0.01588683, 0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 6.26729847],
                        [6.29907214, 6.38318531]]),
  
          (5, (0.6, π - 0.6)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 2.54159265]]),
          (5, (0.6, π)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582]]),
          (5, (0.6, π + 0.6)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.74159265]]),
          (5, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 5.68318531]]),
          (5, (0.6, 2 * π)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 6.26729847]]),
          (5, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        0.69920249],
                        [0.70013543, 1.28116886],
                        [1.28192781, 1.85966484],
                        [1.8604238,  2.44145722],
                        [2.44239017, 3.12570582],
                        [3.15747949, 3.84079514],
                        [3.84172809, 4.42276151],
                        [4.42352047, 5.00125749],
                        [5.00201645, 5.58304987],
                        [5.58398282, 6.26729847],
                        [6.29907214, 6.88318531]]),
  
          # -------------------------------------------------------------------- #
          # dodecapole
          # -------------------------------------------------------------------- #
          # (6, (0, π - 0.1)):
          #     np.array([[0.0,        0.5912871],
          #               [0.5912871,  1.08280933],
          #               [1.08280933, 1.57079633],
          #               [1.57079633, 2.05878332],
          #               [2.05878332, 2.55030555],
          #               [2.55030555, 3.04159265]]),
          # (6, (0, π)):
          #     np.array([[0.0,        0.5912871],
          #               [0.5912871,  1.08280933],
          #               [1.08280933, 1.57079633],
          #               [1.57079633, 2.05878332],
          #               [2.05878332, 2.55030555],
          #               [2.55030555, 3.14159265]]),
          # (6, (0, π + 0.1)):
          #     np.array([[0.0,        0.5912871],
          #               [0.5912871,  1.08280933],
          #               [1.08280933, 1.57079633],
          #               [1.57079633, 2.05878332],
          #               [2.05878332, 2.55030555],
          #               [2.55030555, 3.14159265],
          #               [3.14159265, 3.24159265]]),
  
          (6, (0.6,  π - 0.6)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.54159265]]),
          (6, (0.6,  π)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.55019034],
                        [2.55042078, 3.13429259]]),
          (6, (0.6,  π + 0.6)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.55019034],
                        [2.55042078, 3.13429259],
                        [3.14889272, 3.73276453],
                        [3.73299497, 3.74159265]]),
          (6, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.55019034],
                        [2.55042078, 3.13429259],
                        [3.14889272, 3.73276453],
                        [3.73299497, 4.22431118],
                        [4.22449279, 4.71230374],
                        [4.71247422, 5.20028517],
                        [5.20046678, 5.68318530]]),
          (6, (0.6, 2 * π)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.55019034],
                        [2.55042078, 3.13429259],
                        [3.14889272, 3.73276453],
                        [3.73299497, 4.22431118],
                        [4.22449279, 4.71230374],
                        [4.71247422, 5.20028517],
                        [5.20046678, 5.69178299],
                        [5.69201343, 6.27588524]]),
          (6, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        1.08271852],
                        [1.08290014, 1.57071109],
                        [1.57088157, 2.05869251],
                        [2.05887413, 2.55019034],
                        [2.55042078, 3.13429259],
                        [3.14889272, 3.73276453],
                        [3.73299497, 4.22431118],
                        [4.22449279, 4.71230374],
                        [4.71247422, 5.20028517],
                        [5.20046678, 5.69178299],
                        [5.69201343, 6.27588524],
                        [6.29048538, 6.87435718],
                        [6.87458762, 6.88318531]]),
  
  
          # -------------------------------------------------------------------- #
          # quadecapole
          # -------------------------------------------------------------------- #
          # (7, (0, π - 0.1)):
          #     np.array([[0.0,        0.5120536],
          #               [0.5120536,  0.93763012],
          #               [0.93763012, 1.35993808],
          #               [1.35993808, 1.78165458],
          #               [1.78165458, 2.20396253],
          #               [2.20396253, 2.62953906],
          #               [2.62953906, 3.04159265]]),
          # (7, (0, π)):
          #     np.array([[0.0,        0.5120536],
          #               [0.5120536,  0.93763012],
          #               [0.93763012, 1.35993808],
          #               [1.35993808, 1.78165458],
          #               [1.78165458, 2.20396253],
          #               [2.20396253, 2.62953906],
          #               [2.62953906, 3.14159265]]),
          # (7, (0, π + 0.1)):
          #     np.array([[0.0,        0.5120536],
          #               [0.5120536,  0.93763012],
          #               [0.93763012, 1.35993808],
          #               [1.35993808, 1.78165458],
          #               [1.78165458, 2.20396253],
          #               [2.20396253, 2.62953906],
          #               [2.62953906, 3.14159265],
          #               [3.14159265, 3.24159265]])
  
          (7, (0.6,  π - 0.6)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.54159265]]),
  
          (7, (0.6,  π)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.62951047],
                        [2.62956765, 3.13819626]]),
          (7, (0.6,  π + 0.6)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.62951047],
                        [2.62956765, 3.13819626],
                        [3.14498905, 3.65361766],
                        [3.65367484, 3.74159265]]),
          (7, (0.6, 2 * π - 0.6)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.62951047],
                        [2.62956765, 3.13819626],
                        [3.14498905, 3.65361766],
                        [3.65367484, 4.07920067],
                        [4.07924488, 4.50151069],
                        [4.50155077, 4.92322719],
                        [4.92326727, 5.34553308],
                        [5.3455773,  5.68318530]]),
          (7, (0.6, 2 * π)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.62951047],
                        [2.62956765, 3.13819626],
                        [3.14498905, 3.65361766],
                        [3.65367484, 4.07920067],
                        [4.07924488, 4.50151069],
                        [4.50155077, 4.92322719],
                        [4.92326727, 5.34553308],
                        [5.3455773,  5.77110312],
                        [5.7711603,  6.27978891]]),
          (7, (0.6, 2 * π + 0.6)):
              np.array([[0.6,        0.93760801],
                        [0.93765223, 1.35991803],
                        [1.35995812, 1.78163453],
                        [1.78167462, 2.20394042],
                        [2.20398464, 2.62951047],
                        [2.62956765, 3.13819626],
                        [3.14498905, 3.65361766],
                        [3.65367484, 4.07920067],
                        [4.07924488, 4.50151069],
                        [4.50155077, 4.92322719],
                        [4.92326727, 5.34553308],
                        [5.3455773,  5.77110312],
                        [5.7711603,  6.27978891],
                        [6.2865817,  6.79521031],
                        [6.79526749, 6.88318531]]),
      })
  def test_split_interval(degree, interval, kls, expected):
      fieldlines = kls(degree, **_INIT_PARAMS.get(kls, {}))
      _, intervals = fieldlines.split_interval_by_loop(interval)
      assert np.allclose(intervals, expected)
  
  
  @pytest.mark.parametrize('d', [2, 3], ids='{}d'.format)
  @pytest.mark.mpl_image_compare(baseline_dir='data/images',
                                 remove_text=True,
                                 )
  def test_plot(plotable, d):
      method = getattr(plotable, f'plot{d}d')
      kws = {2: {'rshells': _SHELLS},
             3: {'nshells': 2}}[d]
      art = method(**kws)
  
      if isinstance(art, tuple):
          art = art[0]
  
      return art.axes.figure
  