pytheas package#

Submodules#

pytheas.boat module#

The Boat class of Pytheas.

It represents a boat - a logboat, a plank canoe, a longship - you name it. In the Agent-Based Modelling framework, the Boat represents a basic Agent.

class pytheas.boat.Boat(craft: str, latitude: float, longitude: float, target: Tuple[float, float], land_radar_on: bool = True, uncertainty_sigma: float = 0.0, speed_polar_diagram: DataFrame | None = None, leeway_polar_diagram: DataFrame | None = None, route_to_take: List[float] | None = None)#

Bases: object

Base class for a Boat in Pytheas.

craft#

Name or type of boat.

Type:

str

latitude#

Latitude at which the boat is.

Type:

float

longitude#

Longitude at which the boat is.

Type:

float

target#

Lat/Lon of the target landing site.

Type:

Tuple[float, float]

land_radar_on#

Whether the land radar algorithm acts or not.

Type:

bool

uncertainty_sigma#

standard deviation of the navigation error.

Type:

float

speed_polar_diagram#

Table representing the boat speed polar diagram.

Type:

pd.DataFrame

leeway_polar_diagram#

Table representing the boat leeway polar diagram.

Type:

pd.DataFrame

route_to_take#

List of lat/lon coordinates that the boat has to follow to get to target.

Type:

List[float]

trajectory#

List of lat/lon keeping track of the trajectory of the boat.

Type:

List[float]

distance#

Distance (in km) covered by the boat so far.

Type:

float

bearing#

Current angle between launching site and target.

Type:

float)

nominal_bearings#

list of all the direction that the crew takes to reach the target.

Type:

List[float]

modified_bearings#

list of the actual bearings that the boat takes during the trip, after accounting for currents and land avoidance.

Type:

List[float]

has_hit_land#

Boolean to record if the boat hits land before the end of the trip.

Type:

bool

calculate_displacement(local_winds: ndarray, local_currents: ndarray, bearing: float, timestep: int) ndarray#

Function to calculate the displacement in km of a boat from its current position given winds, currents and bearing.

Parameters:
  • local_winds (np.ndarray) – array containing speed and direction of the wind in the local position.

  • local_currents (np.ndarray) – array containing Eastward (x) and Northward (y) speed of currents in the local position.

  • bearing (float) – bearing taken by the boat.

Returns:

array containing Eastward and Northward displacement of the boat from current position.

Return type:

np.ndarray

generic_displacement(local_winds: ndarray, local_currents: ndarray, bearing_xy: ndarray)#
leeway_due_to_wind(current_winds: ndarray, bearing: float)#

Calculates the leeway due to wind according to a polar diagram, when existing.

Parameters:
  • current_winds (np.ndarray) – Wind velocity (two components)

  • bearing_xy (np.ndarray) – bearing of the boat split in x, y components

Raises:
  • ValueError – Raised if the angle between the bearing and reference is a non-positive number

  • ValueError – Raised if the speed of the wind is higher than 30

Returns:

geographic angle of leeway due to the wind to be added to the bearing to obtain the real angle

at which the boat travels, in degrees

Return type:

leeway_angle

move_boat(landmarks: Tuple[float, float], local_winds: ndarray, local_currents: ndarray, timestep: int, accepted_distance_from_target: float = 1)#

Function tha determines the movement of a boat at each time step. It runs from Travel.

Parameters:
  • (Tuple[float (landmarks) – List containing the distance to the closest land (in km) and the direction to the closest land (in degrees)).

  • float] – List containing the distance to the closest land (in km) and the direction to the closest land (in degrees)).

  • local_winds (np.ndarray) – Array containing the speed and geographic angle of the wind.

  • local_currents (np.ndarray) – Array containing Northward and Eastward components of sea currents speed.

  • timestep (int) – Time step between steps of movement, in minutes.

  • acceted_distance_from_target (float) – Distance from target that does not trigger stirring away from land (if target is not distant, the boat should keep going towards it, not stir away.)

