aegis_sim.recording.featherrecorder

  1import logging
  2import pandas as pd
  3import numpy as np
  4
  5import pathlib
  6
  7from aegis_sim.dataclasses.population import Population
  8from .recorder import Recorder
  9from aegis_sim import variables
 10
 11from aegis_sim import parameterization
 12from aegis_sim.parameterization import parametermanager
 13from aegis_sim.constants import GENETIC_TRAITS
 14from aegis_sim.utilities.funcs import steps_to_end, skip
 15
 16
 17class FeatherRecorder(Recorder):
 18    def __init__(self, odir: pathlib.Path):
 19        self.odir_genotypes = odir / "snapshots" / "genotypes"
 20        self.odir_phenotypes = odir / "snapshots" / "phenotypes"
 21        self.odir_demography = odir / "snapshots" / "demography"
 22        self.init_dir(self.odir_genotypes)
 23        self.init_dir(self.odir_phenotypes)
 24        self.init_dir(self.odir_demography)
 25
 26    def write(self, population: Population):
 27        """Record demographic, genetic and phenotypic data from the current population."""
 28
 29        # If not final snapshots to be taken, and about to skip or the population is extinct, do not write.
 30        final_snapshots = parametermanager.parameters.SNAPSHOT_FINAL_COUNT > steps_to_end()
 31        if not final_snapshots and (skip("SNAPSHOT_RATE") or len(population) == 0):
 32            return
 33
 34        step = variables.steps
 35
 36        logging.debug(f"Snapshots recorded at step {step}.")
 37
 38        self.write_genotypes(step=step, population=population)
 39        self.write_phenotypes(step=step, population=population)
 40        self.write_demography(step=step, population=population)
 41
 42    def write_genotypes(self, step: int, population: Population):
 43        """
 44
 45        # OUTPUT SPECIFICATION
 46        path: /snapshots/genotypes/{step}.feather
 47        filetype: feather
 48        category: genotype
 49        description: A snapshot of complete binary genomes of all individuals at a certain simulation step.
 50        trait granularity: individual
 51        time granularity: snapshot
 52        frequency parameter: SNAPSHOT_RATE
 53        structure: A bool matrix; rows: individuals, columns: genome positions, values: bit states
 54        header: genome positions
 55        """
 56        if len(population) == 0:
 57            # Empty population can't be reshaped by genomes.flatten(); write empty feather
 58            df_gen = pd.DataFrame()
 59        else:
 60            df_gen = pd.DataFrame(np.array(population.genomes.flatten()))
 61            df_gen.columns = [str(c) for c in df_gen.columns]
 62        df_gen.reset_index(drop=True, inplace=True)
 63        df_gen.to_feather(self.odir_genotypes / f"{step}.feather")
 64
 65    def write_phenotypes(self, step: int, population: Population):
 66        """
 67
 68        # OUTPUT SPECIFICATION
 69        path: /snapshots/phenotypes/{step}.feather
 70        filetype: feather
 71        category: phenotype
 72        description: A snapshot of complete intrinsic phenotypes of all individuals at a certain simulation step.
 73        trait granularity: individual
 74        time granularity: snapshot
 75        frequency parameter: SNAPSHOT_RATE
 76        structure: A float matrix; rows: individuals, columns: {trait}_{age} for each evolvable trait, values: trait values
 77        header: {trait}_{age} e.g. surv_0, surv_1, ..., repr_0, repr_1, ...
 78        """
 79        df_phe = pd.DataFrame(population.phenotypes.get())
 80        df_phe.reset_index(drop=True, inplace=True)
 81        df_phe.columns = self._phenotype_columns()
 82        df_phe.to_feather(self.odir_phenotypes / f"{step}.feather")
 83
 84    @staticmethod
 85    def _phenotype_columns():
 86        AGE_LIMIT = parametermanager.parameters.AGE_LIMIT
 87        cols = []
 88        for trait_name in GENETIC_TRAITS:
 89            trait = parameterization.traits[trait_name]
 90            if not trait.evolvable:
 91                continue
 92            if trait.agespecific:
 93                cols.extend(f"{trait_name}_{age}" for age in range(AGE_LIMIT))
 94            else:
 95                cols.append(trait_name)
 96        return cols
 97
 98    def write_demography(self, step: int, population: Population):
 99        """
100
101        # OUTPUT SPECIFICATION
102        path: /snapshots/demography/{step}.feather
103        filetype: feather
104        category: demography
105        description: A recording of life history metrics (age, number of births given, step at which born, current size, sex) of all individuals until a certain simulation step.
106        trait granularity: individual
107        time granularity: snapshot
108        frequency parameter: SNAPSHOT_RATE
109        structure: A matrix of ints and floats
110        header: ['ages', 'births', 'birthdays', 'sizes', 'sexes']
111        """
112        dem_attrs = [
113            "ages",
114            "births",
115            "birthdays",
116            # "generations",
117            "sizes",
118            "sexes",
119        ]
120        demo = {attr: getattr(population, attr) for attr in dem_attrs}
121        df_dem = pd.DataFrame(demo, columns=dem_attrs)
122        df_dem.reset_index(drop=True, inplace=True)
123        df_dem.to_feather(self.odir_demography / f"{step}.feather")
class FeatherRecorder(aegis_sim.recording.recorder.Recorder):
 18class FeatherRecorder(Recorder):
 19    def __init__(self, odir: pathlib.Path):
 20        self.odir_genotypes = odir / "snapshots" / "genotypes"
 21        self.odir_phenotypes = odir / "snapshots" / "phenotypes"
 22        self.odir_demography = odir / "snapshots" / "demography"
 23        self.init_dir(self.odir_genotypes)
 24        self.init_dir(self.odir_phenotypes)
 25        self.init_dir(self.odir_demography)
 26
 27    def write(self, population: Population):
 28        """Record demographic, genetic and phenotypic data from the current population."""
 29
 30        # If not final snapshots to be taken, and about to skip or the population is extinct, do not write.
 31        final_snapshots = parametermanager.parameters.SNAPSHOT_FINAL_COUNT > steps_to_end()
 32        if not final_snapshots and (skip("SNAPSHOT_RATE") or len(population) == 0):
 33            return
 34
 35        step = variables.steps
 36
 37        logging.debug(f"Snapshots recorded at step {step}.")
 38
 39        self.write_genotypes(step=step, population=population)
 40        self.write_phenotypes(step=step, population=population)
 41        self.write_demography(step=step, population=population)
 42
 43    def write_genotypes(self, step: int, population: Population):
 44        """
 45
 46        # OUTPUT SPECIFICATION
 47        path: /snapshots/genotypes/{step}.feather
 48        filetype: feather
 49        category: genotype
 50        description: A snapshot of complete binary genomes of all individuals at a certain simulation step.
 51        trait granularity: individual
 52        time granularity: snapshot
 53        frequency parameter: SNAPSHOT_RATE
 54        structure: A bool matrix; rows: individuals, columns: genome positions, values: bit states
 55        header: genome positions
 56        """
 57        if len(population) == 0:
 58            # Empty population can't be reshaped by genomes.flatten(); write empty feather
 59            df_gen = pd.DataFrame()
 60        else:
 61            df_gen = pd.DataFrame(np.array(population.genomes.flatten()))
 62            df_gen.columns = [str(c) for c in df_gen.columns]
 63        df_gen.reset_index(drop=True, inplace=True)
 64        df_gen.to_feather(self.odir_genotypes / f"{step}.feather")
 65
 66    def write_phenotypes(self, step: int, population: Population):
 67        """
 68
 69        # OUTPUT SPECIFICATION
 70        path: /snapshots/phenotypes/{step}.feather
 71        filetype: feather
 72        category: phenotype
 73        description: A snapshot of complete intrinsic phenotypes of all individuals at a certain simulation step.
 74        trait granularity: individual
 75        time granularity: snapshot
 76        frequency parameter: SNAPSHOT_RATE
 77        structure: A float matrix; rows: individuals, columns: {trait}_{age} for each evolvable trait, values: trait values
 78        header: {trait}_{age} e.g. surv_0, surv_1, ..., repr_0, repr_1, ...
 79        """
 80        df_phe = pd.DataFrame(population.phenotypes.get())
 81        df_phe.reset_index(drop=True, inplace=True)
 82        df_phe.columns = self._phenotype_columns()
 83        df_phe.to_feather(self.odir_phenotypes / f"{step}.feather")
 84
 85    @staticmethod
 86    def _phenotype_columns():
 87        AGE_LIMIT = parametermanager.parameters.AGE_LIMIT
 88        cols = []
 89        for trait_name in GENETIC_TRAITS:
 90            trait = parameterization.traits[trait_name]
 91            if not trait.evolvable:
 92                continue
 93            if trait.agespecific:
 94                cols.extend(f"{trait_name}_{age}" for age in range(AGE_LIMIT))
 95            else:
 96                cols.append(trait_name)
 97        return cols
 98
 99    def write_demography(self, step: int, population: Population):
