Open Karenkkk-cell opened 2 years ago
import math
EPSILON = 1e-5
MAX_ALLOWED_LATITUDE = 85.0 MIN_ALLOWED_LATITUDE = -85.0
def latitude_bounds(latitudes): """ Estimate latitude bound with 2sample standard deviation """ if max(latitudes) - min(latitudes) < 2.0EPSILON: lower_bound = latitudes[0] - EPSILON upper_bound = latitudes[0] + EPSILON else: N = float(len(latitudes)) mean = sum(latitudes) / N sum_squares = sum( (latitude-mean)*2 for latitude in latitudes ) standard_deviation = math.sqrt(sum_squares/float(N)) lower_bound = max(mean - 2.0standard_deviation, -(90.0 - EPSILON)) upper_bound = min(mean + 2.0*standard_deviation, (90.0 - EPSILON)) lower_bound, upper_bound = _constrain_latitude_bounds( lower_bound, upper_bound) return lower_bound, upper_bound
def longitude_bounds(longitudes): """ Estimate longitude bound with 2*sample standard deviation
Note that longitudes wrap around, so have to use parameter
estimation for wrapped probability distribution.
See https://en.wikipedia.org/wiki/Wrapped_normal_distribution
and https://en.wikipedia.org/wiki/Directional_statistics
for how to calculate the relevant statistics.
"""
normalized_longitudes = [
_normalize_longitude(longitude) for longitude in longitudes
]
if max(normalized_longitudes) - min(normalized_longitudes) < 2.0*EPSILON:
mean_longitude = 0.5 * (
max(normalized_longitudes) + min(normalized_longitudes)
)
upper_bound = mean_longitude + EPSILON
lower_bound = mean_longitude - EPSILON
else:
N = float(len(longitudes))
radians = [
math.radians(longitude) for longitude in normalized_longitudes
]
sum_cos = sum(math.cos(r) for r in radians)
sum_cos_sq = sum_cos**2
sum_sin = sum(math.sin(r) for r in radians)
sum_sin_sq = sum_sin**2
mean_radians = math.atan2(sum_sin, sum_cos)
mean_degrees = math.degrees(mean_radians)
Rsq = (1/N**2) * (sum_cos_sq + sum_sin_sq)
standard_deviation = math.sqrt(-math.log(Rsq))
extent = 2.0*math.degrees(standard_deviation)
if extent > 180.0:
# longitudes cover entire map
upper_bound = 180.0 - EPSILON
lower_bound = -upper_bound
else:
lower_bound = _normalize_longitude(mean_degrees - extent)
upper_bound = _normalize_longitude(mean_degrees + extent)
return lower_bound, upper_bound
def merge_longitude_bounds(longitude_bounds_list): """ Return a single set of bounds that encompasses a list of bounds """
# I assume (lng0, lng1) in a layer's
# bounds means that the layer wants the map to
# cover all the longitudes that lie
# (going eastwards) from lng0 to lng1.
# For example: (170,-170) means we cover 20 degrees of
# latitude starting at 170 (through 180)
# Whereas (-170,170) means we start where the previous
# interval ended (at 170), go through lng 0, and eventually
# to 170 (340 degrees).
#
# As a side note, this definition means that (lng1,lng0) is
# the complement of (lng0,lng1) on this notation.
# It is important we have this direction information somehow,
# because otherwise the bounds are underspecified.
#
# As another side note, the meaning of (15, 30) in this notation
# is the same as that of (15+/-360, 30) and that of (15, 30 +/- 360),
# because we stop as soon as we hit the coordinate the first
# time.
#
# -180 180 = -180
# | >---------------> |
# | >-------> |
# | >-------------> |
# |-> >-------> >-----|
# 11000012223334433322221111100000000000000111111|
# ^ biggest empty range
# the bounds are then
# First we find which longitude ranges are feasible
# to cut (they have no range overlaps) by counting number of
# intervals that overlap and finding 0s.
# The initial condition (at -180)
# we find from counting how many intervals have west > east.
# then we go through our list.
# Of all the segments with a 0 count, the longest one
# is the one we should use to cut the map (here we
# have two choices)
# extract and normalize lngs from bounds (if they arent normalized)
directed_intervals = [
(_normalize_longitude(lower), _normalize_longitude(upper))
for lower, upper in longitude_bounds_list
]
# coverage is initially the number of wrap-around intervals. it can be 0.
coverage = sum(1 for lower, upper in directed_intervals if lower > upper)
starts = [(lower, 1) for (lower, _) in directed_intervals]
ends = [(upper, -1) for (_, upper) in directed_intervals]
endpoints = starts + ends
endpoints += [(x + 360, i) for (x, i) in endpoints]
# we repeat the longs shifted by 360 to handle gaps that overlap with 180
# without special-casing.
interleaved = sorted(endpoints)
# The largest clear gap we know of.
# We start by assuming there isn't one.
largest_gap = (-180.0, -180.0)
# current segment starts as -180
seg_start = -180.0
for (bnd, delta) in interleaved:
if coverage == 0 \
and (bnd - seg_start) > (largest_gap[1] - largest_gap[0]):
largest_gap = (seg_start, bnd)
seg_start = bnd
coverage += delta
assert(coverage >= 0)
# reversing the lng order in a gap gives us a valid bound
# the largest gap has the smallest bound
upper, lower = largest_gap
return _normalize_longitude(lower), _normalize_longitude(upper)
def _normalize_longitude(longitude): """ An equivalent longitude in the [-180,180) range """ longitude = longitude % 360 if longitude >= 180: longitude = longitude - 360
return longitude
def _constrain_latitude_bounds(lower_bound, upper_bound): if lower_bound < MIN_ALLOWED_LATITUDE: lower_bound = MIN_ALLOWED_LATITUDE if upper_bound < lower_bound + EPSILON: upper_bound = lower_bound + EPSILON if upper_bound > MAX_ALLOWED_LATITUDE: upper_bound = MAX_ALLOWED_LATITUDE if lower_bound > upper_bound - EPSILON: lower_bound = upper_bound - EPSILON return lower_bound, upper_bound return lower_bound, upper_bound
AssertionError Traceback (most recent call last) in ()
----> 1 drawRoute(locations_list['GB'], centers_list["GB"], shortestRoute_list["GB"])
11 frames in drawRoute(locations_list, C, route)
9 origin = locations_list[route[i]]
10 destination = locations_list[route[i+1]]
---> 11 map.add_layer(gmaps.directions_layer(origin , destination, stroke_color='blue' , show_markers=False , stroke_opacity=1.0, stroke_weight=1.0))
12
13 marker = gmaps.marker_layer(curr_locations)
/usr/local/lib/python3.7/dist-packages/gmaps/figure.py in add_layer(self, layer) 110 except AttributeError: 111 pass --> 112 self._map.add_layer(layer) 113 114
/usr/local/lib/python3.7/dist-packages/gmaps/maps.py in add_layer(self, layer) 199 200 def add_layer(self, layer): --> 201 self.layers = tuple([l for l in self.layers] + [layer]) 202 203 @default('layout')
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in set(self, obj, value) 604 raise TraitError('The "%s" trait is read-only.' % self.name) 605 else: --> 606 self.set(obj, value) 607 608 def _validate(self, obj, value):
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in set(self, obj, value) 2649 return super().set(obj, [value]) 2650 else: -> 2651 return super().set(obj, value) 2652 2653
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in set(self, obj, value) 593 # we explicitly compare silent to True just in case the equality 594 # comparison above returns something other than True/False --> 595 obj._notify_trait(self.name, old_value, new_value) 596 597 def set(self, obj, value):
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in _notify_trait(self, name, old_value, new_value) 1222 new=new_value, 1223 owner=self, -> 1224 type='change', 1225 )) 1226
/usr/local/lib/python3.7/dist-packages/ipywidgets/widgets/widget.py in notify_change(self, change) 684 # Send new state to front-end 685 self.send_state(key=name) --> 686 super(Widget, self).notify_change(change) 687 688 def repr(self):
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in notify_change(self, change) 1227 def notify_change(self, change): 1228 """Notify observers of a change event""" -> 1229 return self._notify_observers(change) 1230 1231 def _notify_observers(self, event):
/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in _notify_observers(self, event) 1264 c = getattr(self, c.name) 1265 -> 1266 c(event) 1267 1268 def _add_notifiers(self, handler, name, type):
/usr/local/lib/python3.7/dist-packages/gmaps/maps.py in _calc_bounds(self, change) 219 ] 220 min_longitude, max_longitude =\ --> 221 merge_longitude_bounds(longitude_bounds) 222 223 self.data_bounds = [
/usr/local/lib/python3.7/dist-packages/gmaps/bounds.py in merge_longitude_bounds(longitude_bounds_list) 147 seg_start = bnd 148 coverage += delta --> 149 assert(coverage >= 0) 150 151 # reversing the lng order in a gap gives us a valid bound
AssertionError: