Source code for laser_core.utils
"""
This module provides utility functions for the laser-measles project.
Functions:
calc_distances(latitudes: np.ndarray, longitudes: np.ndarray, verbose: bool = False) -> np.ndarray:
Calculate the pairwise distances between points given their latitudes and longitudes.
calc_capacity(population: np.uint32, nticks: np.uint32, cbr: np.float32, verbose: bool = False) -> np.uint32:
Calculate the population capacity after a given number of ticks based on a constant birth rate.
"""
import click
import numpy as np
from laser_core.migration import distance
def __deprecated(msg):
def decorator(fn):
def wrapper(*args, **kwargs):
click.echo(f"WARNING: {msg}")
return fn(*args, **kwargs)
return wrapper
return decorator
[docs]
@__deprecated(
"This function is deprecated and will be removed in a future release. Use the distance function from the migration module instead."
)
def calc_distances(latitudes: np.ndarray, longitudes: np.ndarray, verbose: bool = False) -> np.ndarray:
"""
Calculate the pairwise distances between points given their latitudes and longitudes.
Parameters:
latitudes (np.ndarray): A 1-dimensional array of latitudes.
longitudes (np.ndarray): A 1-dimensional array of longitudes with the same shape as latitudes.
verbose (bool, optional): If True, prints the upper left corner of the distance matrix. Default is False.
Returns:
np.ndarray: A 2-dimensional array where the element at [i, j] represents the distance between the i-th and j-th points.
Raises:
AssertionError: If latitudes is not 1-dimensional or if latitudes and longitudes do not have the same shape.
"""
assert latitudes.ndim == 1, "Latitude array must be one-dimensional"
assert longitudes.shape == latitudes.shape, "Latitude and longitude arrays must have the same shape"
npatches = len(latitudes)
distances = np.zeros((npatches, npatches), dtype=np.float32)
for i, (lat, long) in enumerate(zip(latitudes, longitudes)):
distances[i, :] = distance(lat, long, latitudes, longitudes)
if verbose:
click.echo(f"Upper left corner of distance matrix:\n{distances[0:4, 0:4]}")
return distances
[docs]
def calc_capacity(population: np.uint32, nticks: np.uint32, cbr: np.float32, verbose: bool = False) -> np.uint32:
"""
Calculate the population capacity after a given number of ticks based on a constant birth rate (CBR).
Args:
population (np.uint32): The initial population.
nticks (np.uint32): The number of ticks (time steps) to simulate.
cbr (np.float32): The constant birth rate per 1000 people per year.
verbose (bool, optional): If True, prints detailed population growth information. Defaults to False.
Returns:
np.uint32: The estimated population capacity after the given number of ticks.
"""
# We assume a constant birth rate (CBR) for the population growth
# The formula is: P(t) = P(0) * (1 + CBR)^t
# where P(t) is the population at time t, P(0) is the initial population, and t is the number of ticks
# We need to allocate space for the population data for each tick
# We will use the maximum population growth to estimate the capacity
daily_rate = (cbr / 1000) / 365.0 # CBR is per 1000 people per year
capacity = np.uint32(population * (1 + daily_rate) ** nticks)
if verbose:
click.echo(f"Population growth: {population:,} … {capacity:,}")
alternate = np.uint32(population * (1 + cbr / 1000) ** (nticks / 365))
click.echo(f"Alternate growth: {population:,} … {alternate:,}")
return capacity