aegis_sim.submodels.abiotic
Cyclic extrinsic mortality
1"""Cyclic extrinsic mortality 2""" 3 4import math 5import logging 6import numpy as np 7 8 9class Abiotic: 10 """ 11 # TODO maybe mention which phenomena could be modeled by which shape in the doctsring 12 13 GUI 14 Abiotic mortality is an optional source of mortality, useful for modeling death by periodic environmental phenomena such as water availability and temperature. 15 It has no effect when [[ABIOTIC_HAZARD_OFFSET]] and [[ABIOTIC_HAZARD_AMPLITUDE]] are set to 0. 16 It is modeled using periodic functions with a period of [[ABIOTIC_HAZARD_PERIOD]], amplitude of [[ABIOTIC_HAZARD_AMPLITUDE]], 17 shape of [[ABIOTIC_HAZARD_SHAPE]] and constant background mortality of [[ABIOTIC_HAZARD_OFFSET]] (negative or positive). 18 Negative hazard is clipped to zero. 19 Available hazard shapes (waveforms) are flat, sinusoidal, square, triangle, sawtooth, ramp (backward sawtooth) and instant (Dirac comb / impulse train). 20 Importantly, it only affects the living individuals (i.e. it does not affect eggs, if applicable). 21 """ 22 23 def __init__(self, ABIOTIC_HAZARD_SHAPE, ABIOTIC_HAZARD_OFFSET, ABIOTIC_HAZARD_AMPLITUDE, ABIOTIC_HAZARD_PERIOD): 24 25 self.ABIOTIC_HAZARD_SHAPE = ABIOTIC_HAZARD_SHAPE 26 self.ABIOTIC_HAZARD_OFFSET = ABIOTIC_HAZARD_OFFSET 27 self.ABIOTIC_HAZARD_AMPLITUDE = ABIOTIC_HAZARD_AMPLITUDE 28 self.ABIOTIC_HAZARD_PERIOD = ABIOTIC_HAZARD_PERIOD 29 30 self.func = { 31 "flat": self._flat, 32 "sinusoidal": self._sinusoidal, 33 "triangle": self._triangle, 34 "square": self._square, 35 "sawtooth": self._sawtooth, 36 "ramp": self._ramp, 37 "instant": self._instant, 38 "instant_fatal": self._instant_fatal, 39 "instant_deterministic": self._instant_deterministic, 40 }[self.ABIOTIC_HAZARD_SHAPE] 41 42 if self.ABIOTIC_HAZARD_SHAPE == "flat" and self.ABIOTIC_HAZARD_AMPLITUDE > 0 and self.ABIOTIC_HAZARD_OFFSET > 0: 43 logging.info( 44 """ 45 Note that under flat cnf.abiotic hazard, amplitude and offset have the same effects; 46 the total cnf.abiotic mortality is simply their sum. 47 """ 48 ) 49 50 def __call__(self, step): 51 return self.func(step) + self.ABIOTIC_HAZARD_OFFSET 52 53 def _flat(self, step): 54 return self.ABIOTIC_HAZARD_AMPLITUDE 55 56 def _sinusoidal(self, step): 57 return self.ABIOTIC_HAZARD_AMPLITUDE * math.sin(2 * math.pi * step / self.ABIOTIC_HAZARD_PERIOD) 58 59 def _triangle(self, step): 60 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 61 1 - 4 * abs(round(step / self.ABIOTIC_HAZARD_PERIOD - 0.5) - (step / self.ABIOTIC_HAZARD_PERIOD - 0.5)) 62 ) 63 64 def _square(self, step): 65 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 66 1 if (step % self.ABIOTIC_HAZARD_PERIOD) < (self.ABIOTIC_HAZARD_PERIOD / 2) else -1 67 ) 68 69 def _sawtooth(self, step): 70 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 71 2 * (step / self.ABIOTIC_HAZARD_PERIOD - math.floor(step / self.ABIOTIC_HAZARD_PERIOD + 0.5)) 72 ) 73 74 def _ramp(self, step): 75 return self.ABIOTIC_HAZARD_AMPLITUDE * (step % self.ABIOTIC_HAZARD_PERIOD) / self.ABIOTIC_HAZARD_PERIOD 76 77 def _instant(self, step): 78 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills ABIOTIC_HAZARD_AMPLITUDE of the total living population; step 0 is unaffected""" 79 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 80 return 0 81 82 mortality = np.random.beta(a=1, b=3, size=1) 83 return mortality * self.ABIOTIC_HAZARD_AMPLITUDE 84 85 def _instant_fatal(self, step): 86 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills all of the total living population; step 0 is unaffected""" 87 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 88 return 0 89 else: 90 return 1 91 92 def _instant_deterministic(self, step): 93 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills exactly ABIOTIC_HAZARD_AMPLITUDE fraction of the living population; step 0 is unaffected""" 94 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 95 return 0 96 return self.ABIOTIC_HAZARD_AMPLITUDE
10class Abiotic: 11 """ 12 # TODO maybe mention which phenomena could be modeled by which shape in the doctsring 13 14 GUI 15 Abiotic mortality is an optional source of mortality, useful for modeling death by periodic environmental phenomena such as water availability and temperature. 16 It has no effect when [[ABIOTIC_HAZARD_OFFSET]] and [[ABIOTIC_HAZARD_AMPLITUDE]] are set to 0. 17 It is modeled using periodic functions with a period of [[ABIOTIC_HAZARD_PERIOD]], amplitude of [[ABIOTIC_HAZARD_AMPLITUDE]], 18 shape of [[ABIOTIC_HAZARD_SHAPE]] and constant background mortality of [[ABIOTIC_HAZARD_OFFSET]] (negative or positive). 19 Negative hazard is clipped to zero. 20 Available hazard shapes (waveforms) are flat, sinusoidal, square, triangle, sawtooth, ramp (backward sawtooth) and instant (Dirac comb / impulse train). 21 Importantly, it only affects the living individuals (i.e. it does not affect eggs, if applicable). 22 """ 23 24 def __init__(self, ABIOTIC_HAZARD_SHAPE, ABIOTIC_HAZARD_OFFSET, ABIOTIC_HAZARD_AMPLITUDE, ABIOTIC_HAZARD_PERIOD): 25 26 self.ABIOTIC_HAZARD_SHAPE = ABIOTIC_HAZARD_SHAPE 27 self.ABIOTIC_HAZARD_OFFSET = ABIOTIC_HAZARD_OFFSET 28 self.ABIOTIC_HAZARD_AMPLITUDE = ABIOTIC_HAZARD_AMPLITUDE 29 self.ABIOTIC_HAZARD_PERIOD = ABIOTIC_HAZARD_PERIOD 30 31 self.func = { 32 "flat": self._flat, 33 "sinusoidal": self._sinusoidal, 34 "triangle": self._triangle, 35 "square": self._square, 36 "sawtooth": self._sawtooth, 37 "ramp": self._ramp, 38 "instant": self._instant, 39 "instant_fatal": self._instant_fatal, 40 "instant_deterministic": self._instant_deterministic, 41 }[self.ABIOTIC_HAZARD_SHAPE] 42 43 if self.ABIOTIC_HAZARD_SHAPE == "flat" and self.ABIOTIC_HAZARD_AMPLITUDE > 0 and self.ABIOTIC_HAZARD_OFFSET > 0: 44 logging.info( 45 """ 46 Note that under flat cnf.abiotic hazard, amplitude and offset have the same effects; 47 the total cnf.abiotic mortality is simply their sum. 48 """ 49 ) 50 51 def __call__(self, step): 52 return self.func(step) + self.ABIOTIC_HAZARD_OFFSET 53 54 def _flat(self, step): 55 return self.ABIOTIC_HAZARD_AMPLITUDE 56 57 def _sinusoidal(self, step): 58 return self.ABIOTIC_HAZARD_AMPLITUDE * math.sin(2 * math.pi * step / self.ABIOTIC_HAZARD_PERIOD) 59 60 def _triangle(self, step): 61 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 62 1 - 4 * abs(round(step / self.ABIOTIC_HAZARD_PERIOD - 0.5) - (step / self.ABIOTIC_HAZARD_PERIOD - 0.5)) 63 ) 64 65 def _square(self, step): 66 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 67 1 if (step % self.ABIOTIC_HAZARD_PERIOD) < (self.ABIOTIC_HAZARD_PERIOD / 2) else -1 68 ) 69 70 def _sawtooth(self, step): 71 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 72 2 * (step / self.ABIOTIC_HAZARD_PERIOD - math.floor(step / self.ABIOTIC_HAZARD_PERIOD + 0.5)) 73 ) 74 75 def _ramp(self, step): 76 return self.ABIOTIC_HAZARD_AMPLITUDE * (step % self.ABIOTIC_HAZARD_PERIOD) / self.ABIOTIC_HAZARD_PERIOD 77 78 def _instant(self, step): 79 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills ABIOTIC_HAZARD_AMPLITUDE of the total living population; step 0 is unaffected""" 80 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 81 return 0 82 83 mortality = np.random.beta(a=1, b=3, size=1) 84 return mortality * self.ABIOTIC_HAZARD_AMPLITUDE 85 86 def _instant_fatal(self, step): 87 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills all of the total living population; step 0 is unaffected""" 88 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 89 return 0 90 else: 91 return 1 92 93 def _instant_deterministic(self, step): 94 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills exactly ABIOTIC_HAZARD_AMPLITUDE fraction of the living population; step 0 is unaffected""" 95 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 96 return 0 97 return self.ABIOTIC_HAZARD_AMPLITUDE
TODO maybe mention which phenomena could be modeled by which shape in the doctsring
GUI Abiotic mortality is an optional source of mortality, useful for modeling death by periodic environmental phenomena such as water availability and temperature. It has no effect when [[ABIOTIC_HAZARD_OFFSET]] and [[ABIOTIC_HAZARD_AMPLITUDE]] are set to 0. It is modeled using periodic functions with a period of [[ABIOTIC_HAZARD_PERIOD]], amplitude of [[ABIOTIC_HAZARD_AMPLITUDE]], shape of [[ABIOTIC_HAZARD_SHAPE]] and constant background mortality of [[ABIOTIC_HAZARD_OFFSET]] (negative or positive). Negative hazard is clipped to zero. Available hazard shapes (waveforms) are flat, sinusoidal, square, triangle, sawtooth, ramp (backward sawtooth) and instant (Dirac comb / impulse train). Importantly, it only affects the living individuals (i.e. it does not affect eggs, if applicable).
24 def __init__(self, ABIOTIC_HAZARD_SHAPE, ABIOTIC_HAZARD_OFFSET, ABIOTIC_HAZARD_AMPLITUDE, ABIOTIC_HAZARD_PERIOD): 25 26 self.ABIOTIC_HAZARD_SHAPE = ABIOTIC_HAZARD_SHAPE 27 self.ABIOTIC_HAZARD_OFFSET = ABIOTIC_HAZARD_OFFSET 28 self.ABIOTIC_HAZARD_AMPLITUDE = ABIOTIC_HAZARD_AMPLITUDE 29 self.ABIOTIC_HAZARD_PERIOD = ABIOTIC_HAZARD_PERIOD 30 31 self.func = { 32 "flat": self._flat, 33 "sinusoidal": self._sinusoidal, 34 "triangle": self._triangle, 35 "square": self._square, 36 "sawtooth": self._sawtooth, 37 "ramp": self._ramp, 38 "instant": self._instant, 39 "instant_fatal": self._instant_fatal, 40 "instant_deterministic": self._instant_deterministic, 41 }[self.ABIOTIC_HAZARD_SHAPE] 42 43 if self.ABIOTIC_HAZARD_SHAPE == "flat" and self.ABIOTIC_HAZARD_AMPLITUDE > 0 and self.ABIOTIC_HAZARD_OFFSET > 0: 44 logging.info( 45 """ 46 Note that under flat cnf.abiotic hazard, amplitude and offset have the same effects; 47 the total cnf.abiotic mortality is simply their sum. 48 """ 49 )