Skip to content

Commit

Permalink
Fixed importskips
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Peter Krone committed Dec 16, 2024
1 parent 1ce9ea3 commit 2fda767
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 252 deletions.
249 changes: 0 additions & 249 deletions tests/test_draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from iminuit import Minuit
from pathlib import Path
import numpy as np
from numpy.testing import assert_allclose
import contextlib

mpl = pytest.importorskip("matplotlib")
plt = pytest.importorskip("matplotlib.pyplot")
Expand All @@ -15,12 +13,6 @@ def f1(x, y):
return (1 - x) ** 2 + np.exp((y - 1) ** 2)


def qtinteractive(m, plot=None, raise_on_exception=False, **kwargs):
from iminuit.qtwidget import make_widget

return make_widget(m, plot, kwargs, raise_on_exception, run_event_loop=False)


@pytest.fixture
def minuit():
m = Minuit(f1, x=0, y=0)
Expand Down Expand Up @@ -139,244 +131,3 @@ def test_mnmatrix_7(fig):
m = Minuit(lambda x: abs(x) ** 2 + x**4 + 10 * x, x=0)
m.migrad()
m.draw_mnmatrix(cl=[1, 3])


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets(mock_ipython):
ipywidgets = pytest.importorskip("ipywidgets")

def cost(a, b):
return a**2 + b**2

class Plot:
def __init__(self):
self.called = False
self.raises = False

def __call__(self, args):
self.called = True
if self.raises:
raise ValueError("foo")

@contextlib.contextmanager
def assert_call(self):
self.called = False
yield
assert self.called

plot = Plot()

m = Minuit(cost, 1, 1)

with pytest.raises(AttributeError, match="no visualize method"):
m.interactive(raise_on_exception=True)

with plot.assert_call():
out1 = m.interactive(plot)
assert isinstance(out1, ipywidgets.HBox)

# manipulate state to also check this code
ui = out1.children[1]
header, parameters = ui.children
fit_button, update_button, reset_button, algo_select = header.children
with plot.assert_call():
fit_button.click()
assert_allclose(m.values, (0, 0), atol=1e-5)
with plot.assert_call():
reset_button.click()
assert_allclose(m.values, (1, 1), atol=1e-5)

algo_select.value = "Scipy"
with plot.assert_call():
fit_button.click()

algo_select.value = "Simplex"
with plot.assert_call():
fit_button.click()

update_button.value = False
with plot.assert_call():
# because of implementation details, we have to trigger the slider several times
for i in range(5):
parameters.children[0].slider.value = i # change first slider
parameters.children[0].fix.value = True
with plot.assert_call():
parameters.children[0].fit.value = True

class Cost:
def visualize(self, args):
return plot(args)

def __call__(self, a, b):
return (a - 100) ** 2 + (b + 100) ** 2

c = Cost()
m = Minuit(c, 0, 0)
with plot.assert_call():
out = m.interactive(raise_on_exception=True)

# this should modify slider range
ui = out.children[1]
header, parameters = ui.children
fit_button, update_button, reset_button, algo_select = header.children
assert parameters.children[0].slider.max == 1
assert parameters.children[1].slider.min == -1
with plot.assert_call():
fit_button.click()
assert_allclose(m.values, (100, -100), atol=1e-5)
# this should trigger an exception
plot.raises = True
with plot.assert_call():
fit_button.click()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_pyqt6(qtbot):
PyQt6 = pytest.importorskip("PyQt6")

def cost(a, b):
return a**2 + b**2

class Plot:
def __init__(self):
self.called = False
self.raises = False

def __call__(self, args):
self.called = True
if self.raises:
raise ValueError("foo")

@contextlib.contextmanager
def assert_call(self):
self.called = False
yield
assert self.called

plot = Plot()

m = Minuit(cost, 1, 1)

with plot.assert_call():
mw1 = qtinteractive(m, plot)
qtbot.addWidget(mw1)
assert isinstance(mw1, PyQt6.QtWidgets.QWidget)

# manipulate state to also check this code
with plot.assert_call():
mw1.fit_button.click()
assert_allclose(m.values, (0, 0), atol=1e-5)
with plot.assert_call():
mw1.reset_button.click()
assert_allclose(m.values, (1, 1), atol=1e-5)

mw1.algo_choice.setCurrentText("Scipy")
with plot.assert_call():
mw1.fit_button.click()

mw1.algo_choice.setCurrentText("Simplex")
with plot.assert_call():
mw1.fit_button.click()

mw1.update_button.click()
with plot.assert_call():
mw1.parameters[0].slider.valueChanged.emit(int(5e7))
mw1.parameters[0].fix.click()
with plot.assert_call():
mw1.parameters[0].fit.click()

class Cost:
def visualize(self, args):
return plot(args)

def __call__(self, a, b):
return (a - 100) ** 2 + (b + 100) ** 2

c = Cost()
m = Minuit(c, 0, 0)
with plot.assert_call():
mw = qtinteractive(m, raise_on_exception=True)
qtbot.addWidget(mw)

