aegis_sim.parameterization.default_parameters

   1from aegis_sim.parameterization.parameter import Parameter
   2
   3
   4def get_default_parameters():
   5    return {p.key: p.default for p in DEFAULT_PARAMETERS.values()}
   6
   7
   8def get_species_parameters(SPECIES_PRESET):
   9    return {p.key: p.presets[SPECIES_PRESET] for p in DEFAULT_PARAMETERS.values() if SPECIES_PRESET in p.presets}
  10
  11
  12# TODO test these
  13# TODO value interpolation between ages?
  14# TODO report invalid values
  15
  16PRESET_INFO = {
  17    "human": "One cycle corresponds to 2 years.",
  18    "mouse": "One cycle corresponds to one month. Source: https://genomics.senescence.info/species/entry.php?species=Mus_musculus",
  19    "killifish": "One cycle corresponds to one week.",
  20    "yeast": "",
  21    "arabidopsis": "",
  22    "worm": "One cycle corresponds to one day. Up to 300 eggs in optimal conditions.",
  23    "fruitfly": "One cycle corresponds to one day. Up to 100 eggs per day.",
  24}
  25
  26# You need the `key` attribute so you can find the param (in a list, you cannot)
  27DEFAULT_PARAMETERS = {
  28    #
  29    #
  30    # RECORDING
  31    "LOGGING_RATE": Parameter(
  32        key="LOGGING_RATE",
  33        name="",
  34        domain="recording",
  35        default=100,
  36        info="Frequency of logging (in steps)",
  37        info_extended="Log files contain information on simulation execution; e.g. errors and speed. 0 for no logging.",
  38        dtype=int,
  39        drange="[0, inf)",
  40        inrange=lambda x: x >= 0,
  41        evalrange=[1, 10000],
  42    ),
  43    "TICKER_RATE": Parameter(
  44        key="TICKER_RATE",
  45        name="",
  46        domain="recording",
  47        default=1,
  48        info="Frequency of ticking (in seconds)",
  49        info_extended="Ticker files contain information on simulation status; e.g. running or finished. Once the simulation is finished, it stops updating the ticker file which indicates the time at which the simulation stopped.",
  50        dtype=float,
  51        drange="[0, inf)",
  52        inrange=lambda x: x >= 0,
  53        evalrange=[1, 10000],
  54        show_in_gui=False,
  55    ),
  56    "PICKLE_RATE": Parameter(
  57        key="PICKLE_RATE",
  58        name="",
  59        domain="recording",
  60        default=10000,
  61        info="Frequency of pickling (in steps)",
  62        info_extended="0 for no pickles",
  63        dtype=int,
  64        drange="[0, inf)",
  65        inrange=lambda x: x >= 0,
  66        serverrange=lambda x: x >= 1000 or x == 0,
  67        serverrange_info="0 or [1000, inf)",
  68        evalrange=[1, 100000],
  69    ),
  70    "FASTA_RATE": Parameter(
  71        key="FASTA_RATE",
  72        name="",
  73        domain="recording",
  74        default=0,
  75        info="Frequency of writing FASTA exports of the living population (in steps)",
  76        info_extended="0 disables FASTA output. When >0, AEGIS writes /fasta/step{N}.genome.fasta and /fasta/step{N}.mapping.json at step 1, every FASTA_RATE steps, and at the final step. The FASTA encodes each individual's genome with a 4-letter packing (2 bits per base, 00→A 01→C 10→G 11→T) after a uniform XOR mask to debias composition. The mapping JSON contains the mask and shape needed to decode back to the original bits.",
  77        dtype=int,
  78        drange="[0, inf)",
  79        inrange=lambda x: x >= 0,
  80        serverrange=lambda x: x >= 1000 or x == 0,
  81        serverrange_info="0 or [1000, inf)",
  82        evalrange=[0, 1000, 10000],
  83    ),
  84    "FASTA_MASK_SEED": Parameter(
  85        key="FASTA_MASK_SEED",
  86        name="",
  87        domain="recording",
  88        default=0,
  89        info="Seed for the uniform XOR mask applied to genomes before FASTA encoding (debiases base composition)",
  90        info_extended="Independent of RANDOM_SEED so the ledger (mapping.json) is identical across all AEGIS runs that share the same genome architecture. Only set a different value if you want per-experiment mask isolation. Has no effect unless FASTA_RATE > 0.",
  91        dtype=int,
  92        drange="(-inf, inf)",
  93        inrange=lambda x: True,
  94        evalrange=[0, 1, 42],
  95    ),
  96    "VCF_RATE": Parameter(
  97        key="VCF_RATE",
  98        name="",
  99        domain="recording",
 100        default=0,
 101        info="Frequency of writing VCF exports of the living population (in steps)",
 102        info_extended="0 disables VCF output. When >0, AEGIS writes /vcf/step{N}.vcf at step 1, every VCF_RATE steps, and at the final step. Each row is one genome bit (biallelic SNP, REF=A ALT=T), each sample column is one diploid individual with phased genotype chromatid0|chromatid1. The header records architecture metadata (locus_permutation, n_loci, BITS_PER_LOCUS) so the file is self-contained and decodable without re-initializing AEGIS. Only supported for the composite architecture.",
 103        dtype=int,
 104        drange="[0, inf)",
 105        inrange=lambda x: x >= 0,
 106        serverrange=lambda x: x >= 1000 or x == 0,
 107        serverrange_info="0 or [1000, inf)",
 108        evalrange=[0, 1000, 10000],
 109    ),
 110    "GVCF_RATE": Parameter(
 111        key="GVCF_RATE",
 112        name="",
 113        domain="recording",
 114        default=0,
 115        info="Cadence (in steps) at which to write a FASTA-coordinate multi-sample gVCF",
 116        info_extended="0 disables gVCF output. When >0, AEGIS writes /gvcf/step{N}.gvcf at step 1, every GVCF_RATE steps, and at the final step. One gVCF per Population: each individual is one sample column, each row is one FASTA base position (matching FASTA + Badread coordinates), REF is the consensus allele across the population, ALT lists observed non-REF alleles + <NON_REF>. Long runs of all-REF positions are compressed into reference blocks. Output is Clair3-compatible so it can be fed straight into GLnexus alongside read-derived gVCFs for ABBA-BABA-style ground-truth comparisons.",
 117        dtype=int,
 118        drange="[0, inf)",
 119        inrange=lambda x: x >= 0,
 120        serverrange=lambda x: x >= 1000 or x == 0,
 121        serverrange_info="0 or [1000, inf)",
 122        evalrange=[0, 1000, 10000],
 123    ),
 124    "LINEAGE_TRACING": Parameter(
 125        key="LINEAGE_TRACING",
 126        name="",
 127        domain="recording",
 128        default=False,
 129        info="Enable per-individual lineage tracking (asexual reproduction only)",
 130        info_extended="When True, each individual is assigned a unique lineage_id at birth and stores the parent's lineage_id. Initial population members get parent_lineage_id=-1. Currently only the asexual REPRODUCTION_MODE is supported; with sexual reproduction this flag has no effect and a warning is logged. Lineage IDs are stored on the Population (visible in pickles) and written to /lineage/births.csv if LINEAGE_RATE > 0.",
 131        dtype=bool,
 132        drange="{True, False}",
 133        inrange=lambda x: isinstance(x, bool),
 134        evalrange=[True, False],
 135    ),
 136    "LINEAGE_RATE": Parameter(
 137        key="LINEAGE_RATE",
 138        name="",
 139        domain="recording",
 140        default=0,
 141        info="Cadence (in steps) at which the lineage birth log is flushed to disk",
 142        info_extended="0 disables the birth-log file (lineage IDs are still tracked in memory when LINEAGE_TRACING=True, just not written). When >0, /lineage/births.csv accumulates one row per birth (step, lineage_id, parent_lineage_id) plus initial-population rows at step 0. The file is appended to incrementally; the rate controls how often the in-memory buffer is flushed (not how often births are recorded \u2014 every birth is recorded).",
 143        dtype=int,
 144        drange="[0, inf)",
 145        inrange=lambda x: x >= 0,
 146        evalrange=[0, 100, 1000],
 147    ),
 148    "ALLELE_INJECTION_STEP": Parameter(
 149        key="ALLELE_INJECTION_STEP",
 150        name="",
 151        domain="experimental",
 152        default=0,
 153        info="Step at which to inject a forced allele at a specific locus (0 disables the experiment)",
 154        info_extended="At this step (before mortality), AEGIS sets ALLELE_INJECTION_ALLELE at (TRAIT, AGE, BIT) on chromatid 0 of an ALLELE_INJECTION_FRACTION-sized random subset of the living population. The affected individuals' phenotypes are recomputed immediately. Used to measure the selection coefficient s by tracking allele frequency in the SelectionRecorder log (/selection/selection.csv) and fitting log(p/(1-p)) over time via runs/fit_s.py. This is an experimental intervention, NOT the natural per-bit mutation system (which is unchanged and driven by the muta trait). 0 disables both the injection and the selection log.",
 155        dtype=int,
 156        drange="[0, inf)",
 157        inrange=lambda x: x >= 0,
 158        evalrange=[0, 100, 1000],
 159    ),
 160    "ALLELE_INJECTION_TRAIT": Parameter(
 161        key="ALLELE_INJECTION_TRAIT",
 162        name="",
 163        domain="experimental",
 164        default="surv",
 165        info="Trait at which to inject the forced allele",
 166        info_extended="One of 'surv', 'repr', 'neut', 'muta', 'grow'. The trait must be evolvable (G_<trait>_evolvable=True) for the injection to be valid \u2014 non-evolvable traits have no genome loci. Choose a selectable trait (surv, repr, grow) to measure real selection; choose neut for a drift-only null control (requires G_neut_evolvable=True, off by default).",
 167        dtype=str,
 168        drange="{surv, repr, neut, muta, grow}",
 169        inrange=lambda x: x in ("surv", "repr", "neut", "muta", "grow"),
 170        evalrange=["surv", "repr", "neut"],
 171    ),
 172    "ALLELE_INJECTION_AGE": Parameter(
 173        key="ALLELE_INJECTION_AGE",
 174        name="",
 175        domain="experimental",
 176        default=0,
 177        info="Age (0-indexed) at which to inject the forced allele for age-specific traits",
 178        info_extended="Ignored for non-age-specific traits (one locus regardless of age). For age-specific traits, late-life loci are expected to show smaller s because fewer individuals reach the relevant age and residual reproductive value is lower \u2014 this is the classic Hamilton/Williams prediction and the main scientific use of this feature.",
 179        dtype=int,
 180        drange="[0, AGE_LIMIT)",
 181        inrange=lambda x: x >= 0,
 182        evalrange=[0, 5, 20],
 183    ),
 184    "ALLELE_INJECTION_BIT": Parameter(
 185        key="ALLELE_INJECTION_BIT",
 186        name="",
 187        domain="experimental",
 188        default=0,
 189        info="Bit index within the (TRAIT,AGE) locus at which to inject the forced allele",
 190        info_extended="Range: [0, BITS_PER_LOCUS). Different bits at the same locus have the same contribution under uniform/binary interpreters and different contributions under the threshold interpreter.",
 191        dtype=int,
 192        drange="[0, BITS_PER_LOCUS)",
 193        inrange=lambda x: x >= 0,
 194        evalrange=[0, 4, 7],
 195    ),
 196    "ALLELE_INJECTION_ALLELE": Parameter(
 197        key="ALLELE_INJECTION_ALLELE",
 198        name="",
 199        domain="experimental",
 200        default=1,
 201        info="Value to set at the locus: 0 or 1",
 202        info_extended="For surv/repr under the standard binary interpreter, 1 increases the trait probability and 0 decreases it \u2014 use 1 for a beneficial knock-in (expect positive s), 0 for a deleterious knock-out (expect negative s).",
 203        dtype=int,
 204        drange="{0, 1}",
 205        inrange=lambda x: x in (0, 1),
 206        evalrange=[0, 1],
 207    ),
 208    "ALLELE_INJECTION_FRACTION": Parameter(
 209        key="ALLELE_INJECTION_FRACTION",
 210        name="",
 211        domain="experimental",
 212        default=0.05,
 213        info="Fraction of the living population to receive the forced allele on chromatid 0",
 214        info_extended="The classical setting is small (1-5%) so the introduced allele starts rare and its frequency trajectory is informative about s. Heterozygous injection (chromatid 0 only); chromatid 1 keeps whatever bit it had.",
 215        dtype=float,
 216        drange="(0, 1]",
 217        inrange=lambda x: 0 < x <= 1,
 218        evalrange=[0.01, 0.05, 0.2],
 219    ),
 220    "CHECKPOINT_RATE": Parameter(
 221        key="CHECKPOINT_RATE",
 222        name="",
 223        domain="recording",
 224        default=0,
 225        info="Frequency of saving full simulation checkpoints for resuming (in steps)",
 226        info_extended="0 for no checkpoints. Checkpoints capture the entire simulation state and can be used to resume a simulation from where it left off.",
 227        dtype=int,
 228        drange="[0, inf)",
 229        inrange=lambda x: x >= 0,
 230        serverrange=lambda x: x >= 1000 or x == 0,
 231        serverrange_info="0 or [1000, inf)",
 232        evalrange=[0, 1000, 10000],
 233    ),
 234    "SNAPSHOT_RATE": Parameter(
 235        key="SNAPSHOT_RATE",
 236        name="",
 237        domain="recording",
 238        default=10000,
 239        info="Frequency of recording snapshots (in steps)",
 240        info_extended="0 for no snapshots",
 241        dtype=int,
 242        drange="[0, inf)",
 243        inrange=lambda x: x >= 0,
 244        serverrange=lambda x: x >= 1000 or x == 0,
 245        serverrange_info="0 or [1000, inf)",
 246        evalrange=[1, 10000],
 247    ),
 248    "SNAPSHOT_FINAL_COUNT": Parameter(
 249        key="SNAPSHOT_FINAL_COUNT",
 250        name="",
 251        domain="recording",
 252        default=60,
 253        info="Number of subsequent snapshots taken at the end of the simulation (in steps)",
 254        info_extended="0 for no snapshots",
 255        dtype=int,
 256        drange="[0, inf)",
 257        inrange=lambda x: x >= 0,
 258        serverrange=lambda x: 0 <= x <= 60,
 259        serverrange_info="[0, 60]",
 260        evalrange=[1, 10],
 261    ),
 262    "INTERVAL_RATE": Parameter(
 263        key="INTERVAL_RATE",
 264        name="",
 265        domain="recording",
 266        default=1000,
 267        info="Frequency of recording interval data (in steps)",
 268        info_extended="0 for no gui records",
 269        dtype=int,
 270        drange="[0, inf)",
 271        inrange=lambda x: x >= 0,
 272        evalrange=[1, 10000],
 273        serverrange=lambda x: x >= 100,
 274        serverrange_info="[100, inf)",
 275    ),
 276    "TE_RATE": Parameter(
 277        key="TE_RATE",
 278        name="",
 279        domain="recording",
 280        default=10000,
 281        info="Frequency of starting TE cohorts (in steps)",
 282        dtype=int,
 283        drange="[0, inf)",
 284        inrange=lambda x: x >= 0,
 285        evalrange=[1, 10000],
 286        serverrange=lambda x: x >= 100,
 287        serverrange_info="[100, inf)",
 288    ),
 289    "TE_DURATION": Parameter(
 290        key="TE_DURATION",
 291        name="",
 292        domain="recording",
 293        default=500,
 294        info="Length of tracking TE cohorts (in steps)",
 295        dtype=int,
 296        drange="[0, inf)",
 297        inrange=lambda x: x >= 0,
 298        evalrange=[1, 10000],
 299    ),
 300    "POPGENSTATS_RATE": Parameter(
 301        key="POPGENSTATS_RATE",
 302        name="",
 303        domain="recording",
 304        default=1000,
 305        info="Frequency of recording population genetic statistics (in steps)",
 306        info_extended="0 for no recording",
 307        dtype=int,
 308        drange="[0, inf)",
 309        inrange=lambda x: x >= 0,
 310        serverrange=lambda x: x >= 100 or x == 0,
 311        serverrange_info="0 or [100, inf)",
 312        evalrange=[1, 10000],
 313    ),
 314    "POPGENSTATS_SAMPLE_SIZE": Parameter(
 315        key="POPGENSTATS_SAMPLE_SIZE",
 316        name="",
 317        domain="recording",
 318        default=100,
 319        info="Number of individuals to use when calculating population genetic statistics",
 320        dtype=int,
 321        drange="{0, [3, inf)}",
 322        inrange=lambda x: x == 0 or x >= 3,
 323    ),
 324    "NOTES": Parameter(
 325        key="NOTES",
 326        name="",
 327        domain="recording",
 328        default=[],
 329        info="",
 330        dtype=list,
 331        drange="",
 332    ),
 333    #
 334    #
 335    # STARVATION
 336    # "STARVATION_RESPONSE": Parameter(
 337    #     key="STARVATION_RESPONSE",
 338    #     name="",
 339    #     domain="starvation",
 340    #     default="worsening_proportional",
 341    #     info="Mechanism for determining who dies under overcrowding conditions",
 342    #     info_extended="The possible modes can differ in the age distribution of mortality and/or the number of individuals removed.",
 343    #     dtype=str,
 344    #     drange="{gradual, cliff, treadmill_random, treadmill_zoomer, treadmill_boomer, treadmill_boomer_soft, treadmill_zoomer_soft, worsening_proportional}",
 345    #     inrange=lambda x: x
 346    #     in (
 347    #         "gradual",
 348    #         # "cliff",
 349    #         "treadmill_random",
 350    #         "treadmill_zoomer",
 351    #         "treadmill_boomer",
 352    #         "treadmill_boomer_soft",
 353    #         "treadmill_zoomer_soft",
 354    #         "worsening_proportional",
 355    #     ),
 356    #     evalrange=[
 357    #         "gradual",
 358    #         # "cliff",
 359    #         "treadmill_random",
 360    #         "treadmill_zoomer",
 361    #         "treadmill_boomer",
 362    #         "treadmill_boomer_soft",
 363    #         "treadmill_zoomer_soft",
 364    #         "worsening_proportional",
 365    #     ],
 366    # ),
 367    "STARVATION_MORTALITY_FACTOR": Parameter(
 368        key="STARVATION_MORTALITY_FACTOR",
 369        name="",
 370        domain="starvation",
 371        default=None,  # recommended values are None or 0.01
 372        info="Factor that affects the magnitude of starvation mortality. Higher number means higher sensitivity to starvation.",
 373        info_extended="When None, mortality will depend on the resource deficit. When input is a real number, it is the mortality experienced under starvation.",
 374        dtype=float,
 375        drange="(0,inf)",
 376        inrange=lambda x: x is None or x > 0,
 377        evalrange=[None, 0.005, 0.01, 0.05, 0.1, 0.2],
 378    ),
 379    "STARVATION_MORTALITY_MAXIMUM": Parameter(
 380        key="STARVATION_MORTALITY_MAXIMUM",
 381        name="",
 382        domain="starvation",
 383        default=0.5,
 384        info="",
 385        info_extended="",
 386        dtype=float,
 387        drange="(0,1)",
 388        inrange=lambda x: 0 < x < 1,
 389        evalrange=[0.5, 0.75, 0.9],
 390    ),
 391    "STARVATION_PENALTY": Parameter(
 392        key="STARVATION_PENALTY",
 393        name="",
 394        domain="starvation",
 395        default=0.1,
 396        info="Per-step fractional penalty applied to surv and repr when N > resources. Compounds each consecutive step under deficit; resets when resources are sufficient.",
 397        info_extended="effective_phenotype = phenotype * (1 - STARVATION_PENALTY) ** consecutive_starvation_steps. Set to 0 to disable.",
 398        dtype=float,
 399        drange="[0, 1)",
 400        inrange=lambda x: 0 <= x < 1,
 401        evalrange=[0.0, 0.05, 0.1, 0.2],
 402    ),
 403    #
 404    #
 405    # RESOURCES
 406    "RESOURCE_INITIAL_AMOUNT": Parameter(
 407        key="RESOURCE_INITIAL_AMOUNT",
 408        name="",
 409        domain="resources",
 410        default=500,
 411        info="Amount of resources available at the beginning of the simulation",
 412        dtype=float,
 413        drange="[1,inf)",
 414        inrange=lambda x: x >= 1,
 415    ),
 416    "RESOURCE_MAXIMUM_AMOUNT": Parameter(
 417        key="RESOURCE_MAXIMUM_AMOUNT",
 418        name="",
 419        domain="resources",
 420        default=5000,
 421        info="Maximum amount of resources that can be accumulated",
 422        info_extended="When None, no maximum exists.",
 423        dtype=float,
 424        drange="{None, [1,inf)}",
 425        inrange=lambda x: x is None or (x >= 1),
 426    ),
 427    "RESOURCE_ADDITIVE_GROWTH": Parameter(
 428        key="RESOURCE_ADDITIVE_GROWTH",
 429        name="",
 430        domain="resources",
 431        default=500,
 432        info="Absolute value by which the amount of resources increases each step",
 433        info_extended="new_resource_amount = old_resource_amount * RESOURCE_MULTIPLICATIVE_GROWTH + RESOURCE_ADDITIVE_GROWTH",
 434        dtype=float,
 435        drange="[1,inf)",
 436        inrange=lambda x: x >= 1,
 437    ),
 438    "RESOURCE_MULTIPLICATIVE_GROWTH": Parameter(
 439        key="RESOURCE_MULTIPLICATIVE_GROWTH",
 440        name="",
 441        domain="resources",
 442        default=0,
 443        info="Factor by which (+1) the amount of remaining resources are multiplied each step",
 444        info_extended="new_resource_amount = old_resource_amount * (1 + RESOURCE_MULTIPLICATIVE_GROWTH) + RESOURCE_ADDITIVE_GROWTH",
 445        dtype=float,
 446        drange="[0,inf)",
 447        inrange=lambda x: x >= 0,
 448        evalrange=[0.01, 0.02, 0.05, 0.1],
 449    ),
 450    #
 451    #
 452    # REPRODUCTION
 453    "INCUBATION_PERIOD": Parameter(
 454        key="INCUBATION_PERIOD",
 455        name="",
 456        domain="reproduction",
 457        default=0,
 458        info="Time between fertilization and hatching (in steps)",
 459        info_extended="0 if egg period is skipped, -1 if hatching occurs only once no living individuals are around.",
 460        dtype=int,
 461        drange="[-1, inf)",
 462        inrange=lambda x: x >= -1,
 463        presets={},
 464    ),
 465    "MATURATION_AGE": Parameter(
 466        key="MATURATION_AGE",
 467        name="",
 468        domain="reproduction",
 469        default=10,
 470        info="Minimum age at which an individual can reproduce",
 471        info_extended="",
 472        dtype=int,
 473        drange="[1, inf)",
 474        inrange=lambda x: x >= 1,
 475        evalrange=[0, 50],
 476        presets={
 477            "mouse": 1,  # 1 cycle .. 1 month
 478        },
 479    ),
 480    "REPRODUCTION_ENDPOINT": Parameter(
 481        key="REPRODUCTION_ENDPOINT",
 482        name="",
 483        domain="reproduction",
 484        default=0,
 485        info="Minimum age at which an individual can no longer reproduce",
 486        info_extended="When set to 0, there is no loss of fertility.",
 487        dtype=int,
 488        drange="[0, inf)",
 489        inrange=lambda x: x >= 0,
 490        presets={
 491            "human": 50,
 492        },
 493    ),
 494    "MAX_OFFSPRING_NUMBER": Parameter(
 495        key="MAX_OFFSPRING_NUMBER",
 496        name="",
 497        domain="reproduction",
 498        default=1,
 499        info="Maximum number of offspring that an individual can produce each step.",
 500        info_extended="Also known as clutch size, litter size or brood size, depending on the species.",
 501        dtype=int,
 502        drange="[1, inf)",
 503        inrange=lambda x: x >= 1,
 504        presets={},
 505        serverrange=lambda x: x <= 5,
 506        serverrange_info="[1,5]",
 507    ),
 508    "REPRODUCTION_MODE": Parameter(
 509        key="REPRODUCTION_MODE",
 510        name="",
 511        domain="reproduction",
 512        default="sexual",
 513        info="Mode of reproduction",
 514        info_extended="",
 515        dtype=str,
 516        drange="{sexual, asexual}",
 517        inrange=lambda x: x in ("sexual", "asexual"),
 518        presets={
 519            "yeast": "asexual",
 520        },
 521    ),
 522    "REPRODUCTION_REGULATION": Parameter(
 523        key="REPRODUCTION_REGULATION",
 524        name="",
 525        domain="reproduction",
 526        default=False,
 527        info="Density effects on reproduction. When True, no overshooting can occur.",
 528        info_extended="",
 529        dtype=bool,
 530        drange="",
 531    ),
 532    "RECOMBINATION_RATE": Parameter(
 533        key="RECOMBINATION_RATE",
 534        name="",
 535        domain="reproduction",
 536        default=0.1,
 537        info="Probability of recombination occuring between two adjacent sites",
 538        info_extended="If set to 0, there is no recombination.",
 539        dtype=float,
 540        drange="[0, inf)",
 541        inrange=lambda x: x >= 0,
 542        evalrange=[0, 1],
 543        presets={
 544            "yeast": 0,
 545        },
 546    ),
 547    "MUTATION_RATIO": Parameter(
 548        key="MUTATION_RATIO",
 549        name="",
 550        domain="reproduction",
 551        default=0.1,
 552        info="Ratio of 0->1 mutations to 1->0 mutations",
 553        dtype=float,
 554        drange="[0, inf)",
 555        inrange=lambda x: x >= 0,
 556    ),
 557    "MUTATION_AGE_MULTIPLIER": Parameter(
 558        key="MUTATION_AGE_MULTIPLIER",
 559        name="",
 560        domain="reproduction",
 561        default=0,
 562        info="Modifier of germline mutation rate",
 563        info_extended="final germline mutation rate = intrinsic mutation rate + (1 * age * MUTATION_AGE_MULTIPLIER)",
 564        dtype=float,
 565        drange="[0, inf)",
 566        inrange=lambda x: x >= 0,
 567    ),
 568    #
 569    #
 570    # GENETICS
 571    "DOMINANCE_FACTOR": Parameter(
 572        key="DOMINANCE_FACTOR",
 573        name="",
 574        domain="genetics",
 575        default=0.8,
 576        info="Inheritance patterns for non-haploid genomes",
 577        info_extended="DEPRECATED as of v3: use G_<trait>_dominance (per-trait h) instead. This global parameter is parsed but no longer applied by the simulation.",
 578        dtype=float,
 579        drange="[0, inf)",
 580        inrange=lambda x: x >= 0,
 581    ),
 582    "SMOOTHING_FACTOR": Parameter(
 583        key="SMOOTHING_FACTOR",
 584        name="",
 585        domain="genetics",
 586        default=0,
 587        info="Gaussian sigma factor for smoothing of phenotypes",
 588        info_extended="0 for no smoothing",
 589        dtype=float,
 590        drange="[0, inf)",
 591        inrange=lambda x: x >= 0,
 592    ),
 593    "PLOIDY": Parameter(
 594        key="PLOIDY",
 595        name="",
 596        domain="genetics",
 597        default=2,
 598        info="Number of complete sets of chromosomes",
 599        info_extended="If reproduction is sexual, ploidy can only be 2.",
 600        dtype=int,
 601        drange="[1, 4]",
 602        inrange=lambda x: x in (1, 2, 3, 4),
 603    ),
 604    "GENARCH_TYPE": Parameter(
 605        key="GENARCH_TYPE",
 606        name="",
 607        domain="genetics",
 608        default="composite",
 609        info="Modifying or composite architecture",
 610        info_extended="",
 611        dtype=str,
 612        drange="{composite, modifying}",
 613        inrange=lambda x: x in ("composite", "modifying"),
 614    ),
 615    "G_surv_lo": Parameter(
 616        key="G_surv_lo",
 617        name="",
 618        domain="genetics",
 619        default=0.7,
 620        info="Minimum survival probability per step (phenotype floor when all surv bits are 0)",
 621        info_extended="The composite architecture maps interpreter output (in [0,1]) onto [G_surv_lo, G_surv_hi]: phenotype = lo + (hi - lo) * interpreter_output. Setting lo > 0 ensures survival never collapses to 0, which keeps small populations viable when G_surv_initgeno=0.5 (50% random bits). Default 0.7 = a 50%-genome individual has surv ~0.85 at each age (with hi=1.0).",
 622        dtype=float,
 623        drange="[0, 1]",
 624        inrange=lambda x: 0 <= x <= 1,
 625        evalrange=[0.0, 0.5, 0.7, 0.9],
 626    ),
 627    "G_surv_hi": Parameter(
 628        key="G_surv_hi",
 629        name="",
 630        domain="genetics",
 631        default=1.0,
 632        info="Maximum survival probability per step (phenotype ceiling when all surv bits are 1)",
 633        info_extended="See G_surv_lo. Together with G_surv_lo defines the [lo, hi] phenotypic range that the interpreter output is scaled onto.",
 634        dtype=float,
 635        drange="[0, 1]",
 636        inrange=lambda x: 0 <= x <= 1,
 637        evalrange=[0.5, 0.9, 1.0],
 638    ),
 639    "G_repr_lo": Parameter(
 640        key="G_repr_lo",
 641        name="",
 642        domain="genetics",
 643        default=0,
 644        info="Minimum intrinsic fertility",
 645        dtype=float,
 646        drange="",
 647    ),
 648    "G_repr_hi": Parameter(
 649        key="G_repr_hi",
 650        name="",
 651        domain="genetics",
 652        default=0.5,
 653        info="Maximum intrinsic fertility",
 654        dtype=float,
 655        drange="",
 656        evalrange=[0.5, 1],
 657        # presets={
 658        #     "mouse": 1,  # 3.5; litter size of 7; 5.4 litters per year; https://genomics.senescence.info/species/entry.php?species=Mus_musculus
 659        #     "human": 1,  # litter size of 1,
 660        #     "mouse": 1,  # 5.5; litter size of 5-6
 661        #     "killifish": 1,  # 50; 1x-1xx eggs, depending on species
 662        #     "yeast": 1,
 663        #     "athaliana": 1,  # 1xx seeds per plant
 664        #     "worm": 1,  # up to 300 eggs in optimal conditions
 665        #     "fruitfly": 1,  # 100; up to 100 eggs per day in optimal conditions
 666        # },
 667    ),
 668    "G_neut_lo": Parameter(
 669        key="G_neut_lo",
 670        name="",
 671        domain="genetics",
 672        default=0,
 673        info="",
 674        dtype=float,
 675        drange="",
 676    ),
 677    "G_neut_hi": Parameter(
 678        key="G_neut_hi",
 679        name="",
 680        domain="genetics",
 681        default=1,
 682        info="",
 683        dtype=float,
 684        drange="",
 685    ),
 686    "G_muta_lo": Parameter(
 687        key="G_muta_lo",
 688        name="",
 689        domain="genetics",
 690        default=0,
 691        info="Minumum intrinsic mutation rate",
 692        dtype=float,
 693        drange="",
 694    ),
 695    "G_muta_hi": Parameter(
 696        key="G_muta_hi",
 697        name="",
 698        domain="genetics",
 699        default=1,
 700        info="Maximum intrinsic mutation rate",
 701        dtype=float,
 702        drange="",
 703    ),
 704    "G_grow_lo": Parameter(
 705        key="G_grow_lo",
 706        name="",
 707        domain="genetics",
 708        default=0,
 709        info="Minimum intrinsic growth rate",
 710        dtype=float,
 711        drange="",
 712    ),
 713    "G_grow_hi": Parameter(
 714        key="G_grow_hi",
 715        name="",
 716        domain="genetics",
 717        default=1,
 718        info="Maximum intrinsic growth rate",
 719        dtype=float,
 720        drange="",
 721    ),
 722    #
 723    #
 724    # ENVIRONMENTAL DRIFT
 725    "ENVDRIFT_RATE": Parameter(
 726        key="ENVDRIFT_RATE",
 727        name="",
 728        domain="environmental drift",
 729        default=0,
 730        info="Frequency of modification to the fitness landscape (in steps)",
 731        dtype=int,
 732        drange="[0, inf)",
 733        inrange=lambda x: x >= 0,
 734    ),
 735    #
 736    #
 737    # ABIOTIC
 738    "ABIOTIC_HAZARD_AMPLITUDE": Parameter(
 739        key="ABIOTIC_HAZARD_AMPLITUDE",
 740        name="",
 741        domain="abiotic",
 742        default=0,
 743        info="Maximum abiotic hazard",
 744        dtype=float,
 745        drange="[0, inf)",
 746        inrange=lambda x: x >= 0,
 747    ),
 748    "ABIOTIC_HAZARD_PERIOD": Parameter(
 749        key="ABIOTIC_HAZARD_PERIOD",
 750        name="",
 751        domain="abiotic",
 752        default=1,
 753        info="Period of wave form of abiotic hazard (in steps)",
 754        dtype=float,
 755        drange="[1, inf)",
 756        inrange=lambda x: x >= 1,
 757    ),
 758    "ABIOTIC_HAZARD_OFFSET": Parameter(
 759        key="ABIOTIC_HAZARD_OFFSET",
 760        name="",
 761        domain="abiotic",
 762        default=0,
 763        info="Constant, time-independent abiotic hazard",
 764        info_extended=r"e.g. 0.01 means that abiotic mortality is increased by 1% each step",
 765        dtype=float,
 766        drange="[0, inf)",
 767        inrange=lambda x: x >= 0,
 768    ),
 769    "ABIOTIC_HAZARD_SHAPE": Parameter(
 770        key="ABIOTIC_HAZARD_SHAPE",
 771        name="",
 772        domain="abiotic",
 773        default="sinusoidal",
 774        info="Wave form of abiotic hazard",
 775        dtype=str,
 776        drange="{sinusoidal, flat, triangle, square, sawtooth, ramp, instant, instant_fatal, instant_deterministic}",
 777        inrange=lambda x: x
 778        in {"sinusoidal", "flat", "triangle", "square", "sawtooth", "ramp", "instant", "instant_fatal", "instant_deterministic"},
 779    ),
 780    #
 781    #
 782    # INFECTION
 783    "BACKGROUND_INFECTIVITY": Parameter(
 784        key="BACKGROUND_INFECTIVITY",
 785        name="",
 786        domain="infection",
 787        default=0,
 788        info="Tendency to acquire infection from the environment",
 789        info_extended="Probability independent of the infection prevalence in the population; thus constant.",
 790        dtype=float,
 791        drange="[0, inf)",
 792        inrange=lambda x: x >= 0,
 793    ),
 794    "TRANSMISSIBILITY": Parameter(
 795        key="TRANSMISSIBILITY",
 796        name="",
 797        domain="infection",
 798        default=0,
 799        info="Tendency to acquire infection from other infected individuals",
 800        info_extended="Probability dependent on the infection prevalence in the population; thus variable.",
 801        dtype=float,
 802        drange="[0, inf)",
 803        inrange=lambda x: x >= 0,
 804    ),
 805    "RECOVERY_RATE": Parameter(
 806        key="RECOVERY_RATE",
 807        name="",
 808        domain="infection",
 809        info="Tendency to transition from infected to healthy status",
 810        default=0,
 811        dtype=float,
 812        drange="[0, inf)",
 813        inrange=lambda x: x >= 0,
 814    ),
 815    "FATALITY_RATE": Parameter(
 816        key="FATALITY_RATE",
 817        name="",
 818        domain="infection",
 819        info="Tendency to transition from infected to dead status",
 820        default=0,
 821        dtype=float,
 822        drange="[0, inf)",
 823        inrange=lambda x: x >= 0,
 824    ),
 825    #
 826    #
 827    # PREDATION
 828    "PREDATION_RATE": Parameter(
 829        key="PREDATION_RATE",
 830        name="",
 831        domain="predation",
 832        default=0,
 833        info="Vulnerability to predators",
 834        info_extended="Probability to die when number of predators is equal to number of prey. Probability changes logistically with the number of prey.",
 835        dtype=float,
 836        drange="[0, inf)",
 837        inrange=lambda x: x >= 0,
 838    ),
 839    "LATTICE_MODE": Parameter(
 840        key="LATTICE_MODE",
 841        name="",
 842        domain="ecology",
 843        default=False,
 844        info="Enable hexagonal lattice spatial model (one individual per cell, toroidal wraparound, lattice constrains mating + offspring placement + migration)",
 845        info_extended="When True, individuals occupy positions on a toroidal hexagonal lattice. Mating becomes spatial: a female searches expanding rings outward for a fertile male. Offspring are placed in a random adjacent empty cell (birth fails if no adjacent empty cell). Individuals migrate to adjacent empty cells (and rarely, to random distant empty cells). When False (default), AEGIS behavior is unchanged.",
 846        dtype=bool,
 847        drange="{True, False}",
 848        inrange=lambda x: isinstance(x, bool),
 849        evalrange=[True, False],
 850    ),
 851    "LATTICE_TARGET_DENSITY": Parameter(
 852        key="LATTICE_TARGET_DENSITY",
 853        name="",
 854        domain="ecology",
 855        default=0.3,
 856        info="Target occupancy fraction at carrying capacity (only used when LATTICE_MODE=True)",
 857        info_extended="Sets the lattice size at sim init: n_cells = expected_carrying_capacity / LATTICE_TARGET_DENSITY. Higher values = denser populations (mate-finding easier, less Allee effect, closer to well-mixed AEGIS). Lower values = sparser populations (stronger spatial structure, more isolation-by-distance, stronger Allee effect). Recommended baseline: 0.3.",
 858        dtype=float,
 859        drange="(0, 1]",
 860        inrange=lambda x: 0 < x <= 1,
 861        evalrange=[0.1, 0.3, 0.5, 0.9],
 862    ),
 863    "MIGRATION_RATE": Parameter(
 864        key="MIGRATION_RATE",
 865        name="",
 866        domain="ecology",
 867        default=0.1,
 868        info="Per-individual per-step probability of local migration to an adjacent empty cell",
 869        info_extended="Only used when LATTICE_MODE=True. The dominant viscosity knob. Low values = strong isolation-by-distance. High values = effectively well-mixed.",
 870        dtype=float,
 871        drange="[0, 1]",
 872        inrange=lambda x: 0 <= x <= 1,
 873        evalrange=[0.0, 0.01, 0.1, 0.5],
 874    ),
 875    "MIGRATION_LONG_RATE": Parameter(
 876        key="MIGRATION_LONG_RATE",
 877        name="",
 878        domain="ecology",
 879        default=0.005,
 880        info="Per-individual per-step probability of long-distance dispersal to a random empty cell anywhere on the lattice",
 881        info_extended="Only used when LATTICE_MODE=True. Provides a slow genetic-mixing channel even at high viscosity. Set to 0 for pure isolation-by-distance. Real species typically have nonzero long-distance dispersal (storm-driven, seed-mediated, etc.).",
 882        dtype=float,
 883        drange="[0, 1]",
 884        inrange=lambda x: 0 <= x <= 1,
 885        evalrange=[0.0, 0.001, 0.005, 0.05],
 886    ),
 887    "MATING_MAX_SEARCH_RADIUS": Parameter(
 888        key="MATING_MAX_SEARCH_RADIUS",
 889        name="",
 890        domain="ecology",
 891        default=3,
 892        info="How many hex rings outward a female searches for a fertile male",
 893        info_extended="Only used when LATTICE_MODE=True and REPRODUCTION_MODE=sexual. Ring 1 = the 6 adjacent cells, ring 2 = the next 12 cells, etc. The female picks a fertile male at random from the closest non-empty ring. If no fertile male within MATING_MAX_SEARCH_RADIUS rings, no reproduction this step. Mitigates Allee effects at low density; higher values = weaker spatial mating constraint.",
 894        dtype=int,
 895        drange="[1, inf)",
 896        inrange=lambda x: x >= 1,
 897        evalrange=[1, 3, 5, 10],
 898    ),
 899    "LATTICE_RECORD_RATE": Parameter(
 900        key="LATTICE_RECORD_RATE",
 901        name="",
 902        domain="recording",
 903        default=0,
 904        info="Cadence (in steps) at which to write a per-individual lattice snapshot CSV",
 905        info_extended="0 disables lattice snapshots. When >0, AEGIS writes /lattice/step{N}.csv at step 1, every LATTICE_RECORD_RATE steps, and at the final step. Columns: step, q, r, age, sex, lineage_id (-1 if LINEAGE_TRACING off), ancestry_fraction (-1 if INTROGRESSION not used). Use runs/lattice_animate.py to turn the snapshots into a PNG montage or animated GIF. No-op when LATTICE_MODE is False.",
 906        dtype=int,
 907        drange="[0, inf)",
 908        inrange=lambda x: x >= 0,
 909        evalrange=[0, 10, 100],
 910    ),
 911    "PREDATOR_GROWTH": Parameter(
 912        key="PREDATOR_GROWTH",
 913        name="",
 914        domain="predation",
 915        default=0,
 916        info="Intrinsic growth rate of predators",
 917        info_extended="Growth of the predator population is logistic.",
 918        dtype=float,
 919        drange="[0, inf)",
 920        inrange=lambda x: x >= 0,
 921    ),
 922    #
 923    #
 924    # GENETIC ARCHITECTURE (COMPOSITE)
 925    "BITS_PER_LOCUS": Parameter(
 926        key="BITS_PER_LOCUS",
 927        name="",
 928        domain="composite genetic architecture",
 929        default=8,
 930        info="Number of bits that each locus has",
 931        dtype=int,
 932        drange="[1, inf)",
 933        inrange=lambda x: x >= 1,
 934        serverrange=lambda x: x <= 10,
 935        serverrange_info="[1,10]",
 936        evalrange=[1, 100],
 937    ),
 938    # "DIFFUSION_FACTOR": Parameter(
 939    #     key="DIFFUSION_FACTOR",
 940    #     name="",
 941    #     domain="composite genetic architecture",
 942    #     default=1,
 943    #     info="Window for moving average",
 944    #     info_extended="When 1, all variants affect one age and trait only. When 1+, they also affect adjacent ages.",
 945    #     dtype=int,
 946    #     drange="[1, inf)",
 947    #     inrange=lambda x: x >= 1,
 948    #     serverrange=lambda x: x <= 10,
 949    #     serverrange_info="[1,10]",
 950    #
 951    # evalrange=[1, 50],
 952    # ),
 953    "G_surv_evolvable": Parameter(
 954        key="G_surv_evolvable",
 955        name="",
 956        domain="composite genetic architecture",
 957        default=True,
 958        info="Is survival an evolvable trait?",
 959        dtype=bool,
 960        drange="",
 961        inrange=lambda x: True,
 962    ),
 963    "G_surv_agespecific": Parameter(
 964        key="G_surv_agespecific",
 965        name="",
 966        domain="composite genetic architecture",
 967        default=True,
 968        info="Is survival age-specific?",
 969        dtype=bool,
 970        drange="",
 971        inrange=lambda x: True,
 972    ),
 973    "G_surv_interpreter": Parameter(
 974        key="G_surv_interpreter",
 975        name="",
 976        domain="composite genetic architecture",
 977        default="binary",
 978        info="",
 979        dtype=str,
 980        drange="",
 981    ),
 982    "G_surv_initgeno": Parameter(
 983        key="G_surv_initgeno",
 984        name="",
 985        domain="composite genetic architecture",
 986        default=0.5,
 987        info="Initial survival rate",
 988        dtype=float,
 989        drange="",
 990    ),
 991    "G_surv_dominance": Parameter(
 992        key="G_surv_dominance",
 993        name="",
 994        domain="composite genetic architecture",
 995        default=0.5,
 996        info="Per-trait dominance coefficient h for the surv locus (default 0.5 = codominant)",
 997        info_extended="Controls how heterozygous loci are collapsed into the haploid value used by the architect. h=0 fully recessive (the \"1\" allele is hidden in heterozygotes), h=0.5 truly additive/codominant (default), h=1 fully dominant. Each trait has its own value so e.g. surv can be recessive while repr is codominant \u2014 the standard setup for mutation-accumulation studies of aging. The legacy global DOMINANCE_FACTOR is no longer applied; use G_<trait>_dominance instead.",
 998        dtype=float,
 999        drange="[0, inf)",
1000        inrange=lambda x: x is None or x >= 0,
1001        evalrange=[0.0, 0.5, 1.0],
1002    ),
1003    "G_repr_evolvable": Parameter(
1004        key="G_repr_evolvable",
1005        name="",
1006        domain="composite genetic architecture",
1007        default=True,
1008        info="Is fertility an evolvable trait?",
1009        dtype=bool,
1010        drange="",
1011    ),
1012    "G_repr_agespecific": Parameter(
1013        key="G_repr_agespecific",
1014        name="",
1015        domain="composite genetic architecture",
1016        default=True,
1017        info="Is fertility age-specific?",
1018        dtype=bool,
1019        drange="",
1020    ),
1021    "G_repr_interpreter": Parameter(
1022        key="G_repr_interpreter",
1023        name="",
1024        domain="composite genetic architecture",
1025        default="binary",
1026        info="",
1027        dtype=str,
1028        drange="",
1029    ),
1030    "G_repr_initgeno": Parameter(
1031        key="G_repr_initgeno",
1032        name="",
1033        domain="composite genetic architecture",
1034        default=0.5,
1035        info="Initial fertility rate",
1036        dtype=float,
1037        drange="",
1038    ),
1039    "G_repr_dominance": Parameter(
1040        key="G_repr_dominance",
1041        name="",
1042        domain="composite genetic architecture",
1043        default=0.5,
1044        info="Per-trait dominance coefficient h for the repr locus (default 0.5 = codominant)",
1045        info_extended="Controls how heterozygous loci are collapsed into the haploid value used by the architect. h=0 fully recessive (the \"1\" allele is hidden in heterozygotes), h=0.5 truly additive/codominant (default), h=1 fully dominant. Each trait has its own value so e.g. surv can be recessive while repr is codominant \u2014 the standard setup for mutation-accumulation studies of aging. The legacy global DOMINANCE_FACTOR is no longer applied; use G_<trait>_dominance instead.",
1046        dtype=float,
1047        drange="[0, inf)",
1048        inrange=lambda x: x is None or x >= 0,
1049        evalrange=[0.0, 0.5, 1.0],
1050    ),
1051    "G_neut_evolvable": Parameter(
1052        key="G_neut_evolvable",
1053        name="",
1054        domain="composite genetic architecture",
1055        default=False,
1056        info="",
1057        dtype=bool,
1058        drange="",
1059    ),
1060    "G_neut_agespecific": Parameter(
1061        key="G_neut_agespecific",
1062        name="",
1063        domain="composite genetic architecture",
1064        default=False,
1065        info="",
1066        dtype=bool,
1067        drange="",
1068    ),
1069    "G_neut_interpreter": Parameter(
1070        key="G_neut_interpreter",
1071        name="",
1072        domain="composite genetic architecture",
1073        default="binary",
1074        info="",
1075        dtype=str,
1076        drange="",
1077    ),
1078    "G_neut_initgeno": Parameter(
1079        key="G_neut_initgeno",
1080        name="",
1081        domain="composite genetic architecture",
1082        default=0.5,
1083        info="",
1084        dtype=float,
1085        drange="",
1086    ),
1087    "G_neut_dominance": Parameter(
1088        key="G_neut_dominance",
1089        name="",
1090        domain="composite genetic architecture",
1091        default=0.5,
1092        info="Per-trait dominance coefficient h for the neut locus (default 0.5 = codominant)",
1093        info_extended="Controls how heterozygous loci are collapsed into the haploid value used by the architect. h=0 fully recessive (the \"1\" allele is hidden in heterozygotes), h=0.5 truly additive/codominant (default), h=1 fully dominant. Each trait has its own value so e.g. surv can be recessive while repr is codominant \u2014 the standard setup for mutation-accumulation studies of aging. The legacy global DOMINANCE_FACTOR is no longer applied; use G_<trait>_dominance instead.",
1094        dtype=float,
1095        drange="[0, inf)",
1096        inrange=lambda x: x is None or x >= 0,
1097        evalrange=[0.0, 0.5, 1.0],
1098    ),
1099    "G_muta_evolvable": Parameter(
1100        key="G_muta_evolvable",
1101        name="",
1102        domain="composite genetic architecture",
1103        default=False,
1104        info="",
1105        dtype=bool,
1106        drange="",
1107    ),
1108    "G_muta_agespecific": Parameter(
1109        key="G_muta_agespecific",
1110        name="",
1111        domain="composite genetic architecture",
1112        default=False,
1113        info="",
1114        dtype=bool,
1115        drange="",
1116    ),
1117    "G_muta_interpreter": Parameter(
1118        key="G_muta_interpreter",
1119        name="",
1120        domain="composite genetic architecture",
1121        default="binary",
1122        info="",
1123        dtype=str,
1124        drange="",
1125    ),
1126    "G_muta_initgeno": Parameter(
1127        key="G_muta_initgeno",
1128        name="",
1129        domain="composite genetic architecture",
1130        default=0.5,
1131        info="Initial mutation rate",
1132        dtype=float,
1133        drange="",
1134    ),
1135    "G_muta_dominance": Parameter(
1136        key="G_muta_dominance",
1137        name="",
1138        domain="composite genetic architecture",
1139        default=0.5,
1140        info="Per-trait dominance coefficient h for the muta locus (default 0.5 = codominant)",
1141        info_extended="Controls how heterozygous loci are collapsed into the haploid value used by the architect. h=0 fully recessive (the \"1\" allele is hidden in heterozygotes), h=0.5 truly additive/codominant (default), h=1 fully dominant. Each trait has its own value so e.g. surv can be recessive while repr is codominant \u2014 the standard setup for mutation-accumulation studies of aging. The legacy global DOMINANCE_FACTOR is no longer applied; use G_<trait>_dominance instead.",
1142        dtype=float,
1143        drange="[0, inf)",
1144        inrange=lambda x: x is None or x >= 0,
1145        evalrange=[0.0, 0.5, 1.0],
1146    ),
1147    "G_grow_evolvable": Parameter(
1148        key="G_grow_evolvable",
1149        name="",
1150        domain="composite genetic architecture",
1151        default=False,
1152        info="",
1153        dtype=bool,
1154        drange="",
1155    ),
1156    "G_grow_agespecific": Parameter(
1157        key="G_grow_agespecific",
1158        name="",
1159        domain="composite genetic architecture",
1160        default=False,
1161        info="",
1162        dtype=bool,
1163        drange="",
1164    ),
1165    "G_grow_interpreter": Parameter(
1166        key="G_grow_interpreter",
1167        name="",
1168        domain="composite genetic architecture",
1169        default="binary",
1170        info="",
1171        dtype=str,
1172        drange="",
1173    ),
1174    "G_grow_initgeno": Parameter(
1175        key="G_grow_initgeno",
1176        name="",
1177        domain="composite genetic architecture",
1178        default=0.5,
1179        info="",
1180        dtype=float,
1181        drange="",
1182    ),
1183    "G_grow_dominance": Parameter(
1184        key="G_grow_dominance",
1185        name="",
1186        domain="composite genetic architecture",
1187        default=0.5,
1188        info="Per-trait dominance coefficient h for the grow locus (default 0.5 = codominant)",
1189        info_extended="Controls how heterozygous loci are collapsed into the haploid value used by the architect. h=0 fully recessive (the \"1\" allele is hidden in heterozygotes), h=0.5 truly additive/codominant (default), h=1 fully dominant. Each trait has its own value so e.g. surv can be recessive while repr is codominant \u2014 the standard setup for mutation-accumulation studies of aging. The legacy global DOMINANCE_FACTOR is no longer applied; use G_<trait>_dominance instead.",
1190        dtype=float,
1191        drange="[0, inf)",
1192        inrange=lambda x: x is None or x >= 0,
1193        evalrange=[0.0, 0.5, 1.0],
1194    ),
1195    "THRESHOLD": Parameter(
1196        key="THRESHOLD",
1197        name="",
1198        domain="composite genetic architecture",
1199        default=None,  # 3
1200        info="",
1201        dtype=int,
1202        drange="",
1203    ),
1204    #
1205    #
1206    # GENETIC ARCHITECTURE (modifying)
1207    "MODIF_GENOME_SIZE": Parameter(
1208        key="MODIF_GENOME_SIZE",
1209        name="",
1210        domain="modifying genetic architecture",
1211        default=200,
1212        info="Size of the genome under the modifying architecture",
1213        dtype=int,
1214        drange="[1,inf)",
1215        inrange=lambda x: x >= 1,
1216        show_in_gui=True,
1217    ),
1218    "PHENOMAP_SPECS": Parameter(
1219        key="PHENOMAP_SPECS",
1220        name="",
1221        domain="modifying genetic architecture",
1222        default=[],
1223        info="",
1224        dtype=list,
1225        drange="",
1226        show_in_gui=False,
1227    ),
1228    "PHENOMAP": Parameter(
1229        # TODO is this still needed
1230        key="PHENOMAP",
1231        name="",
1232        domain="modifying genetic architecture",
1233        default={},
1234        info="",
1235        dtype=dict,
1236        drange="",
1237        show_in_gui=False,
1238    ),
1239    "G_grow_initpheno": Parameter(
1240        key="G_grow_initpheno",
1241        name="",
1242        domain="modifying genetic architecture",
1243        default=0.5,
1244        info="",
1245        dtype=float,
1246        drange="",
1247    ),
1248    "G_muta_initpheno": Parameter(
1249        key="G_muta_initpheno",
1250        name="",
1251        domain="modifying genetic architecture",
1252        default=0.001,
1253        info="Initial mutation rate",
1254        dtype=float,
1255        drange="",
1256    ),
1257    "G_surv_initpheno": Parameter(
1258        key="G_surv_initpheno",
1259        name="",
1260        domain="modifying genetic architecture",
1261        default=0.95,
1262        info="Initial survival rate",
1263        dtype=float,
1264        drange="",
1265    ),
1266    "G_repr_initpheno": Parameter(
1267        key="G_repr_initpheno",
1268        name="",
1269        domain="modifying genetic architecture",
1270        default=0.75,
1271        info="Initial fertility rate",
1272        dtype=float,
1273        drange="",
1274    ),
1275    "G_neut_initpheno": Parameter(
1276        key="G_neut_initpheno",
1277        name="",
1278        domain="modifying genetic architecture",
1279        default=0.5,
1280        info="",
1281        dtype=float,
1282        drange="",
1283    ),
1284    #
1285    #
1286    # OTHER
1287    "SPECIES_PRESET": Parameter(
1288        key="SPECIES_PRESET",
1289        name="",
1290        domain="other",
1291        default=None,
1292        info="",
1293        dtype=str,
1294        drange="None or [" + ",".join(PRESET_INFO.keys()) + "]",
1295        inrange=lambda x: x in PRESET_INFO.keys() or x is None,
1296        show_in_docs=False,
1297        show_in_gui=False,
1298    ),
1299    #
1300    #
1301    # TIME SCALES
1302    "STEPS_PER_SIMULATION": Parameter(
1303        key="STEPS_PER_SIMULATION",
1304        name="",
1305        domain="other",
1306        default=100000,
1307        info="Number of steps for the simulation to execute",
1308        dtype=int,
1309        drange="[1, inf)",
1310        inrange=lambda x: x >= 1,
1311        serverrange=lambda x: x <= 100000,
1312        serverrange_info="[1,100000]",
1313        evalrange=[1, 10000000],
1314    ),
1315    "AGE_LIMIT": Parameter(
1316        key="AGE_LIMIT",
1317        name="",
1318        domain="other",
1319        default=50,
1320        info="Maximum achievable lifespan (in steps)",
1321        info_extended="Maximum evolved lifespan is lower than the technically restricted, maximum achievable lifespan.",
1322        dtype=int,
1323        drange="[1, inf)",
1324        inrange=lambda x: x >= 1,
1325        serverrange=lambda x: x <= 100,
1326        serverrange_info="[1,100]",
1327        evalrange=[15, 100],
1328    ),
1329    "CARRYING_CAPACITY_EGGS": Parameter(
1330        key="CARRYING_CAPACITY_EGGS",
1331        name="",
1332        domain="other",
1333        default=None,
1334        info="Maximum number of eggs that the environment can sustain; None means no limit",
1335        info_extended="Once the number of eggs exceeds the carrying capacity of eggs, newly laid eggs replace previously laid eggs. Set to None to disable the limit entirely. The limit applies even when hatching/incubation is instant.",
1336        dtype=int,
1337        drange="{None, [1, inf)}",
1338        inrange=lambda x: x is None or x >= 1,
1339        serverrange=lambda x: x is None or x <= 10000,
1340        serverrange_info="{None, [1,10000]}",
1341        evalrange=[None, 1000000],
1342        previous_keys=["CARRYING_CAPACITY_EGGS"],
1343    ),
1344    "INTROGRESSION_SOURCE": Parameter(
1345        key="INTROGRESSION_SOURCE",
1346        name="",
1347        domain="other",
1348        default=None,
1349        info="Path to a pickle file of a pre-evolved population to use as the introgression source (population A). Seeds are drawn from this population and merged into the main population at simulation start.",
1350        info_extended="When set together with INTROGRESSION_SEEDS, individuals from this pickle are seeded into the main population with their ancestry label set to True. Ancestry is then tracked locus-by-locus throughout the simulation.",
1351        dtype=str,
1352        drange="path or null",
1353        inrange=lambda x: x is None or isinstance(x, str),
1354    ),
1355    "INTROGRESSION_SEEDS": Parameter(
1356        key="INTROGRESSION_SEEDS",
1357        name="",
1358        domain="other",
1359        default=0,
1360        info="Number of individuals to draw from INTROGRESSION_SOURCE and seed into the main population at simulation start.",
1361        info_extended="Set to 0 to disable introgression tracking entirely. When > 0, INTROGRESSION_SOURCE must also be set.",
1362        dtype=int,
1363        drange="[0, inf)",
1364        inrange=lambda x: x >= 0,
1365    ),
1366    "INITIAL_POPULATION_SIZE": Parameter(
1367        key="INITIAL_POPULATION_SIZE",
1368        name="",
1369        domain="other",
1370        default=1000,
1371        info="Number of individuals generated at the beginning of the simulation",
1372        info_extended="",
1373        dtype=int,
1374        drange="[1, inf)",
1375        inrange=lambda x: x >= 1,
1376        serverrange=lambda x: x <= 1000 and x >= 1,
1377        serverrange_info="[1,1000]",
1378    ),
1379    "FRAILTY_MODIFIER": Parameter(
1380        key="FRAILTY_MODIFIER",
1381        name="",
1382        domain="other",
1383        default=0,
1384        info="Age-dependent modifier of mortality",
1385        dtype=float,
1386        drange="[0, inf)",
1387        inrange=lambda x: x >= 0,
1388        evalrange=[0, 0.5, 1, 2],
1389    ),
1390    "MORTALITY_ORDER": Parameter(
1391        key="MORTALITY_ORDER",
1392        name="",
1393        domain="other",
1394        default=["intrinsic", "abiotic", "infection", "predation", "starvation"],
1395        info="Order in which mortality sources are computed",
1396        dtype=list,
1397        drange=None,
1398        inrange=lambda order: all(
1399            source in ["intrinsic", "abiotic", "infection", "predation", "starvation"] for source in order
1400        ),
1401        show_in_gui=False,
1402    ),
1403    #
1404    #
1405    # TECHNICAL
1406    "MUTATION_METHOD": Parameter(
1407        key="MUTATION_METHOD",
1408        name="",
1409        domain="technical",
1410        default="by_bit",
1411        info="Vectorized or non-vectorized method of calculating incidence of new mutations",
1412        info_extended="Mutate by XOR with a randomized bit matrix ('by_bit') or generate random indices to mutate ('by_index')",
1413        dtype=str,
1414        drange="{by_bit, by_index}",
1415        inrange=lambda x: x in ("by_bit", "by_index"),
1416    ),
1417    "RANDOM_SEED": Parameter(
1418        key="RANDOM_SEED",
1419        name="",
1420        domain="technical",
1421        default=None,
1422        info="Number used as seed for pseudorandom number generator",
1423        info_extended="If nothing is given, a random integer will be used as the seed; otherwise the given integer will be used as the seed",
1424        dtype=int,
1425        drange="{None, (-inf, inf)}",
1426        inrange=lambda x: True,
1427    ),
1428    "PHENOMAP_METHOD": Parameter(
1429        key="PHENOMAP_METHOD",
1430        name="",
1431        domain="technical",
1432        default="by_loop",
1433        info="Non-vectorized, vectorized and blank method of calculating phenotypes from genotypes",
1434        info_extended="Blank method disables pleiotropy.",
1435        dtype=str,
1436        drange="{by_loop, by_dot, by_dummy}",
1437        inrange=lambda x: x in ("by_loop", "by_dot", "by_dummy"),
1438    ),
1439}
def get_default_parameters():
5def get_default_parameters():
6    return {p.key: p.default for p in DEFAULT_PARAMETERS.values()}
def get_species_parameters(SPECIES_PRESET):
 9def get_species_parameters(SPECIES_PRESET):
