# Concept of Slicing¶

## How to get a part of an object / a subset of a Base¶

Antares objects do not **only** behave like dictionaries, they are also
ordered. In this notebook, we introduce the indexes and slicing
functionalities to retrieve sub-part of the Antares objects.

NB: From python 3.6.1, dictionaries are ordered. That was not the cas in previous versions of python.

There are many similarities with the python slice.

The slicing is very often used with Antares: + separate rows of turbomachinery + separate chimera blocks + keep only some variables

Let’s build a base.

```
import antares as ant
base = ant.Base()
base.init(zones=['z0', 'z1', 'z2', 'z3'], instants=['t0', 't1', 't2'])
```

We have already seen that an element of an Antares object can be accessed with its key, but also with its index. Note that indices start at 0 in Python.

We use the operator **[ ]**, and give a string or an integer as the
argument.

The element ‘z1’ has been set after the element ‘z0’, therefore, its index is 1. Note that if the element ‘z1’ had been set before the element ‘z0’, its index would have been 0.

```
print(base['z1'])
print(base[1])
```

# First-Level Base Slicing: Zone slicing¶

If you have a huge base, and you only want to focus on some zones, use
also the operator **[ ]** with a tuple of keys or indices as argument.

```
sliced_base = base[('z1', 'z3')] # Use a tuple
```

The slicing operation always returns a *Base*.

In the example, we get a *Base* with two zones that still have their
instants.

```
print(sliced_base)
print(sliced_base[0])
```

## Slicing an object returns an object of the same type.¶

The slicing operation applied on a *Base* always returns a *Base*. This
holds for *Zone* and *Instant* too.

```
print(type(sliced_base))
```

```
sliced_zone = base['z1'][('t0', 't2')] # Use a tuple
print(sliced_zone)
print(type(sliced_zone))
```

You can use both keys and indexes as arguments of the slicing operation.

```
sliced_base = base[(0, 2)]
print(sliced_base)
```

A tuple of one element has to be written with a comma, otherwise it is not recognized as a tuple.

e.g. (0,) or (‘z1’,)

The slicing can be done with a tuple but you can use the python slice notation [start:end:step]

The end value represents the first value that is not in the selected slice.

The difference beween end and start is the number of elements selected (if step is 1, the default).

a[start:end] # items start through end-1

a[start:] # items start through the rest of the array

a[:end] # items from the beginning through end-1

a[:] # a copy of the whole array

a[-1] # last item in the array

a[-2:] # last two items in the array

a[:-2] # everything except the last two items

refer to https://docs.python.org/3/library/functions.html#slice

```
sliced_base = base[1:4:2] # slice
print(sliced_base)
```

# Second-Level Base Slicing: Instant slicing¶

If you want to extract some data from the zones AND the instants of a
*Base*, use also the operator **[ ]** with two positional arguments. The
first argument is for the *Zone*, and the second for the *Instant*.

The slicing operation on the *Instant* is applied on the result of the
slicing operation on the *Zone*.

The following example shows how to retrieve all zones (with the semi-column), and the instant ‘t1’ for all zones.

```
base.init(zones=['z0', 'z1', 'z2', 'z3'], instants=['t0', 't1', 't2'])
base2 = base[:,('t2',)]
print(base2)
print(base2[0])
```

# Third-Level Base Slicing: Variable slicing¶

If you add a third positional argument to the operator **[ ]**, the
slice corresponds to the variables contained in the *Instant*.

Set the following example.

```
import numpy as np
base.init(zones=['z0', 'z1', 'z2', 'z3'], instants=['t0', 't1', 't2'])
for zone in base.values():
for inst in zone.values():
inst['v1'] = np.arange(6)
inst['v2'] = np.arange(6)
print(base[0][0])
print(base[0][0]['v2'], id(base[0][0]['v2']))
```

The following line shows how to retrieve all zones and instants with only the variable ‘v2’.

```
base2 = base[:,:,('v2',)]
print(base2[0][0])
print(base2[0][0][0], id(base2[0][0][0]))
```

Numpy arrays are not copied in the slicing method **[ ]**, a reference
(pointer) is used.

If numpy arrays from one base are modified with the right operators, they are also modified in the other base.

```
base2[0][0][0] += 10 # in-place addition
print(base2[0][0][0])
print(base[0][0][1])
```

You can reordered data with slicing

```
base.init(zones=['z0', 'z1', 'z2', 'z3'], instants=['t0', 't1', 't2'])
for zone in base.values():
for inst in zone.values():
inst['v1'] = np.arange(6)
inst['v2'] = np.arange(6)
print(base[0][0])
base2 = base[(0,), ('t2',), ('v2', 'v1')]
print(base2[0][0])
```