plot_trajectory(bbox: Tuple[float, float, float, float]) None#

Quick trajectory plot utility, to show a simulated trajectory.

Parameters:

bbox (Tuple[float, float, float, float]) – list containing [min latitude, min longitude, max latitude, max longitude] for map plotting.

speed_due_to_wind(current_winds: ndarray, bearing: float)#

Calculate the combined speed of paddling with the effect of the wind according to a polar diagram, when existing.

Parameters:
  • current_winds (np.ndarray) – Wind velocity (two components), 0-element is speed in m/s, 1-element is direction in degrees.

  • bearing_xy (np.ndarray) – Bearing of the boat split in x, y components.

Raises:
  • ValueError – Raised if the angle between the bearing and reference is a non-positive number.

  • ValueError – Raised if the speed of the wind is higher than 30.

Returns:

Speed in m/s of the paddling crew.

Return type:

speed (float)

pytheas.map module#

The map object of Pytheas.

It represents the space over which the Boat will travel. It is a continuous space where we super impose three distinct layers of data: winds, currents and waves. The wind and current layers directly affect the movement of the boat, while the wave layer is necessary to record encountered waves. In the Agent-Based Modelling framework, the Map corresponds to the Space.

class pytheas.map.Map(bounding_box: Tuple[float, float, float, float], earliest_time: Timestamp, latest_time: Timestamp, wind_data_path: str, current_data_path: str, waves_data_path: str)#

Bases: object

The base Map object in Pytheas.

bounding_box#

Bounding box including [min_latitude, min_longitude, max_latitude, max_longitude].

Type:

List[float, float, float, float]

earliest_time#

Earliest time included in the Map dataset.

Type:

pd.Timestamp

latest_time#

Latest time included in the Map dataset.

Type:

pd.Timestamp

wind_path#

Folder where the wind data are stored.

Type:

str

current_path#

Folder where the current data are stored.

Type:

str

waves_path#

Folder where the waves data are stored.

Type:

str

winds_data#

Data array containing winds data (each point has component speed in m/s and angle in degrees).

Type:

xr.DataArray

currents_data#

Data array containing currents data (each point is speed in x/y - both m/s).

Type:

xr.DataArray

waves_data#

Data array containing waves height data (each point is wave height in meters).

Type:

xr.DataArray

create_route(launching_site: Tuple[float, float], landing_site: Tuple[float, float], target_interval: int = 5, **kwargs)#

Create a route that hugs the coast from a launching site to a landing site. The kwargs need to be weights (a list) and iterations (also a list, of the same length as weights) to modify the creation of different “weight corridors” along the shoreline.

Parameters:
  • launching_site (Tuple[float, float]) – Launching site in lat/lon format.

  • landing_site (Tuple[float, float]) – Landing site in in lat/lon format.

  • target_interval (int) – Interval between the nodes in the route. Defaults to 5.

Raises:

RuntimeError – Raised if the algorithm was unable to find a route.

Returns:

List of coordinates through which the routes goes.

Return type:

List[Tuple[float, float]]

find_closest_land(position_on_water: Tuple[float, float], radar_radius: float = 0.2) Tuple[float, float]#

Find land closest to a point in water.

Parameters:
  • position_on_water (Tuple[float, float]) – Position on the water in latitude / longitude.

  • radar_radius (float, optional) – Radius within which to look for land, in degrees. Defaults to 0.2 degrees.

Returns:

Distance from closest land and angle to closest land.

Return type:

Tuple[float, float]

find_closest_water(position_on_land: Tuple[float, float], radar_radius: float = 10) Tuple[float, float]#

Find coordinates in water closest to a point on land.

Parameters:
  • position_on_land (Tuple[float, float]) – Position on land in lon/lat format.

  • radar_radius (float, optional) – Radius within which to look for water, in degrees. Defaults to 10 degrees.

Returns:

Lat/lon of closest point.

Return type:

Tuple[float, float]

find_nearest_index_to_point(point: Tuple[float, float]) Tuple[int, int]#

