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 }[self.ABIOTIC_HAZARD_SHAPE] 40 41 if self.ABIOTIC_HAZARD_SHAPE == "flat" and self.ABIOTIC_HAZARD_AMPLITUDE > 0 and self.ABIOTIC_HAZARD_OFFSET > 0: 42 logging.info( 43 """ 44 Note that under flat cnf.abiotic hazard, amplitude and offset have the same effects; 45 the total cnf.abiotic mortality is simply their sum. 46 """ 47 ) 48 49 def __call__(self, step): 50 return self.func(step) + self.ABIOTIC_HAZARD_OFFSET 51 52 def _flat(self, step): 53 return self.ABIOTIC_HAZARD_AMPLITUDE 54 55 def _sinusoidal(self, step): 56 return self.ABIOTIC_HAZARD_AMPLITUDE * math.sin(2 * math.pi * step / self.ABIOTIC_HAZARD_PERIOD) 57 58 def _triangle(self, step): 59 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 60 1 - 4 * abs(round(step / self.ABIOTIC_HAZARD_PERIOD - 0.5) - (step / self.ABIOTIC_HAZARD_PERIOD - 0.5)) 61 ) 62 63 def _square(self, step): 64 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 65 1 if (step % self.ABIOTIC_HAZARD_PERIOD) < (self.ABIOTIC_HAZARD_PERIOD / 2) else -1 66 ) 67 68 def _sawtooth(self, step): 69 return self.ABIOTIC_HAZARD_AMPLITUDE * ( 70 2 * (step / self.ABIOTIC_HAZARD_PERIOD - math.floor(step / self.ABIOTIC_HAZARD_PERIOD + 0.5)) 71 ) 72 73 def _ramp(self, step): 74 return self.ABIOTIC_HAZARD_AMPLITUDE * (step % self.ABIOTIC_HAZARD_PERIOD) / self.ABIOTIC_HAZARD_PERIOD 75 76 def _instant(self, step): 77 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills ABIOTIC_HAZARD_AMPLITUDE of the total living population; step 0 is unaffected""" 78 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 79 return 0 80 81 mortality = np.random.beta(a=1, b=3, size=1) 82 return mortality * self.ABIOTIC_HAZARD_AMPLITUDE 83 84 def _instant_fatal(self, step): 85 """Mortality function that every ABIOTIC_HAZARD_PERIOD steps kills all of the total living population; step 0 is unaffected""" 86 if step == 0 or step % self.ABIOTIC_HAZARD_PERIOD: 87 return 0 88 else: 89 return 1
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 }[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
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 }[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 )