Repository: fjosw/pyerrors

Issue:
least_squares fit using migrad is broken
```python
import pyerrors as pe
import numpy as np
x = np.arange(10)
y = [pe.pseudo_Obs(i+1, i*.2+.01, 'test') for i in x]
[o.gamma_method() for o in y]
def func(a, x):
    return a[0] + a[1] * x
pe.fits.least_squares(x, y, func)
pe.fits.least_squares(x, y, func, method='migrad')
```
results in 
```
KeyError                                  Traceback (most recent call last)
/opt/anaconda3/lib/python3.6/site-packages/scipy/optimize/optimize.py in __getattr__(self, name)
    121         try:
--> 122             return self[name]
    123         except KeyError:

KeyError: 'nit'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-18-79beea198971> in <module>
      7     return a[0] + a[1] * x
      8 pe.fits.least_squares(x, y, func)
----> 9 pe.fits.least_squares(x, y, func, method='migrad')

~/phd/git/pyerrors_github/pyerrors/fits.py in least_squares(x, y, func, priors, silent, **kwargs)
    118         return _prior_fit(x, y, func, priors, silent=silent, **kwargs)
    119     else:
--> 120         return _standard_fit(x, y, func, silent=silent, **kwargs)
    121 
    122 

~/phd/git/pyerrors_github/pyerrors/fits.py in _standard_fit(x, y, func, silent, **kwargs)
    501         chisquare = fit_result.fun
    502 
--> 503         output.iterations = fit_result.nit
    504     else:
    505         output.method = 'Levenberg-Marquardt'

/opt/anaconda3/lib/python3.6/site-packages/scipy/optimize/optimize.py in __getattr__(self, name)
    122             return self[name]
    123         except KeyError:
--> 124             raise AttributeError(name)
    125 
    126     __setattr__ = dict.__setitem__

AttributeError: nit
```

using python3.6 and migrad 2.8.4 (and 2.8.3)

Discussion:

Patch:
diff --git a/pyerrors/fits.py b/pyerrors/fits.py
index 22c69fe..311fba8 100644
--- a/pyerrors/fits.py
+++ b/pyerrors/fits.py
@@ -487,20 +487,21 @@ def _standard_fit(x, y, func, silent=False, **kwargs):
             chisq = anp.sum(((y_f - model) / dy_f) ** 2)
             return chisq
 
-    if 'method' in kwargs:
+    if 'method' in kwargs and not (kwargs.get('method', 'Levenberg-Marquardt') == 'Levenberg-Marquardt'):
         output.method = kwargs.get('method')
         if not silent:
             print('Method:', kwargs.get('method'))
         if kwargs.get('method') == 'migrad':
             fit_result = iminuit.minimize(chisqfunc, x0)
             fit_result = iminuit.minimize(chisqfunc, fit_result.x)
+            output.iterations = fit_result.nfev
         else:
             fit_result = scipy.optimize.minimize(chisqfunc, x0, method=kwargs.get('method'))
             fit_result = scipy.optimize.minimize(chisqfunc, fit_result.x, method=kwargs.get('method'), tol=1e-12)
+            output.iterations = fit_result.nit
 
         chisquare = fit_result.fun
 
-        output.iterations = fit_result.nit
     else:
         output.method = 'Levenberg-Marquardt'
         if not silent:


Test patch:
diff --git a/tests/fits_test.py b/tests/fits_test.py
index 48012ed..33a3b95 100644
--- a/tests/fits_test.py
+++ b/tests/fits_test.py
@@ -49,6 +49,8 @@ def test_least_squares():
         y = a[0] * np.exp(-a[1] * x)
         return y
 
+    out = pe.least_squares(x, oy, func, method='migrad')
+    out = pe.least_squares(x, oy, func, method='Powell')
     out = pe.least_squares(x, oy, func, expected_chisquare=True, resplot=True, qqplot=True)
     beta = out.fit_parameters