100        """
101
102        # OUTPUT SPECIFICATION
103        path: /snapshots/demography/{step}.feather
104        filetype: feather
105        category: demography
106        description: A recording of life history metrics (age, number of births given, step at which born, current size, sex) of all individuals until a certain simulation step.
107        trait granularity: individual
108        time granularity: snapshot
109        frequency parameter: SNAPSHOT_RATE
110        structure: A matrix of ints and floats
111        header: ['ages', 'births', 'birthdays', 'sizes', 'sexes']
112        """
113        dem_attrs = [
114            "ages",
115            "births",
116            "birthdays",
117            # "generations",
118            "sizes",
119            "sexes",
120        ]
121        demo = {attr: getattr(population, attr) for attr in dem_attrs}
122        df_dem = pd.DataFrame(demo, columns=dem_attrs)
123        df_dem.reset_index(drop=True, inplace=True)
124        df_dem.to_feather(self.odir_demography / f"{step}.feather")
FeatherRecorder(odir: pathlib.Path)
19    def __init__(self, odir: pathlib.Path):
20        self.odir_genotypes = odir / "snapshots" / "genotypes"
21        self.odir_phenotypes = odir / "snapshots" / "phenotypes"
22        self.odir_demography = odir / "snapshots" / "demography"
23        self.init_dir(self.odir_genotypes)
24        self.init_dir(self.odir_phenotypes)
25        self.init_dir(self.odir_demography)
odir_genotypes
odir_phenotypes
odir_demography
def write(self, population: aegis_sim.dataclasses.population.Population):
27    def write(self, population: Population):
28        """Record demographic, genetic and phenotypic data from the current population."""
29
30        # If not final snapshots to be taken, and about to skip or the population is extinct, do not write.
31        final_snapshots = parametermanager.parameters.SNAPSHOT_FINAL_COUNT > steps_to_end()
32        if not final_snapshots and (skip("SNAPSHOT_RATE") or len(population) == 0):
33            return
34
35        step = variables.steps
36
37        logging.debug(f"Snapshots recorded at step {step}.")
38
39        self.write_genotypes(step=step, population=population)
40        self.write_phenotypes(step=step, population=population)
41        self.write_demography(step=step, population=population)

