Skip to content

Commit f05cd8d

Browse files
authored
fixes for minos everywhere when fcn is n-dim (#591)
1 parent 1a30804 commit f05cd8d

File tree

3 files changed

+206
-82
lines changed

3 files changed

+206
-82
lines changed

src/iminuit/_minuit.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,8 @@ def minos(self, *parameters, cl=None, ncall=None):
793793
794794
self
795795
"""
796+
ncall = 0 if ncall is None else int(ncall)
797+
796798
if cl is None:
797799
factor = 1.0
798800
else:
@@ -803,19 +805,20 @@ def minos(self, *parameters, cl=None, ncall=None):
803805
factor = chi2(1).ppf(cl)
804806

805807
if not self._fmin:
806-
# create a FunctionMinimum for MnMinos
808+
# create a seed minimum for MnMinos
807809
fm = FunctionMinimum(
808810
self._fcn, self._last_state, self._strategy, self._tolerance
809811
)
812+
# running MnHesse on seed is necessary for MnMinos to work
813+
hesse = MnHesse(self.strategy)
814+
hesse(self._fcn, fm, ncall)
815+
self._last_state = fm.state
816+
self._make_covariance()
810817
else:
811818
fm = self._fmin._src
812819

813-
ncall = 0 if ncall is None else int(ncall)
814-
815820
if not fm.is_valid:
816-
raise RuntimeError(
817-
"Function minimum is not valid. Make sure MIGRAD converged."
818-
)
821+
raise RuntimeError("Function minimum is not valid.")
819822

820823
if len(parameters) == 0:
821824
pars = [par for par in self.parameters if not self.fixed[par]]

tests/test_minuit.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -1461,10 +1461,14 @@ def test_minos_new_min():
14611461
assert m.merrors["x"].upper == approx(1.1, abs=1e-2)
14621462

14631463

1464-
@pytest.mark.parametrize("x", (0.9, 1.0, 1.1))
1465-
def test_minos_without_migrad(x):
1466-
m = Minuit(lsq(lambda x: (x - 1) ** 2), x)
1464+
def test_minos_without_migrad():
1465+
m = Minuit(lsq(lambda x, y: (x - 1) ** 2 + (y / 2) ** 2), 1.001, 0.001)
14671466
m.minos()
14681467
me = m.merrors["x"]
1469-
assert x + me.lower == approx(0, abs=5e-3)
1470-
assert x + me.upper == approx(2, abs=5e-3)
1468+
assert me.is_valid
1469+
assert me.lower == approx(-1, abs=5e-3)
1470+
assert me.upper == approx(1, abs=5e-3)
1471+
me = m.merrors["y"]
1472+
assert me.is_valid
1473+
assert me.lower == approx(-2, abs=5e-3)
1474+
assert me.upper == approx(2, abs=5e-3)

0 commit comments

Comments
 (0)