Find the index of the latitude/longitude in the data closest to a given point.

Parameters:

point (Tuple[float, float]) – A geographical point in lat/lon format.

Returns:

x index and y index of closest coordinate in the data to a given point.

Return type:

Tuple[int, int]

load_dataset_currents() DataArray#

Load the dataset for currents in xarray’s DataArray format.

Returns:

Data array containing the currents data.

Return type:

xr.DataArray

load_dataset_waves()#

Load the dataset for waves in xarray’s DataArray format.

Returns:

Data array containing the waves data.

Return type:

xr.DataArray

load_dataset_winds() DataArray#

Load the dataset for winds in xarray’s DataArray format.

Returns:

Data array containing the winds data.

Return type:

xr.DataArray

return_local_currents(location: ndarray, time: Timestamp, average: bool = True, radius: float = 0.075) ndarray#

Return horizontal and vertical components of current speed at a location and a time. Currents are measured in a square of +/-0.075 degrees around the location, and an average of all the values found in that “radius” is output. The radius is chosen based on the grid size for the ECMWF dataset (~5.5 x 5.5 km). The value of 0.075 has been found with trial and error.

Parameters:
  • location (np.ndarray) – Array of latitude and longitude of a location.

  • time (pd.Timestamp) – Timestamp of time at which one wants the measure.

  • radius (float, optional) – “Square” radius around which the measure of wind datapoints is performed. Defaults to 0.02.

Returns:

An array containing horizontal (Eastward) and vertical (Northward) component of the currents speed.

Return type:

np.ndarray

return_local_waves(location: ndarray, time: Timestamp, radius: float = 0.2) float#

Return wave height at a location and a time. Waves are measured in a square of +/-0.2 degrees around the location, and an average of all the values found in that “radius” is output. The radius is chosen based on the grid size for the ECMWF dataset (~5.5 x 5.5 km). The value of 0.2 has been found with trial and error.

Parameters:
  • location (np.ndarray) – Array of latitude and longitude of a location.

  • time (pd.Timestamp) – Timestamp of time at which one wants the measure.

  • radius (float, optional) – “Square” radius around which the measure of wind datapoints is performed. Defaults to 0.05.

Returns:

A wave height.

Return type:

float

return_local_winds(location: ndarray, time: Timestamp, radius: float = 0.05) ndarray#

Return wind speed and direction given a location and a time. Winds are measured in a square of +/-0.05 degrees around the location, and an average of all the values found in that radius is output. The radius is chosen based on the grid size for the CERRA dataset (~2 x 2 km). The value of 0.05 has been found with trial and error.

Parameters:
  • location (np.ndarray) – Array of latitude and longitude of a location.

  • time (pd.Timestamp) – Timestamp of time at which one wants the measure.

  • radius (float, optional) – “Square” radius around which the measure of wind datapoints is performed. Defaults to 0.05.

Returns:

An array containing wind speed (m/s) and wind direction (degrees).

Return type:

np.ndarray

pytheas.travel module#

The Travel class of Pytheas.

It represents a travel from A to B. This class collects all the different components of the travel of a Boat from A to B on a Map. In the Agent-Based Modelling framework, it represents the Model.

class pytheas.travel.Travel(boat: Boat, map: Map, start_day: str, max_duration: int, timestep: int, night_travel: bool = False, tolerance_distance: float = 3, twilights_of_stops: str = 'sun')#

Bases: object

Base class for a Travel in Pytheas.

Attr:

