------------------------
This is a breaking change for Interface that was deprecated in 1.x has been removed. In addition, breaking changes were made to the interface to arrive at a clean minimal state that is easier to learn, safer to use, and ready for the long-term future. **To keep existing scripts running, pin your major iminuit version to <2**, i.e. ``pip install 'iminuit<2'`` installs the 1.x series.
Under the hood, Cython was replaced with pybind11 to generate the bindings to the C++ Minuit2 library. This simplified the code considerably (Cython is bad at generating correct C++ bindings, while it is a breeze with pybind11).
Removed and changed interface (breaking changes)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``Minuit.__init__``
- Keywords ``error_*``, ``fix_*``, and ``limit_*`` were removed; assign to ``Minuit.errors``, ``Minuit.fixed``, and ``Minuit.limits`` to set initial step sizes, fix parameters, and set limits
- Keyword ``pedantic`` was removed; parameters must be initialised with values now or an error is raised
- Keyword ``errordef`` was removed; assign to ``Minuit.errordef`` to set the error definition of the cost function or better create an attribute called ``errordef`` on the cost function, Minuit uses this attribute if it exists
- Keyword ``throw_nan`` was removed; assign to ``Minuit.throw_nan`` instead
- Keyword ``print_level`` was removed; assign to ``Minuit.print_level`` instead
- Setting starting values with positional parameters is now allowed, e.g. ``Minuit(my_fcn, 1, 2)`` initialises the first parameters to 1 and the second to 2
- Keyword ``use_array_call`` was removed; call type is inferred from the initialisation value, if it is a sequence, the array call is used (see next item below)
- ``Minuit.from_array_func`` was removed; use ``Minuit(some_numpy_function, starting_array)`` instead
- ``Minuit.args`` was removed, use ``Minuit.values[:]`` to get the current parameter values as a tuple
- ``Minuit.values``
- Now behaves like an array instead of like a dict, i.e. methods like ``keys()`` and ``items()`` are gone and ``for x in minuit.values`` iterates over the values
- Item access via index and via parameter name is supported, e.g. ``minuit.values[0]`` and ``minuit.values["a"]`` access the value for the first parameter "a"
- Broadcasting is supported, e.g. ``minuit.values = 0`` sets all parameter values to 0
- Slicing is supported for setting and getting several parameter values at once
- ``Minuit.errors``: see changes to ``Minuit.values``
- ``Minuit.fixed``: see changes to ``Minuit.values``
- ``Minuit.migrad``
- Keyword ``resume`` was removed; use ``Minuit.reset`` instead
- Keyword ``precision`` was removed; use ``Minuit.precision`` instead
- Return value is now ``self`` instead of ``self.fmin, self.params``
- ``Minuit.hesse``: Return value is now ``self`` instead of ``self.params``
- ``Minuit.minos``
- Now accepts more than one positional argument (which must be parameter names) and computes Minos errors for them
- Return value is now ``self`` instead of ``self.merrors``
- ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy)
- ``Minuit.mncontour`` and ``Minuit.draw_mncontour``
- ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy)
- ``numpoints`` keyword replaced with ``size``
- Keyword arguments are keyword-only
- Return value is reduced to just the contour points as a numpy array
- ``Minuit.mnprofile`` and ``Minuit.draw_mnprofile``
- ``sigma`` keyword replaced with ``cl`` to set confidence level (requires scipy)
- ``numpoints`` keyword replaced with ``size``
- Keyword arguments are keyword-only
- ``Minuit.profile`` and ``Minuit.draw_profile``
- ``bins`` keyword replaced with ``size``
- Keyword arguments are keyword-only
- ``Minuit.fitarg`` was removed; to copy state use ``m2.values = m1.values; m2.limits = m1.limits`` etc. (Minuit object may become copyable and pickleable in the future)
- ``Minuit.matrix`` was removed; see ``Minuit.covariance``
- ``Minuit.covariance`` instead of a dict-like class is now an enhanced subclass of numpy.ndarray (util.Matrix) with the features:
- Behaves like a numpy.ndarray in numerical computations
- Rich display of the matrix in ipython and Jupyter notebook
- Element access via parameter names in addition to indices, e.g. Minuit.covariance["a", "b"] access the covariance of parameters "a" and "b"
- ``Minuit.covariance.correlation()`` computes the correlation matrix from the covariance matrix and returns it
- Has always full rank, number of rows and columns is equal to the number of parameters even when some are fixed; elements corresponding to fixed parameters are set to zero in the matrix
- ``Minuit.gcc`` was removed for lack of a known use-case (submit an issue if you need this, then it will come back)
- ``Minuit.is_clean_state`` was removed; use ``Minuit.fmin is None`` instead
- ``Minuit.latex_param`` was removed; LaTeX and other table formats can be produced by passing the output of ``minuit.params.to_table()`` to the external ``tabulate`` module available on PyPI
- ``Minuit.latex_initial_param`` was removed; see ``Minuit.latex_param``
- ``Minuit.latex_matrix`` was removed; LaTeX and other table formats can be produced by passing the output of ``minuit.covariance.to_table()`` to the external ``tabulate`` module available on PyPI
- ``Minuit.ncalls_total`` was replaced with ``Minuit.nfcn``
- ``Minuit.ngrads_total`` was replaced with ``Minuit.ngrad``
- ``Minuit.np_covariance`` is now obsolete and was removed; see ``Minuit.covariance``
- ``Minuit.np_matrix`` is now obsolete and was removed; see ``Minuit.covariance``
- ``Minuit.np_values`` was removed; use ``Minuit.values`` instead or ``np.array(m.values)``
- ``Minuit.np_errors`` was removed; use ``Minuit.errors`` instead or ``np.array(m.errors)``
- ``Minuit.np_merrors`` was removed; use ``Minuit.merrors`` or ``Minuit.params`` instead
- ``Minuit.use_array_call`` was removed, ``Minuit.fcn`` and ``Minuit.grad`` always require parameter values in form of sequences, e.g. ``minuit.fcn((1, 2))``
- ``util.FMin`` is now a data class with read-only attributes, the dict-like interface was removed (methods like ``keys()``, ``items()`` are gone)
- ``tolerance`` attribute was replaced with ``edm_goal``, since the effect of ``tolerance`` varies for ``Minuit.migrad`` and ``Minuit.simplex``, ``edm_goal`` is the actual value of interest
- Property ``nfcn`` is the total number of function calls so far
- Property ``ngrad`` is the total number of gradient calls so far
- ``ngrad_total`` was removed and replaced by ``ngrad``
- ``nfcn_total`` was removed and replaced by ``nfcn``
- ``up`` was removed and replaced by ``errordef`` (to have one consistent name)
- ``util.MError`` is now a data class, dict-like interface was removed (see ``util.FMin``)
- ``util.Param`` is now a data class, dict-like interface was removed (see ``util.FMin``)
- ``util.Matrix`` is now a subclass of a numpy.ndarray instead of a tuple of tuples
- ``util.InitialParamWarning`` was removed since it is no longer used
- ``util.MigradResult`` was removed since it is no longer used
- ``util.arguments_from_inspect`` was removed from the public interface, it lives on as a private function
New features
~~~~~~~~~~~~
- ``Minuit`` class
- Now a class with `__slots__`; assigning to a non-existent attribute (e.g. because of a typo) now raises an error
- Parameter names in Unicode are now fully supported, e.g. ``def fcn(α, β): ...`` works
- New method ``simplex`` to minimise the function with the Nelder-Mead method
- New method ``scan`` to minimise the function with a brute-force grid search (not recommended and infeasible for fits with more than a few free parameters)
- New method ``reset`` reverts to the initial parameter state
- New property ``limits``, an array-like view of the current parameter limits; allows to query and set limits with a behaviour analog to ``values``, ``errors`` etc.; broadcasting is supported, e.g. ``minuit.limits = (0, 1)`` makes all parameters bounded between 0 and 1 and ``minuit.limits = None`` removes all limits
- New property ``precision`` to change the precision that Minuit assumes for internal calculations of derivatives
- Support for calling numba-compiled functions that release the GIL (slightly more efficient already today and may be used in the future to compute derivatives in parallel)
- Now pretty-prints itself in Jupyter notebooks and the ipython shell, showing the equivalent of ``Minuit.fmin``, ``Minuit.params``, ``Minuit.merrors``, ``Minuit.covariance``, whatever is available
- ``util.Param`` class
- New attribute ``merror``, which either returns a tuple of the lower and upper Minos error or None
- All attributes are now documented inline with docstrings which can be investigated with ``pydoc`` and ``help()`` in the REPL
- ``util.Params`` class
- New method ``to_table``, which returns a format that can be consumed by the external ``tabulate`` Python module
- ``util.FMin`` class
- New attribute ``ngrad`` which is the number of gradient calls so far
- New attribute ``has_parameters_at_limit`` which returns True if any parameter values is close to a limit
- All attributes are now documented inline with docstrings which can be investigated with ``pydoc`` and ``help()`` in the REPL
- ``util.Matrix`` class
- New method ``to_table``, which returns a format that can be consumed by the external ``tabulate`` Python module
- New method ``correlation``, which computes and returns the correlation matrix (also a ``util.Matrix``)
Bug-fixes
~~~~~~~~~
- Calling ``Minuit.hesse`` when all parameters were fixed now raises an error instead of producing a segfault
- Many life-time/memory leak issues in the iminuit interface code should be resolved now, even when there is an exception during the minimisation (there can still be errors in the underlying C++ Minuit2 library, which would have to be fixed upstream)
Other changes
~~~~~~~~~~~~~
- Several attributes were replaced with properties to avoid accidental overrides and to protect against assigning invalid input, e.g. ``Minuit.tol`` and ``Minuit.errordef`` only accept positive numbers
- Documentation update and clean up
- Logging messages from C++ Minuit2, which are produced when ``Minuit.print_level`` is set to 1 to 3 are now properly shown inside the notebook or the Python session instead of being printed to the terminal
- Assigning to ``Minuit.print_level`` changes the logging threshold for all current and future ``Minuit`` instances in the current Python session, this is not really desired but cannot be avoided since the C++ logger is a global variable
- docstring parsing for ``util.describe`` was rewritten; behaviour of ``describe`` for corner cases of functions with positional and variable number of positional and keyword arguments are now well-defined
- iminuit now has 100 % line coverage by unit tests