def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.data['_xbin'] = (x / self.binsize).astype(int) self.data['_ybin'] = (y / self.binsize).astype(int) uniquevalues = set([ tuple(row) for row in np.vstack([self.data['_xbin'], self.data['_ybin']]).T ]) results = {(v1,v2): self.f_group(self.data.where((self.data['_xbin'] == v1) & (self.data['_ybin'] == v2))) \ for v1, v2 in uniquevalues} del self.data['_xbin'] del self.data['_ybin'] self.hotspot = HotspotManager() if self.scalemax: self.vmax = self.scalemax else: self.vmax = max(results.values()) if len(results) > 0 else 0 if self.vmax >= 1: for (ix, iy), value in list(results.items()): if value > self.scalemin: self.painter.set_color( self.cmap.to_color(value, self.vmax, self.colorscale)) l = self.binsize rx = ix * self.binsize ry = iy * self.binsize self.painter.rect(rx, ry, rx + l, ry + l) if self.show_tooltip: self.hotspot.add_rect(rx, ry, l, l, 'Value: %d' % value)
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()
def invalidate(self, proj): self.painter = BatchPainter() x0, y0 = proj.lonlat_to_screen(self.data[self.src_lon], self.data[self.src_lat]) x1, y1 = proj.lonlat_to_screen(self.data[self.dest_lon], self.data[self.dest_lat]) if type(self.color) == list: self.painter.set_color(self.color) self.painter.lines(x0, y0, x1, y1, width=self.linewidth) else: if self.color_by == 'distance': manhattan = np.abs(x0-x1) + np.abs(y0-y1) vmax = manhattan.max() segmentations = np.logspace(0, log10(vmax), 20) self.seg_scale = 'log' else: manhattan = self.data[self.color_by] vmax = manhattan.max() if self.seg_scale == 'log': # value 20 maybe should be optional segmentations = np.logspace(0, log10(vmax), 20) else: # linear segmentations = np.linspace(0, vmax ,20) for i in range(len(segmentations)-1, 1, -1): mask = (manhattan > segmentations[i-1]) & (manhattan <= segmentations[i]) self.painter.set_color(self.cmap.to_color(segmentations[i], vmax, self.seg_scale)) self.painter.lines(x0[mask], y0[mask], x1[mask], y1[mask], width=self.linewidth)
def invalidate(self, proj): try: from scipy.spatial.qhull import Voronoi except ImportError: print('VoronoiLayer needs scipy >= 0.12') raise x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) points = zip(x,y) vor = Voronoi(points) regions, vertices = VoronoiLayer.__voronoi_finite_polygons_2d(vor) self.hotspots = HotspotManager() self.painter = BatchPainter() for idx, region in enumerate(regions): polygon = vertices[region] if self.line_color: self.painter.set_color(self.line_color) self.painter.linestrip(polygon[:,0], polygon[:,1], width=self.line_width, closed=True) if self.cmap: area = VoronoiLayer._get_area(polygon.tolist()) area = max(area, 1) self.painter.set_color(self.cmap.to_color(area, self.max_area, 'log')) self.painter.poly(polygon[:,0], polygon[:,1]) if self.f_tooltip: record = {k: self.data[k][idx] for k in self.data.keys()} self.hotspots.add_poly(polygon[:,0], polygon[:,1], self.f_tooltip(record))
def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) w = x.max() - x.min() h = y.max() - y.min() w = np.ceil(w / 2) * 2 h = np.ceil(h / 2) * 2 l = max(w, h) root = QuadTree(x.min(), x.min() + l, y.min() + l, y.min()) maxarea = (root.right - root.left) * (root.top - root.bottom) queue = [root] done = [] while len(queue) > 0: qt = queue.pop() if qt.can_split(x, y): queue.extend(qt.split()) else: done.append(qt) print((len(queue), len(done))) if self.cmap is not None: for qt in done: area = (qt.right - qt.left) * (qt.top - qt.bottom) self.painter.set_color( self.cmap.to_color(1 + area, 1 + maxarea, 'log')) self.painter.rect(qt.left, qt.top, qt.right, qt.bottom) else: for qt in done: self.painter.linestrip([qt.left, qt.right, qt.right, qt.left], [qt.top, qt.top, qt.bottom, qt.bottom], closed=True)
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()
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')
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 invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.painter.set_color(self.color) self.painter.labels(x, y, self.data[self.label_column], font_name=self.font_name, font_size=self.font_size, anchor_x=self.anchor_x, anchor_y=self.anchor_y)
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 invalidate(self, proj): self.painter = BatchPainter() self.hotspots = HotspotManager() self.painter.set_color(self.color) if self.worker: self.worker.stop() self.worker.join() self.queue = Queue.Queue() self.worker = ShapeLoadingThread(self.queue, self.reader, self.shape_type, proj) self.worker.start()
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 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']))
class GraphLayer(BaseLayer): def __init__(self, data, src_lat, src_lon, dest_lat, dest_lon, linewidth=1, alpha=220, color='hot'): """Create a graph drawing a line between each pair of (src_lat, src_lon) and (dest_lat, dest_lon) :param data: data access object :param src_lat: field name of source latitude :param src_lon: field name of source longitude :param dest_lat: field name of destination latitude :param dest_lon: field name of destination longitude :param linewidth: line width :param alpha: color alpha :param color: color or colormap """ self.data = data self.src_lon = src_lon self.src_lat = src_lat self.dest_lon = dest_lon self.dest_lat = dest_lat self.linewidth = linewidth alpha = alpha self.color = color if type(self.color) == str: self.cmap = colors.ColorMap(self.color, alpha) def invalidate(self, proj): self.painter = BatchPainter() x0, y0 = proj.lonlat_to_screen(self.data[self.src_lon], self.data[self.src_lat]) x1, y1 = proj.lonlat_to_screen(self.data[self.dest_lon], self.data[self.dest_lat]) if type(self.color) == list: self.painter.set_color(self.color) self.painter.lines(x0, y0, x1, y1, width=self.linewidth) else: manhattan = np.abs(x0-x1) + np.abs(y0-y1) vmax = manhattan.max() distances = np.logspace(0, log10(manhattan.max()), 20) for i in range(len(distances)-1, 1, -1): mask = (manhattan > distances[i-1]) & (manhattan <= distances[i]) self.painter.set_color(self.cmap.to_color(distances[i], vmax, 'log')) self.painter.lines(x0[mask], y0[mask], x1[mask], y1[mask], width=self.linewidth) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() def bbox(self): return BoundingBox.from_points(lons=np.hstack([self.data[self.src_lon], self.data[self.dest_lon]]), lats=np.hstack([self.data[self.src_lat], self.data[self.dest_lat]]))
def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() self.painter.set_color([0,0,255]) df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 30*60)) proj.fit(BoundingBox.from_points(lons=df['lon'], lats=df['lat']), max_zoom=14) x, y = proj.lonlat_to_screen(df['lon'], df['lat']) self.painter.linestrip(x, y, 10) self.t += 30 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 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)
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 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
def invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.lon_edges, self.lat_edges) rects = [] cols = [] for ix in range(len(xv)-1): for iy in range(len(yv)-1): d = self.values[iy, ix] if d > self.vmin: rects.append((xv[ix], yv[iy], xv[ix+1], yv[iy+1])) cols.append(self.cmap.to_color(d, self.vmax, self.colormap_scale)) self.painter.batch_rects(rects, cols)
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
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 list(self.data.keys())} self.hotspots.add_rect(x[i] - self.marker_preferred_size / 2, y[i] - self.marker_preferred_size / 2, self.marker_preferred_size, self.marker_preferred_size, self.f_tooltip(record)) self.painter.sprites(self.marker, x, y, self.scale)
class MarkersLayer(BaseLayer): def __init__(self, data, marker, f_tooltip=None, marker_preferred_size=32): """ Draw markers :param data: data access object :param marker: full filename of the marker image :param f_tooltip: function to generate a tooltip on mouseover :param marker_preferred_size: size in pixel for the marker images """ self.data = data self.f_tooltip = f_tooltip self.marker_preferred_size = float(marker_preferred_size) self.marker = pyglet.image.load(marker) self.marker.anchor_x = self.marker.width / 2 self.marker.anchor_y = self.marker.height / 2 self.scale = self.marker_preferred_size / max(self.marker.width, self.marker.height) 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.marker_preferred_size/2, y[i] - self.marker_preferred_size/2, self.marker_preferred_size, self.marker_preferred_size, self.f_tooltip(record)) self.painter.sprites(self.marker, x, y, self.scale) 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'])
def invalidate(self, proj): try: from scipy.spatial.qhull import Delaunay except ImportError: print('DelaunayLayer needs scipy >= 0.12') raise self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) points = list(set(zip(x, y))) dela = Delaunay(points) edges = set() for tria in dela.vertices: edges.add((tria[0], tria[1])) edges.add((tria[1], tria[2])) edges.add((tria[2], tria[0])) allx0 = [] ally0 = [] allx1 = [] ally1 = [] colors = [] for a, b in edges: x0, y0 = dela.points[a] x1, y1 = dela.points[b] allx0.append(x0) ally0.append(y0) allx1.append(x1) ally1.append(y1) if self.line_color: colors.append(self.line_color) colors.append(self.line_color) elif self.cmap: l = math.sqrt((x0 - x1)**2 + (y0 - y1)**2) c = self.cmap.to_color(l, self.max_lenght, 'log') colors.append(c) colors.append(c) self.painter.lines(allx0, ally0, allx1, ally1, colors, width=self.line_width)
def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.data['_xbin'] = (x / self.binsize).astype(int) self.data['_ybin'] = (y / self.binsize).astype(int) uniquevalues = set([tuple(row) for row in np.vstack([self.data['_xbin'],self.data['_ybin']]).T]) results = {(v1,v2): self.f_group(self.data.where((self.data['_xbin'] == v1) & (self.data['_ybin'] == v2))) \ for v1, v2 in uniquevalues} del self.data['_xbin'] del self.data['_ybin'] self.hotspot = HotspotManager() if self.scalemax: vmax = self.scalemax else: vmax = max(results.values()) if len(results) > 0 else 0 if vmax >= 1: for (ix, iy), value in results.items(): if value > self.scalemin: self.painter.set_color(self.cmap.to_color(value, vmax, self.colorscale)) l = self.binsize rx = ix * self.binsize ry = iy * self.binsize self.painter.rect(rx, ry, rx+l, ry+l) if self.show_tooltip: self.hotspot.add_rect(rx, ry, l, l, 'Value: %d' % value)
def invalidate(self, proj): try: from scipy.spatial.qhull import Voronoi except ImportError: print('VoronoiLayer needs scipy >= 0.12') raise x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) points = list(set(zip(x,y))) vor = Voronoi(points) regions, vertices = VoronoiLayer.__voronoi_finite_polygons_2d(vor) self.hotspots = HotspotManager() self.painter = BatchPainter() for idx, region in enumerate(regions): polygon = vertices[region] if self.line_color: self.painter.set_color(self.line_color) self.painter.linestrip(polygon[:,0], polygon[:,1], width=self.line_width, closed=True) if self.cmap: area = VoronoiLayer._get_area(polygon.tolist()) area = max(area, 1) self.painter.set_color(self.cmap.to_color(area, self.max_area, 'log')) self.painter.poly(polygon[:,0], polygon[:,1]) if self.f_tooltip: record = {k: self.data[k][idx] for k in self.data.keys()} self.hotspots.add_poly(polygon[:,0], polygon[:,1], self.f_tooltip(record))
def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) w = x.max() - x.min() h = y.max() - y.min() w = np.ceil(w / 2) * 2 h = np.ceil(h / 2) * 2 l = max(w, h) root = QuadTree(x.min(), x.min() + l, y.min() + l, y.min()) maxarea = (root.right - root.left) * (root.top - root.bottom) queue = [root] done = [] while len(queue) > 0: qt = queue.pop() if qt.can_split(x, y): queue.extend(qt.split()) else: done.append(qt) print len(queue), len(done) if self.cmap is not None: for qt in done: area = (qt.right - qt.left) * (qt.top - qt.bottom) self.painter.set_color(self.cmap.to_color(1 + area, 1 + maxarea, 'log')) self.painter.rect(qt.left, qt.top, qt.right, qt.bottom) else: for qt in done: self.painter.linestrip([qt.left, qt.right, qt.right, qt.left], [qt.top, qt.top, qt.bottom, qt.bottom], closed=True)
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))
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
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))
class GridLayer(BaseLayer): def __init__(self, lon_edges, lat_edges, values, cmap, alpha=255, vmin=None, vmax=None): self.lon_edges = lon_edges self.lat_edges = lat_edges self.values = values self.cmap = colors.ColorMap(cmap, alpha=alpha) if vmin: self.vmin = vmin else: self.vmin = 0 if vmax: self.vmax = vmax else: self.vmax = self.values.max() def invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.lon_edges, self.lat_edges) rects = [] cols = [] for ix in range(len(xv) - 1): for iy in range(len(yv) - 1): d = self.values[iy, ix] if d > self.vmin: rects.append((xv[ix], yv[iy], xv[ix + 1], yv[iy + 1])) cols.append(self.cmap.to_color(d, self.vmax, 'lin')) self.painter.batch_rects(rects, cols) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
def invalidate(self, proj): self.painter = BatchPainter() x0, y0 = proj.lonlat_to_screen(self.data[self.src_lon], self.data[self.src_lat]) x1, y1 = proj.lonlat_to_screen(self.data[self.dest_lon], self.data[self.dest_lat]) manhattan = np.abs(x0 - x1) + np.abs(y0 - y1) vmax = manhattan.max() distances = np.logspace(0, log10(manhattan.max()), 20) for i in range(len(distances) - 1, 1, -1): mask = (manhattan > distances[i - 1]) & (manhattan <= distances[i]) if type(self.color) == list: self.painter.set_color(self.color) else: self.painter.set_color( self.cmap.to_color(distances[i], vmax, 'log')) self.painter.lines(x0[mask], y0[mask], x1[mask], y1[mask], width=self.linewidth)
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
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 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)
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 invalidate(self, proj): self.painter = BatchPainter() x0, y0 = proj.lonlat_to_screen(self.data[self.src_lon], self.data[self.src_lat]) x1, y1 = proj.lonlat_to_screen(self.data[self.dest_lon], self.data[self.dest_lat]) manhattan = np.abs(x0-x1) + np.abs(y0-y1) vmax = manhattan.max() distances = np.logspace(0, log10(manhattan.max()), 20) for i in range(len(distances)-1, 1, -1): mask = (manhattan > distances[i-1]) & (manhattan <= distances[i]) if type(self.color) == list: self.painter.set_color(self.color) else: self.painter.set_color(self.cmap.to_color(distances[i], vmax, 'log')) self.painter.lines(x0[mask], y0[mask], x1[mask], y1[mask], width=self.linewidth)
def invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.lon_edges, self.lat_edges) rects = [] cols = [] for ix in range(len(xv)-1): for iy in range(len(yv)-1): d = self.values[iy, ix] if d > self.vmin: rects.append((xv[ix], yv[iy], xv[ix+1], yv[iy+1])) cols.append(self.cmap.to_color(d, self.vmax, 'lin')) self.painter.batch_rects(rects, cols)
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.marker_preferred_size/2, y[i] - self.marker_preferred_size/2, self.marker_preferred_size, self.marker_preferred_size, self.f_tooltip(record)) self.painter.sprites(self.marker, x, y, self.scale)
class GridLayer(BaseLayer): def __init__(self, lon_edges, lat_edges, values, cmap, alpha=255, vmin=None, vmax=None): self.lon_edges = lon_edges self.lat_edges = lat_edges self.values = values self.cmap = colors.ColorMap(cmap, alpha=alpha) if vmin: self.vmin = vmin else: self.vmin = 0 if vmax: self.vmax = vmax else: self.vmax = self.values.max() def invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.lon_edges, self.lat_edges) rects = [] cols = [] for ix in range(len(xv)-1): for iy in range(len(yv)-1): d = self.values[iy, ix] if d > self.vmin: rects.append((xv[ix], yv[iy], xv[ix+1], yv[iy+1])) cols.append(self.cmap.to_color(d, self.vmax, 'lin')) self.painter.batch_rects(rects, cols) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
class QuadsLayer(BaseLayer): def __init__(self, data, cmap='hot_r'): self.data = data if cmap is not None: self.cmap = geoplotlib.colors.ColorMap(cmap, alpha=196) else: self.cmap = None def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) w = x.max() - x.min() h = y.max() - y.min() w = np.ceil(w / 2) * 2 h = np.ceil(h / 2) * 2 l = max(w, h) root = QuadTree(x.min(), x.min() + l, y.min() + l, y.min()) maxarea = (root.right - root.left) * (root.top - root.bottom) queue = [root] done = [] while len(queue) > 0: qt = queue.pop() if qt.can_split(x, y): queue.extend(qt.split()) else: done.append(qt) print len(queue), len(done) if self.cmap is not None: for qt in done: area = (qt.right - qt.left) * (qt.top - qt.bottom) self.painter.set_color(self.cmap.to_color(1 + area, 1 + maxarea, 'log')) self.painter.rect(qt.left, qt.top, qt.right, qt.bottom) else: for qt in done: self.painter.linestrip([qt.left, qt.right, qt.right, qt.left], [qt.top, qt.top, qt.bottom, qt.bottom], closed=True) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
class QuadsLayer(BaseLayer): def __init__(self, data, cmap='hot_r'): self.data = data if cmap is not None: self.cmap = geoplotlib.colors.ColorMap(cmap, alpha=196) else: self.cmap = None def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) w = x.max() - x.min() h = y.max() - y.min() w = np.ceil(w / 2) * 2 h = np.ceil(h / 2) * 2 l = max(w, h) root = QuadTree(x.min(), x.min() + l, y.min() + l, y.min()) maxarea = (root.right - root.left) * (root.top - root.bottom) queue = [root] done = [] while len(queue) > 0: qt = queue.pop() if qt.can_split(x, y): queue.extend(qt.split()) else: done.append(qt) print((len(queue), len(done))) if self.cmap is not None: for qt in done: area = (qt.right - qt.left) * (qt.top - qt.bottom) self.painter.set_color( self.cmap.to_color(1 + area, 1 + maxarea, 'log')) self.painter.rect(qt.left, qt.top, qt.right, qt.bottom) else: for qt in done: self.painter.linestrip([qt.left, qt.right, qt.right, qt.left], [qt.top, qt.top, qt.bottom, qt.bottom], closed=True) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()
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 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 invalidate(self, proj): try: from scipy.spatial.qhull import Delaunay except ImportError: print('DelaunayLayer needs scipy >= 0.12') raise self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) points = list(set(zip(x,y))) dela = Delaunay(points) edges = set() for tria in dela.vertices: edges.add((tria[0], tria[1])) edges.add((tria[1], tria[2])) edges.add((tria[2], tria[0])) allx0 = [] ally0 = [] allx1 = [] ally1 = [] colors = [] for a, b in edges: x0, y0 = dela.points[a] x1, y1 = dela.points[b] allx0.append(x0) ally0.append(y0) allx1.append(x1) ally1.append(y1) if self.line_color: colors.append(self.line_color) colors.append(self.line_color) elif self.cmap: l = math.sqrt((x0 - x1)**2+(y0 - y1)**2) c = self.cmap.to_color(l, self.max_lenght, 'log') colors.append(c) colors.append(c) self.painter.lines(allx0, ally0, allx1, ally1, colors, width=self.line_width)
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 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 LabelsLayer(BaseLayer): def __init__(self, data, label_column, color=None, font_name=FONT_NAME, font_size=14, anchor_x='left', anchor_y='top'): """Create a layer with a text label for each sample :param data: data access object :param label_column: column in the data access object where the labels text is stored :param color: color :param font_name: font name :param font_size: font size :param anchor_x: anchor x :param anchor_y: anchor y """ self.data = data self.label_column = label_column self.color = color self.font_name = font_name self.font_size = font_size self.anchor_x = anchor_x self.anchor_y = anchor_y if self.color is None: self.color = [255,0,0] def invalidate(self, proj): self.painter = BatchPainter() x, y = proj.lonlat_to_screen(self.data['lon'], self.data['lat']) self.painter.set_color(self.color) self.painter.labels(x, y, self.data[self.label_column], font_name=self.font_name, font_size=self.font_size, anchor_x=self.anchor_x, anchor_y=self.anchor_y) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw() def bbox(self): return BoundingBox.from_points(lons=self.data['lon'], lats=self.data['lat'])
class TrailsLayer(BaseLayer): def __init__(self): self.data = read_csv('data/taxi.csv') self.data = self.data.where(self.data['taxi_id'] == list(set(self.data['taxi_id']))[2]) self.t = self.data['timestamp'].min() self.painter = BatchPainter() def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter = BatchPainter() self.painter.set_color([0,0,255]) df = self.data.where((self.data['timestamp'] > self.t) & (self.data['timestamp'] <= self.t + 30*60)) proj.fit(BoundingBox.from_points(lons=df['lon'], lats=df['lat']), max_zoom=14) x, y = proj.lonlat_to_screen(df['lon'], df['lat']) self.painter.linestrip(x, y, 10) self.t += 30 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 invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.values['lon'], self.values['lat']) rects_vertices = [] rects_colors = [] if self.method == 'kde': try: import statsmodels.api as sm except: raise Exception('KDE requires statsmodel') kde_res = sm.nonparametric.KDEMultivariate(data=[xv, yv], var_type='cc', bw=self.bw) xgrid, ygrid = self._get_grid(proj) xmesh, ymesh = np.meshgrid(xgrid,ygrid) grid_coords = np.append(xmesh.reshape(-1,1), ymesh.reshape(-1,1),axis=1) z = kde_res.pdf(grid_coords.T) z = z.reshape(len(ygrid), len(xgrid)) # np.save('z.npy', z) # z = np.load('z.npy') print('smallest non-zero density:', z[z > 0][0]) print('max density:', z.max()) if self.cut_below is None: zmin = z[z > 0][0] else: zmin = self.cut_below if self.clip_above is None: zmax = z.max() else: zmax = self.clip_above for ix in range(len(xgrid)-1): for iy in range(len(ygrid)-1): if z[iy, ix] > zmin: rects_vertices.append((xgrid[ix], ygrid[iy], xgrid[ix+1], ygrid[iy+1])) rects_colors.append(self.cmap.to_color(z[iy, ix], zmax, self.scaling)) elif self.method == 'hist': try: from scipy.ndimage import gaussian_filter except: raise Exception('KDE requires scipy') xgrid, ygrid = self._get_grid(proj) H, _, _ = np.histogram2d(yv, xv, bins=(ygrid, xgrid)) H = gaussian_filter(H, sigma=self.bw) print('smallest non-zero count', H[H > 0][0]) print('max count:', H.max()) if self.cut_below is None: Hmin = H[H > 0][0] else: Hmin = self.cut_below if self.clip_above is None: Hmax = H.max() else: Hmax = self.clip_above if self.scaling == 'ranking': from statsmodels.distributions.empirical_distribution import ECDF ecdf = ECDF(H.flatten()) for ix in range(len(xgrid)-2): for iy in range(len(ygrid)-2): if H[iy, ix] > Hmin: rects_vertices.append((xgrid[ix], ygrid[iy], xgrid[ix+1], ygrid[iy+1])) if self.scaling == 'ranking': rects_colors.append(self.cmap.to_color(ecdf(H[iy, ix]) - ecdf(Hmin), 1 - ecdf(Hmin), 'lin')) else: rects_colors.append(self.cmap.to_color(H[iy, ix], Hmax, self.scaling)) else: raise Exception('method not supported') self.painter.batch_rects(rects_vertices, rects_colors)
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 __init__(self): self.data = read_csv('data/taxi.csv') self.data = self.data.where(self.data['taxi_id'] == list(set(self.data['taxi_id']))[2]) self.t = self.data['timestamp'].min() self.painter = BatchPainter()
class KDELayer(BaseLayer): def __init__(self, values, bw, cmap='hot', method='hist', scaling='sqrt', alpha=220, cut_below=None, clip_above=None, binsize=1, cmap_levels=10): """ Kernel density estimation visualization :param data: data access object :param bw: kernel bandwidth (in screen coordinates) :param cmap: colormap :param method: if kde use KDEMultivariate from statsmodel, which provides a more accurate but much slower estimation. If hist, estimates density applying gaussian smoothing on a 2D histogram, which is much faster but less accurate :param scaling: colorscale, lin log or sqrt :param alpha: color alpha :param cut_below: densities below cut_below are not drawn :param clip_above: defines the max value for the colorscale :param binsize: size of the bins for hist estimator :param cmap_levels: discretize colors into cmap_levels """ self.values = values self.bw = bw self.cmap = colors.ColorMap(cmap, alpha=alpha, levels=cmap_levels) self.method = method self.scaling = scaling self.cut_below = cut_below self.clip_above = clip_above self.binsize = binsize def _get_grid(self, proj): west, north = proj.lonlat_to_screen([proj.bbox().west], [proj.bbox().north]) east, south = proj.lonlat_to_screen([proj.bbox().east], [proj.bbox().south]) xgrid = np.arange(west, east, self.binsize) ygrid = np.arange(south, north, self.binsize) return xgrid, ygrid def invalidate(self, proj): self.painter = BatchPainter() xv, yv = proj.lonlat_to_screen(self.values['lon'], self.values['lat']) rects_vertices = [] rects_colors = [] if self.method == 'kde': try: import statsmodels.api as sm except: raise Exception('KDE requires statsmodel') kde_res = sm.nonparametric.KDEMultivariate(data=[xv, yv], var_type='cc', bw=self.bw) xgrid, ygrid = self._get_grid(proj) xmesh, ymesh = np.meshgrid(xgrid,ygrid) grid_coords = np.append(xmesh.reshape(-1,1), ymesh.reshape(-1,1),axis=1) z = kde_res.pdf(grid_coords.T) z = z.reshape(len(ygrid), len(xgrid)) # np.save('z.npy', z) # z = np.load('z.npy') print('smallest non-zero density:', z[z > 0][0]) print('max density:', z.max()) if self.cut_below is None: zmin = z[z > 0][0] else: zmin = self.cut_below if self.clip_above is None: zmax = z.max() else: zmax = self.clip_above for ix in range(len(xgrid)-1): for iy in range(len(ygrid)-1): if z[iy, ix] > zmin: rects_vertices.append((xgrid[ix], ygrid[iy], xgrid[ix+1], ygrid[iy+1])) rects_colors.append(self.cmap.to_color(z[iy, ix], zmax, self.scaling)) elif self.method == 'hist': try: from scipy.ndimage import gaussian_filter except: raise Exception('KDE requires scipy') xgrid, ygrid = self._get_grid(proj) H, _, _ = np.histogram2d(yv, xv, bins=(ygrid, xgrid)) H = gaussian_filter(H, sigma=self.bw) print('smallest non-zero count', H[H > 0][0]) print('max count:', H.max()) if self.cut_below is None: Hmin = H[H > 0][0] else: Hmin = self.cut_below if self.clip_above is None: Hmax = H.max() else: Hmax = self.clip_above if self.scaling == 'ranking': from statsmodels.distributions.empirical_distribution import ECDF ecdf = ECDF(H.flatten()) for ix in range(len(xgrid)-2): for iy in range(len(ygrid)-2): if H[iy, ix] > Hmin: rects_vertices.append((xgrid[ix], ygrid[iy], xgrid[ix+1], ygrid[iy+1])) if self.scaling == 'ranking': rects_colors.append(self.cmap.to_color(ecdf(H[iy, ix]) - ecdf(Hmin), 1 - ecdf(Hmin), 'lin')) else: rects_colors.append(self.cmap.to_color(H[iy, ix], Hmax, self.scaling)) else: raise Exception('method not supported') self.painter.batch_rects(rects_vertices, rects_colors) def draw(self, proj, mouse_x, mouse_y, ui_manager): self.painter.batch_draw()