boat (Boat): The boat that will travel. map (Map): The map over which the boat will travel. max_duration (int): The maximal duration of the trip (in hours). timestep (int): Time between each step (in minutes). launching_site (Tuple[float, float]): Departure site in lat/lon format, inherited from boat. start_time (pd.Timestamp): The day and time of departure for the trip. target (Tuple[float, float]): Target landing site in lat/lon format, inherited from boat. night_travel (bool): Whether the boat is stops for night or not. twilight_of_stops (str): Determines whether tips start and end at sunrise or twilight. Options are “sun” (sunrise), “civil”, “nautical” and “astronomical”. current_time (pd.Timestamp): Keeps track of the current time in the travel. is_completed (bool): Marks whether the travel is completed within tolerance. tolerance (float): Tolerance distance from target to be considered “arrived” (in km). Defaults to 3 km, a distance within which a boat travelling at 3 m/s can travel in 15 minutes. encountered_currents (List): List of tuples (x, y) of currents encountered on the travel. encountered_winds (List): List of tuples (speed, angle) of winds encountered on the travel. encountered_waves (List[float]): List of wave heights encountered on the travel. times_of_stops (List[pd.Timestamp]): List of times at which stops for night were initiated. It gets populated only if night_travel = True. stop_coords (List): List of lat/lon points at which the boat stopped for night.

append_to_aggregates(output_path: str, radius_for_success: float = 5) None#
output_geojson(output_path: str) dict#

Save GeoJSON file of the travel and return it.

Parameters:

output_path (str) – filepath for output.

Returns:

GeoJSON of the travel containing various data.

Return type:

dict

run(verbose: bool = False) None#

Run the travel from the launching site to the target landing site or until it hits land.

Parameters:

verbose (bool) – Boolean determining whether to print a final short summary of the trip.

step() None#

Advance the travel by one step.

pytheas.search module#

Searching algorithms. This module is copied from Voyager. It was developed by Victor Wåhlstrand Skärström (@waahlstrand on Github).

This script contains tools to calculate paths and routes through a simulation.

This file can be imported as module and contains the following functions:
  • heuristic - Generic measure between two positions

And the following classes:
  • Grid - represents the map as an approximately equidistant grid

  • WeightedGrid - inherits from Grid, used to symbolize a map where not all positions are equally likely to traverse

  • PriorityQueue - used in A-star algorithm to deal with queues and stacking

  • Astar - implementation of A-star algorithm

class pytheas.search.Astar(graph: WeightedGrid)#

Bases: object