10    return {p.key: p.presets[SPECIES_PRESET] for p in DEFAULT_PARAMETERS.values() if SPECIES_PRESET in p.presets}
PRESET_INFO = {'human': 'One cycle corresponds to 2 years.', 'mouse': 'One cycle corresponds to one month. Source: https://genomics.senescence.info/species/entry.php?species=Mus_musculus', 'killifish': 'One cycle corresponds to one week.', 'yeast': '', 'arabidopsis': '', 'worm': 'One cycle corresponds to one day. Up to 300 eggs in optimal conditions.', 'fruitfly': 'One cycle corresponds to one day. Up to 100 eggs per day.'}
DEFAULT_PARAMETERS = {'LOGGING_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'TICKER_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'PICKLE_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'FASTA_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'FASTA_MASK_SEED': <aegis_sim.parameterization.parameter.Parameter object>, 'VCF_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'GVCF_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'LINEAGE_TRACING': <aegis_sim.parameterization.parameter.Parameter object>, 'LINEAGE_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_STEP': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_TRAIT': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_AGE': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_BIT': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_ALLELE': <aegis_sim.parameterization.parameter.Parameter object>, 'ALLELE_INJECTION_FRACTION': <aegis_sim.parameterization.parameter.Parameter object>, 'CHECKPOINT_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'SNAPSHOT_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'SNAPSHOT_FINAL_COUNT': <aegis_sim.parameterization.parameter.Parameter object>, 'INTERVAL_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'TE_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'TE_DURATION': <aegis_sim.parameterization.parameter.Parameter object>, 'POPGENSTATS_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'POPGENSTATS_SAMPLE_SIZE': <aegis_sim.parameterization.parameter.Parameter object>, 'NOTES': <aegis_sim.parameterization.parameter.Parameter object>, 'STARVATION_MORTALITY_FACTOR': <aegis_sim.parameterization.parameter.Parameter object>, 'STARVATION_MORTALITY_MAXIMUM': <aegis_sim.parameterization.parameter.Parameter object>, 'STARVATION_PENALTY': <aegis_sim.parameterization.parameter.Parameter object>, 'RESOURCE_INITIAL_AMOUNT': <aegis_sim.parameterization.parameter.Parameter object>, 'RESOURCE_MAXIMUM_AMOUNT': <aegis_sim.parameterization.parameter.Parameter object>, 'RESOURCE_ADDITIVE_GROWTH': <aegis_sim.parameterization.parameter.Parameter object>, 'RESOURCE_MULTIPLICATIVE_GROWTH': <aegis_sim.parameterization.parameter.Parameter object>, 'INCUBATION_PERIOD': <aegis_sim.parameterization.parameter.Parameter object>, 'MATURATION_AGE': <aegis_sim.parameterization.parameter.Parameter object>, 'REPRODUCTION_ENDPOINT': <aegis_sim.parameterization.parameter.Parameter object>, 'MAX_OFFSPRING_NUMBER': <aegis_sim.parameterization.parameter.Parameter object>, 'REPRODUCTION_MODE': <aegis_sim.parameterization.parameter.Parameter object>, 'REPRODUCTION_REGULATION': <aegis_sim.parameterization.parameter.Parameter object>, 'RECOMBINATION_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'MUTATION_RATIO': <aegis_sim.parameterization.parameter.Parameter object>, 'MUTATION_AGE_MULTIPLIER': <aegis_sim.parameterization.parameter.Parameter object>, 'DOMINANCE_FACTOR': <aegis_sim.parameterization.parameter.Parameter object>, 'SMOOTHING_FACTOR': <aegis_sim.parameterization.parameter.Parameter object>, 'PLOIDY': <aegis_sim.parameterization.parameter.Parameter object>, 'GENARCH_TYPE': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_lo': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_hi': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_lo': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_hi': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_lo': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_hi': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_lo': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_hi': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_lo': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_hi': <aegis_sim.parameterization.parameter.Parameter object>, 'ENVDRIFT_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'ABIOTIC_HAZARD_AMPLITUDE': <aegis_sim.parameterization.parameter.Parameter object>, 'ABIOTIC_HAZARD_PERIOD': <aegis_sim.parameterization.parameter.Parameter object>, 'ABIOTIC_HAZARD_OFFSET': <aegis_sim.parameterization.parameter.Parameter object>, 'ABIOTIC_HAZARD_SHAPE': <aegis_sim.parameterization.parameter.Parameter object>, 'BACKGROUND_INFECTIVITY': <aegis_sim.parameterization.parameter.Parameter object>, 'TRANSMISSIBILITY': <aegis_sim.parameterization.parameter.Parameter object>, 'RECOVERY_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'FATALITY_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'PREDATION_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'LATTICE_MODE': <aegis_sim.parameterization.parameter.Parameter object>, 'LATTICE_TARGET_DENSITY': <aegis_sim.parameterization.parameter.Parameter object>, 'MIGRATION_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'MIGRATION_LONG_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'MATING_MAX_SEARCH_RADIUS': <aegis_sim.parameterization.parameter.Parameter object>, 'LATTICE_RECORD_RATE': <aegis_sim.parameterization.parameter.Parameter object>, 'PREDATOR_GROWTH': <aegis_sim.parameterization.parameter.Parameter object>, 'BITS_PER_LOCUS': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_evolvable': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_agespecific': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_interpreter': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_initgeno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_dominance': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_evolvable': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_agespecific': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_interpreter': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_initgeno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_dominance': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_evolvable': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_agespecific': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_interpreter': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_initgeno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_dominance': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_evolvable': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_agespecific': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_interpreter': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_initgeno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_dominance': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_evolvable': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_agespecific': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_interpreter': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_initgeno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_dominance': <aegis_sim.parameterization.parameter.Parameter object>, 'THRESHOLD': <aegis_sim.parameterization.parameter.Parameter object>, 'MODIF_GENOME_SIZE': <aegis_sim.parameterization.parameter.Parameter object>, 'PHENOMAP_SPECS': <aegis_sim.parameterization.parameter.Parameter object>, 'PHENOMAP': <aegis_sim.parameterization.parameter.Parameter object>, 'G_grow_initpheno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_muta_initpheno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_surv_initpheno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_repr_initpheno': <aegis_sim.parameterization.parameter.Parameter object>, 'G_neut_initpheno': <aegis_sim.parameterization.parameter.Parameter object>, 'SPECIES_PRESET': <aegis_sim.parameterization.parameter.Parameter object>, 'STEPS_PER_SIMULATION': <aegis_sim.parameterization.parameter.Parameter object>, 'AGE_LIMIT': <aegis_sim.parameterization.parameter.Parameter object>, 'CARRYING_CAPACITY_EGGS': <aegis_sim.parameterization.parameter.Parameter object>, 'INTROGRESSION_SOURCE': <aegis_sim.parameterization.parameter.Parameter object>, 'INTROGRESSION_SEEDS': <aegis_sim.parameterization.parameter.Parameter object>, 'INITIAL_POPULATION_SIZE': <aegis_sim.parameterization.parameter.Parameter object>, 'FRAILTY_MODIFIER': <aegis_sim.parameterization.parameter.Parameter object>, 'MORTALITY_ORDER': <aegis_sim.parameterization.parameter.Parameter object>, 'MUTATION_METHOD': <aegis_sim.parameterization.parameter.Parameter object>, 'RANDOM_SEED': <aegis_sim.parameterization.parameter.Parameter object>, 'PHENOMAP_METHOD': <aegis_sim.parameterization.parameter.Parameter object>}