aegis_sim.submodels.genetics.composite.architecture
1import numpy as np 2from aegis_sim import constants 3from aegis_sim import variables 4 5from aegis_sim.submodels.genetics.composite.interpreter import Interpreter 6from aegis_sim import parameterization 7from aegis_sim.submodels.genetics import ploider 8 9 10class CompositeArchitecture: 11 """ 12 13 GUI 14 - when pleiotropy is not needed; 15 - it is quick, easy to analyze, delivers a diversity of phenotypes 16 - every trait (surv repr muta neut) can be evolvable or not 17 - if not evolvable, the value is set by !!! 18 - if evolvable, it can be agespecific or age-independent 19 - probability of a trait at each age is determined by a BITS_PER_LOCUS adjacent bits forming a "locus" / gene 20 - the method by which these loci are converted into a phenotypic value is the Interpreter type 21 22 """ 23 24 def __init__(self, BITS_PER_LOCUS, AGE_LIMIT, THRESHOLD): 25 self.BITS_PER_LOCUS = BITS_PER_LOCUS 26 self.n_loci = sum(trait.length for trait in parameterization.traits.values()) 27 self.length = self.n_loci * BITS_PER_LOCUS 28 self.AGE_LIMIT = AGE_LIMIT 29 30 self.evolvable = [trait for trait in parameterization.traits.values() if trait.evolvable] 31 32 self.interpreter = Interpreter( 33 self.BITS_PER_LOCUS, 34 THRESHOLD, 35 ) 36 37 # Fixed seed=0 so all populations (including hybridizing ones with different RANDOM_SEEDs) 38 # share an identical physical genome layout; locus_permutation[i] = physical position of logical locus i 39 self.locus_permutation = np.random.default_rng(0).permutation(self.n_loci) 40 41 def get_number_of_bits(self): 42 return ploider.ploider.y * self.n_loci * self.BITS_PER_LOCUS 43 44 def get_shape(self): 45 return (ploider.ploider.y, self.n_loci, self.BITS_PER_LOCUS) 46 47 def init_genome_array(self, popsize): 48 # TODO enable agespecific False 49 array = variables.rng.random(size=(popsize, *self.get_shape())) 50 51 for trait in parameterization.traits.values(): 52 phys_pos = self.locus_permutation[trait.start:trait.end] 53 array[:, :, phys_pos, :] = array[:, :, phys_pos, :] < trait.initgeno 54 55 return array 56 57 def compute(self, genomes): 58 59 if genomes.shape[1] == 1: # Do not calculate mean if genomes are haploid 60 genomes = genomes[:, 0] 61 else: 62 genomes = ploider.ploider.diploid_to_haploid(genomes) 63 64 # Reorder from physical storage order to logical (trait×age) order 65 genomes = genomes[:, self.locus_permutation, :] 66 67 interpretome = np.zeros(shape=(genomes.shape[0], genomes.shape[1]), dtype=np.float32) 68 for trait in parameterization.traits.values(): 69 loci = genomes[:, trait.slice] # fetch 70 probs = self.interpreter.call(loci, trait.interpreter) # interpret 71 # self.diffuse(probs) 72 interpretome[:, trait.slice] += probs # add back 73 74 return interpretome 75 76 # def diffuse(self, probs): 77 # window_size = parametermanager.parameters.DIFFUSION_FACTOR * 2 + 1 78 # p = np.empty(shape=(probs.shape[0], probs.shape[1] + window_size - 1)) 79 # p[:, :window_size] = np.repeat(probs[:, 0], window_size).reshape(-1, window_size) 80 # p[:, window_size - 1 :] = probs[:] 81 # diffusome = np.convolve(p[0], np.ones(window_size) / window_size, mode="valid") 82 83 def get_map(self): 84 pass
class
CompositeArchitecture:
11class CompositeArchitecture: 12 """ 13 14 GUI 15 - when pleiotropy is not needed; 16 - it is quick, easy to analyze, delivers a diversity of phenotypes 17 - every trait (surv repr muta neut) can be evolvable or not 18 - if not evolvable, the value is set by !!! 19 - if evolvable, it can be agespecific or age-independent 20 - probability of a trait at each age is determined by a BITS_PER_LOCUS adjacent bits forming a "locus" / gene 21 - the method by which these loci are converted into a phenotypic value is the Interpreter type 22 23 """ 24 25 def __init__(self, BITS_PER_LOCUS, AGE_LIMIT, THRESHOLD): 26 self.BITS_PER_LOCUS = BITS_PER_LOCUS 27 self.n_loci = sum(trait.length for trait in parameterization.traits.values()) 28 self.length = self.n_loci * BITS_PER_LOCUS 29 self.AGE_LIMIT = AGE_LIMIT 30 31 self.evolvable = [trait for trait in parameterization.traits.values() if trait.evolvable] 32 33 self.interpreter = Interpreter( 34 self.BITS_PER_LOCUS, 35 THRESHOLD, 36 ) 37 38 # Fixed seed=0 so all populations (including hybridizing ones with different RANDOM_SEEDs) 39 # share an identical physical genome layout; locus_permutation[i] = physical position of logical locus i 40 self.locus_permutation = np.random.default_rng(0).permutation(self.n_loci) 41 42 def get_number_of_bits(self): 43 return ploider.ploider.y * self.n_loci * self.BITS_PER_LOCUS 44 45 def get_shape(self): 46 return (ploider.ploider.y, self.n_loci, self.BITS_PER_LOCUS) 47 48 def init_genome_array(self, popsize): 49 # TODO enable agespecific False 50 array = variables.rng.random(size=(popsize, *self.get_shape())) 51 52 for trait in parameterization.traits.values(): 53 phys_pos = self.locus_permutation[trait.start:trait.end] 54 array[:, :, phys_pos, :] = array[:, :, phys_pos, :] < trait.initgeno 55 56 return array 57 58 def compute(self, genomes): 59 60 if genomes.shape[1] == 1: # Do not calculate mean if genomes are haploid 61 genomes = genomes[:, 0] 62 else: 63 genomes = ploider.ploider.diploid_to_haploid(genomes) 64 65 # Reorder from physical storage order to logical (trait×age) order 66 genomes = genomes[:, self.locus_permutation, :] 67 68 interpretome = np.zeros(shape=(genomes.shape[0], genomes.shape[1]), dtype=np.float32) 69 for trait in parameterization.traits.values(): 70 loci = genomes[:, trait.slice] # fetch 71 probs = self.interpreter.call(loci, trait.interpreter) # interpret 72 # self.diffuse(probs) 73 interpretome[:, trait.slice] += probs # add back 74 75 return interpretome 76 77 # def diffuse(self, probs): 78 # window_size = parametermanager.parameters.DIFFUSION_FACTOR * 2 + 1 79 # p = np.empty(shape=(probs.shape[0], probs.shape[1] + window_size - 1)) 80 # p[:, :window_size] = np.repeat(probs[:, 0], window_size).reshape(-1, window_size) 81 # p[:, window_size - 1 :] = probs[:] 82 # diffusome = np.convolve(p[0], np.ones(window_size) / window_size, mode="valid") 83 84 def get_map(self): 85 pass
GUI
- when pleiotropy is not needed;
- it is quick, easy to analyze, delivers a diversity of phenotypes
- every trait (surv repr muta neut) can be evolvable or not
- if not evolvable, the value is set by !!!
- if evolvable, it can be agespecific or age-independent
- probability of a trait at each age is determined by a BITS_PER_LOCUS adjacent bits forming a "locus" / gene
- the method by which these loci are converted into a phenotypic value is the Interpreter type
CompositeArchitecture(BITS_PER_LOCUS, AGE_LIMIT, THRESHOLD)
25 def __init__(self, BITS_PER_LOCUS, AGE_LIMIT, THRESHOLD): 26 self.BITS_PER_LOCUS = BITS_PER_LOCUS 27 self.n_loci = sum(trait.length for trait in parameterization.traits.values()) 28 self.length = self.n_loci * BITS_PER_LOCUS 29 self.AGE_LIMIT = AGE_LIMIT 30 31 self.evolvable = [trait for trait in parameterization.traits.values() if trait.evolvable] 32 33 self.interpreter = Interpreter( 34 self.BITS_PER_LOCUS, 35 THRESHOLD, 36 ) 37 38 # Fixed seed=0 so all populations (including hybridizing ones with different RANDOM_SEEDs) 39 # share an identical physical genome layout; locus_permutation[i] = physical position of logical locus i 40 self.locus_permutation = np.random.default_rng(0).permutation(self.n_loci)
def
init_genome_array(self, popsize):
48 def init_genome_array(self, popsize): 49 # TODO enable agespecific False 50 array = variables.rng.random(size=(popsize, *self.get_shape())) 51 52 for trait in parameterization.traits.values(): 53 phys_pos = self.locus_permutation[trait.start:trait.end] 54 array[:, :, phys_pos, :] = array[:, :, phys_pos, :] < trait.initgeno 55 56 return array
def
compute(self, genomes):
58 def compute(self, genomes): 59 60 if genomes.shape[1] == 1: # Do not calculate mean if genomes are haploid 61 genomes = genomes[:, 0] 62 else: 63 genomes = ploider.ploider.diploid_to_haploid(genomes) 64 65 # Reorder from physical storage order to logical (trait×age) order 66 genomes = genomes[:, self.locus_permutation, :] 67 68 interpretome = np.zeros(shape=(genomes.shape[0], genomes.shape[1]), dtype=np.float32) 69 for trait in parameterization.traits.values(): 70 loci = genomes[:, trait.slice] # fetch 71 probs = self.interpreter.call(loci, trait.interpreter) # interpret 72 # self.diffuse(probs) 73 interpretome[:, trait.slice] += probs # add back 74 75 return interpretome