def plot_old(self, plot_points=False, mark_peaks=0): ''' Plot the points on the sphere with their values ''' from scipy import rand import matplotlib.colors as colors #from mpl_toolkits.mplot3d import Axes3D import mpl_toolkits.mplot3d as a3 import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111, projection='3d') if plot_points: ax.scatter(self.x, self.y, self.z, c='b', marker='o') if mark_peaks > 0: id = self.find_peaks(k=mark_peaks) s = 1.05 ax.scatter(s * self.x[id], s * self.y[id], s * self.z[id], c='k', marker='o') voronoi = sp.SphericalVoronoi(self.cartesian.T) voronoi.sort_vertices_of_regions() if self.values is not None: col_max = self.values.max() col_min = self.values.min() if col_min != col_max: col_map = (self.values - col_min) / (col_max - col_min) else: col_map = self.values / col_max else: col_map = np.zeros(self.n_points) cmap = plt.get_cmap('coolwarm') # plot the walls for v_ind, col in zip(voronoi.regions, col_map): triangle = a3.art3d.Poly3DCollection([voronoi.vertices[v_ind]], alpha=1., linewidth=0.0) triangle.set_color(cmap(col)) triangle.set_edgecolor('k') ax.add_collection3d(triangle) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_xlim([-1, 1]) ax.set_ylim([-1, 1]) ax.set_zlim([-1, 1])
def get_area_weights(self, balance_axes: bool = True): """return the weight of each point associated with the unit cell size Args: balance_axes (bool): Flag determining whether the weights should be chosen such that the weighted average of all points is the zero vector Returns: :class:`~numpy.ndarray`: The weight associated with each point """ from scipy import spatial points_flat = self.points.reshape(-1, self.dim) if self.dim == 1: assert points_flat.shape == (2, 1) weights = np.array([0.5, 0.5]) elif self.dim == 2: # get angles φ = np.arctan2(points_flat[:, 1], points_flat[:, 0]) idx = np.argsort(φ) s0 = φ[idx[0]] + 2 * π - φ[idx[-1]] sizes = np.r_[s0, np.diff(φ[idx]), s0] weights = (sizes[1:] + sizes[:-1]) / 2 weights /= 2 * π elif self.dim == 3: # calculate weights using spherical voronoi construction voronoi = spatial.SphericalVoronoi(points_flat) voronoi.sort_vertices_of_regions() weight_vals = [ get_spherical_polygon_area(voronoi.vertices[ix]) for ix in voronoi.regions ] weights = np.array(weight_vals, dtype=np.double) weights /= surface_from_radius(1, dim=self.dim) else: raise NotImplementedError() if balance_axes: weights /= weights.sum() # normalize weights # adjust weights such that all distances are weighted equally, i.e., # the weighted sum of all shell vectors should vanish. Additionally, # the sum of all weights needs to be one. To satisfy these # constraints simultaneously, the weights are adjusted minimally # (in a least square sense). matrix = np.c_[points_flat, np.ones(len(points_flat))] vector = -weights @ matrix + np.r_[np.zeros(self.dim), 1] weights += np.linalg.lstsq(matrix.T, vector, rcond=None)[0] return weights.reshape(self.points.shape[:-1])
def test_spherical_voronoi(): """ test spatial.SphericalVoronoi """ # random points on the sphere ps = np.random.random((32, 3)) - 0.5 ps /= np.linalg.norm(ps, axis=1)[:, None] voronoi = spatial.SphericalVoronoi(ps) voronoi.sort_vertices_of_regions() total = sum( spherical.get_spherical_polygon_area(voronoi.vertices[reg]) for reg in voronoi.regions) assert total == pytest.approx(4 * np.pi)
def plot_voronoi_cells(self, facecmap: Optional[str] = 'Blues_r', ncols: int = 20, edgecolor: str = '#32519D', cell_centers: bool = True, markercolor: str = 'k', markersize: float = 2, linewidths=1, alpha: float = 0.9, seed: int = 0): r""" Plots the tessellation defined by the set's Voronoi decomposition. Parameters ---------- facecmap: Optional[str] Color map to be used for random coloring the tessellation faces. ncols: int Number of colors in the color map. edgecolor: str Color of the cell edges. cell_centers: bool Whether or not the cell centers are displayed. markercolor: str Color of the cell centers. markersize: float Size of the cell centers. linewidths: float Width of the cell edges. alpha: float Transparency of the cell faces. seed: int Seed for random coloring reproducibility. Warnings -------- This method can be **very slow** for large point sets (>10'000 points)! """ voronoi = sp.SphericalVoronoi(self.vec.transpose(), radius=1) voronoi.sort_vertices_of_regions() vertices = [[voronoi.vertices[region]] for region in voronoi.regions] self._plot_spherical_polygons(vertices, facecmap=facecmap, ncols=ncols, edgecolor=edgecolor, cell_centers=cell_centers, markercolor=markercolor, markersize=markersize, linewidths=linewidths, alpha=alpha, seed=seed)
def plot_old(self, plot_points=False, mark_peaks=0): """Plot the points on the sphere with their values""" from scipy import rand try: import matplotlib.colors as colors # from mpl_toolkits.mplot3d import Axes3D import mpl_toolkits.mplot3d as a3 import matplotlib.pyplot as plt except ImportError: import warnings warnings.warn("Matplotlib is required for plotting") return fig = plt.figure() ax = fig.add_subplot(111, projection="3d") if plot_points: ax.scatter(self.x, self.y, self.z, c="b", marker="o") if mark_peaks > 0: id = self.find_peaks(k=mark_peaks) s = 1.05 ax.scatter(s * self.x[id], s * self.y[id], s * self.z[id], c="k", marker="o") voronoi = sp.SphericalVoronoi(self.cartesian.T) voronoi.sort_vertices_of_regions() if self.values is not None: col_max = self.values.max() col_min = self.values.min() if col_min != col_max: col_map = (self.values - col_min) / (col_max - col_min) else: col_map = self.values / col_max else: col_map = np.zeros(self.n_points) cmap = plt.get_cmap("coolwarm") # plot the walls for v_ind, col in zip(voronoi.regions, col_map): triangle = a3.art3d.Poly3DCollection([voronoi.vertices[v_ind]], alpha=1.0, linewidth=0.0) triangle.set_color(cmap(col)) triangle.set_edgecolor("k") ax.add_collection3d(triangle) ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.set_xlim([-1, 1]) ax.set_ylim([-1, 1]) ax.set_zlim([-1, 1])
def plot_groups(equal_area_points, bin_values, fig=None, filename=None, grid_resolution=0.2, color_range=None, cmap='hot', reverse=True, pen='0.1p,gray50', transparency=0, **kwargs): """ Generate a visual representation of spatially binned data generated by 'groupby_healpix'. The result can either be added to a pygmt figure or saved to a GIS file (with the file type taken from the filename extension of the optional 'filename' parameter, e.g. shp, gmt, geojson) """ points = pygplates.MultiPointOnSphere(zip(equal_area_points.latitude,equal_area_points.longitude)).to_xyz_array() radius = 1 center = np.array([0, 0, 0]) sv = spatial.SphericalVoronoi(points, radius, center) sv.sort_vertices_of_regions() polygon_features = [] for region,zval in zip(sv.regions,bin_values): polygon = np.vstack((sv.vertices[region],sv.vertices[region][0,:])) polygon_feature = pygplates.Feature() polygon_feature.set_geometry(pygplates.PolygonOnSphere(polygon)) polygon_feature.set_shapefile_attribute('zval', zval) polygon_features.append(polygon_feature) if filename: return_file = True pygplates.FeatureCollection(polygon_features).write(filename) else: return_file = False plot_file = tempfile.NamedTemporaryFile(delete=False, suffix='.gmt') plot_file.close() filename = plot_file.name pygplates.FeatureCollection(polygon_features).write(filename) if fig: grid_lon, grid_lat = np.meshgrid(np.arange(-180.,180.,grid_resolution),np.arange(-90.,90.,grid_resolution)) d,l = sampleOnSphere(np.radians(equal_area_points.longitude), np.radians(equal_area_points.latitude), np.array(bin_values), np.radians(grid_lon).ravel(), np.radians(grid_lat).ravel(), k=1) grid_z = np.array(bin_values)[l].reshape(grid_lon.shape) #spherical_triangulation = stripy.sTriangulation(lons=np.radians(equal_area_points.longitude), lats=np.radians(equal_area_points.latitude)) #grid_z,_ = spherical_triangulation.interpolate_nearest(np.radians(grid_lon).ravel(), np.radians(grid_lat).ravel(), np.array(bin_values)) ds = xr.DataArray(grid_z.reshape(grid_lon.shape), coords=[('lat',grid_lat[:,0]), ('lon',grid_lon[0,:])], name='z') #pygmt.config(COLOR_FOREGROUND='white', COLOR_BACKGROUND='black') if not color_range: color_range = (np.nanmin(bin_values), np.nanmax(bin_values)) reverse = True pygmt.makecpt(cmap=cmap, series='{:f}/{:f}'.format(color_range[0],color_range[1]), reverse=reverse, background='o') # This line would allow the polygons to be plotted directly with a colormap, but tends to crash when # healpix of N=32 or greater is input #fig.plot(data=filename, pen=pen, color='+z', cmap=True, a='Z=zval', close=True, **kwargs) fig.grdimage(ds, transparency=transparency, cmap=True, nan_transparent=True) fig.plot(data=filename, pen=pen, transparency=transparency, close=True, **kwargs) if not return_file: os.unlink(plot_file.name)
def Do_Voronoi(x, file_prefix, rad=1., do_plot=0, FTYPE='jpg', MATDPI=80, FS=10, DO_hold_image=0, BMS=(0, 0)): '''Enter x array (and possibly a radius, whose default value is 1). We'll use that and its negative projection to do voronoi calculations. What could be more fun? ''' X = np.concatenate((x, -x)) # the fully monty lx, ly = np.shape(X) #vor = vu.Voronoi_Sphere_Surface(X, rad) vor = spsp.SphericalVoronoi(X, rad) vor.sort_vertices_of_regions() vor_regs = make_voronoi_region_dict(vor) vor_areas = calculate_all_polygon_areas(vor_regs) if do_plot: Amean = np.mean(vor_areas) Astd = np.std(vor_areas) Amin = np.min(vor_areas) Amax = np.max(vor_areas) vor_areas_norm = np.array(vor_areas) - Amean vor_areas_perc = 100. * vor_areas_norm / Amean if Astd: vor_areas_norm /= Astd print "++ Polygon area mean and std: (%.5f, %.5f)" % (Amean, Astd) tcolors = [ (0, 0, 205), # MediumBlue (65, 105, 225), # RoyalBlue (135, 206, 250), # sky blue (224, 255, 255), # light cyan (255, 255, 255), # white (255, 255, 255), # white (245, 245, 150), # sooomething (255, 215, 0), # Gold (255, 69, 0), # OrangeRed (220, 20, 60), # crimson ] test_cmap = make_cmap(tcolors, bit=True, Nsegs=len(tcolors)) mm = plt.cm.ScalarMappable(cmap=test_cmap) #plt.cm.RdBu)#BrBG_r) col_range = [-100, 100] mm.set_array(col_range) mm.set_clim(vmin=col_range[0], vmax=col_range[1]) # plot fig = plt.figure() overall_size = 6. fig.set_size_inches(overall_size * 9. / 8., overall_size) for bb in range(2): for cc in range(2): idx = 2 * bb + cc ax = fig.add_subplot('22' + str(idx + 1), projection='3d') for ii in range(len(vor_regs)): ireg = np.array(vor_regs[ii]) #col_wt = Convert_Z_to_BandColor(vor_areas_norm[ii]) hsv = np.array( csys.rgb_to_hsv(abs(X[ii, 0]), abs(X[ii, 1]), abs(X[ii, 2]))) #hsv[1] = 1-abs(vor_areas_perc[ii]) #1-abs(np.tanh(vor_areas_norm[ii])) hsv[2] = 0.75 #1 my_rgb = csys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]) #print hsv asdf = mm.to_rgba(vor_areas_perc[ii]) '''asdf2 = np.zeros(4) asdf2[:3] = abs(X[ii]) asdf2[3] = abs(col_wt) ''' #fill in the Voronoi region (polygon) that contains the #generator: polygon = Poly3DCollection([ireg], alpha=1) #1.0) polygon.set_color( asdf ) #[0,0,0])# my_rgb)#mm.to_rgba(vor_areas_norm[ii]))#my_rgb) #random_color) polygon.set_linewidth(1) polygon.set_edgecolor( my_rgb ) #np.array([0,0,0])) #*(1-abs(vor_areas_perc[ii]))) #[0,0,0])#clr.rgb2hex(abs(X[ii]))) #0,0,0])) #textt = Text3D( x = np.mean(voronoi_region[:,0]), \ # y = np.mean(voronoi_region[:,1]), \ # z = np.mean(voronoi_region[:,2]), \ # s = str(ii)) ax.add_collection3d(polygon) ax.set_xlim3d(aar[0] * 0.7, aar[1] * 0.7) ax.set_ylim3d(aar[0] * 0.7, aar[1] * 0.7) ax.set_zlim3d(aar[0] * 0.7, aar[1] * 0.7) ax.set_xticks([]) ax.set_xticklabels([''] * len(aar)) ax.set_yticks([]) ax.set_yticklabels([''] * len(aar)) ax.set_zticks([]) ax.set_zticklabels([''] * len(aar)) ax.view_init(azim=axview[idx][0], elev=axview[idx][1]) plt.tick_params(axis='both', which='major', labelsize=10) arr_a = Arrow3D(px[idx][0], px[idx][1], px[idx][2], mutation_scale=40, lw=2, arrowstyle="-|>", color="r") arr_b = Arrow3D(py[idx][0], py[idx][1], py[idx][2], mutation_scale=40, lw=2, arrowstyle="-|>", color="g") arr_c = Arrow3D(pz[idx][0], pz[idx][1], pz[idx][2], mutation_scale=40, lw=2, arrowstyle="-|>", color="b") ax.text2D(x=0.2, y=0.9, s=axview_lab[idx], fontsize=FS + 2, horizontalalignment='center', verticalalignment='center', fontdict=None, withdash=False, transform=ax.transAxes) plt.tight_layout(h_pad=-2, w_pad=-2) ax.add_artist(arr_a) ax.add_artist(arr_b) ax.add_artist(arr_c) #ax.w_xaxis.line.set_lw(0.) #ax.w_yaxis.line.set_lw(0.) #ax.w_zaxis.line.set_lw(0.) ax.set_axis_off() if BMS[0] > 10: info_textT = "$b$-val: %.0f $\pm$ %.0f" \ % (BMS[0], BMS[1]) else: info_textT = "$b$-val: %.2f $\pm$ %.2f" \ % (BMS[0], BMS[1]) info_textB = "\nArea\n(mean, SD) = (%.4f, %.4f)" \ % (Amean, Astd) info_textB+= "\n(min, max) = (%.4f, %.4f)" \ % (Amin, Amax) colbar = fig.add_axes([0.82, 0.31, 0.05, 0.35]) clb = fig.colorbar(mm, cax=colbar) clb.ax.set_title('$\mathsf{\Delta A \%}$', fontsize=FS) clb.ax.tick_params(labelsize=FS) #plt.colorbar(im_tmpX, cax=colbar, cmap=plt.cm.RdBu ) fig.subplots_adjust(bottom=0.04, top=0.94, right=0.8) fig.text(x=0.4, y=0.08, s=info_textB, horizontalalignment='center', verticalalignment='center', fontsize=FS) fig.text(x=0.4, y=0.95, s=info_textT, horizontalalignment='center', verticalalignment='center', fontsize=FS) plt.ion() plt.show() name_out = file_prefix + "_VOR" name_out_full = name_out + '.' + FTYPE plt.savefig(name_out_full, dpi=MATDPI) if DO_hold_image: raw_input() else: plt.close("all") std_area = np.std(vor_areas) mean_area = np.mean(vor_areas) max_area = np.max(vor_areas) min_area = np.min(vor_areas) theor_area = 4 * np.pi * rad * rad / float(lx) print "\t ratio stdev/mean is : %.4f" % (std_area / mean_area) print "\t max of the area is : %.4f" % max_area print "\t min of the area is : %.4f" % min_area print "\t mean of the area is : %.4f" % mean_area print "\t stdev of the area is : %.4f" % std_area print "\t Theoretical area is : %.4f" % theor_area return vor_areas, mean_area, std_area, max_area, min_area, \ vor, vor_regs