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])