Record demographic, genetic and phenotypic data from the current population.

def write_genotypes( self, step: int, population: aegis_sim.dataclasses.population.Population):
43    def write_genotypes(self, step: int, population: Population):
44        """
45
46        # OUTPUT SPECIFICATION
47        path: /snapshots/genotypes/{step}.feather
48        filetype: feather
49        category: genotype
50        description: A snapshot of complete binary genomes of all individuals at a certain simulation step.
51        trait granularity: individual
52        time granularity: snapshot
53        frequency parameter: SNAPSHOT_RATE
54        structure: A bool matrix; rows: individuals, columns: genome positions, values: bit states
55        header: genome positions
56        """
57        if len(population) == 0:
58            # Empty population can't be reshaped by genomes.flatten(); write empty feather
59            df_gen = pd.DataFrame()
60        else:
61            df_gen = pd.DataFrame(np.array(population.genomes.flatten()))
62            df_gen.columns = [str(c) for c in df_gen.columns]
63        df_gen.reset_index(drop=True, inplace=True)
64        df_gen.to_feather(self.odir_genotypes / f"{step}.feather")

OUTPUT SPECIFICATION

path: /snapshots/genotypes/{step}.feather filetype: feather category: genotype description: A snapshot of complete binary genomes of all individuals at a certain simulation step. trait granularity: individual time granularity: snapshot frequency parameter: SNAPSHOT_RATE structure: A bool matrix; rows: individuals, columns: genome positions, values: bit states header: genome positions

