modifiers Module
Genetic and fitness modifiers.
Overview
The modifiers module defines how various genetic and external factors influence individual fitness and allele inheritance.
Complete Module Reference
natal.modifiers
Modifier system for population simulations.
This module defines protocols and helper functions for constructing and wrapping modifiers that alter gamete or zygote production in the simulation. Modifiers are callable objects that return frequency distributions, and are converted into tensor‑level functions that directly update NumPy arrays.
Two modifier types are supported: - Gamete modifiers: alter the mapping from (sex, diploid genotype) to haploid gamete frequencies. - Zygote modifiers: alter the mapping from a pair of haploid gametes (with gamete labels) to a diploid zygote genotype.
The wrapper factories (wrap_gamete_modifier, wrap_zygote_modifier) take
high‑level modifiers that return domain‑object dictionaries and produce
callables that operate on NumPy tensors.
GameteModifier
Bases: Protocol
Protocol for a bulk gamete modifier.
Implementations should provide a callable that accepts either zero or one
argument (an optional population object) and returns a nested mapping of
gamete frequency updates. The canonical return type is::
Dict[Tuple[int, int], Dict[int, float]]
where the outer key is (sex_idx, genotype_idx) and the inner mapping is
{ compressed_hg_glab_idx: frequency, ... }. Keys may be flexible types
in wrappers (for convenience) but should ultimately resolve to integers.
sex_idx is an int. genotype_idx may be an int, a
Genotype object, or a string produced by Genotype.to_string().
Examples:
return {(0, 5): {3: 0.2, 4: 0.8}, (1, 5): {3: 1.0}}
The result writes frequency distributions for compressed indices directly back into numeric tensors.
ZygoteModifier
Bases: Protocol
Protocol for a bulk zygote modifier.
Implementations should provide a callable that accepts zero or one argument
(an optional population) and returns a mapping from a flexible key to a
replacement. The key identifies the zygote pairing and may take one of
several forms that wrappers can resolve into compressed coordinate pairs
(c1, c2).
Supported key representations include
- compressed index pair
(c1, c2) - nested tuples
((hg_obj|hg_str|idx_hg, glab_label?), (hg_obj|hg_str|idx_hg, glab_label?)) - other wrapper-resolvable representations
Replacement values may be one of
- an integer index
idx_modified(index into diploid genotype list) - a
Genotypeinstance (wrappers will convert to an index) - a dict
{ idx_modified: probability, ... }specifying a distribution
The protocol returns::
Dict[Any, Union[int, Genotype, Dict[int, float]]]
evaluate_genotype_filter
evaluate_genotype_filter(genotype_filter: GenotypeFilter, genotype: Genotype, compiled_filter: Optional[Callable[[Genotype], bool]]) -> Tuple[bool, Optional[Callable[[Genotype], bool]]]
Evaluate genotype_filter and lazily compile pattern-string filters.
The function supports three filter forms:
- None: always pass
- callable: evaluate directly
- string pattern: compile once via GenotypePatternParser then reuse
Source code in src/natal/modifiers.py
resolve_optional_glab_index
Resolve an optional glab selector to an integer index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
GlabSelector
|
Glab selector as |
required |
glab_to_index
|
Mapping[str, int]
|
Mapping from glab labels to integer indices. |
required |
Returns:
| Type | Description |
|---|---|
Optional[int]
|
The resolved glab index. Returns |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in src/natal/modifiers.py
wrap_gamete_modifier
wrap_gamete_modifier(mod: GameteModifier, population: Any, index_registry: Any, haploid_genotypes: List[HaploidGenotype], diploid_genotypes: List[Genotype], n_glabs: int) -> Callable[[np.ndarray], np.ndarray]
Wrap a high-level GameteModifier into a tensor-level callable.
The returned callable accepts a tensor of shape (n_sexes, n_genotypes, n_hg_glabs) and returns a modified copy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mod
|
GameteModifier
|
A GameteModifier callable (returns dict mapping keys to freq dicts). |
required |
population
|
Any
|
The population object (passed to mod if it takes an argument). |
required |
index_registry
|
Any
|
IndexRegistry instance for key resolution. |
required |
haploid_genotypes
|
List[HaploidGenotype]
|
List of all HaploidGenotype objects. |
required |
diploid_genotypes
|
List[Genotype]
|
List of all Genotype objects. |
required |
n_glabs
|
int
|
Number of gamete-label variants. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[ndarray], ndarray]
|
A callable (np.ndarray) -> np.ndarray. |
Source code in src/natal/modifiers.py
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | |
wrap_zygote_modifier
wrap_zygote_modifier(mod: ZygoteModifier, population: Any, index_registry: Any, haploid_genotypes: List[HaploidGenotype], diploid_genotypes: List[Genotype], n_glabs: int) -> Callable[[np.ndarray], np.ndarray]
Wrap a high-level ZygoteModifier into a tensor-level callable.
The returned callable accepts a tensor of shape (n_hg_glabs, n_hg_glabs, n_genotypes) and returns a modified copy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mod
|
ZygoteModifier
|
A ZygoteModifier callable. |
required |
population
|
Any
|
The population object (passed to mod if it takes an argument). |
required |
index_registry
|
Any
|
IndexRegistry instance for key resolution. |
required |
haploid_genotypes
|
List[HaploidGenotype]
|
List of all HaploidGenotype objects. |
required |
diploid_genotypes
|
List[Genotype]
|
List of all Genotype objects. |
required |
n_glabs
|
int
|
Number of gamete-label variants. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[ndarray], ndarray]
|
A callable (np.ndarray) -> np.ndarray. |
Source code in src/natal/modifiers.py
build_modifier_wrappers
build_modifier_wrappers(gamete_modifiers: List[Tuple[int, Optional[str], GameteModifier]], zygote_modifiers: List[Tuple[int, Optional[str], ZygoteModifier]], population: Any, index_registry: Any, haploid_genotypes: List[HaploidGenotype], diploid_genotypes: List[Genotype], n_glabs: int = 1) -> Tuple[List[Callable[[np.ndarray], np.ndarray]], List[Callable[[np.ndarray], np.ndarray]]]
Wrap high-level gamete/zygote modifiers into tensor-level callables.
This is the shared implementation used by BasePopulation and any external modifier systems that need to convert high-level modifiers to tensor ops.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gamete_modifiers
|
List[Tuple[int, Optional[str], GameteModifier]]
|
List of (modifier_id, name, modifier) tuples for gamete modifiers. |
required |
zygote_modifiers
|
List[Tuple[int, Optional[str], ZygoteModifier]]
|
List of (modifier_id, name, modifier) tuples for zygote modifiers. |
required |
population
|
Any
|
The population object. |
required |
index_registry
|
Any
|
IndexRegistry instance. |
required |
haploid_genotypes
|
List[HaploidGenotype]
|
List of all HaploidGenotype objects. |
required |
diploid_genotypes
|
List[Genotype]
|
List of all Genotype objects. |
required |
n_glabs
|
int
|
Number of gamete-label variants. |
1
|
Returns:
| Type | Description |
|---|---|
List[Callable[[ndarray], ndarray]]
|
Tuple of (gamete_modifier_funcs, zygote_modifier_funcs), each a list |
List[Callable[[ndarray], ndarray]]
|
of callables that accept and return NumPy tensors. |