Creating your own pdf#

A core feature of zfit is the ability to create custom pdfs and functions in an simple and straightforward way.

There are two main possibilities to create a custom pdf, an easier for most use-cases and an advanced way..

The simple way#

While the same works for functions, an example with a PDF is shown here.

import numpy as np
import zfit
from zfit import z
/home/docs/checkouts/readthedocs.org/user_builds/zfit/checkouts/latest/.venv/lib/python3.12/site-packages/zfit/__init__.py:60: UserWarning: TensorFlow warnings are by default suppressed by zfit. In order to show them, set the environment variable ZFIT_DISABLE_TF_WARNINGS=0. In order to suppress the TensorFlow warnings AND this warning, set ZFIT_DISABLE_TF_WARNINGS=1.
  warnings.warn(
2025-01-16 14:47:49.480645: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
E0000 00:00:1737038869.494418    2003 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered
E0000 00:00:1737038869.498459    2003 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered

The first way is the most simple and should only be used for the trivial cases, i.e. if you’re not familiar with Python classes (especially not with the __init__ method).

class MyGauss(zfit.pdf.ZPDF):
    _N_OBS = 1  # dimension, can be omitted
    _PARAMS = ['mean', 'std']  # the name of the parameters

    @zfit.supports()
    def _unnormalized_pdf(self, x, params):
        x0 = x[0]  # using the 0th axis
        mean = params['mean']
        std = params['std']
        return z.exp(- ((x0 - mean) / std) ** 2)

Done. Now we can use our pdf already!

The slightly more general way involves overwritting the __init__ and gives you all the possible flexibility: to use custom parameters, to preprocess them etc.

Here we inherit from BasePDF

class MyGauss(zfit.pdf.BasePDF):

    def __init__(self, mean, std, obs, extended=None, norm=None, name=None, label=None):
        params = {'mean': mean,  # 'mean' is the name as it will be named in the PDF, mean is just the parameter to create the PDF
                  'std': std
                  }
        super().__init__(obs=obs, params=params, extended=extended, norm=norm,
                         name=name, label=label)

    @zfit.supports()
    def _unnormalized_pdf(self, x, params):
        x0 = x[0]  # using the 0th axis
        mean = params['mean']
        std = params['std']
        return z.exp(- ((x0 - mean) / std) ** 2)
obs = zfit.Space('obs1', -3, 6)

data_np = np.random.random(size=1000)
data = zfit.Data(data_np, obs=obs)
2025-01-16 14:47:52.932810: E external/local_xla/xla/stream_executor/cuda/cuda_driver.cc:152] failed call to cuInit: INTERNAL: CUDA error: Failed call to cuInit: UNKNOWN ERROR (303)

Create two parameters and an instance of your own pdf

mean = zfit.Parameter("mean", 1.)
std = zfit.Parameter("std", 1.)
my_gauss = MyGauss(obs=obs, mean=mean, std=std)
probs = my_gauss.pdf(data)
print(probs[:20])
tf.Tensor(
[0.46373369 0.42927452 0.21636689 0.4581734  0.35300346 0.42272391
 0.34904079 0.29650338 0.53731698 0.56416782 0.48109953 0.54481379
 0.52928329 0.54690905 0.31840048 0.50552511 0.48599765 0.56417652
 0.55112653 0.49145882], shape=(20,), dtype=float64)

If we want to make sure it’s a numpy array, we can use zfit.run

We could improve our PDF by registering an integral

def gauss_integral_from_any_to_any(limits, params, model):
    lower, upper = limits.v1.limits
    mean = params['mean']
    std = params['std']
    # write your integral here
    return 42.  # dummy integral, must be a scalar!
limits = zfit.Space(axes=0, lower=zfit.Space.ANY_LOWER, upper=zfit.Space.ANY_UPPER)
MyGauss.register_analytic_integral(func=gauss_integral_from_any_to_any, limits=limits)

More advanced custom PDFs are introduced in the guide on custom PDFs.