An attempt at speeding up the conversion between decimal longitude and latitude and British National Grid (epsg:27700) coordinates, using an external Rust binary and Python FFI.
Python is relatively slow; this type of conversion is usually carried out in bulk, so an order-of-magnitude improvement could save precious minutes
cargo build --release
from the repo rootipython notebook
, and open rust_BNG
.An IPython (sorry, Jupyter) notebook with some benchmarks is here
Python: 10000 loops, best of 10: 31 µs per loop
Rust: 100000 loops, best of 10: 2.04 µs per loop* 💅
Pyproj: 100000 loops, best of 10: 11.8 µs per loop†
*Test warns that intermediate results may have been cached
Convert 100,000 sets of random coordinates
Python: 1 loops, best of 10: 804 ms per loop
Rust: 1 loops, best of 10: 204 ms per loop
Pyproj: 10 loops, best of 10: 99.5 ms per loop 💅
Rust (threaded): 10 loops, best of 10: 162.5 ms per loop
Using multithreading, we can get much closer (pyproj is now only 65% faster). Not bad, considering the relative youth of Rust as a language (let alone this library), and the maturity of the PROJ.4 project.
The Helmert transform used is accurate to within 4 – 5 metres, so this library is not suitable for calculations used in e.g. surveying. If higher accuracy is required, please use a product which incorporates the OSTN02 calculations, which adjust for local variation within the Terrestrial Reference Frame. See here for more information.
convert_bng
is available from PyPI:
pip install convertbng
Usage:
from convertbng.util import convertbng, convertbng_list
res = convertbng(lon, lat)
lons = [lon1, lon2, lon3]
lats = [lat1, lat2, lat3]
# assumes import numpy as np
lons_np = np.array(lons)
lats_np = np.array(lats)
res_list = convertbng_list(lons, lats)
res_list_np = convertbng_list(lons_np, lats_np)
Note that the return type for convertbng_list()
is always a list of tuples.
MIT