A python package for generating the shortest sea route between two points on Earth.
Project description
Searoute py
A python package for generating the shortest sea route between two points on Earth.
If points are on land, the function will attempt to find the nearest point on the sea and calculate the route from there.
Not for routing purposes! This library was developed to generate realistic-looking sea routes for visualizations of maritime routes, not for mariners to route their ships.
Installation
pip install searoute
Usage
import searoute as sr
#Define origin and destination points:
origin = [0.3515625, 50.064191736659104]
destination = [117.42187500000001, 39.36827914916014]
route = sr.searoute(origin, destination)
# > Returns a GeoJSON LineString Feature
# show route distance with unit
print("{:.1f} {}".format(route.properties['length'], route.properties['units']))
# Optionally, define the units for the length calculation included in the properties object.
# Defaults to km, can be can be 'm' = meters 'mi = miles 'ft' = feet 'in' = inches 'deg' = degrees
# 'cen' = centimeters 'rad' = radians 'naut' = nautical 'yd' = yards
routeMiles = sr.searoute(origin, destination, units="mi")
Bring your network :
# using version >= 1.2.0
# nodes representing (1,2) of lon = 1, lat = 2
# required : 'x' for lon, 'y' for lat ; optional 'tt' for terminals (boolean or None)
my_nodes = {
(1, 2): {'x': 1, 'y': 2},
(2, 2): {'x': 2, 'y': 2}
}
# (1,2) -> (2,2) with weight, representing the distance, other attributes can be added
# recognized attributes are : `weight` (distance), `passage` (name of the passage to be restricted by restrictions)
# Note: Ensure that both directions of the edge are included. If (u, v) is added, (v, u) should also be included to account for bidirectional relationships.
my_edges = {
(1, 2): {
(2, 2): {"weight": 10, "other_attr": "some_value u->v"}
}
(2, 2): {
(1, 2): {"weight": 10, "other_attr": "some_value v->u"}
}
}
# Marnet
myM = sr.from_nodes_edges_set(sr.Marnet(), my_nodes, my_edges)
# Ports
myP = sr.from_nodes_edges_set(sr.Ports(), my_nodes, None)
# get shortest with your ports
route_with_my_ports = sr.searoute(origin, destination, P = myP, include_ports=True)
# get shortest with your ports
route_with_my_ntw = sr.searoute(origin, destination, P = myP, M = myM )
Nodes and Edges
Nodes
A node (or vertex) is a fundamental unit of which the graphs Ports and Marnet are formed.
In searoute, a node is represented by it's id as a tuple of lon,lat, and it's attributes:
x: float ; requiredy: float ; requiredt: bool ; optional. default isFalse, will be used for filtering ports withterminals.
{
(lon:float, lat:float): {'x': lon:float, 'y': lat:float, *args:any},
...
}
Edges
An edge is a line or connection between a note and an other. This connection can be represented by a set of node_id->node_id with it's attributes:
weight: float ; required. Can be distance, cost etc... if not set will by default calculate the distance between nodes using Haversine formula.passage: str ; optional. Can be one of Passage (searoute.classes.passages.Passage). If not not set, no restriction will be applied. If set make sure to updateMarnet().restrictions = [...]with your list of passages to avoid.
{
(lon:float, lat:float)->node_id: {
(lon:float, lat:float)->node_id: {
"weight": distance:float,
*args: any}
},
...
}
Example with more parameters :
## Using all parameters, wil include ports as well
route = sr.searoute(origin, destination, append_orig_dest=True, restrictions=['northwest'], include_ports=True, port_params={'only_terminals':True, 'country_pol': 'FR', 'country_pod' :'CN'})
returns :
{
"geometry": {
"coordinates": [],
"type": "LineString"
},
"properties": {
"duration_hours": 461.88474412693756,
"length": 20529.85310695412,
"port_origin": {
"cty": "France",
"name": "Le Havre",
"port": "FRLEH",
"t": 1,
"x": 0.107054,
"y": 49.485998
},
"port_dest": {
"cty": "China",
"name": "Tianjin",
"port": "CNTSN",
"t": 1,
"x": 117.744852,
"y": 38.986802
},
"units": "km"
},
"type": "Feature"
}
Preferred Ports
Preferred ports can be defined using one or more AreaFeature objects:
Start by creating or referencing preferred ports with the PortProps class.A PortProps instance includes:
port_id— the port identifiershare— a positive weight used for selectionprops— optional attributes describing the port (e.g., coordinates or metadata)
# your preferred ports
port_one = PortProps('MY_PORT_ID', 2, {'x':1, 'y':2})
port_two = PortProps('USNYC', 1)
Initiate a AreaFeature with its coords and a name, as well as list of preferred_ports (could be a list, str, or PortProps)
# initiate an AreaFeature
area_one = AreaFeature(coordinates=[[[0,0], [0,10],[0,20], [20, 20], [0, 0]]], name= 'Special_Name', preferred_ports=[port_one, port_two])
# create other AreaFeature
area_two = AreaFeature(...)
When multiple AreaFeature objects contain a point, the smallest area will be used to determine the preferred ports.
Finally, call the function which will return a tuple of 3 values, or 4 values when include_area_name is set to True:
# myPorts is the instance of Port, by default is sr.setup_P()
origin = (11, 12)
pref_ports = myPorts.get_preferred_ports(*origin, AreaFeature.create([area_one, area_two]), top=2, include_area_name = True)
Usage in main function
areas = AreaFeature.create([area_one, area_two])
sr.searoute(..., include_ports = True, port_params = {'ports_in_areas': areas})
Parameters
-
origin(required) Tuple or array of two floats representing the longitude and latitude of the starting point.Example:
(lon, lat)
-
destination(required) Tuple or array of two floats representing the longitude and latitude of the destination point.Example:
(lon, lat)
-
units(optional) Unit used to compute the route distance.Default:
kmSupported values:
km= kilometers,m= metersmi= milesft= feetsin= inchesdeg= degreescen= centimetersrad= radiansnaut= nauticalsyd= yards
-
speed_knot(optional) Vessel speed used to estimate route duration.Default:
24Unit: knots
-
append_orig_dest(optional) IfTrue, the origin and destination coordinates will be appended to the returnedLineString.Default:
False
-
restrictions(optional) List of maritime passages to avoid during route calculation.Default:
["northwest"]Supported values:
babalmandab,bosporus,gibraltar,suez,panama,ormuz,northwest,malacca,sunda,chili,south_africa
-
include_ports(optional) IfTrue, the algorithm includes the port of loading (POL) and port of discharge (POD) in the result.Default:
False
-
port_params(optional) Additional configuration used wheninclude_ports=True.Available options:
-
only_terminalsInclude only terminal ports. Default:False -
country_polISO-2 country code used to select the Port of Loading (POL). If not provided, the closest port geographically will be selected.Example:
"FR" -
country_podISO-2 country code used to select the Port of Discharge (POD). If not provided, the closest port geographically will be selected. -
country_restrictedFilters out ports that define ato_ctyattribute containing the same country code ascountry_pod.Default:
False -
ports_in_areasOverrides all previous port filtering rules and defines preferred ports within geographic areas.Must be created using:
AreaFeature.create([...])Notes:
- Preferred ports with
share = 0are ignored. - If multiple ports match, the function returns multiple GeoJSON routes.
- Preferred ports with
-
ports_in_areas_fromSame behavior asports_in_areas, but applied only to the origin point (POL). -
ports_in_areas_toSame behavior asports_in_areas, but applied only to the destination point (POD). -
strict_areaOnly relevant when usingports_in_areas,ports_in_areas_from, orports_in_areas_to.Default:
TrueBehavior:
False→ if the point is outside all areas, the closest area is used.True→ if the point is outside all areas, the configuration is ignored.
-
-
return_passages(optional) IfTrue, the result will include the list of traversed maritime passages.Default:
False
Return Value
The function returns:
GeoJSON Feature
or (when many routes configured in port_params)
List[GeoJSON Feature]
Credits
- NetworkX, a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.
- GeoJson, a python package for GeoJSON
- turfpy, a Python library for performing geo-spatial data analysis which reimplements turf.js. (up to version
searoute 1.1.0) - OSMnx, for geo-spacial networks. (up to version
searoute 1.1.0) - Eurostat's Searoute Java library
Change Log
1.0.2 (30/09/2022)
- First Release, published module
1.0.3 (04/10/2022)
- changed the core of the calculation to osmnx library for better performance
- making 1.0.2 obsolete
- added duration measurement together with length in the LineString properties
1.0.4 (04/10/2022)
- fix requirements of the module
1.0.5 (04/10/2022)
- Adjusted network (.json) by connecting all LineStrings in order to return a route from any location to any location
1.0.6 (05/10/2022)
- Improved network connectivity
1.0.7 (13/10/2022)
- Improved network connectivity
- Connection points were not adjusted
1.0.8 (25/10/2022)
- Improved network connectivity
- Added append_orig_dest parameter as input to append origin and destination points to the LineString
- Updated README.md
1.0.9 (04/01/2023)
- Improved network connectivity
- Added restrictions parameter as input to control restrictiveness of connections due to different reasons
- Updated README.md
1.1.0 (23/05/2023)
- Improved network connectivity
- Added new feature : closest port of load and port of discharge
- Updated README.md
1.2.0 (24/08/2023)
- 35x Faster: Significantly accelerated compared to v1.1 by rethinking and reorganizing the code.
- Re-think Class Design: Re-structured and simplified class structure.
- Easy API Access
- Improved Network Connectivity: Enhanced network reliability.
- Updated README.md: Revised for the latest information.
1.2.1 (28/08/2023)
- Patch fixed issue when querying country with no port result
1.2.2 (08/09/2023)
- Patch fixed and simplified coords line normalization
1.2.3 (05/01/2024)
- Patch fixed and improved coords validation
1.3.0 (11/01/2024)
- Added in port_params additional parameter country_restricted
- Updated license to Apache 2.0
1.3.1 (27/01/2024)
- Enriched network with additional passages
1.4.0 (09/06/2024)
- Enriched network with additional passages : chili and south_africa (#27)
- Adjusted logic of port selection (#28)
- Add feature to suggest preferred port of load and port of discharge (#29)
- Fixed del property
to_ctyin main function (#30) - Created unit tests
- return passages traversed by the path (#34)
1.4.1 (22/06/2024)
- Fixed support python 3.7 3.8 (issue #36)
- Fixed bug in
return_passages(issue #35) - Added tests for
return_passages
1.4.2 (22/08/2024)
- Improved Marnet around Baltic sea #37
- Fixed issue with returned passage when crossing the ocean #35
- Adding unit tests
- Added test for mandatory passages example
1.4.3 (22/02/2025)
- Added CITATION.cff as per suggestion #44
- Added clarification on README as per suggestion #47
- Added BERING passage #46
- Added examples as notebook files #43 #41
1.5.0 (15/03/2026)
- Added feature in port and area selection
port_paramsforports_in_areas - Fixed issue with returned passage when no path available #53
- Updated README
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file searoute-1.5.0.tar.gz.
File metadata
- Download URL: searoute-1.5.0.tar.gz
- Upload date:
- Size: 1.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d7f302503869b304f92c5ca6c53497934d412f60b759e1f3615b4cdc1680751
|
|
| MD5 |
aa16a2c92f0da9f629f38484169dbea2
|
|
| BLAKE2b-256 |
9c8b21c0c220c4938a60d8a497aaba4562d1b7ee4a00b243917a3524cb59aabc
|