Implementation of A-star algorithm (see e.g. https://en.wikipedia.org/wiki/A*_search_algorithm)

graph#

weighted graph over which to perform the search

Type:

WeightedGrid

search(start, goal)#

find a route from a start position to a goal position

recontruct_path(came_from, start, goal)#

reconstruct the route from the graph pointing to previous positions.

reconstruct_path(came_from: Dict[Tuple[int, int], Tuple[int, int]], start: Tuple[int, int], goal: Tuple[int, int]) List[Tuple[int, int]]#

Reconstruct the route from the graph pointing to previous positions.

Parameters:
  • came_from (Dict[Position, Position]) – Dictionary pointing from one position to another

  • start (Position) – Start position

  • goal (Position) – End position

Returns:

The resulting route as a list of positions

Return type:

List[Position]

search(start: Tuple[int, int], goal: Tuple[int, int]) Tuple[Dict[Tuple[int, int], Tuple[int, int]], Dict[Tuple[int, int], float]]#

Find a route from a start position to a goal position.

Parameters:
  • start (Position) – Start position

  • goal (Position) – End position

Returns:

A dict as a graph pointing to the previous position, and the current cost of the route.

Return type:

Tuple[Dict[Position, Position], Dict[Position, float]]

class pytheas.search.Grid(width: int, height: int)#

Bases: object

Represents the map as an approximately equidistant grid, with methods to find if the current position is in bounds, if there are obstacles “walls”, and which are the closest places to go.

width#

width of the grid

Type:

int

height#

height of the grid

Type:

int

walls#

walls of the map, defined as unpassable steps in the A-star algorithm

Type:

Position

in_bounds(id)#

Checks if the current position is in bounds

passable(id)#

Checks if current position has any obstacles around (walls)

neighbors(id)#

Calculates all traversable neighbors of a current position

in_bounds(id: Tuple[int, int]) bool#

Checks if the current position is in bounds of the map.

Parameters:

id (Position) – Current position

Returns:

Whether position is in bounds

Return type:

bool

neighbors(id: Tuple[int, int]) Iterator[Tuple[int, int]]#

Calculates the traversable neighbours of the current position as an iterator

Parameters:

id (Position) – Current position

Returns:

A traversable neighbour to the current position

Return type:

Position

Yields:

Iterator[Position] – An iterator with the traversable neighbours

passable(id: Tuple[int, int]) bool#

Checks if the current position has any obstacles, so called “walls”.

Parameters:

id (Position) – Current position

Returns:

Whether the position is passable, or if it has walls

Return type:

bool

class pytheas.search.PriorityQueue#

Bases: object

Class to define PriorityQueue (used in Astar).

elements#

elements a queue used to check points in A-star algorithm.

Type:

List[Tuple[float, T]]

empty()#

return True if self.elements is empty.

put(item, priority)#

insert new element in priority list

get()#

return weight for iteration step

empty() bool#
get() T#
put(item: T, priority: float)#
class pytheas.search.WeightedGrid(width: int, height: int)#

Bases: Grid

The WeightedGrid is a Grid used to symbolize a map where not all positions are equally likely to traverse. Some are more likely, these regions being weighted.

weights#

weights of different points of the Grid.

weigthed_mask#

mask to superpose on Grid with weights.

cost(from_node, to_node)#

calculate cost of movement between two points

from_map(map, **kwargs)#

class method to generate WeightedGrid from an array where land is marked

create_shoreline_contour(mask, weights=[5, 0.5], iterations=[1, 4], kernel_size=3)#

creates weighted shoreline contours for the map.

mask_to_graph(mask)#

superposes mask on Grid.

cost(from_node: Tuple[int, int], to_node: Tuple[int, int]) float#
static create_shoreline_contour(mask: ndarray, weights=[5, 0.5], iterations=[1, 4], kernel_size=3) ndarray#

Create a weight mask corresponding to the shoreline contour of the map.

The contours are created using dilation of the land for a number of iterations and a given kernel size. The result is a contour with a specific width, which is then assigned a specific weight.

This mimics the tendency to avoid close shorelines and open sea.

Parameters:
  • mask (np.ndarray) – A mask symbolizing the land

  • weights (list, optional) – A list of weights for each contour. Defaults to [5, 0.5].

  • iterations (list, optional) – Number of iterations to broaden the contour. Defaults to [1, 4].

  • kernel_size (int, optional) – The kernel size used for broadening of the contour. Defaults to 3.

Returns:

A weighted array corresponding to a map with contours around the land

Return type:

np.ndarray

classmethod from_map(map: ndarray, **kwargs)#

Generate a WeightedGrid from a numpy array, wehere the land is symbolized as NaN.

Parameters:

map (np.ndarray) – An array with land as NaN

Returns:

A WeightedGrid instance

Return type:

WeightedGrid

static mask_to_graph(mask)#

Superposes mask on Grid. :param mask: mask with weights to be superposed on Grid. :type mask: np.ndarray

Returns:

array with weighted Grid

Return type:

np.ndarray

pytheas.search.heuristic(a: Tuple[int, int], b: Tuple[int, int]) float#

Distance measure between two positions.

Parameters:
  • a (Position) – Current position

  • b (Position) – Other position

Returns:

A measure of the distance between the points

Return type:

float

pytheas.utilities module#

Module containing utility functions that are not used within a particular class. These are generally functions that deal with geography, measurements and distances, or time functions, such as ephemeris functions.

pytheas.utilities.angle_uncertainty(sigma=0) float#

Returns an angle error in radiants.

pytheas.utilities.bearing_from_latlon(position: Tuple[float, float], target: Tuple[float, float]) float#

Gives angle between a coordinate and a target (in degrees with respect to North). Taken from Voyager.

Parameters:
  • position (np.ndarray) – current position (lat/lon)

  • target (np.ndarray) – target position (lat/lon)

Returns:

bearing (angle) between a position and a target in degrees

Return type:

float

pytheas.utilities.calculate_end_of_day(day: str, position: Tuple[float, float], type_of_twilight: str = 'sun') Timestamp#

Function to calculate at what time the sun goes down (or twilight).

Parameters:
  • day (str) – date in format ‘yyyy-mm-dd’

  • position (Tuple[float, float]) – position at which you want to calculate the end of the day

  • type_of_twilight (str, optional) – whether you want to calculate sunset, civil, nautical or astronomical twilight. Defaults to ‘sun’.

Raises:

ValueError – If ‘type_of_twilight’ is not one of ‘civil’, ‘nautical’, ‘astronomical’ or ‘sun’.

Returns:

timestamp of date and time of end of the day.

Return type:

pd.Timestamp

pytheas.utilities.calculate_start_of_day(day: str, position: Tuple[float, float], type_of_twilight: str = 'sun') Timestamp#

Function to calculate at what time the sun rises (or twilight).

Parameters:
  • day (str) – date in format ‘yyyy-mm-dd’

  • position (Tuple[float, float]) – position at which you want to calculate the start of the day, in format lon / lat

  • type_of_twilight (str, optional) – whether you want to calculate sunrise, civil, nautical or astronomical twilight. Defaults to ‘sun’.

Raises:

ValueError – If ‘type_of_twilight’ is not one of ‘civil’, ‘nautical’, ‘astronomical’ or ‘sun’.

Returns:

timestamp of date and time of end of the day.

Return type:

pd.Timestamp

pytheas.utilities.difference_between_geographic_angles(bearing: float, angle_wind: float) float#

Calculate the difference between geographic angles. Used to turn the absolute wind angle into the wind angle with the respect to the boat.

Parameters:
  • bearing (float) – Bearing of the boat (in degrees).

  • angle_wind (float) – Absolute angle of the wind (in degrees).

Returns:

Returns the angle of the wind with respect to the boat (in degrees).

Return type:

float

pytheas.utilities.direction_from_displacement(displacement: ndarray) float#

Calculates the absolute direction of a displacement in given as a vector (x, y).

Parameters:

displacement (np.ndarray) – Array containing displacement (in km) in the x and y axis.

Returns:

Angle of displacement with respect to the North (in degrees).

Return type:

float

pytheas.utilities.distance_km(origin: Tuple[float, float], target: Tuple[float, float]) float#

Calculates distance in km between two lat/lon points, in km

Parameters:
  • origin (Tuple[float, float]) – point of origin as [lon, lat]

  • target (Tuple[float, float]) – point of destination as [lon, lat]

Returns:

distance between origin and target

Return type:

float

pytheas.utilities.geographic_angle_to_xy(angle: float) ndarray#

From a geographic angle (with 0 degrees signifying North, 90 East, 180 South and 270 W) return x and y.

Parameters:

angle (float) – geographic angle in degrees

Returns:

array with dx (horizontal Eastward) and dy (vertical Northward)

Return type:

np.ndarray

pytheas.utilities.is_it_night(date_and_time: Timestamp, position: Tuple[float, float], type_of_twilight='sun') bool#

Calculates whether a set of coordinates refer to a moment in the day or in the night. We consider sunrise time as day, and sunset time as night.

Parameters:
  • date_and_time (pd.Timestamp) – day of the year

  • position (Tuple[float, float]) – place in format [longitude, latitude]

  • type_of_twilight (str) – type of twilight, “civil”, “nautical” or “astronomical”. Defaults to “sun”.

Returns:

returns whether the point is during the night or not

Return type:

bool

pytheas.utilities.knots_to_si(knots: float) float#

Converts knots to SI units (m/s)

Parameters:

knots (float) – Speed in knots

Returns:

Speed in metres/second

Return type:

float

pytheas.utilities.si_to_knots(si: float) float#

Converts SI units (m/s) to knots

Parameters:

si (float) – Speed in m/s

Returns:

Speed in knots

Return type:

float

Module contents#