class KMeansLayer(BaseLayer): def __init__(self, data): self.data = data self.k = 2 def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) k_means = KMeans(n_clusters=self.k) k_means.fit(np.vstack([x,y]).T) labels = k_means.labels_ self.cmap = create_set_cmap(set(labels), 'hsv') for l in set(labels): self.painter.set_color(self.cmap[l]) self.painter.convexhull(x[labels == l], y[labels == l]) self.painter.points(x[labels == l], y[labels == l], 2) def draw(self, proj, mouse_x, mouse_y, ui_manager): ui_manager.info('Use left and right to increase/decrease the number of clusters. k = %d' % self.k) self.painter.batch_draw() def on_key_release(self, key, modifiers): if key == pyglet.window.key.LEFT: self.k = max(2,self.k - 1) return True elif key == pyglet.window.key.RIGHT: self.k = self.k + 1 return True return False
class KMeansLayer(BaseLayer): def __init__(self, data): self.data = data def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) k_means = KMeans() k_means.fit(np.vstack([x,y]).T) labels = k_means.labels_ self.cmap = create_set_cmap(set(labels), 'hsv') for l in set(labels): try: self.painter.set_color(self.cmap[l]) self.painter.convexhull(x[labels == l], y[labels == l]) self.painter.points(x[labels == l], y[labels == l], 2) except Exception: print '=============',l,'==============' def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() def on_key_release(self, key, modifiers): return False
class TrailsLayer(BaseLayer): def __init__(self): self.data = read_csv('SLOCs.csv') self.cmap = colorbrewer(self.data['name'], alpha=220) self.t = self.data['timestamp'].min() self.painter = BatchPainter() def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 24*3600)) #set minimum time interval for name in set(df['name']): grp = df.where(df['name'] == name) self.painter.set_color('blue') #set color, default: self.cmap[name] x0, y0 = proj.lonlat_to_screen(grp['Slon'], grp['Slat']) x1, y1 = proj.lonlat_to_screen(grp['Flon'], grp['Flat']) self.painter.points(x0, y0, 3) self.painter.lines(x0,y0,x1,y1,width=3) self.t += 24*3600 #set animation step size if self.t > self.data['timestamp'].max(): self.t = self.data['timestamp'].min() self.painter.batch_draw() ui_manager.info(epoch_to_str(self.t)) def bbox(self): return BoundingBox(north=9, west=110, south=1, east=95) #set boundingbox
class ConvexHullLayer(BaseLayer): def __init__(self, data, col, fill=True, point_size=4): """ Convex hull for a set of points :param data: points :param col: color :param fill: whether to fill the convexhull polygon or not :param point_size: size of the points on the convexhull. Points are not rendered if None """ self.data = data self.col = col self.fill = fill self.point_size=point_size def invalidate(self, proj): self.painter = BatchPainter() self.painter.set_color(self.col) x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) if len(x) >= 3: self.painter.convexhull(x, y, self.fill) else: self.painter.linestrip(x, y) if self.point_size > 0: self.painter.points(x, y, self.point_size) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
class KMeansLayer(BaseLayer): def __init__(self, data): self.data = data self.k = 2 def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) k_means = KMeans(n_clusters=self.k) k_means.fit(np.vstack([x, y]).T) labels = k_means.labels_ self.cmap = create_set_cmap(set(labels), 'hsv') for l in set(labels): self.painter.set_color(self.cmap[l]) self.painter.convexhull(x[labels == l], y[labels == l]) self.painter.points(x[labels == l], y[labels == l], 2) def draw(self, proj, mouse_x, mouse_y, ui_manager): ui_manager.info( 'Use left and right to increase/decrease the number of clusters. k = %d' % self.k) self.painter.batch_draw() def on_key_release(self, key, modifiers): if key == pyglet.window.key.LEFT: self.k = max(2, self.k - 1) return True elif key == pyglet.window.key.RIGHT: self.k = self.k + 1 return True return False
class ConvexHullLayer(BaseLayer): def __init__(self, data, col, fill=True, point_size=4): """ Convex hull for a set of points :param data: points :param col: color :param fill: whether to fill the convexhull polygon or not :param point_size: size of the points on the convexhull. Points are not rendered if None """ self.data = data self.col = col self.fill = fill self.point_size = point_size def invalidate(self, proj): self.painter = BatchPainter() self.painter.set_color(self.col) x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) if len(x) >= 3: self.painter.convexhull(x, y, self.fill) else: self.painter.linestrip(x, y) if self.point_size > 0: self.painter.points(x, y, self.point_size) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
class TrailsLayer(BaseLayer): def __init__(self): self.data = read_csv('data/taxi.csv') self.cmap = colorbrewer(self.data['taxi_id'], alpha=220) self.t = self.data['timestamp'].min() self.painter = BatchPainter() def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 15*60)) for taxi_id in set(df['taxi_id']): grp = df.where(df['taxi_id'] == taxi_id) self.painter.set_color(self.cmap[taxi_id]) x, y = proj.lonlat_to_screen(grp['lon'], grp['lat']) self.painter.points(x, y, 10) self.t += 2*60 if self.t > self.data['timestamp'].max(): self.t = self.data['timestamp'].min() self.painter.batch_draw() ui_manager.info(epoch_to_str(self.t)) def bbox(self): return BoundingBox(north=40.110222, west=115.924463, south=39.705711, east=116.803369)
class TrailsLayer(BaseLayer): def __init__(self): self.data = read_csv('data/taxi.csv') self.cmap = colorbrewer(self.data['taxi_id'], alpha=220) self.t = self.data['timestamp'].min() self.painter = BatchPainter() def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 15 * 60)) for taxi_id in set(df['taxi_id']): grp = df.where(df['taxi_id'] == taxi_id) self.painter.set_color(self.cmap[taxi_id]) x, y = proj.lonlat_to_screen(grp['lon'], grp['lat']) self.painter.points(x, y, 10) self.t += 2 * 60 if self.t > self.data['timestamp'].max(): self.t = self.data['timestamp'].min() self.painter.batch_draw() ui_manager.info(epoch_to_str(self.t)) def bbox(self): return BoundingBox(north=40.110222, west=115.924463, south=39.705711, east=116.803369)
class TrailsLayer(BaseLayer): def __init__(self): self.data = read_csv('alex.csv') self.cmap = colorbrewer(self.data['runner_id'], alpha=220) self.t = self.data['timestamp'].min() self.painter = BatchPainter() def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 15 * 60)) for taxi_id in set(df['runner_id']): grp = df.where(df['runner_id'] == taxi_id) self.painter.set_color(self.cmap[taxi_id]) x, y = proj.lonlat_to_screen(grp['lon'], grp['lat']) self.painter.points(x, y, 10) self.t += 2 * 60 if self.t > self.data['timestamp'].max(): self.t = self.data['timestamp'].min() self.painter.batch_draw() ui_manager.info(epoch_to_str(self.t)) # this should get modified as well moving forward def bbox(self): return BoundingBox(north=37.801421, west=-122.517339, south=37.730097, east=-122.424474)
class DotDensityLayer(BaseLayer): def __init__(self, data, color=None, point_size=2, f_tooltip=None): """Create a dot density map :param data: data access object :param color: color :param point_size: point size :param f_tooltip: function to return a tooltip string for a point """ self.frame_counter = 0 self.data = data self.color = color if self.color is None: self.color = [255,0,0] self.point_size = point_size self.f_tooltip = f_tooltip self.hotspots = HotspotManager() def invalidate(self, proj): self.x, self.y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) if self.f_tooltip: for i in range(0, len(x)): record = {k: self.data[k][i] for k in self.data.keys()} self.hotspots.add_rect(x[i] - self.point_size, y[i] - self.point_size, 2*self.point_size, 2*self.point_size, self.f_tooltip(record)) self.color= "blue" #random.choice(foo) self.painter.set_color(self.color) self.painter.points(x[self.frame_counter], y[self.frame_counter], 2*self.point_size, False) self.painter.batch_draw() picked = self.hotspots.pick(mouse_x, mouse_y) if picked: ui_manager.tooltip(picked) self.frame_counter += 1 time.sleep(0.4) if self.frame_counter == len(x): self.frame_counter = 0 def bbox(self): return BoundingBox.from_points(lons=self.data['lon'], lats=self.data['lat'])
class PointsLayer(BaseLayer): def __init__(self, data, color, point_size): self.data = data self.color = color self.point_size = point_size def invalidate(self, proj): x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.painter = BatchPainter() self.painter.set_color(self.color) self.painter.points(x, y, point_size=self.point_size, rounded=True) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
class AnimatedLayer(BaseLayer): """ geoplotlib 动画类图层 """ def __init__(self, data): self.data = data self.frame_counter = 0 def invalidate(self, proj): self.x, self.y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() self.painter.points(self.x[self.frame_counter], self.y[self.frame_counter]) self.painter.batch_draw() self.frame_counter += 1
class DotDensityLayer(BaseLayer): def __init__(self, data, color=None, point_size=2, f_tooltip=None): """Create a dot density map :param data: data access object :param color: color :param point_size: point size :param f_tooltip: function to return a tooltip string for a point """ self.data = data self.color = color if self.color is None: self.color = [255,0,0] self.point_size = point_size self.f_tooltip = f_tooltip self.hotspots = HotspotManager() def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) if self.f_tooltip: for i in range(0, len(x)): record = {k: self.data[k][i] for k in self.data.keys()} self.hotspots.add_rect(x[i] - self.point_size, y[i] - self.point_size, 2*self.point_size, 2*self.point_size, self.f_tooltip(record)) self.painter.set_color(self.color) self.painter.points(x, y, 2*self.point_size, False) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() picked = self.hotspots.pick(mouse_x, mouse_y) if picked: ui_manager.tooltip(picked) def bbox(self): return BoundingBox.from_points(lons=self.data['lon'], lats=self.data['lat'])
class GeoJSONLayer(BaseLayer): def __init__(self, geojson_or_fname, color='b', linewidth=1, fill=False, f_tooltip=None): self.color = color self.linewidth = linewidth self.fill = fill self.f_tooltip = f_tooltip if type(geojson_or_fname) == str: with open(geojson_or_fname) as fin: self.data = json.load(fin) elif type(geojson_or_fname) == dict: self.data = geojson_or_fname else: raise Exception('must provide either dict or filename') self.boundingbox = None for feature in self.data['features']: if feature['geometry']['type'] == 'Polygon': for poly in feature['geometry']['coordinates']: poly = np.array(poly) self.__update_bbox(poly[:, 0], poly[:, 1]) elif feature['geometry']['type'] == 'MultiPolygon': for multipoly in feature['geometry']['coordinates']: for poly in multipoly: poly = np.array(poly) self.__update_bbox(poly[:, 0], poly[:, 1]) elif feature['geometry']['type'] == 'Point': lon, lat = feature['geometry']['coordinates'] self.__update_bbox(np.array([lon]), np.array([lat])) elif feature['geometry']['type'] == 'LineString': line = np.array(feature['geometry']['coordinates']) self.__update_bbox(line[:, 0], line[:, 1]) def __update_bbox(self, lon, lat): if self.boundingbox is None: self.boundingbox = BoundingBox(north=lat.max(), south=lat.min(), west=lon.min(), east=lon.max()) else: self.boundingbox = BoundingBox(north=max(self.boundingbox.north, lat.max()), south=min(self.boundingbox.south, lat.min()), west=min(self.boundingbox.west, lon.min()), east=max(self.boundingbox.east, lon.max())) def invalidate(self, proj): self.painter = BatchPainter() self.hotspots = HotspotManager() for feature in self.data['features']: if isfunction(self.color): self.painter.set_color(self.color(feature['properties'])) else: self.painter.set_color(self.color) if feature['geometry']['type'] == 'Polygon': for poly in feature['geometry']['coordinates']: poly = np.array(poly) x, y = proj.lonlat_to_screen(poly[:, 0], poly[:, 1]) if self.fill: self.painter.poly(x, y) else: self.painter.linestrip(x, y, self.linewidth, closed=True) if self.f_tooltip: self.hotspots.add_poly( x, y, self.f_tooltip(feature['properties'])) elif feature['geometry']['type'] == 'MultiPolygon': for multipoly in feature['geometry']['coordinates']: for poly in multipoly: poly = np.array(poly) x, y = proj.lonlat_to_screen(poly[:, 0], poly[:, 1]) if self.fill: self.painter.poly(x, y) else: self.painter.linestrip(x, y, self.linewidth, closed=True) if self.f_tooltip: self.hotspots.add_poly( x, y, self.f_tooltip(feature['properties'])) elif feature['geometry']['type'] == 'Point': lon, lat = feature['geometry']['coordinates'] x, y = proj.lonlat_to_screen(np.array([lon]), np.array([lat])) self.painter.points(x, y) elif feature['geometry']['type'] == 'LineString': line = np.array(feature['geometry']['coordinates']) x, y = proj.lonlat_to_screen(line[:, 0], line[:, 1]) self.painter.linestrip(x, y, self.linewidth, closed=False) else: print(('unknow geometry %s' % feature['geometry']['type'])) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() picked = self.hotspots.pick(mouse_x, mouse_y) if picked: ui_manager.tooltip(picked) def bbox(self): if self.boundingbox: return self.boundingbox else: return BoundingBox.WORLD
class LineLayer(layers.BaseLayer): """ Draws line connecting points in hurricane path """ def __init__(self, data, num, color=None, point_size=2, linewidth=1, f_tooltip=None): """ Creates a LineLayer for the python geoplotlib library :param data: DataAccessObject of latitudes and longitudes :param num: number of data points in dat :param color: color of lines, just to red if none :param point_size: size of points :param linewidth: width of lines :param f_tooltip: an attribute of geoplotlib's BaseLayer that is not used """ self.data = data self.indexlst = num self.color = color if self.color is None: self.color = [255, 0, 0] self.point_size = point_size self.f_tooltip = f_tooltip self.linewidth = linewidth self.hotspots = HotspotManager() def invalidate(self, proj): """ This method is called each time layers need to be redrawn, i.e. on zoom. Typically in this method a BatchPainter is instantiated and all the rendering is performed :param proj: the current Projector object """ self.painter = BatchPainter() self.painter.set_color(self.color) x1, y1 = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.painter.points(x1, y1, 2 * self.point_size, False) for i in self.indexlst: if i < len(self.data['lon']) - 1: x1 = self.data['lon'][i] y1 = self.data['lat'][i] x2 = self.data['lon'][i+1] y2 = self.data['lat'][i+1] x1, y1 = proj.lonlat_to_screen(x1, y1) x2, y2 = proj.lonlat_to_screen(x2, y2) self.painter.lines(x1, y1, x2, y2, width=self.linewidth) if self.f_tooltip: for i in range(0, len(x1)): record = {k: self.data[k][i] for k in self.data.keys()} self.hotspots.add_rect(x1[i] - self.point_size, y1[i] - self.point_size, 2 * self.point_size, 2 * self.point_size, self.f_tooltip(record)) def draw(self, proj, mouse_x, mouse_y, ui_manager): """ This method is called at every frame, and typically executes BatchPainter.batch_draw() :param proj: the current Projector object :param mouse_x: mouse x :param mouse_y: mouse y :param ui_manager: the current UiManager """ self.painter.batch_draw() picked = self.hotspots.pick(mouse_x, mouse_y) if picked: ui_manager.tooltip(picked) def bbox(self): """ Return the bounding box for this layer """ return BoundingBox.from_points(lons=self.data['lon'], lats=self.data['lat']) def on_key_release(self, key, modifiers): """ Override this method for custom handling of keystrokes :param key: the key that has been released :param modifiers: the key modifiers :return: True if the layer needs to call invalidate """ return False
class AnimatedProcess(BaseLayer): def __init__(self, network, edgelists, show_addresses=False, save_frames=False, line_width=1.3): # Set network and edge lists. self.network = network self.edgelists = edgelists self.num_frames = len(self.edgelists) # Set flag specifying whether to show addresses. self.show_addresses = show_addresses # Set flag specifying whether to save frames. self.save_frames = save_frames # Set line width. self.line_width = line_width # Initialize state counter. self.count = 0 # Initialize geolocator for retrieving addresses. geolocator = Nominatim(user_agent='test') # Set coordinates of nodes and get addresses. self.node_coordinates = np.empty((2, network.number_of_nodes()), dtype=float) self.node_addresses = [] for idx, node in enumerate(network.nodes()): self.node_coordinates[:, idx] = np.array(self.network.nodes[node]['latlon']) if self.show_addresses: address = geolocator.reverse(self.node_coordinates[:, idx]).address self.node_addresses.append(address[:address.index(',', address.index(',') + 1)]) def invalidate(self, proj): self.x, self.y = proj.lonlat_to_screen(self.node_coordinates[1, :], self.node_coordinates[0, :]) def draw(self, proj, mouse_x, mouse_y, ui_manager): # Prepare edges for next frame. self.edge_src = np.empty((2, len(self.edgelists[self.count])), dtype=float) self.edge_dst = np.empty((2, len(self.edgelists[self.count])), dtype=float) for idx, edge in enumerate(self.edgelists[self.count]): self.edge_src[:, idx] = self.network.nodes[edge[0]]['latlon'] self.edge_dst[:, idx] = self.network.nodes[edge[1]]['latlon'] self.edge_src_trans_x, self.edge_src_trans_y = proj.lonlat_to_screen(self.edge_src[1, :], self.edge_src[0, :]) self.edge_dst_trans_x, self.edge_dst_trans_y = proj.lonlat_to_screen(self.edge_dst[1, :], self.edge_dst[0, :]) # Initialize painter, plot nodes and addresses. self.painter = BatchPainter() self.painter.points(self.x, self.y, point_size=10, rounded=True) if self.show_addresses: self.painter.labels(self.x, self.y, self.node_addresses, font_size=10, anchor_x='left') # Plot edges. self.painter.set_color([255, 0, 0]) self.painter.lines(self.edge_src_trans_x, self.edge_src_trans_y, self.edge_dst_trans_x, self.edge_dst_trans_y, width=self.line_width) # Draw and increment counter. self.painter.batch_draw() if self.count < len(self.edgelists) - 1: self.count += 1 self.count = self.count % self.num_frames print("count: {0}/{1}".format(self.count, self.num_frames)) # If saving frames. if self.save_frames: GeoplotlibApp.screenshot(f'./results/animation_frames/{self.count}.png')
class GeoJSONLayer(BaseLayer): def __init__(self, geojson_or_fname, color='b', linewidth=1, fill=False, f_tooltip=None): self.color = color self.linewidth = linewidth self.fill = fill self.f_tooltip = f_tooltip if type(geojson_or_fname) == str: with open(geojson_or_fname) as fin: self.data = json.load(fin) elif type(geojson_or_fname) == dict: self.data = geojson_or_fname else: raise Exception('must provide either dict or filename') self.boundingbox = None for feature in self.data['features']: if feature['geometry']['type'] == 'Polygon': for poly in feature['geometry']['coordinates']: poly = np.array(poly) self.__update_bbox(poly[:,0], poly[:,1]) elif feature['geometry']['type'] == 'MultiPolygon': for multipoly in feature['geometry']['coordinates']: for poly in multipoly: poly = np.array(poly) self.__update_bbox(poly[:,0], poly[:,1]) elif feature['geometry']['type'] == 'Point': lon,lat = feature['geometry']['coordinates'] self.__update_bbox(np.array([lon]), np.array([lat])) elif feature['geometry']['type'] == 'LineString': line = np.array(feature['geometry']['coordinates']) self.__update_bbox(line[:,0], line[:,1]) def __update_bbox(self, lon, lat): if self.boundingbox is None: self.boundingbox = BoundingBox(north=lat.max(), south=lat.min(), west=lon.min(), east=lon.max()) else: self.boundingbox = BoundingBox( north=max(self.boundingbox.north, lat.max()), south=min(self.boundingbox.south, lat.min()), west=min(self.boundingbox.west, lon.min()), east=max(self.boundingbox.east, lon.max())) def invalidate(self, proj): self.painter = BatchPainter() self.hotspots = HotspotManager() for feature in self.data['features']: if isfunction(self.color): self.painter.set_color(self.color(feature['properties'])) else: self.painter.set_color(self.color) if feature['geometry']['type'] == 'Polygon': for poly in feature['geometry']['coordinates']: poly = np.array(poly) x, y = proj.lonlat_to_screen(poly[:,0], poly[:,1]) if self.fill: self.painter.poly(x, y) else: self.painter.linestrip(x, y, self.linewidth, closed=True) if self.f_tooltip: self.hotspots.add_poly(x, y, self.f_tooltip(feature['properties'])) elif feature['geometry']['type'] == 'MultiPolygon': for multipoly in feature['geometry']['coordinates']: for poly in multipoly: poly = np.array(poly) x, y = proj.lonlat_to_screen(poly[:,0], poly[:,1]) if self.fill: self.painter.poly(x, y) else: self.painter.linestrip(x, y, self.linewidth, closed=True) if self.f_tooltip: self.hotspots.add_poly(x, y, self.f_tooltip(feature['properties'])) elif feature['geometry']['type'] == 'Point': lon,lat = feature['geometry']['coordinates'] x, y = proj.lonlat_to_screen(np.array([lon]), np.array([lat])) self.painter.points(x, y) elif feature['geometry']['type'] == 'LineString': line = np.array(feature['geometry']['coordinates']) x, y = proj.lonlat_to_screen(line[:,0], line[:,1]) self.painter.linestrip(x, y, self.linewidth, closed=False) else: print('unknow geometry %s' % feature['geometry']['type']) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() picked = self.hotspots.pick(mouse_x, mouse_y) if picked: ui_manager.tooltip(picked) def bbox(self): if self.boundingbox: return self.boundingbox else: return BoundingBox.WORLD