Skip to main content

A python package for generating the shortest sea route between two points on Earth.

Project description

Searoute-py

Package version Downloads Supported Python versions


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.

Searoute map

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 ; required
  • y : float ; required
  • t : bool ; optional. default is False, will be used for filtering ports with terminals.
{
    (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 update Marnet().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 identifier
  • share — a positive weight used for selection
  • props — 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:

    km
    

    Supported values: km = kilometers, m = meters mi = miles ft = feets in = inches deg = degrees cen = centimeters rad = radians naut = nauticals yd = yards


  • speed_knot (optional) Vessel speed used to estimate route duration.

    Default:

    24
    

    Unit: knots


  • append_orig_dest (optional) If True, the origin and destination coordinates will be appended to the returned LineString.

    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) If True, the algorithm includes the port of loading (POL) and port of discharge (POD) in the result.

    Default:

    False
    

  • port_params (optional) Additional configuration used when include_ports=True.

    Available options:

    • only_terminals Include only terminal ports. Default: False

    • country_pol ISO-2 country code used to select the Port of Loading (POL). If not provided, the closest port geographically will be selected.

      Example:

      "FR"
      
    • country_pod ISO-2 country code used to select the Port of Discharge (POD). If not provided, the closest port geographically will be selected.

    • country_restricted Filters out ports that define a to_cty attribute containing the same country code as country_pod.

      Default:

      False
      
    • ports_in_areas Overrides all previous port filtering rules and defines preferred ports within geographic areas.

      Must be created using:

      AreaFeature.create([...])
      

      Notes:

      • Preferred ports with share = 0 are ignored.
      • If multiple ports match, the function returns multiple GeoJSON routes.
    • ports_in_areas_from Same behavior as ports_in_areas, but applied only to the origin point (POL).

    • ports_in_areas_to Same behavior as ports_in_areas, but applied only to the destination point (POD).

    • strict_area Only relevant when using ports_in_areas, ports_in_areas_from, or ports_in_areas_to.

      Default:

      True
      

      Behavior:

      • 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) If True, 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_cty in 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_params for ports_in_areas
  • Fixed issue with returned passage when no path available #53
  • Updated README

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

searoute-1.5.0.tar.gz (1.0 MB view details)

Uploaded Source

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

Hashes for searoute-1.5.0.tar.gz
Algorithm Hash digest
SHA256 0d7f302503869b304f92c5ca6c53497934d412f60b759e1f3615b4cdc1680751
MD5 aa16a2c92f0da9f629f38484169dbea2
BLAKE2b-256 9c8b21c0c220c4938a60d8a497aaba4562d1b7ee4a00b243917a3524cb59aabc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page