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
class Abiotic:
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).

Abiotic( ABIOTIC_HAZARD_SHAPE, ABIOTIC_HAZARD_OFFSET, ABIOTIC_HAZARD_AMPLITUDE, ABIOTIC_HAZARD_PERIOD)
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            )
ABIOTIC_HAZARD_SHAPE
ABIOTIC_HAZARD_OFFSET
ABIOTIC_HAZARD_AMPLITUDE
ABIOTIC_HAZARD_PERIOD
func