Arrays

The escape.core.array module provides thin Python wrappers around the C++ array_t<T> class defined in escape/core/array.h. Two wrapper classes are exposed:

Classes

double_array_obj

Wraps array_t<double> – a double-precision floating-point array.

mask_array_obj

Wraps array_t<bool> – a boolean mask array.

View vs Copy Semantics

Both classes can be created with copy=False (the default) or copy=True.

  • copy=False – the wrapper tries to share the underlying memory of the input numpy array directly (zero-copy). This succeeds only when the input is a C-contiguous, aligned, writeable numpy array of the correct dtype that owns its data. If any of these conditions are not met the data is copied automatically and a warning is emitted.

    Warning

    When wrapping succeeds, the caller must keep the original numpy array alive for the entire lifetime of the wrapper. Deleting or garbage-collecting the numpy array while the wrapper is still in use will result in a dangling pointer.

  • copy=True – the data is always copied into memory owned by the C++ side. The resulting wrapper is fully independent of the original array.

Shape Support

1-D and 2-D arrays are supported. The C++ shape is stored as (nrows, ncols). A 1-D array of length N is represented as (1, N). The shape property exposes this tuple, and np.asarray(wrapper) restores the 2-D shape when nrows > 1.

Examples

Creating array views:

>>> import escape as esc
>>> import numpy as np
>>> a = np.arange(10, dtype=float)
>>> view = esc.double_array_obj.convert(a)
>>> view
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
>>> a[0] = 100
>>> view
array([100., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

Creating deep copies:

>>> copy = esc.double_array_obj.convert(a, copy=True)
>>> a[1] = 200
>>> copy  # unchanged
array([100., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

Converting back to numpy:

>>> np.asarray(view)
array([100., 200., 2., 3., 4., 5., 6., 7., 8., 9.])
escape.core.array.double_array(src: ndarray[tuple[Any, ...], dtype[_ScalarT]] | List, copy: bool = False) double_array_obj

Create a double_array_obj that either wraps or copies src.

This is a convenience function equivalent to double_array_obj.convert(src, copy).

Args:

src: A numpy float64 array or a Python list of floats. copy: If True, always copy the data. If False (default),

try to wrap the data without copying. See double_array_obj.convert() for the conditions under which wrapping succeeds.

Returns:

A new double_array_obj instance.

escape.core.array.mask_array(src: ndarray[tuple[Any, ...], dtype[_ScalarT]] | List, copy: bool = False) mask_array_obj

Create a mask_array_obj that either wraps or copies src.

This is a convenience function equivalent to mask_array_obj.convert(src, copy).

Args:

src: A numpy bool array or a Python list of bools. copy: If True, always copy the data. If False (default),

try to wrap the data without copying. See mask_array_obj.convert() for the conditions under which wrapping succeeds.

Returns:

A new mask_array_obj instance.

class escape.core.array.double_array_obj
static convert(input: ndarray[tuple[Any, ...], dtype[float64]] | List[float], copy: bool = False) double_array_obj

Create a wrapper of a numpy array or python list with double elements.

When copy is False (the default), the method attempts to wrap the input array’s data pointer directly (zero-copy). This succeeds only when the input is a C-contiguous, aligned, writeable float64 numpy array that owns its data. If any of those conditions are not met the data is copied automatically and a warning is emitted.

When wrapping succeeds the caller must keep the original numpy array alive for the entire lifetime of the returned wrapper – otherwise the wrapper will hold a dangling pointer.

When copy is True, the data is always copied into C++-owned memory, producing a fully independent array.

Args:

input: A numpy float64 array or a Python list of floats. copy: If True, always copy. If False, try to wrap without

copying (may still copy if requirements are not met).

Returns:

A new double_array_obj instance.

Raises:

ValueError: If the input has more than 2 dimensions. TypeError: If the input is neither an ndarray nor a list, or

cannot be converted to float64.

shape

Shape of the array as (nrows, ncols).

A 1-D array of length N has shape (1, N).

class escape.core.array.mask_array_obj
static convert(input: ndarray[tuple[Any, ...], dtype[bool]] | List[bool], copy: bool = False) mask_array_obj

Create a wrapper of a numpy array or python list with boolean elements.

When copy is False (the default), the method attempts to wrap the input array’s data pointer directly (zero-copy). This succeeds only when the input is a C-contiguous, aligned, writeable bool numpy array that owns its data. If any of those conditions are not met the data is copied automatically and a warning is emitted.

When wrapping succeeds the caller must keep the original numpy array alive for the entire lifetime of the returned wrapper.

When copy is True, the data is always copied into C++-owned memory, producing a fully independent array.

Args:

input: A numpy bool array or a Python list of bools. copy: If True, always copy. If False, try to wrap without

copying (may still copy if requirements are not met).

Returns:

A new mask_array_obj instance.

Raises:

ValueError: If the input has more than 2 dimensions. TypeError: If the input is neither an ndarray nor a list, or

cannot be converted to bool.

shape

Shape of the array as (nrows, ncols).

A 1-D array of length N has shape (1, N).