# Space, Observable and Range#

Inside zfit, `Space`

defines the domain of objects by specifying the observables/axes and *maybe* also
the limits. Any model and data needs to be specified in a certain domain, which is usually done using the
`obs`

argument. It is crucial that the axis used by the observable of the data and the model match, and this matching is
handle by the `Space`

class.

```
import zfit
from zfit import z
import numpy as np
```

```
obs = zfit.Space("x")
model = zfit.pdf.Gauss(obs=obs, ...)
data = zfit.Data.from_numpy(obs=obs, ...)
```

## Definitions#

**Space**: an *n*-dimensional definition of a domain (either by using one or more observables or axes),
with or without limits.

Note

Difference to RooFit

*compared to ``RooFit``, a space is **not** the equivalent of an observable but rather corresponds
to an object combining **a set** of observables (which of course can be of size 1). Furthermore,
there is a **strong** distinction in zfit between a `Space`

(or observables)
and a `Parameter`

, both conceptually and in terms of implementation and usage.*

**Observable**: a string defining the axes; a named axes.

*(for advanced usage only, can be skipped on first read)*
**Axis**: integer defining the axes *internally* of a model. There is always a mapping of observables <-> axes *once inside a model*.

**Limit**The range on a certain axis. Typically defines an interval. In fact, there are two times of limits:**rectangular**: This type is the usual limit as e.g.`(-2, 5)`

for a simple, 1 dimensional interval.

A space should usually be created with limits that define the default space of an object.
This correspond for example to the default normalization range `norm`

or sampling range.

```
obs1 = zfit.Space("x", 0, 1)
obs2 = zfit.Space("y", -4, 1)
model1 = zfit.pdf.Gauss(obs=obs1, ...)
model2 = zfit.pdf.Gauss(obs=obs2, ...)
# creating a composite pdf
product = model1 * model2
# OR, equivalently
product = zfit.pdf.ProductPDF([model1, model2])
assert obs1 * obs2 == product.space
```

The `product`

is now defined in the space with observables `['x', 'y']`

. Any `Data`

object
to be combined with `product`

has to be specified in the same space.

```
# create the space
combined_obs = obs1 * obs2
data = zfit.Data.from_numpy(obs=combined_obs, ...)
```

Now we have a `Data`

object that is defined in the same domain as `product`

and can be used to build a loss function.

## Limits#

In many places, just defining the observables is not enough and an interval, specified by its limits, is required. Examples are a normalization range, the limits of an integration or sampling in a certain region.

### Using the limits#

To use the limits of any object, the methods `inside()`

(to test if values are inside or outside of the boundaries)
and `filter()`

can be used.