Skip to content

DummyArray

Represents a single array (variable or coordinate) with metadata.

Overview

DummyArray is used for both coordinates and variables in a DummyDataset. Each array contains:

  • Dimensions - List of dimension names
  • Attributes - Metadata dictionary
  • Data - Optional numpy array
  • Encoding - Encoding parameters (dtype, chunks, compression)

Key Features

  • Automatic dimension inference from data shape
  • xarray-compatible attribute assignment
  • History tracking (if enabled)
  • Rich repr for interactive exploration

Usage

from dummyxarray import DummyArray
import numpy as np

# Create array with dimensions
arr = DummyArray(dims=["time", "lat", "lon"])

# Set attributes
arr.assign_attrs(
    standard_name="air_temperature",
    units="K",
    long_name="Air Temperature"
)

# Add data
arr.data = np.random.rand(10, 64, 128)

# Set encoding
arr.encoding = {
    "dtype": "float32",
    "chunks": (5, 32, 64),
    "compressor": "zstd"
}

API Reference

Represents a single array (variable or coordinate) with metadata.

Source code in src/dummyxarray/core.py
class DummyArray:
    """Represents a single array (variable or coordinate) with metadata."""

    def __init__(self, dims=None, attrs=None, data=None, encoding=None, _record_history=True):
        """
        Initialize a DummyArray.

        Parameters
        ----------
        dims : list of str, optional
            List of dimension names
        attrs : dict, optional
            Metadata attributes
        data : array-like, optional
            Data array (numpy array or list)
        encoding : dict, optional
            Encoding parameters (dtype, chunks, compressor, fill_value, etc.)
        _record_history : bool, optional
            Whether to record operation history (default: True)
        """
        self.dims = dims
        self.attrs = attrs or {}
        self.data = data
        self.encoding = encoding or {}

        # Operation history tracking
        self._history = [] if _record_history else None
        if _record_history:
            # Record initialization
            init_args = {}
            if dims is not None:
                init_args["dims"] = dims
            if attrs:
                init_args["attrs"] = attrs
            if data is not None:
                init_args["data"] = "<data>"
            if encoding:
                init_args["encoding"] = encoding
            self._record_operation("__init__", init_args)

    def __repr__(self):
        """Return a string representation of the DummyArray."""
        lines = ["<dummyxarray.DummyArray>"]

        # Dimensions
        if self.dims:
            lines.append(f"Dimensions: ({', '.join(self.dims)})")
        else:
            lines.append("Dimensions: ()")

        # Data info
        if self.data is not None:
            data_array = np.asarray(self.data)
            lines.append(f"Shape: {data_array.shape}")
            lines.append(f"dtype: {data_array.dtype}")

            # Show a preview of the data
            if data_array.size <= 10:
                lines.append(f"Data: {data_array}")
            else:
                flat = data_array.flatten()
                preview = f"[{flat[0]}, {flat[1]}, ..., {flat[-1]}]"
                lines.append(f"Data: {preview}")
        else:
            lines.append("Data: None")

        # Attributes
        if self.attrs:
            lines.append("Attributes:")
            for key, value in self.attrs.items():
                value_str = str(value)
                if len(value_str) > 50:
                    value_str = value_str[:47] + "..."
                lines.append(f"    {key}: {value_str}")

        # Encoding
        if self.encoding:
            lines.append("Encoding:")
            for key, value in self.encoding.items():
                lines.append(f"    {key}: {value}")

        return "\n".join(lines)

    def infer_dims_from_data(self):
        """
        Infer dimension names and sizes from data shape.

        Returns
        -------
        dict
            Dictionary mapping dimension names to sizes
        """
        if self.data is not None:
            shape = np.asarray(self.data).shape
            if self.dims is None:
                self.dims = [f"dim_{i}" for i in range(len(shape))]
            return dict(zip(self.dims, shape, strict=True))
        return {}

    def _record_operation(self, func_name, args):
        """
        Record an operation in the history.

        Parameters
        ----------
        func_name : str
            Name of the function/method called
        args : dict
            Arguments passed to the function
        """
        if self._history is not None:
            self._history.append({"func": func_name, "args": args})

    def get_history(self):
        """
        Get the operation history for this array.

        Returns
        -------
        list of dict
            List of operations

        Examples
        --------
        >>> arr = DummyArray(dims=["time"], attrs={"units": "days"})
        >>> arr.get_history()
        [{'func': '__init__', 'args': {'dims': ['time'], 'attrs': {'units': 'days'}}}]
        """
        return self._history.copy() if self._history is not None else []

    def replay_history(self, history=None):
        """
        Replay a sequence of operations to recreate an array.

        Parameters
        ----------
        history : list of dict, optional
            History to replay. If None, uses self.get_history()

        Returns
        -------
        DummyArray
            New array with operations replayed
        """
        if history is None:
            history = self.get_history()

        # Get __init__ args
        init_op = history[0] if history and history[0]["func"] == "__init__" else {}
        init_args = init_op.get("args", {})

        # Create new array
        arr = DummyArray(**init_args, _record_history=False)

        # Replay other operations
        for op in history[1:]:
            func = getattr(arr, op["func"], None)
            if func and callable(func):
                func(**op["args"])

        return arr

    def assign_attrs(self, **kwargs):
        """
        Assign new attributes to this array (xarray-compatible API).

        Parameters
        ----------
        **kwargs
            Attributes to assign

        Returns
        -------
        self
            Returns self for method chaining

        Examples
        --------
        >>> arr = DummyArray(dims=["time"])
        >>> arr.assign_attrs(units="days", calendar="gregorian")
        """
        self._record_operation("assign_attrs", kwargs)
        self.attrs.update(kwargs)
        return self

    def to_dict(self):
        """
        Export structure (without data) for serialization.

        Returns
        -------
        dict
            Dictionary representation
        """
        return {
            "dims": self.dims,
            "attrs": self.attrs,
            "encoding": self.encoding,
            "has_data": self.data is not None,
        }