# this should modify slider range
assert mw.parameters[0].vmax == 1
assert mw.parameters[1].vmin == -1
with plot.assert_call():
mw.fit_button.click()
assert_allclose(m.values, (100, -100), atol=1e-5)
# this should trigger an exception
# plot.raises = True
# with plot.assert_call():
# mw.fit_button.click()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets_raises(mock_ipython):
pytest.importorskip("ipywidgets")

def raiser(args):
raise ValueError

m = Minuit(lambda x, y: 0, 0, 1)

# by default do not raise
m.interactive(raiser)

with pytest.raises(ValueError):
m.interactive(raiser, raise_on_exception=True)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_pyqt6_raises(qtbot):
pytest.importorskip("PyQt6")

def raiser(args):
raise ValueError

m = Minuit(lambda x, y: 0, 0, 1)

# by default do not raise
qtinteractive(m, raiser)

with pytest.raises(ValueError):
qtinteractive(m, raiser, raise_on_exception=True)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets_with_array_func(mock_ipython):
pytest.importorskip("ipywidgets")

def cost(par):
return par[0] ** 2 + (par[1] / 2) ** 2

class TraceArgs:
nargs = 0

def __call__(self, par):
self.nargs = len(par)

trace_args = TraceArgs()
m = Minuit(cost, (1, 2))

m.interactive(trace_args)
assert trace_args.nargs > 0


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_pyqt6_with_array_func(qtbot):
pytest.importorskip("PyQt6")

def cost(par):
return par[0] ** 2 + (par[1] / 2) ** 2

class TraceArgs:
nargs = 0

def __call__(self, par):
self.nargs = len(par)

trace_args = TraceArgs()
m = Minuit(cost, (1, 2))

qtinteractive(m, trace_args)
assert trace_args.nargs > 0
129 changes: 129 additions & 0 deletions tests/test_ipywidget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import pytest
from iminuit import Minuit
from numpy.testing import assert_allclose
import contextlib

mpl = pytest.importorskip("matplotlib")
plt = pytest.importorskip("matplotlib.pyplot")
ipywidgets = pytest.importorskip("ipywidgets")

mpl.use("Agg")


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets(mock_ipython):
def cost(a, b):
return a**2 + b**2

class Plot:
def __init__(self):
self.called = False
self.raises = False

def __call__(self, args):
self.called = True
if self.raises:
raise ValueError("foo")

@contextlib.contextmanager
def assert_call(self):
self.called = False
yield
assert self.called

plot = Plot()

m = Minuit(cost, 1, 1)

with pytest.raises(AttributeError, match="no visualize method"):
m.interactive(raise_on_exception=True)

with plot.assert_call():
out1 = m.interactive(plot)
assert isinstance(out1, ipywidgets.HBox)

# manipulate state to also check this code
ui = out1.children[1]
header, parameters = ui.children
fit_button, update_button, reset_button, algo_select = header.children
with plot.assert_call():
fit_button.click()
assert_allclose(m.values, (0, 0), atol=1e-5)
with plot.assert_call():
reset_button.click()
assert_allclose(m.values, (1, 1), atol=1e-5)

algo_select.value = "Scipy"
with plot.assert_call():
fit_button.click()

algo_select.value = "Simplex"
with plot.assert_call():
fit_button.click()

update_button.value = False
with plot.assert_call():
# because of implementation details, we have to trigger the slider several times
for i in range(5):
parameters.children[0].slider.value = i # change first slider
parameters.children[0].fix.value = True
with plot.assert_call():
parameters.children[0].fit.value = True

class Cost:
def visualize(self, args):
return plot(args)

def __call__(self, a, b):
return (a - 100) ** 2 + (b + 100) ** 2

c = Cost()
m = Minuit(c, 0, 0)
with plot.assert_call():
out = m.interactive(raise_on_exception=True)

# this should modify slider range
ui = out.children[1]
header, parameters = ui.children
fit_button, update_button, reset_button, algo_select = header.children
assert parameters.children[0].slider.max == 1
assert parameters.children[1].slider.min == -1
with plot.assert_call():
fit_button.click()
assert_allclose(m.values, (100, -100), atol=1e-5)
# this should trigger an exception
plot.raises = True
with plot.assert_call():
fit_button.click()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets_raises(mock_ipython):
def raiser(args):
raise ValueError

m = Minuit(lambda x, y: 0, 0, 1)

# by default do not raise
m.interactive(raiser)

with pytest.raises(ValueError):
m.interactive(raiser, raise_on_exception=True)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_interactive_ipywidgets_with_array_func(mock_ipython):
def cost(par):
return par[0] ** 2 + (par[1] / 2) ** 2

class TraceArgs:
nargs = 0

def __call__(self, par):
self.nargs = len(par)

trace_args = TraceArgs()
m = Minuit(cost, (1, 2))

m.interactive(trace_args)
assert trace_args.nargs > 0
Loading

0 comments on commit 2fda767

Please sign in to comment.