Mercurial > hg > GlobalNeighbors
annotate globalneighbors/distance.py @ 18:87ae70245201
ubuntu wants .conf, redhat wants ini of course
author | Jeff Hammel <k0scist@gmail.com> |
---|---|
date | Sun, 25 Jun 2017 15:13:29 -0700 |
parents | 27925261c137 |
children | 811adc9736eb |
rev | line source |
---|---|
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
1 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
2 distance functionality |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
3 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
4 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
5 import argparse |
8 | 6 import bisect |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
7 import json |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
8 import sys |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
9 import time |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
10 from math import asin, sin, cos, sqrt, pi, fabs |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
11 from .cli import CitiesParser |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
12 from .constants import Rearth |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
13 from .locations import locations |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
14 from .read import read_cities |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
15 from .schema import fields |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
16 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
17 DEGREESTORADIANS = pi/180. |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
18 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
19 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
20 def haversine(lat1, lon1, lat2, lon2, r=1): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
21 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
22 see |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
23 https://en.wikipedia.org/wiki/Haversine_formula |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
24 Coordinates in radians |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
25 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
26 return 2*r*asin( |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
27 sqrt(sin(0.5*(lat2-lat1))**2 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
28 +cos(lat1)*cos(lat2)*(sin(0.5*(lon2-lon1))**2) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
29 )) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
30 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
31 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
32 def deg_to_rad(degrees): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
33 return degrees*DEGREESTORADIANS |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
34 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
35 |
5
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
36 def insert_distance(distances, i, new_distance, k): |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
37 """ |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
38 insert `(i, new_distance)` into `distances` |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
39 keeping distances in order with maximum of size `k` |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
40 """ |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
41 |
7
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
42 if len(distances) == k and new_distance >= distances[-1][-1]: |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
43 return |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
44 |
5
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
45 # TODO: Binary Search Tree |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
46 for _index, (geoid, old_distance) in enumerate(distances): |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
47 if new_distance < old_distance: |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
48 distances.insert(_index, (i, new_distance)) |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
49 if len(distances) == k+1: |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
50 distances.pop() |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
51 break |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
52 else: |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
53 distances.append((i, new_distance)) |
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
54 |
9
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
55 |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
56 class KeyWrapper(object): |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
57 """wrapper for python's `bisect` methods""" |
8 | 58 def __init__(self, iterable, key): |
59 self.it = iterable | |
60 self.key = key | |
61 | |
62 def __getitem__(self, i): | |
63 return self.key(self.it[i]) | |
64 | |
65 def __len__(self): | |
66 return len(self.it) | |
7
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
67 |
9
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
68 |
7
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
69 def insert_distance_bisect(distances, i, new_distance, k): |
8 | 70 |
7
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
71 if not distances: |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
72 distances.append((i, new_distance)) |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
73 return |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
74 if new_distance >= distances[-1][-1]: |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
75 if len(distances) < k: |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
76 distances.append((i, new_distance)) |
254195d0bac2
partial implementation of autocomplete using jqueryui; easyautocomplete.com may be more what we want
Jeff Hammel <k0scist@gmail.com>
parents:
6
diff
changeset
|
77 return |
6 | 78 |
8 | 79 point = bisect.bisect_left(KeyWrapper(distances, |
80 key=lambda x: x[-1]), | |
81 new_distance) | |
82 distances.insert(point, (i, new_distance)) | |
83 if len(distances) == k+1: | |
84 distances.pop() | |
5
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
85 |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
86 def calculate_distances(locations, r=Rearth): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
87 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
88 WARNING! This is an N-squared approach |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
89 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
90 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
91 # convert to rad |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
92 rad_locations = [(location, tuple([deg_to_rad(i) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
93 for i in latlon])) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
94 for location, latlon |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
95 in locations.items()] |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
96 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
97 # use haversince function on N-body problem |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
98 for index, loc1 in enumerate(rad_locations): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
99 id1, (lat1, lon1) = loc1 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
100 for loc2 in rad_locations[index+1:]: |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
101 id2, (lat2, lon2) = loc2 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
102 key = (id1, id2) if id2 > id1 else (id2, id1) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
103 yield (key, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
104 haversine(lat1, lon1, lat2, lon2, r=r)) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
105 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
106 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
107 def calculate_neighbors(locations, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
108 k=10, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
109 lat_tol=1., |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
110 lon_tol=1., |
3 | 111 output=None, |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
112 neighbors=None): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
113 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
114 calculate `k` nearest neighbors for each location |
3 | 115 |
116 locations -- dict of `geoid: (lat, lon)` | |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
117 """ |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
118 neighbors = neighbors or {} |
3 | 119 items = locations.items() # copy |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
120 index = 0 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
121 n_items = len(items) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
122 start = int(time.time()) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
123 while items: |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
124 index += 1 |
3 | 125 if output and not index % output: |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
126 # output status counter |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
127 now = int(time.time()) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
128 duration = now - start |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
129 start = now |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
130 print ('{},{},{},{}'.format(index, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
131 len(items), |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
132 n_items, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
133 duration)) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
134 id1, (lat1, lon1) = items.pop() |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
135 for loc2 in items: |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
136 id2, (lat2, lon2) = loc2 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
137 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
138 # filter out locations based on latlon boxing |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
139 if fabs(lat2 - lat1) > lat_tol: |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
140 continue |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
141 if fabs(lon2 - lon1) > lon_tol: |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
142 continue |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
143 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
144 # determine distance |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
145 args = [deg_to_rad(i) for i in |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
146 (lat1, lon1, lat2, lon2)] |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
147 new_distance = haversine(*args, r=Rearth) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
148 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
149 # insert in order |
14
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
150 ids = (id1, id2) |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
151 for i in (0, 1): |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
152 distances = neighbors.setdefault(ids[i], []) |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
153 insert_distance_bisect(distances, |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
154 ids[i-1], |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
155 new_distance, |
27925261c137
fix broken tests including an aggregious case where we add ourselves as a neighbor to ourself
Jeff Hammel <k0scist@gmail.com>
parents:
9
diff
changeset
|
156 k) |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
157 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
158 return neighbors |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
159 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
160 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
161 def main(args=sys.argv[1:]): |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
162 """CLI""" |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
163 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
164 # parse command line arguments |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
165 description = """write nearest neighborfiles""" |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
166 parser = CitiesParser(description=description) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
167 parser.add_argument('output', type=argparse.FileType('w'), |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
168 help="output file to dump JSON to") |
9
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
169 parser.add_argument('--latlon', dest='latlon', type=float, |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
170 nargs=2, metavar=("LAT", "LON"), |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
171 default=(1., 1.), |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
172 help="tolerance of latitude and longitude in degrees [DEFAULT: %(default)s]") |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
173 parser.add_argument('--counter', '--output-counter', |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
174 dest='output_counter', |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
175 type=int, default=100, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
176 help="how often to output progress updates [DEFAULT: %(default)s]") |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
177 parser.add_argument('-k', dest='k', |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
178 type=int, default=50, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
179 help="number of neighbors to determine [DEFAULT: %(default)s]") |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
180 options = parser.parse_args(args) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
181 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
182 # parse cities |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
183 cities = list(read_cities(options.cities, fields=fields)) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
184 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
185 # get locations |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
186 city_locations = locations(cities) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
187 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
188 # calculate neighbors |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
189 neighbors = calculate_neighbors(city_locations, |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
190 k=options.k, |
9
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
191 lat_tol=options.latlon[0], |
638fad06e556
use bisect function; it has been tested faster
Jeff Hammel <k0scist@gmail.com>
parents:
8
diff
changeset
|
192 lon_tol=options.latlon[-1], |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
193 output=options.output_counter) |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
194 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
195 # output |
5
7e27e874655b
test a larger grid + move distance insertion to its own function
Jeff Hammel <k0scist@gmail.com>
parents:
3
diff
changeset
|
196 options.output.write(json.dumps(neighbors)) |
0
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
197 |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
198 if __name__ == '__main__': |
5dba84370182
initial commit; half-working prototype
Jeff Hammel <k0scist@gmail.com>
parents:
diff
changeset
|
199 main() |