__init__

__init__(
    dims=None,
    attrs=None,
    data=None,
    encoding=None,
    _record_history=True,
)

Initialize a DummyArray.

Parameters:

Name Type Description Default
dims list of str

List of dimension names

None
attrs dict

Metadata attributes

None
data array - like

Data array (numpy array or list)

None
encoding dict

Encoding parameters (dtype, chunks, compressor, fill_value, etc.)

None
_record_history bool

Whether to record operation history (default: True)

True
Source code in src/dummyxarray/core.py
def __init__(self, dims=None, attrs=None, data=None, encoding=None, _record_history=True):
    """
    Initialize a DummyArray.

    Parameters
    ----------
    dims : list of str, optional
        List of dimension names
    attrs : dict, optional
        Metadata attributes
    data : array-like, optional
        Data array (numpy array or list)
    encoding : dict, optional
        Encoding parameters (dtype, chunks, compressor, fill_value, etc.)
    _record_history : bool, optional
        Whether to record operation history (default: True)
    """
    self.dims = dims
    self.attrs = attrs or {}
    self.data = data
    self.encoding = encoding or {}

    # Operation history tracking
    self._history = [] if _record_history else None
    if _record_history:
        # Record initialization
        init_args = {}
        if dims is not None:
            init_args["dims"] = dims
        if attrs:
            init_args["attrs"] = attrs
        if data is not None:
            init_args["data"] = "<data>"
        if encoding:
            init_args["encoding"] = encoding
        self._record_operation("__init__", init_args)

__repr__

__repr__()

Return a string representation of the DummyArray.

Source code in src/dummyxarray/core.py
def __repr__(self):
    """Return a string representation of the DummyArray."""
    lines = ["<dummyxarray.DummyArray>"]

    # Dimensions
    if self.dims:
        lines.append(f"Dimensions: ({', '.join(self.dims)})")
    else:
        lines.append("Dimensions: ()")

    # Data info
    if self.data is not None:
        data_array = np.asarray(self.data)
        lines.append(f"Shape: {data_array.shape}")
        lines.append(f"dtype: {data_array.dtype}")

        # Show a preview of the data
        if data_array.size <= 10:
            lines.append(f"Data: {data_array}")
        else:
            flat = data_array.flatten()
            preview = f"[{flat[0]}, {flat[1]}, ..., {flat[-1]}]"
            lines.append(f"Data: {preview}")
    else:
        lines.append("Data: None")

    # Attributes
    if self.attrs:
        lines.append("Attributes:")
        for key, value in self.attrs.items():
            value_str = str(value)
            if len(value_str) > 50:
                value_str = value_str[:47] + "..."
            lines.append(f"    {key}: {value_str}")

    # Encoding
    if self.encoding:
        lines.append("Encoding:")
        for key, value in self.encoding.items():
            lines.append(f"    {key}: {value}")

    return "\n".join(lines)

