Julia bindings for Minuit2

Description

Julia bindings for the Minuit2 minimization package. It provides a Julia-friendly interface to the C++ library, maintained by CERN's ROOT team. Minuit2 is designed for function minimization, particularly in statistical applications such as maximum-likelihood estimation and least-squares fitting. It computes best-fit parameters and error estimates using likelihood profile analysis

The API and additional features of this package are heavily inspired by iminuit, which offers a Python-friendly interface to the same library.

We have provided an additional module Minuit2.RooFit with an initial implementation in Julia of the RooFit modeling package often used in HEP data analysis. This package can help to build complex PDF models using basic elements and combining them.

Installation

The Minuit2.jl package does no require any special installation. Stable releases are registered into the Julia general registry, and therefore can be deployed with the standard Pkg Julia package manager.

julia> using Pkg
julia> Pkg.add("Minuit2")

API Guidelines

A mutable Minuit structure instance is constructed from the cost function to be minimised and its gradient, if available, otherwise Minuit2 uses an internal numerical differentiation, and a number of initial parameters. This structure is later used in the application to perform different minimization algorithms with different strategies and the evaluation of the results. The user provides always a Julia cost function to be evaluated by the C++ engine as a callback.

Getting Started

julia> using Minuit2

julia> rosenbrock(x, y) = (1 - x)^2 + 100 * (y - x^2)^2
rosenbrock (generic function with 1 method)

julia> m = Minuit(rosenbrock, x=0, y=0, tolerance=1e-4)
Minuit(FCN = rosenbrock(x, y), X0 = [0, 0], Method = migrad)

julia> migrad!(m)
┌──────────────┬──────────────┬───────────┬────────────┬────────────┐
│ FCN          │ Method       │ Ncalls    │ Iterations │ Up         │
│ 1.68596e-8   │ migrad       │ 146       │ 19         │ 1.0        │
├──────────────┼──────────────┼───────────┼────────────┼────────────┤
│ Valid Min.   │ Valid Param. │ Above EDM │ Call limit │ Edm        │
│ true         │ true         │ false     │ false      │ 1.68793e-8 │
├──────────────┼──────────────┼───────────┼────────────┼────────────┤
│ Hesse failed │ Has cov.     │ Accurate  │ Pos. def.  │ Forced     │
│ false        │ true         │ true      │ true       │ false      │
└──────────────┴──────────────┴───────────┴────────────┴────────────┘
┌──────┬──────────┬─────────────┬────────┬────────┬────────┬────────┬───────┐
│ Name │ Value    │ Hesse Error │ Minos- │ Minos+ │ Limit- │ Limit+ │ Fixed │
├──────┼──────────┼─────────────┼────────┼────────┼────────┼────────┼───────┤
│ x    │ 0.999952 │ 1.00372     │        │        │        │        │       │
│ y    │ 0.999892 │ 2.00986     │        │        │        │        │       │
└──────┴──────────┴─────────────┴────────┴────────┴────────┴────────┴───────┘


julia> minos!(m)
┌──────────────┬──────────────┬───────────┬────────────┬────────────┐
│ FCN          │ Method       │ Ncalls    │ Iterations │ Up         │
│ 1.68596e-8   │ migrad       │ 146       │ 19         │ 1.0        │
├──────────────┼──────────────┼───────────┼────────────┼────────────┤
│ Valid Min.   │ Valid Param. │ Above EDM │ Call limit │ Edm        │
│ true         │ true         │ false     │ false      │ 1.68793e-8 │
├──────────────┼──────────────┼───────────┼────────────┼────────────┤
│ Hesse failed │ Has cov.     │ Accurate  │ Pos. def.  │ Forced     │
│ false        │ true         │ true      │ true       │ false      │
└──────────────┴──────────────┴───────────┴────────────┴────────────┘
┌──────┬──────────┬─────────────┬───────────┬─────────┬────────┬────────┬───────┐
│ Name │ Value    │ Hesse Error │ Minos-    │ Minos+  │ Limit- │ Limit+ │ Fixed │
├──────┼──────────┼─────────────┼───────────┼─────────┼────────┼────────┼───────┤
│ x    │ 0.999952 │ 1.00372     │ -0.999952 │ 1.00005 │        │        │       │
│ y    │ 0.999892 │ 2.00986     │ -1.03349  │ 3.00136 │        │        │       │
└──────┴──────────┴─────────────┴───────────┴─────────┴────────┴────────┴───────┘


julia> x, y = m.values
[0.9999518621622189, 0.9998916674647496]

julia> ex, ey = m.errors
[1.0037197729944198, 2.009856810740231]

Minuit2.RooFit module

This is simple example of the functionality of the Minuit2.RooFit module provided additionally to this package.

#---Observable
mes =  RealVar(:mes, limits=(5.20, 5.30), nbins=50)

#---Gaussian signal
sigmean = RealVar(:sigmean, 5.28, limits=(5.20, 5.30))
sigwidth = RealVar(:sigwidth, 0.0027, limits=(0.001, 0.1))
sig = Gaussian(:sig, mes, sigmean, sigwidth)

#---Build Argus background
argpar = RealVar(:argpar, -20.0, limits=(-100., -1.))
argus = ArgusPdf(:argus, mes, ConstVar(:m₀, 5.291), argpar)

#---Build the model
nsig = RealVar(:nsig, 200., limits=(0., 10000.))
nbkg = RealVar(:nbkg, 800., limits=(0., 10000.))
model = AddPdf(:model, [sig, argus], [nsig, nbkg])

#--- Generate a toyMC sample from composite PDF ---
data = generate(model, 2000)

#--- Perform extended unbinned NLL fit ---
m = fitTo(model, data)

#--- Visualize the results
visualize(m, model, components=(:sig, :argus); nbins=50, linestyle=:dash, legend=:topleft)

Examples

Some notebooks are provided as examples. They are located in directory examples. They can be run using Julia to launch the notebook or jupyterlab.

julia --project=Minuit2.jl/examples

julia> ]instantiate
julia> installkernel("Julia", env=Dict("JULIA_PROJECT" => "@."))
julia> jupyterlab(dir="Minuit2.jl/examples")

introduction.ipynb

Basic introduction to minimization with Minuit using simple Julia functions and exercising the plotting capabilities.

costfunction.ipynb

Introduction of the provided cost functions for a typical HEP minimization problem.

combined.ipynb

A quick guide on how to combined several fits into a single one using the Minuit2 package.

roofit.ipynb

A quick guide on how to use the RooFit module to perform fits.

Tests

Unit tests can be run with julia --project=. test/runtests.jl

Roadmap

There are a number of issues and problems still to be resolved. We keep track of them in this list:

  • Weighted histograms need to be implemented
  • More tutorials:
    • Automatic differentiation
    • Benchmarks (fit quality and performance)
  • More in RooFit module
    • Complete the available PDFs (e.g. RooBCPEffDecay, RooBMixDecay, RooBifurGauss, RooBreitWigner, RooCBShape, RooPolynomial, etc.)
    • More compositions (e.g. multiplication, composition and convolution)