Source code for pyEpiabm.utility.distance_metrics
#
# Calculates distance metrics between spatial points
#
import typing
import numpy as np
[docs]
class DistanceFunctions:
"""Class which contains multiple distance functions
for use when considering spatial infections, either
inter-place or inter-cell.
"""
[docs]
@staticmethod
def dist(loc1: typing.Tuple[float, float],
loc2: typing.Tuple[float, float] = (0.0, 0.0)) -> float:
"""Calculate distance based on currently configured distance metric
Parameters
----------
loc1 : Tuple[float, float]
(x,y) coordinates of the first place
loc2 : Tuple[float, float]
(x,y) coordinates of the second place
Returns
-------
float
Distance between the two locations
"""
return DistanceFunctions.dist_euclid(loc1, loc2)
[docs]
@staticmethod
def dist_euclid(loc1: typing.Tuple[float, float],
loc2: typing.Tuple[float, float] = (0.0, 0.0)):
"""Calculates distance based on the standard L2, Euclidean
norm. This assumes the space is approximately planar, and
so is a good approximation for smaller areas where the curvature
of the Earth is not significant. Passing a single location
argument will return the norm of this tuple.
Parameters
----------
loc1 : Tuple[float, float]
(x,y) coordinates of the first place
loc2 : Tuple[float, float]
(x,y) coordinates of the second place
Returns
-------
float
Euclidean distance between the two locations
"""
x1, y1 = loc1
x2, y2 = loc2
return ((x1-x2)**2+(y1-y2)**2)**(1/2)
[docs]
@staticmethod
def dist_periodic(loc1: typing.Tuple[int, int],
stride: int,
scales: typing.Tuple[float, float],
loc2: typing.Tuple[int, int] = (0, 0)):
"""One of the function for calculating distances implemented in
CovidSim. Locations are integer points on a grid, which can be
mapped to the whole globe. Periodic conditions at the boundary
mean this only applies to a global grid. Scales should be
(Earth perimeter, vertical range)
Parameters
----------
loc1 : Tuple[int, int]
Index location of the first place
stride : int
Number of indices in a row
scales : Tuple[float, float]
Conversion to global coordinates
loc2 : Tuple[int, int]
Index location of the second place
Returns
-------
float
Periodic distance between the two locations
"""
# Convert indices to distance measures by dividing by
# total number of indices in each row.
# These points are still on a rectangular grid
scales = np.asarray(scales)
stride = np.asarray(stride)
global1 = (scales*np.asarray(loc1)) / stride
global2 = (scales*np.asarray(loc2)) / stride
for loc in [global1, global2]:
if loc[1] < 0:
loc[1] = scales[1] + loc[1] + (scales/stride)[1]
diff = np.abs(global1 - global2)
# Enforce periodicity of the map from the grid to the Earth.
# If the distance between points is more than half the total length,
# it would be quicker to "go round the back" of the Earth
for index in range(2):
if diff[index] > 0.5 * scales[index]:
diff[index] = scales[index] - diff[index]
return np.linalg.norm(diff)
[docs]
def minimum_between_cells(cell1, cell2):
"""Function to find the minimum distance between microcells
in two cells. Covidsim uses this to weight the spatial kernel.
Parameters
----------
cell1 : Cell
First cell to find the minimum distance between
cell2 : Cell
Second cell to find the minimum distance between
Returns
-------
float
Minimum distance between the two cells
"""
dist = np.inf
for microcell1 in cell1.microcells:
for microcell2 in cell2.microcells:
microcell_dist = DistanceFunctions.dist(microcell1.location,
microcell2.location)
if microcell_dist < dist:
dist = microcell_dist
return dist