Karenkkk-cell / py

0 stars 0 forks source link

Assertion error: reversing the lng order in a gap gives us a valid bound #1

Open Karenkkk-cell opened 2 years ago

Karenkkk-cell commented 2 years ago

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:

Karenkkk-cell commented 2 years ago

import math

EPSILON = 1e-5

GoogleMaps imposes latitude restrictions

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