infer_dims_from_data

infer_dims_from_data()

Infer dimension names and sizes from data shape.

Returns:

Type Description
dict

Dictionary mapping dimension names to sizes

Source code in src/dummyxarray/core.py
def infer_dims_from_data(self):
    """
    Infer dimension names and sizes from data shape.

    Returns
    -------
    dict
        Dictionary mapping dimension names to sizes
    """
    if self.data is not None:
        shape = np.asarray(self.data).shape
        if self.dims is None:
            self.dims = [f"dim_{i}" for i in range(len(shape))]
        return dict(zip(self.dims, shape, strict=True))
    return {}

get_history

get_history()

Get the operation history for this array.

Returns:

Type Description
list of dict

List of operations

Examples:

>>> arr = DummyArray(dims=["time"], attrs={"units": "days"})
>>> arr.get_history()
[{'func': '__init__', 'args': {'dims': ['time'], 'attrs': {'units': 'days'}}}]
Source code in src/dummyxarray/core.py
def get_history(self):
    """
    Get the operation history for this array.

    Returns
    -------
    list of dict
        List of operations

    Examples
    --------
    >>> arr = DummyArray(dims=["time"], attrs={"units": "days"})
    >>> arr.get_history()
    [{'func': '__init__', 'args': {'dims': ['time'], 'attrs': {'units': 'days'}}}]
    """
    return self._history.copy() if self._history is not None else []

replay_history

replay_history(history=None)

Replay a sequence of operations to recreate an array.

Parameters:

Name Type Description Default
history list of dict

History to replay. If None, uses self.get_history()

None

Returns:

Type Description
DummyArray

New array with operations replayed

Source code in src/dummyxarray/core.py
def replay_history(self, history=None):
    """
    Replay a sequence of operations to recreate an array.

    Parameters
    ----------
    history : list of dict, optional
        History to replay. If None, uses self.get_history()

    Returns
    -------
    DummyArray
        New array with operations replayed
    """
    if history is None:
        history = self.get_history()

    # Get __init__ args
    init_op = history[0] if history and history[0]["func"] == "__init__" else {}
    init_args = init_op.get("args", {})

    # Create new array
    arr = DummyArray(**init_args, _record_history=False)

    # Replay other operations
    for op in history[1:]:
        func = getattr(arr, op["func"], None)
        if func and callable(func):
            func(**op["args"])

    return arr

assign_attrs

assign_attrs(**kwargs)

Assign new attributes to this array (xarray-compatible API).

Parameters:

Name Type Description Default
**kwargs

Attributes to assign

{}

Returns:

Type Description
self

Returns self for method chaining

Examples:

>>> arr = DummyArray(dims=["time"])
>>> arr.assign_attrs(units="days", calendar="gregorian")
Source code in src/dummyxarray/core.py
def assign_attrs(self, **kwargs):
    """
    Assign new attributes to this array (xarray-compatible API).

    Parameters
    ----------
    **kwargs
        Attributes to assign

    Returns
    -------
    self
        Returns self for method chaining

    Examples
    --------
    >>> arr = DummyArray(dims=["time"])
    >>> arr.assign_attrs(units="days", calendar="gregorian")
    """
    self._record_operation("assign_attrs", kwargs)
    self.attrs.update(kwargs)
    return self

to_dict

to_dict()

Export structure (without data) for serialization.

Returns:

Type Description
dict

Dictionary representation

Source code in src/dummyxarray/core.py
def to_dict(self):
    """
    Export structure (without data) for serialization.

    Returns
    -------
    dict
        Dictionary representation
    """
    return {
        "dims": self.dims,
        "attrs": self.attrs,
        "encoding": self.encoding,
        "has_data": self.data is not None,
    }