9.3. Making arrays¶
Every example on the rest of these pages starts with an
ndarray already in hand. This page
is the catalogue of how that array comes to be. There
are four families of constructor:
From a Python iterable – the usual literal / list / tuple form.
Pre-filled at a given shape – zeros, ones, a constant value, an identity matrix.
Generated as a sequence – ranged or evenly spaced values.
Wrapping a buffer already in RAM – the peripheral case.
Every constructor takes a dtype= keyword and defaults
to float. The Dtypes page
covers why almost every call to one of these on sensor
data should override that default.
Every example below starts with:
from ulab import numpy as np
9.3.1. From a Python iterable¶
array() builds an ndarray from any
iterable of numbers:
a = np.array([1, 2, 3, 4])
print(a)
Output:
array([1.0, 2.0, 3.0, 4.0], dtype=float64)
Nested iterables produce multi-dimensional arrays. The
inner iterables must all have the same length, or
ValueError is raised:
m = np.array([[1, 2, 3],
[4, 5, 6]], dtype=np.uint8)
A pre-existing ndarray is also a valid input;
array() always copies. To avoid the copy
when one is not needed, use asarray():
b = np.asarray(a, dtype=np.float) # same dtype -> no copy
9.3.2. Pre-filled at a given shape¶
When the target shape is known but the contents are not yet, allocate the buffer up front and write into it later:
zeros(shape, dtype=float)()– filled with zeros.ones(shape, dtype=float)()– filled with ones.)()– filled withvalue.)()– alias forzeros()(ulabdoes not leave the buffer uninitialised).eye(N, M=None, k=0)()– identity-likeNbyMmatrix with ones on thek-th diagonal.diag(v, k=0)()– a diagonal matrix from a vector, or the diagonal of a matrix.
np.zeros((3, 3)) # 3x3 of zeros
np.ones(5, dtype=np.uint8) # length-5 vector of ones
np.full((2, 3), 7, dtype=np.int8) # 2x3, all 7
np.eye(4) # 4x4 identity
np.diag([1, 2, 3]) # 3x3, [1, 2, 3] on the diagonal
The shape argument is either a single integer (for a
1-D array) or a tuple.
9.3.3. Generated as a sequence¶
)()– evenly spaced values like the built-inrange(), but always returning anndarray:np.arange(0, 10, 2) # array([0, 2, 4, 6, 8])linspace(start, stop, num=50, endpoint=True)()–numevenly spaced points between two limits, withendpoint=Trueincluding the upper bound:np.linspace(0, 1, num=11) # 0.0, 0.1, ..., 1.0logspace(start, stop, num=50, base=10)()– geometrically spaced points.startandstopare exponents, not endpoints; the result runs frombase ** starttobase ** stop:np.logspace(0, 3, num=4) # 1.0, 10.0, 100.0, 1000.0meshgrid(x, y, indexing='xy')()– two coordinate matrices from two 1-D inputs. Useful for per-pixel transforms expressed asf(x, y)over the pixel grid:x = np.arange(4) y = np.arange(3) X, Y = np.meshgrid(x, y) # X is the column index repeated; Y is the row index repeated.
9.3.4. Joining¶
concatenate() joins a tuple of arrays
along an existing axis:
a = np.array([[1, 2], [3, 4]], dtype=np.uint8)
b = np.array([[5, 6]], dtype=np.uint8)
np.concatenate((a, b), axis=0)
# array([[1, 2], [3, 4], [5, 6]], dtype=uint8)
All inputs must share the same dtype and ndim, and
match on every axis other than the joining one. This is
the right shape for accumulating short buffers into a
longer one when the final length is known up front; for
the streaming-append pattern see Performance.
9.3.5. Wrapping an existing buffer¶
The most useful constructor on a camera is
frombuffer(). It re-interprets an
existing bytes-like buffer as a 1-D
ndarray without copying a single
byte:
buf = bytearray(8)
audio = np.frombuffer(buf, dtype=np.int16)
# 4 int16 samples, sharing memory with buf
Writes through audio are visible in buf and vice
versa. The chosen dtype must evenly divide the
buffer length.
offset= skips a header at the start of the buffer;
count= limits how many elements are read:
np.frombuffer(buf, dtype=np.uint8, offset=2, count=4)
This is the right constructor whenever a peripheral hands
the application a raw buffer – ADC samples in a
bytearray, an audio frame from
I2S, a payload pulled from
SPI. The bytes the peripheral wrote
are the array.
When the peripheral’s byte order disagrees with the
camera’s, the byteswap()
method flips each multi-byte element.
a.byteswap() returns a new array;
a.byteswap(inplace=True) modifies the source in
place.
frombuffer() only handles the dtypes
numpy itself defines. For peripherals that
produce 32-bit integer samples,
from_int32_buffer() and friends
convert to float in one pass; see
Filtering and spectrograms.
For the complete argument-level reference of every constructor on this page, see numpy — numpy-compatible array operations.