-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vectorized functions #147
Vectorized functions #147
Changes from all commits
95d0ea5
5a094bf
1f18873
a66cbc1
6951ba4
471b9ab
e0314f5
b54523b
71aac1a
f3eb767
798b4bd
f2baf37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
cimport h3lib | ||
from h3lib cimport H3int | ||
from .util cimport deg2coord | ||
|
||
from cython cimport boundscheck, wraparound | ||
from libc.math cimport sqrt, sin, cos, asin | ||
|
||
cdef double haversineDistance(double th1, double ph1, double th2, double ph2) nogil: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this belong in this binding? I don't think we provide haversine distance support in any of the other bindings? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm considering anything under In the short term, this is hard to do anywhere except within the Cython bindings. In the future however, we could consider making it easy for folks to do this outside the Cython bindings, by letting them write their own Cython code which just does I'd say that's probably the way to go in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's pretty easy to make a vectorized # a, b arrays of hex ids
a_geo = h3_to_geo(a)
b_geo = h3_to_geo(b)
dist = haversine(a_geo, b_geo) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will expose a haversine function when uber/h3#377 lands: It would be easy to add that to the |
||
cdef: | ||
double dx, dy, dz | ||
double R = 6371.0088 | ||
|
||
ph1 -= ph2 | ||
|
||
dz = sin(th1) - sin(th2) | ||
dx = cos(ph1) * cos(th1) - cos(th2) | ||
dy = sin(ph1) * cos(th1) | ||
|
||
return asin(sqrt(dx*dx + dy*dy + dz*dz) / 2)*2*R | ||
|
||
|
||
@boundscheck(False) | ||
@wraparound(False) | ||
cpdef void haversine_vect( | ||
const H3int[:] a, | ||
const H3int[:] b, | ||
double[:] out | ||
) nogil: | ||
|
||
cdef h3lib.GeoCoord p1, p2 | ||
|
||
with nogil: | ||
# todo: add these back in when cython 3.0 comes out | ||
#assert len(a) == len(b) | ||
#assert len(a) <= len(out) | ||
|
||
for i in range(len(a)): | ||
h3lib.h3ToGeo(a[i], &p1) | ||
h3lib.h3ToGeo(b[i], &p2) | ||
out[i] = haversineDistance( | ||
p1.lat, p1.lng, | ||
p2.lat, p2.lng | ||
) | ||
|
||
@boundscheck(False) | ||
@wraparound(False) | ||
cpdef void geo_to_h3_vect( | ||
const double[:] lat, | ||
const double[:] lng, | ||
int res, | ||
H3int[:] out | ||
) nogil: | ||
|
||
cdef h3lib.GeoCoord c | ||
|
||
with nogil: | ||
for i in range(len(lat)): | ||
c = deg2coord(lat[i], lng[i]) | ||
out[i] = h3lib.geoToH3(&c, res) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ | |
) | ||
|
||
from . import v4 | ||
from . import vect |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from .._cy import unstable_vect as _vect | ||
|
||
import numpy as np | ||
|
||
|
||
def geo_to_h3(lats, lngs, res): | ||
""" | ||
Convert arrays describing lat/lng paris to cells. | ||
|
||
Parameters | ||
---------- | ||
lats, lngs : arrays of floats | ||
|
||
res: int | ||
Resolution for output cells. | ||
|
||
Returns | ||
------- | ||
array of H3Cells | ||
""" | ||
assert len(lats) == len(lngs) | ||
|
||
out = np.zeros(len(lats), dtype='uint64') | ||
|
||
_vect.geo_to_h3_vect(lats, lngs, res, out) | ||
|
||
return out | ||
|
||
|
||
def cell_haversine(a, b): | ||
""" | ||
Compute haversine distance between the centers of cells given in | ||
arrays a and b. | ||
|
||
|
||
Parameters | ||
---------- | ||
a, b : arrays of H3Cell | ||
|
||
Returns | ||
------- | ||
float | ||
Haversine distance in kilometers | ||
""" | ||
|
||
assert len(a) == len(b) | ||
|
||
out = np.zeros(len(a), dtype='double') | ||
|
||
_vect.haversine_vect(a, b, out) | ||
|
||
return out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you determine which functions get
nogil
? Is it just the ones you want to optimize right now?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just added it to the functions I needed it for in this PR. We could probably add
nogil
to each of the functions in the API, as thenogil
tag just promises that the function won't manipulate any Python objects, which is true for everything in theh3-c
API.I'll probably do a more thorough job of this when I tackle #140