slim.simulation.cage module
Cages contain almost all of the modelling logic in SLIM. They model single cages (aka pens) of salmon and lice. In contrast to literature we only assume eggs to be floating between cages.
This module is not meant for external use, and should be relatively self-contained.
- class slim.simulation.cage.Cage(cage_id: int, cfg: Config, farm: Farm, initial_lice_pop: Optional[GrossLiceDistrib] = None)
Bases:
slim.log.LoggableMixin
The class that contains fish and lice and deals with all their lifecycle logic.
Avoid instantiating this class directly. Usually a cage belongs to an instance of
Farm
which will deal with cage-to-farm lice movements.In general, making a cage step resolves to calling the
update()
method every day.- Parameters
cage_id – the label (id) of the cage within the farm
cfg – the farm configuration
farm – a Farm object
initial_lice_pop – if provided, overrides default generated lice population
- property aggregation_rate
The aggregation rate is the number of lice over the total number of fish. Elsewhere, it is referred to as infection rate, but here “infection rate” only refers to host fish.
- Returns
the aggregation rate
- average_fish_mass(days)
Average fish mass.
- Params days
number of elapsed days
- Returns
the average fish mass (in grams).
- create_offspring(cur_time: datetime.datetime) GenoDistrib
Hatch the eggs from the event queue
- Parameters
cur_time – the current time
- Returns
a delta egg genomics
- property current_treatments
- Returns
a list of current treatments
- do_infection_events(days: int) int
Infect fish in this cage if the sea lice are in stage L2 and at least 1 day old
- Parameters
cur_date – current date of simulation
days – days the number of days elapsed
- Returns
number of evolving lice, or equivalently the new number of infections
- do_mating_events() Tuple[int, GenoDistrib]
Will generate two deltas: one to add to unavailable dams and subtract from available dams, one to add to eggs Assume males don’t become unavailable? in this case we don’t need a delta for sires
- Returns
a pair (mating_dams, new_eggs)
- fallow()
Put the cage in a fallowing state.
Implications:
All the fish would be removed.
L3/L4/L5 would therefore disappear as they are attached to fish.
Dam waiting and treatment queues will be flushed.
- generate_eggs_discrete_batch(sire_distrib: GenoDistrib, dam_distrib: GenoDistrib, number_eggs: int) GenoDistrib
Get number of eggs based on discrete genetic mechanism.
The algorithm emulates the following scenario: each sire s_i is sampled from sire_distrib and will have a given genomic \(g_{s_i}\) and similarly a dam \(d_i\) will have a genotype \(g_{d_i}\). Because the genomic of a lice can only be dominant, recessive or partial dominant then the mating will result in one of these happening depending on the usual Mendelevian mechanism. The algorithm terminates when all sires and dams have been mated. Here we emulate such sampling strategy via a O(1) algorithm as follows: we compute the probabilities of each combination arising and adopt a multinomial distribution in order to achieve a given number of eggs. The rationale for the formulae used here is the following:
to get an A (dominant) one needs a combination of dominant and dominant allele, or dominant and the right half of partially dominant genes;
to get an a (recessive) one does the same as above, but with fully recessive alleles instead;
to get a partially dominant one, we use the inclusion-exclusion principle and subtract the cases above from all the possible pairings.
Together with being fast, this approach naturally models statistical uncertainty compared to a perfect Mendelevian split. Unfortunately it does not naturally include mutation to non-existent strains (e.g. a mating between pure dominant lice distributions can never yield partial dominance or recessive genomics in the offspring).
- Parameters
sire_distrib – the genotype distribution of the sires
dam_distrib – the genotype distribution of the eggs
number_eggs – the total number of eggs
- Returns
the newly sampled eggs as a
GenoDistrib
.
- generate_eggs_maternal_batch(dams: GenoDistrib, number_eggs: int) GenoDistrib
Get number of eggs based on maternal genetic mechanism.
Maternal-only inheritance - all eggs have mother’s genotype.
- Parameters
dams – the genomics of the dams
number_eggs – the number of eggs produced
- Returns
genomics distribution of eggs produced
- get_arrivals(cur_date: datetime.datetime) GenoDistrib
Process the arrivals queue.
- Parameters
cur_date – Current date of simulation
- Returns
Genotype distribution of eggs hatched in travel
- get_background_lice_mortality() Dict[str, int]
Background death in a stage (remove entry) -> rate = number of individuals in stage*stage rate (nauplii 0.17/d, copepods 0.22/d, pre-adult female 0.05, pre-adult male … Stien et al 2005)
- Returns
the current background mortality. The return value is genotype-agnostic
- get_cleaner_fish_delta() int
Call this function before
get_lice_treatment_mortality()
!
- get_dying_lice_from_dead_fish(num_dead_fish: int) Dict[str, int]
Get the number of lice that die when fish die.
- Parameters
num_dead_fish – the number of dead fish
- Returns
a gross distribution
- get_egg_batch(cur_date: datetime.datetime, egg_distrib: GenoDistrib) EggBatch
Get the expected arrival date of an egg batch
- Parameters
cur_date – the current time
egg_distrib – the egg distribution
- Returns
EggBatch representing egg distribution and expected hatching date
- get_fish_growth(days_since_start) Tuple[int, int]
Get the number of fish that get killed either naturally or by lice.
- Param
days_since_start: the number of days since the beginning.
- Returns
a tuple (natural_deaths, lice_induced_deaths, lice_deaths)
- get_fish_treatment_mortality(days_since_start: int, fish_lice_deaths: int, fish_background_deaths: int) int
Get fish mortality due to treatment. Mortality due to treatment is defined in terms of point percentage increases, thus we can only account for “excess deaths”. If multiple treatments are performed their side effects are additively combined. If no treatment is currently in action, no fish deaths are counted.
- Parameters
days_since_start – the number of days since the beginning of the simulation
fish_lice_deaths – the number of fish dead by lice
fish_background_deaths – the number of fish dead by natural reasons
- Returns
number of fish death events
- get_infecting_population(*args) int
Get the number of lice infecting a population.
- Parameters
*args – consider the given stages as infecting (default: CH to AM/AF)
- Returns
gross number of infecting lice
- get_infection_rates(days_since_start) Tuple[float, int]
Compute the number of lice that can infect and what their infection rate (number per fish) is.
Compared to Aldrin et al. we do not calculate a softmax across cage rates as this would cause multiprocessing issues. We still perform
- Parameters
days_since_start – days since the cage has opened
- Returns
a pair (Einf, num_avail_lice)
- get_lice_lifestage(cur_date: datetime.datetime) Tuple[int, int, int, int]
Move lice between lifecycle stages. See Section 2.1 of Aldrin et al. (2017)
- Parameters
cur_date – the current date
- Returns
a tuple (new_l2, new_l4, new_l5f, new_l5m)
- get_lice_treatment_mortality(cur_date) Tuple[Dict[str, GenoDistrib], float]
Calculate the number of lice in each stage killed by treatment.
Note: this method consumes the internal event queue
- Parameters
cur_date – the current date
- Returns
a pair (distribution of dead lice, cost of treatment)
- get_lice_treatment_mortality_rate(cur_date: datetime.datetime) Dict[str, GenoTreatmentValue]
Check if the cage is currently being treated. If yes, calculate the treatment rates. Note: this method consumes the internal treatment event queue.
- Parameters
cur_date – the current date
- Returns
the mortality rates broken down by geno data.
- get_mean_infected_fish(*args) int
Get the average number of infected fish.
- Parameters
*args – the stages to consider (optional, by default all stages from the third onward are taken into account)
- Returns
the number of infected fish
- get_num_eggs(mated_females) int
Get the number of new eggs
- Parameters
mated_females – the number of mated females that reproduce
- Returns
the number of eggs produced
- get_num_matings() int
Get the number of matings. Implement Cox (2017)’s approach assuming an unbiased sex distribution.
- get_reservoir_lice(pressure: int, external_pressure_ratios: numpy.ndarray) Dict[str, GenoDistrib]
Get distribution of lice coming from the reservoir
- Parameters
pressure – External pressure
external_pressure_ratios – the external pressure ratios to sample from
- Returns
Distribution of lice in L1 and L2
- get_stage_ages_distrib(stage: str, temp_c: float = 10.0)
Create an age distribution (in days) for the sea lice within a lifecycle stage.
This distribution is computed by using a simplified version of formulae (4), (6), (8) in Aldrin et al.: we assume that all lice of a stage m-1 that evolve at stage m will be put at a stage-age of 0, and that this is going to be a constant/stable amount.
- get_temperature(cur_date: datetime.datetime) float
Get the cage temperature at this farm and day
- Parameters
cur_date – the current day
- Returns
the temperature (in °C)
- static get_variance_infected_fish(num_fish: int, infecting_lice: int) float
Compute the variance of the lice infecting the fish.
Rationale: assuming that we generate \(N\) bins that sum to \(K\), we can model this as a multinomial distribution where all \(p_i\) are the same. Therefore, the variance of each bin is \(k \frac{n-1}{n^2}\)
Because we are considering the total variance of k events at the same time we need to multiply by \(k\), thus yielding \(k^2 \frac{n-1}{n^2}\) .
- Parameters
num_fish – the number of fish
infecting_lice – the number of lice attached to the fish
- Returns
the variance
- property is_fallowing
True if the cage is fallowing.
- is_treated(treatment_type: Optional[Treatment] = None)
Check if a farm is treated.
- Parameters
treatment_type – if provided, check if there is a treatment of the given type
- Returns
True if the cage is being treated
- mutate(eggs: GenoDistrib, mutation_rate: float) GenoDistrib
Mutate the genotype distribution
- Parameters
eggs – the genotype distribution of the newly produced eggs
mutation_rate – the rate of mutation with respect to the number of eggs.
- promote_population(prev_stage: Union[str, GenoDistrib], cur_stage: str, leaving_lice: int, entering_lice: Optional[int] = None)
Promote the population by stage and respect the genotypes
- Parameters
prev_stage – the lice stage from which cur_stage evolves
cur_stage – the lice stage that is about to evolve
leaving_lice – the number of lice in the _cur_stage=>next_stage_ progression
entering_lice – the number of lice in the _prev_stage=>cur_stage_ progression. If _prev_stage_ is a a string, _entering_lice_ must be an _int_
- select_lice(distrib_lice_available: GenoDistrib, num_lice: int) GenoDistrib
From a geno distribution of eligible lice sample a given Genotype distribution
Note: this is very similar to
GenoDistrib.normalise_to()
but performs an explicit sampling.TODO: should we integrate this into GenoDistrib class
- Parameters
distrib_lice_available – the starting dam genomic distribution
num_lice – the wished number of dams to sample
- to_json_dict()
Create a JSON-serialisable dictionary version of a cage.
- update(cur_date: datetime.datetime, pressure: int, ext_pressure_ratio: numpy.ndarray) Tuple[GenoDistrib, Optional[datetime.datetime], float]
Update the cage at the current time step.
- Parameters
cur_date – Current date of simulation
pressure – External pressure, planctonic lice coming from the reservoir
ext_pressure_ratio – The genotype ratio to use for the external pressure
- Returns
Tuple (egg genotype distribution, hatching date, cost)
- update_arrivals(arrivals_dict: GenoDistribByHatchDate, arrival_date: dt.datetime)
Update the arrivals queue
- Parameters
arrivals_dict – List of dictionaries of genotype distributions based on hatch date
arrival_date – Arrival date at this cage
- update_deltas(dead_lice_dist: Dict[str, int], treatment_mortality: Dict[str, GenoDistrib], fish_deaths_natural: int, fish_deaths_from_lice: int, fish_deaths_from_treatment: int, new_L2: int, new_L4: int, new_females: int, new_males: int, new_infections: int, lice_from_reservoir: Dict[str, GenoDistrib], delta_dams_batch: int, new_offspring_distrib: GenoDistrib, hatched_arrivals_dist: GenoDistrib, cleaner_fish_delta: int = 0)
Update the number of fish and the lice in each life stage
- Parameters
dead_lice_dist – the number of dead lice due to background death (as a distribution)
treatment_mortality – the distribution of genotypes being affected by treatment
fish_deaths_natural – the number of natural fish death events
fish_deaths_from_lice – the number of lice-induced fish death events
fish_deaths_from_treatment – the number of treatment-induced fish death events
new_L2 – number of new L2 fish
new_L4 – number of new L4 fish
new_females – number of new adult females
new_males – number of new adult males
new_infections – the number of new infections (i.e. progressions from L2 to L3)
lice_from_reservoir – the number of lice taken from the reservoir
delta_dams_batch – the genotypes of now-unavailable females in batch events
new_offspring_distrib – the new offspring obtained from hatching and migrations
hatched_arrivals_dist – new offspring obtained from arrivals
cleaner_fish_delta – new cleaner fish