Build Status

Introduction

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.

Motivation

Python is relatively slow; this type of conversion is usually carried out in bulk, so an order-of-magnitude improvement could save precious minutes

Instructions

Benchmark

An IPython (sorry, Jupyter) notebook with some benchmarks is here

Results

Simple Test

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

Real-world Test

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

Conclusion

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.

Accuracy

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.

Package

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.

Benchmark machine spec:

TODO

License

MIT

† Really, pyproj?
mediocre