def write_phenotypes( self, step: int, population: aegis_sim.dataclasses.population.Population):
66    def write_phenotypes(self, step: int, population: Population):
67        """
68
69        # OUTPUT SPECIFICATION
70        path: /snapshots/phenotypes/{step}.feather
71        filetype: feather
72        category: phenotype
73        description: A snapshot of complete intrinsic phenotypes of all individuals at a certain simulation step.
74        trait granularity: individual
75        time granularity: snapshot
76        frequency parameter: SNAPSHOT_RATE
77        structure: A float matrix; rows: individuals, columns: {trait}_{age} for each evolvable trait, values: trait values
78        header: {trait}_{age} e.g. surv_0, surv_1, ..., repr_0, repr_1, ...
79        """
80        df_phe = pd.DataFrame(population.phenotypes.get())
81        df_phe.reset_index(drop=True, inplace=True)
82        df_phe.columns = self._phenotype_columns()
83        df_phe.to_feather(self.odir_phenotypes / f"{step}.feather")

OUTPUT SPECIFICATION

path: /snapshots/phenotypes/{step}.feather filetype: feather category: phenotype description: A snapshot of complete intrinsic phenotypes of all individuals at a certain simulation step. trait granularity: individual time granularity: snapshot frequency parameter: SNAPSHOT_RATE structure: A float matrix; rows: individuals, columns: {trait}_{age} for each evolvable trait, values: trait values header: {trait}_{age} e.g. surv_0, surv_1, ..., repr_0, repr_1, ...

def write_demography( self, step: int, population: aegis_sim.dataclasses.population.Population):
 99    def write_demography(self, step: int, population: Population):
100        """
101
102        # OUTPUT SPECIFICATION
103        path: /snapshots/demography/{step}.feather
104        filetype: feather
105        category: demography
106        description: A recording of life history metrics (age, number of births given, step at which born, current size, sex) of all individuals until a certain simulation step.
107        trait granularity: individual
108        time granularity: snapshot
109        frequency parameter: SNAPSHOT_RATE
110        structure: A matrix of ints and floats
111        header: ['ages', 'births', 'birthdays', 'sizes', 'sexes']
112        """
113        dem_attrs = [
114            "ages",
115            "births",
116            "birthdays",
117            # "generations",
118            "sizes",
119            "sexes",
120        ]
121        demo = {attr: getattr(population, attr) for attr in dem_attrs}
122        df_dem = pd.DataFrame(demo, columns=dem_attrs)
123        df_dem.reset_index(drop=True, inplace=True)
124        df_dem.to_feather(self.odir_demography / f"{step}.feather")

OUTPUT SPECIFICATION

path: /snapshots/demography/{step}.feather filetype: feather category: demography description: A recording of life history metrics (age, number of births given, step at which born, current size, sex) of all individuals until a certain simulation step. trait granularity: individual time granularity: snapshot frequency parameter: SNAPSHOT_RATE structure: A matrix of ints and floats header: ['ages', 'births', 'birthdays', 'sizes', 'sexes']