- \subsection{Spaces and Dimensions}
- \label{sec:spaces and dimensions}
-
- The extension to more than one dimension when fitting a model contains some
- ambiguities. The data, limits and the models all have corresponding axes or
- columns that should match.
- To deal with that in a simple, yet consistent manner, \zfit{} has a \zspace{}.
- The
- responsibility of this class is to define and handle the axes or dimensions and
- limits. To
- understand the concept and the \zspace{} itself, three definitions need to be
- made:
-
- \begin{description}
- \item[Observables] The observables are the
- \textit{named axes of a coordinate system}. A single observable is a string
- and a list of strings acts as several observables describing a higher
- dimensional system. In the context of data this is equivalent
- to columns in a data frame. Observables allow a named, \textit{inter-object}
- identification of axes. Therefore, working with observables allows to work
- independently of the underlying data ordering.
- \item[Axes] Axes are integers and are used to \textit{enumerate the axes
- of a coordinate system}. This corresponds to indices of an array and
- provides the fully order-based mapping necessary for \textit{intra-object}
- manipulations. For example, a \zdata{} with three
- columns has three axes, 0, 1, and 2, which can though be reordered so that
- the corresponding observables match the order of some other observables.
- \item[Limits] A description of boundaries that can be used to define any
- kind of limits of the axes. Currently only rectangular limits are supported
- but arbitrary shaped limits will be provided in the future.
- \end{description}
-
- A \zspace{} can be initialized with observables and limits to define a domain.
- When
- it's assigned to an object, it automatically connects the axes of the object
- with the observables from the \zspace{}. More details on the implementation and
- use cases as well as additional functionality for dimensional handling can be
- found in Appendix \ref{appendix:spaces defined}.
-
- \subsubsection{Limits}
- \label{sec:multiple limits}
-
- Limits are used in many instances, be it in sampling limits, integration or
- data limits. A \zspace{} not only defines the observables but typically also
- has limits associated with it.
- In one-dimensional fits, limits as seen in the
- example in Sec. \ref{sec:quickstart}
- are needed. Simple limits consist of a tuple for each observable with lower and
- upper limits. For example a \zspace{} in one observable \texttt{x} from $-5$ to
- $3$ can be created like
-
- \begin{center}
- \begin{minipage}{\textwidth}
- \begin{python}
- limits = zfit.Space(obs="x", limits=(-5, 3))
- \end{python}
- \end{minipage}
- \end{center}
-
- This is the simplest way of specifying limits and rather a special case. For
- anything more sophisticated, such as multiple limits or multiple observables,
- either a composition of \zspace s or the more
- general format as explained in Appendix
- \ref{appendix:general limits} has to be used. For example when blinding a
- region, a \zspace{}
- with
- multiple limits can be used.
-
- While the general format is fully specified independent of a \zspace{} and can
- therefore be useful programmatically, a \zspace{} with multiple limits can be
- built
- unambiguously from \zspace s with simple limits by adding them, either through
- a dedicated \zfit{} function or using the addition operator in Python. In
- this way, multiple limits can be created through simple composition and without
- the need of using the more general format.
-
- As an example, let's assume a \zspace{} should be created with the observables
- \texttt{x, y} in the two domains $l_01$ and $l_23$
- \begin{align*}
- l_01 &= \{(x, y) | x_0 < x < x_1, y_0 < y < y_1\} \\
- l_23 &= \{(x, y) | x_2 < x < x_3, y_2 < y < y_3\}.
- \end{align*}
-
- We start out creating the domains by specifying the limits in the \textit{x}
- observable
-
- \begin{center}
- \begin{minipage}{\textwidth}
- \begin{python}
- limit_x_01 = zfit.Space(obs="x", limits=(x0, x1))
- limit_x_23 = zfit.Space(obs="x", limits=(x2, x3))
- limits_x = limit_x_01 + limit_x_23
- \end{python}
- \end{minipage}
- \end{center}
-
- Equivalently \pyth{limits_y} can be composed. Since going to higher dimensions
- is unambiguous with two limits in each space, this can be done using the
- multiplication operator in Python or the function
- \pyth{combine}.\footnote{If a different number of limits were defined, an error
- would be thrown.}
-
- \begin{center}
- \begin{minipage}{\textwidth}
- \begin{python}
- limits_xy = limits_x * limits_y
- limits_yx = limits_y * limits_x
- \end{python}
- \end{minipage}
- \end{center}
-
- The difference between \pyth{limits_xy} and \pyth{limits_yx} is the order of
- the observables. In the first case, it's \pyth{["x", "y"]} while for the latter
- it's \pyth{["y", "x"]}. In order to ensure consistency, if the two \zspace s
- already have observables in common, the limits in this observables have to be
- the same. \footnote{This exact behaviour
- of the multiplication and observables is the same if models are multiplied.}
- Reordering the \zspace{} is possible as well as extracting a subspace, a
- \zspace{} only defined in subset of the dimensions. More details can be found
- in Appendix \ref{appendix:spaces defined}.