Using NumPy¶
NumPy is a Python library for handling large amounts of array-based data and provides the technological basis for array-based NumPy trace step templates. The official NumPy manual can be accessed via the following link: https://docs.scipy.org/doc/numpy/index.html
The quickstart tutorial is especially recommended as an introduction: https://docs.scipy.org/doc/numpy/user/quickstart.html
In addition, some aspects that are particularly relevant for trace analysis are highlighted below.
Boolean Operators¶
Neither the expression if arr: print('hallo') nor the statement bool(arr) can be used to
check, whether a NumPy array is empty or whether it contains True values. Instead,
corresponding mechanisms of NumPy must be used, which are described in the following example:
import numpy as np
arr = np.array([3, 1, -2, 0], dtype=np.float64)
# Is arr valid?
if isinstance(arr, np.ndarray):
print('arr is a valid NumPy array')
# Is arr empty?
if len(arr) > 0:
print('arr is not empty')
# Handling of Boolean values
positive = arr >= 0 # comparison with zero is carried out element by element and stored in new array: [True, True, False, True]
print(np.all(positive)) # False, as not all elements of positive are True
print(np.any(positive)) # True, as positive is True in at least one (three, in fact) element
Caution
The Boolean value of np.nan (“not a number”) is True! The expression np.all(np.array([0.1, 3.0, np.nan]))
therefore evaluates to True.
Masking¶
Python’s indexing/slicing mechanism can also be used with NumPy to access single values or partial arrays:
import numpy as np
arr = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
print(arr[3:5]) # [3, 4]
print(arr[:4]) # [0, 1, 2, 3]
print(arr[8:]) # [8, 9]
NumPy, however, offers even more powerful options for selecting a subset of values. On the one hand, certain values can be selected by specifying a Boolean mask, on the other hand, desired elements can also be specified in an array of indices.
Boolean mask: All values >= threshold
import numpy as np
arr = np.array([0, 3, 7, 13, 10, 11, 12.5, 15])
threshold = 12
mask = arr >= threshold # Boolean mask: [False, False, False, True, False, False, True, True]
print(arr[mask]) # [13, 12.5, 15]
Boolean mask: All signal values from time interval
import numpy as np
values = np.array([100, 200, 300, 400, 500])
timestamps = np.arange(5.0) # [0.0, 1.0, 2.0, 3.0, 4.0]
# All values from the closed time interval between 1.0 and 2.5
mask = np.logical_and(1.0 <= timestamps, timestamps <= 2.5)
print(values[mask]) # [200, 300]
Index array: Signal change from 20 to 30
import numpy as np
values = np.array([0, 10, 20, 30, 40])
timestamps = np.arange(5.0) # [0.0, 1.0, 2.0, 3.0, 4.0]
# Create Boolean mask that contains True where a value of 20 is followed by 30
boolMask = np.logical_and(values[:-1] == 20, values[1:] == 30) # [False, False, True, False]
# Create corresponding index array, Attention: boolMask contains one element less than values
indexArr = np.arange(values.shape[0] - 1)[boolMask] # [2]
# indexArr refers to the position of 20 by now, but shall refer to the change from 20 to 30
indexArr = indexArr + 1 # [3]
# Alternative: numpy.where()
indexArr = np.where(boolMask)[0] + 1 # [3]
print(timestamps[indexArr]) # [3.0]
print(values[indexArr]) # [30]