def test_embed(): p3.clear() x, y, z = np.random.random((3, 100)) p3.scatter(x, y, z) p3.save("tmp/ipyolume_scatter_online.html", offline=False) assert os.path.getsize("tmp/ipyolume_scatter_online.html") > 0 p3.save("tmp/ipyolume_scatter_offline.html", offline=True, scripts_path='js/subdir') assert os.path.getsize("tmp/ipyolume_scatter_offline.html") > 0
def plot(self, width=800, height=600, voxel_count_offset=0, voxel_limit=None, use_centroids_instead=False, ipyvol_fig=None, scaling=1, **kwargs): """ This method needs better documentation. :param **kwargs: Is used in ipyvolume.pylab.scatter() or ipyvolume.pylab.plot() depending on whether use_centroids_instead is set to true or not. """ if ipyvol_fig is None: p3.figure(width=width, height=height) else: p3.figure(ipyvol_fig) voxels_length = len(self) if voxel_count_offset >= voxels_length: raise ValueError( "voxel_count_offset is greater than the number of voxels!") else: if voxel_limit is None: n_voxels_to_plot = len(self) else: n_voxels_to_plot = voxel_count_offset + voxel_limit if n_voxels_to_plot > voxels_length: n_voxels_to_plot = len(self) if use_centroids_instead: if 'marker' not in kwargs: kwargs['marker'] = 'sphere' if 'color' not in kwargs: kwargs['color'] = 'blue' if 'size' not in kwargs: kwargs['size'] = 0.5 p3.scatter( *self.centroids[voxel_count_offset:n_voxels_to_plot].T * scaling, **kwargs) else: voxel_count_offset *= 18 n_voxels_to_plot *= 18 drawable_bboxes = self.drawable_bboxes[ voxel_count_offset:n_voxels_to_plot] p3.plot(*drawable_bboxes.T * scaling, **kwargs) p3.squarelim() p3.show()
def test_bokeh(): from bokeh.io import output_notebook, show from bokeh.plotting import figure import ipyvolume.bokeh x, y, z = np.random.random((3, 100)) p3.figure() scatter = p3.scatter(x, y, z) tools = "wheel_zoom,box_zoom,box_select,lasso_select,help,reset," p = figure(title="E Lz space", tools=tools, webgl=True, width=500, height=500) r = p.circle(x, y, color="navy", alpha=0.2) ipyvolume.bokeh.link_data_source_selection_to_widget( r.data_source, scatter, 'selected') from bokeh.resources import CDN from bokeh.embed import components script, div = components(p) ipyvolume.embed.embed_html( "tmp/bokeh.html", [p3.gcc(), ipyvolume.bokeh.wmh], all=True, extra_script_head=script + CDN.render_js() + CDN.render_css(), body_pre="<h2>Do selections in 2d (bokeh)<h2>" + div + "<h2>And see the selection in ipyvolume<h2>")
def _scalar_handler(self, change): import ipyvolume.pylab as p3 array_name = change['owner'].owner pa_widgets = self._widgets.particles[array_name] new = change['new'] old = change['old'] if old == 'None' and new == 'None': pass elif old != 'None' and new == 'None': self.scatters[array_name].visible = False elif old != 'None' and new != 'None': colormap = getattr(mpl.cm, pa_widgets.scalar_cmap.value) data = self.get_frame(self._widgets.frame.value)['arrays'] c = colormap(getattr(data[array_name], pa_widgets.scalar.value)) self.scatters[array_name].color = c else: colormap = getattr(mpl.cm, pa_widgets.scalar_cmap.value) data = self.get_frame(self._widgets.frame.value)['arrays'] c = colormap(getattr(data[array_name], pa_widgets.scalar.value)) self.scatters[array_name] = p3.scatter( data[array_name].x, data[array_name].y, data[array_name].z, color=c, size=pa_widgets.scalar_size.value, ) self._legend_handler(None)
def show_spatial_series(node: SpatialSeries, **kwargs): data, unit = get_timeseries_in_units(node) tt = get_timeseries_tt(node) if len(data.shape) == 1: fig, ax = plt.subplots() ax.plot(tt, data, **kwargs) ax.set_xlabel('t (sec)') if unit: ax.set_xlabel('x ({})'.format(unit)) else: ax.set_xlabel('x') ax.set_ylabel('x') elif data.shape[1] == 2: fig, ax = plt.subplots() ax.plot(data[:, 0], data[:, 1], **kwargs) if unit: ax.set_xlabel('x ({})'.format(unit)) ax.set_ylabel('y ({})'.format(unit)) else: ax.set_xlabel('x') ax.set_ylabel('y') ax.axis('equal') elif data.shape[1] == 3: import ipyvolume.pylab as p3 fig = p3.figure() p3.scatter(data[:, 0], data[:, 1], data[:, 2], **kwargs) p3.xlim(np.min(data[:, 0]), np.max(data[:, 0])) p3.ylim(np.min(data[:, 1]), np.max(data[:, 1])) p3.zlim(np.min(data[:, 2]), np.max(data[:, 2])) else: raise NotImplementedError return fig
def init_vector(show=True): #This function initializes a figure with basis vectors in world frame - requires import ipyvolume.pylab as p3 outside scope #p3.clear() origin = np.array([0.0, 0.0, 0.0]) x = origin + np.array([1.0, 0.0, 0.0]) y = origin + np.array([0.0, 1.0, 0.0]) z = origin + np.array([0.0, 0.0, 1.0]) u = np.array([1.0, 0.0, 0.0]) v = np.array([0.0, 1.0, 0.0]) w = np.array([0.0, 0.0, 1.0]) quiver = p3.quiver(x, y, z, u, v, w, size=10, marker='arrow', color=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])) #ipv.show() scatter = p3.scatter(np.array([origin[0]]), np.array([origin[0]]), np.array([origin[0]]), size=5, marker='sphere', color='red') line1 = p3.plot(np.array([origin[0], x[0]]), np.array([origin[0], x[1]]), np.array([origin[0], x[2]]), color='red') line2 = p3.plot(np.array([origin[0], y[0]]), np.array([origin[0], y[1]]), np.array([origin[0], y[2]]), color='green') line3 = p3.plot(np.array([origin[0], z[0]]), np.array([origin[0], z[1]]), np.array([origin[0], z[2]]), color='blue') #scatter = p3.scatter(x,y,z,size=2,marker = 'sphere',color='red') # the origin if show: p3.show() p3.style.box_off() handle = { 'origin': scatter, 'arrows': quiver, 'linex': line1, 'liney': line2, 'linez': line3 } #p3.style.axes_off() return handle
def test_widgets_state(performance): try: _remove_buffers = None try: from ipywidgets.widgets.widget import _remove_buffers except: pass ipyvolume.serialize.performance = performance x, y, z = np.random.random((3, 100)) p3.figure() scatter = p3.scatter(x, y, z) state = scatter.get_state() if _remove_buffers: _remove_buffers(state) else: scatter._split_state_buffers(state) finally: ipyvolume.serialize.performance = 0
def interactive_plot(self): import ipyvolume.pylab as p3 self._create_widgets() self.scatters = {} self.vectors = {} self.legend = widgets.Output() with self.legend: self.pltfigure = plt.figure(figsize=(8, 8)) # creating a dummy figure, so that 'self.pltfigure.clf()' # in self._legend_handler() does not throw an error # during initialization p3.clear() data = self.get_frame(self._widgets.frame.value)['arrays'] for array_name in self._widgets.particles.keys(): pa_widgets = self._widgets.particles[array_name] if pa_widgets.scalar.value != 'None': colormap = getattr(mpl.cm, pa_widgets.scalar_cmap.value) c = colormap(getattr(data[array_name], pa_widgets.scalar.value)) self.scatters[array_name] = p3.scatter( data[array_name].x, data[array_name].y, data[array_name].z, color=c, size=pa_widgets.scalar_size.value, ) self.plot_container = p3.gcc() self.plot = p3.gcf() # used in 'self._save_figure_handler()' self._legend_handler(None) display( widgets.HBox( [widgets.VBox([self.plot]), widgets.VBox([self.legend])])) # HBox does not allow custom layout, therefore using an HBox # of two VBoxes to place 'plot' and 'legend' next to each other display(self._widgets._create_vbox())
def interactive_plot(self): self._create_widgets() self.scatters = {} display(self._widgets._create_vbox()) self.vectors = {} self.legend = widgets.Output() import ipyvolume.pylab as p3 p3.clear() data = self.get_frame(self._widgets.frame.value)['arrays'] for array_name in self._widgets.particles.keys(): pa_widgets = self._widgets.particles[array_name] colormap = getattr(mpl.cm, pa_widgets.scalar_cmap.value) c = colormap(getattr(data[array_name], pa_widgets.scalar.value)) self.scatters[array_name] = p3.scatter( data[array_name].x, data[array_name].y, data[array_name].z, color=c, size=pa_widgets.scalar_size.value, ) self._legend_handler(None) display(widgets.VBox((p3.gcc(), self.legend)))
def quickscatter(x, y, z, **kwargs): import ipyvolume.pylab as p3 p3.figure() p3.scatter(x, y, z, **kwargs) return p3.current.container
def test_scatter(): x, y, z = np.random.random((3, 100)) p3.scatter(x, y, z) p3.save("tmp/ipyolume_scatter.html")
def process_the_lidar(filename): # Get today's date, used for Nearmap data imagery. This way, the API will pull the latest image todays_date = datetime.datetime.today().strftime('%Y%m%d') trees = gpd.read_file(las_shapefile) # Name the output as the RBG plant id number lidarextension = filename.split('/')[-1].split('.')[0][-2:] lidarnumber = str(trees['RBGno'].loc[trees['LASfile'] == 'merged_0000' + str(lidarextension)].values[0]) if os.path.isfile( os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + 'meta.csv')): print(lidarnumber, '- Already has been run, skipping') else: df = import_lidar(filename) df = df.loc[df['tree_potential']] print(lidarnumber, "- Amount of tree points in dataframe:", len(df)) lep = local_max( df.loc[df['tree_potential'], ['X', 'Y', 'Z', 'HeightAboveGround', 'X_0', 'Y_0', 'Z_0']], radius=3, density_threshold=15) treetop_spheres = p3.scatter(lep['Y'], lep['Z'], lep['X'], color='black', size=.5, marker='sphere') # Cluster the trees. We're using KDTree method here. But something better could be used kdtree = scipy.spatial.kdtree.KDTree(lep[['X', 'Y', 'Z']]) dist, idx = kdtree.query(df.loc[df['tree_potential'], ['X', 'Y', 'Z']].values) df.loc[df['tree_potential'], 'tree_idx'] = idx # DBSCAN clustering alternative. This takes up too much memory when multiprocessing -- Python doesn't seem # garbage collect the lidar data and exceeds 32gb of RAM when using this. Although, will be ok when running # small LAS files individually. If used, comment out the last 3 lines and uncomment the next two. #dbscan = DBSCAN(eps=0.9, min_samples=7).fit(df.loc[df['tree_potential'],['X','Y','Z']].values) #df.loc[df['tree_potential'], 'tree_idx'] = dbscan.labels_ # Define centroid of XYZ plane centroid = df['Y'].mean(), df['Z'].mean(), df['X'].mean() # Calculate distance of tree top points to centroid, add their distance to lep tree_distances = [] for tree in lep.values.tolist(): tree_distances.append( euclid_dist(tree[0], tree[1], centroid[0], centroid[1])) lep['distance'] = tree_distances # Pull out tree top with the shorted distance to centroid. The index will be the tree id closest_treetop = lep[lep['distance'] == lep['distance'].min()] # Builds an entire dataframe which corresponds to the tree that matched in the closest_treetop search centre_tree_df = df.loc[df['tree_idx'] == df.loc[ closest_treetop.index[0]]['tree_idx']] # Get CRS of project from the shapefile of trees (caution: not the lidar) project_crs = trees.crs['init'] nearmap_crs = 'epsg:4326' # Reproject coordinate of tree to one suitable for Nearmap's API (WGS84/EPSG:4326) inProj = Proj(init=project_crs) outProj = Proj(init=nearmap_crs) x1, y1 = closest_treetop[['X_0', 'Y_0']].values[0][0], closest_treetop[[ 'X_0', 'Y_0' ]].values[0][1] x2, y2 = transform(inProj, outProj, x1, y1) # Tree's coordinates in WGS84 tree_coords_wgs84 = (x2, y2) tree_coords_wgs84utm = (x1, y1) print( lidarnumber, "- WGS84 UTM coordinates are:\t", str(tree_coords_wgs84utm[1]) + ',' + str(tree_coords_wgs84utm[0])) print(lidarnumber, "- WGS84 long coordinates are:\t", str(tree_coords_wgs84[1]) + ',' + str(tree_coords_wgs84[0])) if not os.path.isdir(os.path.join('.', output_folder)): os.makedirs(os.path.join('.', output_folder)) print(lidarnumber, "- Created folder", os.path.join('.', output_folder)) if not os.path.isdir(os.path.join('.', output_folder, 'lidar')): os.makedirs(os.path.join('.', output_folder, 'lidar')) print(lidarnumber, "- Created folder", os.path.join('.', output_folder, 'lidar')) # Volume and height of tree cloud (in cubic metres, expecting coordinate system is metres - UTM WGS84 in this case) tree_volume = round( scipy.spatial.ConvexHull(centre_tree_df[['X', 'Y', 'Z']]).volume, 2) tree_height = round(closest_treetop['HeightAboveGround'].values[0], 2) print(lidarnumber, "- Dimensions of the tree are:\t Volume:", str(tree_volume) + "m^3", "Height:", str(tree_height) + "m") # Save lidar 3D plot fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.dist = 8 ax.scatter(centre_tree_df['X'].values, centre_tree_df['Y'].values, centre_tree_df['Z'].values, zdir="z", s=1, marker='^') ax.view_init(elev=10., azim=0) fig.savefig(os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + '_plot0deg.jpg'), dpi=400) print( lidarnumber, "- Saved 0° plot to:\t\t", os.path.join('.', output_folder, 'lidar', lidarnumber + '_plot0deg.jpg')) ax.view_init(elev=10., azim=45) fig.savefig(os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + '_plot45deg.jpg'), dpi=400) print( lidarnumber, "- Saved 45° plot to:\t\t", os.path.join('.', output_folder, 'lidar', lidarnumber + '_plot45deg.jpg')) ax.view_init(elev=10., azim=90) fig.savefig(os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + '_plot90deg.jpg'), dpi=400) print( lidarnumber, "- Saved 90° plot to:\t\t", os.path.join('.', output_folder, 'lidar', lidarnumber + '_plot45deg.jpg')) plt.close() # Obtain nearmap imagery nearmap_url = "http://au0.nearmap.com/staticmap?center=" + str( tree_coords_wgs84[1] ) + "," + str( tree_coords_wgs84[0] ) + "&size=3000x3000&zoom=22&date=" + todays_date + "&httpauth=false&apikey=" + NEARMAP_API_KEY fn, _ = urllib.request.urlretrieve( nearmap_url, os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + '_aerial.jpg')) print( lidarnumber, "- Saved Nearmap imagery to:\t", os.path.join('.', output_folder, 'lidar', lidarnumber + '_aerial.jpg')) import csv with open( os.path.join(os.getcwd(), output_folder, 'lidar', lidarnumber + 'meta.csv'), 'w') as csvfile: lidar_metawriter = csv.writer(csvfile, delimiter=',') lidar_metawriter.writerow([ 'treenumber', 'long', 'lat', 'utm_x', 'utm_y', 'height', 'tree_volume' ]) lidar_metawriter.writerow([ lidarnumber, tree_coords_wgs84[0], tree_coords_wgs84[1], tree_coords_wgs84utm[0], tree_coords_wgs84utm[1], tree_height, tree_volume ]) print( lidarnumber, "- Written csv file: ./" + output_folder + "/lidar/" + lidarnumber + "meta.csv")
def create_ivol(vstruct, width=500, height=400, ssize=5, min_voxels=None, max_voxels=None, **volargs): """ Parameters ---------- vstruct: dict width: int height: int ssize: int min_voxels : int minimum number of voxels in density cube max_voxels : int maximum number of voxels in density cube volargs: dict Returns ------- Examples -------- >>> from jsonextended import edict >>> dstruct = { ... 'type': 'repeat_density', ... 'dtype': 'charge', ... 'name': '', ... 'dcube':np.ones((3,3,3)), ... 'centre':[0,0,0], ... 'cell_vectors':{ ... 'a':[2.,0,0], ... 'b':[0,2.,0], ... 'c':[0,0,2.]}, ... 'color_bbox': 'black', ... 'transforms': [] ... } >>> cstruct = { ... 'type': 'repeat_cell', ... 'name': '', ... 'centre':[0,0,0], ... 'cell_vectors':{ ... 'a':[2.,0,0], ... 'b':[0,2.,0], ... 'c':[0,0,2.]}, ... 'color_bbox': 'black', ... 'sites': [{ ... 'label': "Fe", ... 'ccoord': [1,1,1], ... 'color_fill': "red", ... 'color_outline': None, ... 'transparency': 1, ... 'radius': 1, ... }], ... 'bonds': [], ... 'transforms': [] ... } >>> vstruct = {"elements": [dstruct, cstruct], "transforms": []} >>> new_struct, fig, controls = create_ivol(vstruct) >>> print(edict.apply(edict.filter_keys(new_struct, ["ivol"], list_of_dicts=True), ... "ivol", lambda x: [v.__class__.__name__ for v in x], list_of_dicts=True)) {'elements': [{'ivol': ['Figure', 'Mesh']}, {'ivol': ['Mesh', 'Scatter']}]} """ new_struct = apply_transforms(vstruct) bonds = compute_bonds( new_struct ) #edict.filter_keyvals(vstruct, {"type": "repeat_cell"}, keep_siblings=True)) # ivolume currently only allows one volume rendering per plot # voltypes = edict.filter_keyvals(vstructs,[('type','repeat_density')]) vol_index = [ i for i, el in enumerate(vstruct['elements']) if el['type'] == 'repeat_density' ] assert len( vol_index) <= 1, "ipyvolume only allows one volume rendering per scene" p3.clear() fig = p3.figure(width=width, height=height, controls=True) fig.screen_capture_enabled = True # the volume rendering must be created first, # for appropriately scaled axis if vol_index: volstruct = new_struct['elements'][vol_index[0]] a = volstruct['cell_vectors']['a'] b = volstruct['cell_vectors']['b'] c = volstruct['cell_vectors']['c'] centre = volstruct['centre'] #print(centre) # convert dcube to cartesian out = cube_frac2cart(volstruct['dcube'], a, b, c, centre, max_voxels=max_voxels, min_voxels=min_voxels, make_cubic=True) new_density, (xmin, ymin, zmin), (xmax, ymax, zmax) = out vol = p3.volshow(new_density, **volargs) if volstruct["color_bbox"] is not None: a = np.asarray(a) b = np.asarray(b) c = np.asarray(c) o = np.asarray(centre) - 0.5 * (a + b + c) mesh = _create_mesh([ o, o + a, o + b, o + c, o + a + b, o + a + c, o + c + b, o + a + b + c ], color=volstruct["color_bbox"], line_indices=[[0, 1], [0, 2], [0, 3], [2, 4], [2, 6], [1, 4], [1, 5], [3, 5], [3, 6], [7, 6], [7, 4], [7, 5]]) vol = [vol, mesh] # todo better way of storing ivol components? volstruct['ivol'] = vol # appropriately scale axis p3.xlim(xmin, xmax) p3.ylim(ymin, ymax) p3.zlim(zmin, zmax) for element in new_struct['elements']: if element['type'] == 'repeat_density': continue elif element['type'] == 'repeat_cell': scatters = [] if element["color_bbox"] is not None: a = np.asarray(element['cell_vectors']['a']) b = np.asarray(element['cell_vectors']['b']) c = np.asarray(element['cell_vectors']['c']) centre = element['centre'] o = np.asarray(centre) - 0.5 * (a + b + c) mesh = _create_mesh([ o, o + a, o + b, o + c, o + a + b, o + a + c, o + c + b, o + a + b + c ], color=element["color_bbox"], line_indices=[[0, 1], [0, 2], [0, 3], [2, 4], [2, 6], [1, 4], [1, 5], [3, 5], [3, 6], [7, 6], [7, 4], [7, 5]]) scatters.append(mesh) for color, radius in set([(s['color_fill'], s['radius']) for s in element["sites"]]): scatter = edict.filter_keyvals(element, { "color_fill": color, "radius": radius }, "AND", keep_siblings=True, list_of_dicts=True) scatter = edict.combine_lists(scatter, ["sites"], deepcopy=False) scatter = edict.remove_keys(scatter, ["sites"], deepcopy=False) x, y, z = np.array(scatter['ccoord']).T s = p3.scatter(x, y, z, marker='sphere', size=ssize * radius, color=color) scatters.append(s) element['ivol'] = scatters elif element['type'] == 'repeat_poly': polys = [] for poly in element['polys']: mesh = _create_mesh(poly, element['color'], element['solid']) polys.append(mesh) element['ivol'] = polys else: raise ValueError("unknown element type: {}".format( element['type'])) for bond in bonds: p1, p2, c1, c2, radius = bond meshes = _create_bond(p1, p2, c1, c2, radius) # split up controls if vol_index: (level_ctrls, figbox, extractrl1, extractrl2) = p3.gcc().children controls = OrderedDict([('transfer function', [level_ctrls]), ('lighting', [extractrl1, extractrl2])]) else: # figbox = p3.gcc().children controls = {} return new_struct, fig, controls