Skip to content

utils Module

General-purpose utilities for the simulation framework.

Overview

The utils subpackage provides Sex, Age, GameteLabel type aliases, ParamDescriptor for the parameter registry, and helper functions.

Complete Module Reference

natal.utils

Utility modules — types, helpers, and parameter descriptors.

ParamDescriptor dataclass

ParamDescriptor(domain: str, name: str, config_field: str | None, config_path: tuple[int, ...], dtype: type, bounds: tuple[float, float], doc: str = '', aliases: tuple[str, ...] = (), is_tensor: bool = False, is_0d: bool = False, is_array: bool = False, target: str = 'config')

A single estimable parameter mapping a user-facing name to a config field.

Attributes:

Name Type Description
domain str

Category this parameter belongs to (e.g. "competition").

name str

User-facing name (e.g. "carrying_capacity").

config_field str | None

PopulationConfig field name; None for spatial-only params.

config_path tuple[int, ...]

Index tuple into the config array. Scalars use ().

dtype type

Python type (float, int, or bool).

bounds tuple[float, float]

Plausible range (lo, hi).

doc str

One-line description.

aliases tuple[str, ...]

Historical names mapped to this parameter.

is_tensor bool

Multi-dimensional array (e.g. fitness tensors).

is_0d bool

0-d ndarray, writable via field[()] = v.

is_array bool

1-D or 2-D slice, written by Configurator directly.

target str

"config", "spatial", or "hook".

Sex

Bases: IntEnum

Sex enum backed by integers.

Using :class:IntEnum makes values directly usable as array indices and compatible with Numba-friendly code.

resolve_sex_label

resolve_sex_label(sex_label: object) -> int

Convert sex label to PopulationConfig sex index.

Convention follows Sex enum and PopulationConfig: - female/f -> 0 - male/m -> 1

Source code in src/natal/utils/helpers.py
def resolve_sex_label(sex_label: object) -> int:
    """Convert sex label to PopulationConfig sex index.

    Convention follows ``Sex`` enum and ``PopulationConfig``:
    - female/f -> 0
    - male/m -> 1
    """
    assert isinstance(sex_label, (Sex, int, str)), (
        f"Invalid sex label type '{type(sex_label).__name__}'. Expected Sex, int, or str."
    )

    sex_value: object = sex_label
    if isinstance(sex_value, int):
        if sex_value in (0, 1):
            return sex_value
        raise ValueError(f"Invalid sex index '{sex_value}'. Expected 0/1.")
    if isinstance(sex_value, Sex):
        return sex_value.value
    normalized = sex_value.lower()
    if normalized in ('female', 'f'):
        return 0
    if normalized in ('male', 'm'):
        return 1
    raise ValueError(f"Invalid sex label '{sex_value}'. Expected female/male/f/m.")

validate_name

validate_name(name: str) -> bool

Validate if a name is valid.

A valid name consists of only letters, numbers, and underscores.

Parameters:

Name Type Description Default
name str

The name to validate.

required

Returns:

Name Type Description
bool bool

True if the name is valid, False otherwise.

Source code in src/natal/utils/helpers.py
def validate_name(name: str) -> bool:
    """Validate if a name is valid.

    A valid name consists of only letters, numbers, and underscores.

    Args:
        name (str): The name to validate.

    Returns:
        bool: True if the name is valid, False otherwise.
    """
    import re

    pattern = r'^[A-Za-z0-9_]+$'
    return bool(re.match(pattern, name))