Parameter¶
Several objects in zfit, most importantly models, have one or more parameter which typically parametrise a function or distribution. There are two different kinds of parameters in zfit:
- Independent: can be changed in a fit (or explicitly be set to fixed).
- Dependent: cannot be directly changed but _may_ depend on independent parameters.
Independent Parameter¶
To create a parameter that can be changed, e.g., to fit a model, a Parameter
has to
be instantiated.
The syntax is as follows:
param1 = zfit.Parameter("param_name_human_readable", start_value[, lower_limit, upper_limit])
Furthermore, a step_size
can be specified. If not, it is set to a default value around 0.001.
Parameter
can have limits (tested with has_limits()
), which will
clip the value to the limits given by lower_limit()
and
upper_limit()
.
While this closely follows the RooFit syntax, it is very important to note that the optional limits
of the parameter behave differently:
if not given, the parameter will be “unbounded”, not fixed (as in RooFit).
Parameters are therefore floating by default, but their value can be fixed by setting the attribute
floating
to False
or already specifying it in the init.
The value of the parameter can be changed with the set_value()
method.
Using this method as a context manager, the value can also temporarily changed.
However, be aware that anything _dependent_ on the parameter will have a value with the
parameter evaluated with the new value at run-time:
>>> mu = zfit.Parameter("mu_one", 1) # no limits, but FLOATING (!)
>>> with mu.set_value(3):
... # in here, mu has the value 3
... mu_val = zfit.run(mu) # 3
... five_mu = 5 * mu
... five_mu_val = zfit.run(five_mu) # is evaluated with mu = 5. -> five_mu_val is 15
>>> # here, mu is again 1
>>> mu_val_after = zfit.run(mu) # 1
>>> five_mu_val_after = zfit.run(five_mu) # is evaluated with mu = 1! -> five_mu_val_after is 5
Dependent Parameter¶
A parameter can be composed of several other parameters. They can be used equivalently to Parameter
.
>>> mu2 = zfit.Parameter("mu_two", 7)
>>> dependent_func = lambda m, m2: m * 5 + m2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, params=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_dependencies() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_dependencies() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_cache_deps() # returns ordered-set(mu, mu2)
A special case of the above is :py
>>> dependent_func = lambda: mu * 5 + mu2 # or any kind of computation
>>> dep_param = zfit.ComposedParameter("dependent_param", dependent_func, dependents=[mu, mu2])
>>> dependents = dep_param.get_params() # returns ordered-set(mu, mu2)
A special case of the above is ComplexParameter
: it takes a complex tf.Tensor
as input and
provides a few special methods (like real()
, ComplexParameterconj()
etc.)
to easier deal with them.
Additionally, the from_cartesian()
and from_polar()
methods can be used to initialize polar parameters from floats, avoiding the need of creating complex
tf.Tensor
objects.