Skip to content

Instantly share code, notes, and snippets.

@rdmurphy
Last active November 1, 2015 19:50
Show Gist options
  • Save rdmurphy/f4407b3b1ebffc940b1d to your computer and use it in GitHub Desktop.
Save rdmurphy/f4407b3b1ebffc940b1d to your computer and use it in GitHub Desktop.
A test run of adding basic geographic features to agate.
#!/usr/bin/env python
from agate.computations import Computation
from agate.data_types import Number
from agate.exceptions import DataTypeError
from agategeo.utils import haversine
class Distance(Computation):
"""
Computes the distance from a given point.
"""
def __init__(self, point, longitude_column_name, latitude_column_name):
self._point = point
self._latitude_column_name = latitude_column_name
self._longitude_column_name = longitude_column_name
def get_computed_data_type(self, table):
return Number()
def prepare(self, table):
latitude_column = table.columns[self._latitude_column_name]
longitude_column = table.columns[self._longitude_column_name]
if not isinstance(latitude_column.data_type, Number):
raise DataTypeError('Distance latitude column must contain Number data.')
if not isinstance(longitude_column.data_type, Number):
raise DataTypeError('Distance longitude column must contain Number data.')
def run(self, row):
return haversine(self._point, [
row[self._longitude_column_name], row[self._latitude_column_name]])
#!/usr/bin/env python
from agate.table import allow_tableset_proxy
from agategeo.utils import haversine
class TableGeo(object):
@allow_tableset_proxy
def nearest(self, point, longitude_key, latitude_key):
nearest_row = None
for row in self._rows:
distance = haversine(point, (
row[longitude_key], row[latitude_key]))
if not nearest_row:
nearest_row = (row, distance)
else:
if distance < nearest_row[1]:
nearest_row = (row, distance)
return nearest_row[0]
#!/usr/bin/env python
"""
This module contains a collection of utility classes and functions used in
agate-geo.
"""
from math import atan2, cos, pow, radians, sin, sqrt
def haversine(point_1, point_2, measurement='kilometers'):
dlat = radians(point_2[1] - point_1[1])
dlon = radians(point_2[0] - point_1[0])
lat1 = radians(point_1[1])
lat2 = radians(point_2[1])
a = pow(sin(dlat / 2), 2) + pow(sin(dlon / 2), 2) * cos(lat1) * cos(lat2)
c = 2 * atan2(sqrt(a), sqrt(1 - a))
if measurement in ('kilometers', 'km', 'kms'):
earth_radius = 6371
elif measurement in ('miles', 'mi', 'mis'):
earth_radius = 3959
else:
raise ValueError('A valid measurement type must be provided.')
return earth_radius * c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment