def plot_field(self, field): """ Map the given field. Parameters: ----------- field : 1D array TOCHECK Field to plot. """ if self.mask is not None: field = np.ma.masked_where(field <= self.mask, field) # Update array values if the plot has already been initialised if self.tripcolor_plot: field = field[self.masked_tris].mean(axis=1) self.tripcolor_plot.set_array(field) return # Create tripcolor plot x, y = self.m(self.lon, self.lat) self.tri = Triangulation(x, y, self.triangles) self.masked_tris = self.tri.get_masked_triangles() field = field[self.masked_tris].mean(axis=1) self.tripcolor_plot = self.axes.tripcolor(self.tri, field, vmin=self.vmin, vmax=self.vmax, cmap=self.cmap, edgecolors=self.edgecolors, zorder=1, norm=self.norm) # Overlay the grid # self.axes.triplot(self.tri, zorder=2) # Overlay stations in the first instance if self.stations is not None: mx, my = self.m(self.stations[0, :], self.stations[1, :]) self.axes.scatter(mx, my, marker='*', c='k', s=self.s_stations, edgecolors='none', zorder=4) # Add colorbar scaled to axis width divider = make_axes_locatable(self.axes) cax = divider.append_axes("right", size="5%", pad=0.05) self.cbar = self.figure.colorbar(self.tripcolor_plot, cax=cax, extend=self.extend) self.cbar.ax.tick_params(labelsize=self.fs) if self.cb_label: self.cbar.set_label(self.cb_label) return
def generate_mesh(nodes): from matplotlib.tri.triangulation import Triangulation from numpy import array x = []; y = [] for nid in sorted(nodes.keys()): x_, y_ = nodes[nid] x.append(x_) y.append(y_) t = Triangulation(x, y) return array(x), array(y), t.triangles
def _refine_triangulation_once(triangulation, ancestors=None): """ This function refines a matplotlib.tri *triangulation* by splitting each triangle into 4 child-masked_triangles built on the edges midside nodes. The masked triangles, if present, are also splitted but their children returned masked. If *ancestors* is not provided, returns only a new triangulation: child_triangulation. If the array-like key table *ancestor* is given, it shall be of shape (ntri,) where ntri is the number of *triangulation* masked_triangles. In this case, the function returns (child_triangulation, child_ancestors) child_ancestors is defined so that the 4 child masked_triangles share the same index as their father: child_ancestors.shape = (4 * ntri,). """ x = triangulation.x y = triangulation.y # According to tri.triangulation doc: # neighbors[i,j] is the triangle that is the neighbor # to the edge from point index masked_triangles[i,j] to point # index masked_triangles[i,(j+1)%3]. neighbors = triangulation.neighbors triangles = triangulation.triangles npts = np.shape(x)[0] ntri = np.shape(triangles)[0] if ancestors is not None: ancestors = np.asarray(ancestors) if np.shape(ancestors) != (ntri,): raise ValueError( "Incompatible shapes provide for triangulation" ".masked_triangles and ancestors: {0} and {1}".format( np.shape(triangles), np.shape(ancestors))) # Initiating tables refi_x and refi_y of the refined triangulation # points # hint: each apex is shared by 2 masked_triangles except the borders. borders = np.sum(neighbors == -1) added_pts = (3*ntri + borders) / 2 refi_npts = npts + added_pts refi_x = np.zeros(refi_npts) refi_y = np.zeros(refi_npts) # First part of refi_x, refi_y is just the initial points refi_x[:npts] = x refi_y[:npts] = y # Second part contains the edge midside nodes. # Each edge belongs to 1 triangle (if border edge) or is shared by 2 # masked_triangles (interior edge). # We first build 2 * ntri arrays of edge starting nodes (edge_elems, # edge_apexes) ; we then extract only the masters to avoid overlaps. # The so-called 'master' is the triangle with biggest index # The 'slave' is the triangle with lower index # (can be -1 if border edge) # For slave and master we will identify the apex pointing to the edge # start edge_elems = np.ravel(np.vstack([np.arange(ntri, dtype=np.int32), np.arange(ntri, dtype=np.int32), np.arange(ntri, dtype=np.int32)])) edge_apexes = np.ravel(np.vstack([np.zeros(ntri, dtype=np.int32), np.ones(ntri, dtype=np.int32), np.ones(ntri, dtype=np.int32)*2])) edge_neighbors = neighbors[edge_elems, edge_apexes] mask_masters = (edge_elems > edge_neighbors) # Identifying the "masters" and adding to refi_x, refi_y vec masters = edge_elems[mask_masters] apex_masters = edge_apexes[mask_masters] x_add = (x[triangles[masters, apex_masters]] + x[triangles[masters, (apex_masters+1) % 3]]) * 0.5 y_add = (y[triangles[masters, apex_masters]] + y[triangles[masters, (apex_masters+1) % 3]]) * 0.5 refi_x[npts:] = x_add refi_y[npts:] = y_add # Building the new masked_triangles ; each old masked_triangles hosts # 4 new masked_triangles # there are 6 pts to identify per 'old' triangle, 3 new_pt_corner and # 3 new_pt_midside new_pt_corner = triangles # What is the index in refi_x, refi_y of point at middle of apex iapex # of elem ielem ? # If ielem is the apex master: simple count, given the way refi_x was # built. # If ielem is the apex slave: yet we do not know ; but we will soon # using the neighbors table. new_pt_midside = np.empty([ntri, 3], dtype=np.int32) cum_sum = npts for imid in range(3): mask_st_loc = (imid == apex_masters) n_masters_loc = np.sum(mask_st_loc) elem_masters_loc = masters[mask_st_loc] new_pt_midside[:, imid][elem_masters_loc] = np.arange( n_masters_loc, dtype=np.int32) + cum_sum cum_sum += n_masters_loc # Now dealing with slave elems. # for each slave element we identify the master and then the inode # onces slave_masters is indentified, slave_masters_apex is such that: # neighbors[slaves_masters, slave_masters_apex] == slaves mask_slaves = np.logical_not(mask_masters) slaves = edge_elems[mask_slaves] slaves_masters = edge_neighbors[mask_slaves] diff_table = np.abs(neighbors[slaves_masters, :] - np.outer(slaves, np.ones(3, dtype=np.int32))) slave_masters_apex = np.argmin(diff_table, axis=1) slaves_apex = edge_apexes[mask_slaves] new_pt_midside[slaves, slaves_apex] = new_pt_midside[ slaves_masters, slave_masters_apex] # Builds the 4 child masked_triangles child_triangles = np.empty([ntri*4, 3], dtype=np.int32) child_triangles[0::4, :] = np.vstack([ new_pt_corner[:, 0], new_pt_midside[:, 0], new_pt_midside[:, 2]]).T child_triangles[1::4, :] = np.vstack([ new_pt_corner[:, 1], new_pt_midside[:, 1], new_pt_midside[:, 0]]).T child_triangles[2::4, :] = np.vstack([ new_pt_corner[:, 2], new_pt_midside[:, 2], new_pt_midside[:, 1]]).T child_triangles[3::4, :] = np.vstack([ new_pt_midside[:, 0], new_pt_midside[:, 1], new_pt_midside[:, 2]]).T child_triangulation = Triangulation(refi_x, refi_y, child_triangles) # Builds the child mask if triangulation.mask is not None: child_triangulation.set_mask(np.repeat(triangulation.mask, 4)) if ancestors is None: return child_triangulation else: return child_triangulation, np.repeat(ancestors, 4)
def show_img(self, start_frame, period=None, output=None, cell_rep=1, vmax=None, scalebar=False, boundary=None, offset=5, boundary_offset=5, img_offset=10, cmap="gray", mode='tri', bin_step=1, r=5, bin_rep=7, tri_method='linear', roll_correction=True): if start_frame < 0: start_frame = len(self.Z_history) - 1 if period is None: period = 100000000 for num in range(start_frame, len(self.Z_history), period): img_name = "rip.{}.png".format(str(int(num / period)).zfill(5)) print("DISPL NUM::{}".format(num)) X_, Y_, Z_ = self.leveled_xyz(self.Z_history[num], cell_rep, correction=roll_correction) flat = [None, None, None] flat[0] = X_.flatten() flat[1] = Y_.flatten() flat[2] = Z_.flatten() flat = np.asarray(flat) if boundary is None: boundary = self.get_img_boundary(X_, Y_, Z_) boundary[0][0] += offset boundary[1][0] += offset boundary[0][1] -= offset boundary[1][1] -= offset print(boundary) if mode == 'scatter3d' or mode == 'scatter': #x_flag = np.logical_and(flat_[0] > boundary[0][0], flat_[0] < boundary[0][1]) #y_flag = np.logical_and(flat_[1] > boundary[1][0], flat_[1] < boundary[1][1]) #flat = np.array(flat_) #flat = flat[:, np.logical_and(x_flag, y_flag)] if mode == 'scatter3d': fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(flat[0], flat[1], flat[2]) ax.set_xlabel("X axis") ax.set_ylabel("Y axis") plt.show() else: plt.scatter(flat[0], flat[1]) plt.show() elif mode == 'surf': r2 = np.power(r, 2) bin_centers = [ np.arange(boundary[0, 0], boundary[0, 1] + 0.001, bin_step), np.arange(boundary[1, 0], boundary[1, 1] + 0.001, bin_step) ] bin_edges = np.array([ bin_centers[0][:-1] + 0.5 * bin_step, bin_centers[1][:-1] + 0.5 * bin_step ]) indexes = [None, None] indexes[0] = np.digitize(flat_[0], bin_edges[0]) # x bins indexes[1] = np.digitize(flat_[1], bin_edges[1]) # y bins safe_offset = -1000000 Z_holder = np.ones( (bin_centers[1].shape[0], bin_centers[0].shape[0], 3, 3), dtype=float) * safe_offset for i in range(len(flat_[0])): ix = indexes[0][i] iy = indexes[1][i] cr_z = flat_[2][i] if (Z_holder[iy, ix, 0, 2] < cr_z): Z_holder[iy, ix, 2] = Z_holder[iy, ix, 1] Z_holder[iy, ix, 1] = Z_holder[iy, ix, 0] Z_holder[iy, ix, 0] = [flat_[0][i], flat_[1][i], cr_z] elif (Z_holder[iy, ix, 1, 2] < cr_z): Z_holder[iy, ix, 2] = Z_holder[iy, ix, 1] Z_holder[iy, ix, 1] = [flat_[0][i], flat_[1][i], cr_z] elif (Z_holder[iy, ix, 2, 2] < cr_z): Z_holder[iy, ix, 2] = [flat_[0][i], flat_[1][i], cr_z] # discard edges Z_holder = Z_holder[1:-1, 1:-1, :, :] probe_bins = (bin_rep * 2 + 1) * (bin_rep * 2 + 1) probe_bins_total = probe_bins * 3 Z_full_holder = np.empty((Z_holder.shape[0], Z_holder.shape[1], probe_bins_total, 3)) bin_rep_arr = list(range(-bin_rep, bin_rep + 1)) for n_, roll_ in zip( range(probe_bins), itertools.product(bin_rep_arr, bin_rep_arr)): #print(roll_, n_*3, (n_+1)*3) Z_full_holder[:, :, n_ * 3:(n_ + 1) * 3] = np.roll( Z_holder, (roll_[0], roll_[1]), axis=(0, 1)) Z_full_holder = Z_full_holder[1:-1, 1:-1, :, :] bin_centers[0] = bin_centers[0][2:-2] bin_centers[1] = bin_centers[1][2:-2] probe = np.stack(np.meshgrid(bin_centers[0], bin_centers[1]), -1) probe = np.append(probe, np.zeros( (probe.shape[0], probe.shape[1], 1)), axis=2) probe = np.tile(probe, probe_bins_total).reshape( probe.shape[0], probe.shape[1], probe_bins_total, 3) probe_diff = Z_full_holder - probe probe_height = np.sqrt(r2 - (np.power(probe_diff[:, :, :, 0], 2) + np.power(probe_diff[:, :, :, 1], 2))) probe_z = Z_full_holder[:, :, :, 2] + probe_height probe_z[np.isnan(probe_z)] = safe_offset probe_z = np.amax(probe_z, -1) probe_z[probe_z <= safe_offset + 1] = 0.0 probe_z -= np.min(probe_z) print("Probe {}".format(np.max(probe_z))) if vmax is None: vmax = np.max(probe_z) if vmax == "get": return np.max(probe_z) # normalize probe_z = probe_z / vmax probe_z = (0.5 - np.mean(probe_z)) + probe_z if output: plt.imsave("{}/{}".format(output, img_name), probe_z, cmap=cmap) else: plt.imshow(probe_z, cmap=cmap, vmin=0.0, vmax=1.0) plt.show() elif mode == 'tri' or mode == 'tri_scatter': tri = Triangulation(flat[0], flat[1]) if tri_method == 'cube': interpol = CubicTriInterpolator(tri, flat[2]) else: interpol = LinearTriInterpolator(tri, flat[2]) x_new = np.arange(boundary[0][0], boundary[0][1], self.img_dx) y_new = np.arange(boundary[1][0], boundary[1][1], self.img_dx) X_new, Y_new = np.meshgrid(x_new, y_new) Z_new = interpol(X_new, Y_new) print("Orginal range: {} {}".format(np.min(Z_new), np.max(Z_new))) Z_new = Z_new - np.min(Z_new) if vmax == "get": return np.max(Z_new) if vmax is None: vmax = np.max(Z_new) Z_new = Z_new / vmax Z_new += (1 - np.max(Z_new)) * 0.5 if scalebar: plt.gca().add_artist(ScaleBar(1.0 / self.img_dx, 'nm')) if output: if mode == 'tri': plt.imsave("{}/{}".format(output, img_name), Z_new, vmin=0, vmax=1, cmap=cmap) else: inside_box = np.logical_and( np.logical_and(flat[0] > boundary[0][0], flat[0] < boundary[0][1]), np.logical_and(flat[1] > boundary[1][0], flat[1] < boundary[1][1])) scatter_x = flat[0, inside_box] scatter_y = flat[1, inside_box] plt.imshow(Z_new, vmin=0, vmax=1, cmap=cmap) plt.scatter(scatter_x - boundary[0][0], scatter_y - boundary[1][0], marker=',', s=1, lw=0, color='red') plt.savefig("{}/{}".format(output, img_name)) plt.cla() else: plt.imshow(Z_new, vmin=0, vmax=1, cmap=cmap) if mode == 'tri_scatter': inside_box = np.logical_and( np.logical_and(flat[0] > boundary[0][0], flat[0] < boundary[0][1]), np.logical_and(flat[1] > boundary[1][0], flat[1] < boundary[1][1])) scatter_x = flat[0, inside_box] scatter_y = flat[1, inside_box] plt.scatter(scatter_x - boundary[0][0], scatter_y - boundary[1][0], marker=',', s=1, lw=0, color='red') plt.show()
def _get_interp_tri(x_in, y_in, gr_x, gr_y, method=None): """ For each value (x_in, y_in) returns _indexes of the closets 3 values (Delaunay) in the (gr_x, gr_y) table, and the corresponding coefficients. @method: tri_surf', 'plan_interp' """ methods = ['tri_surf', 'plan_interp'] calling = 'interp_3D' pc.log_.message('Entering interp 3D', calling=calling) if not pc.config.INSTALLED['Triangulation']: pc.log_.error('Triangulation package not available from matplotlib.', calling=calling) return None if method is None: method = methods[0] if method not in methods: pc.log_.error('{0} is not a valid method'.format(method), calling=calling) return None n_points = np.size(x_in) indexes = np.zeros((n_points, 3), dtype=int) - 1 coeffs = np.zeros((n_points, 3)) if method == 'tri_surf': def get_coeff(x, y, P1, P2, P3): v1x = P1[0] - x v1y = P1[1] - y v2x = P2[0] - x v2y = P2[1] - y v3x = P3[0] - x v3y = P3[1] - y d1 = abs(v2x * v3y - v2y * v3x) d2 = abs(v1x * v3y - v1y * v3x) d3 = abs(v1x * v2y - v1y * v2x) dsum = d1 + d2 + d3 return np.squeeze(np.transpose([d1 / dsum, d2 / dsum, d3 / dsum])) elif method == 'plan_interp': def get_coeff(x, y, P1, P2, P3): XY = np.asarray((x, y)) d1 = misc.dist_point_line(XY, P2, P3) / dpl1 d2 = misc.dist_point_line(XY, P1, P3) / dpl2 d3 = misc.dist_point_line(XY, P1, P2) / dpl3 dsum = d1 + d2 + d3 return np.squeeze(np.transpose([d1 / dsum, d2 / dsum, d3 / dsum])) tri = Triangulation(gr_x, gr_y) pc.log_.message('Triangulation done', calling=calling) n_triangles = tri.triangle_nodes.shape[0] for i, triangle in enumerate(tri.triangle_nodes): T1 = np.asarray((gr_x[triangle[0]], gr_y[triangle[0]])) T2 = np.asarray((gr_x[triangle[1]], gr_y[triangle[1]])) T3 = np.asarray((gr_x[triangle[2]], gr_y[triangle[2]])) points_inside = misc.points_inside_triangle(x_in, y_in, T1, T2, T3) pc.log_.message('{0} points inside triangle {1} over {2}'.format( points_inside.sum(), i, n_triangles), calling=calling) if method == 'plan_interp': dpl1 = misc.dist_point_line(T1, T2, T3) dpl2 = misc.dist_point_line(T2, T3, T1) dpl3 = misc.dist_point_line(T3, T1, T2) if points_inside.sum() != 0: indexes[points_inside] = triangle coeffs[points_inside] = get_coeff(x_in[points_inside], y_in[points_inside], T1, T2, T3) return indexes, coeffs
# Read in the grid's dimensions n_nodes = mediator.get_dimension_variable('node') n_elems = mediator.get_dimension_variable('element') # Grid connectivity/adjacency nv = mediator.get_grid_variable('nv', (3, n_elems), int) # Cartesian coordinates x_nodes = mediator.get_grid_variable('x', (n_nodes), float) y_nodes = mediator.get_grid_variable('y', (n_nodes), float) x_centroids = mediator.get_grid_variable('xc', (n_elems), float) y_centroids = mediator.get_grid_variable('yc', (n_elems), float) triangles = nv.transpose() tri = Triangulation(x_nodes, y_nodes, triangles) # Plot fig = plt.figure() ax = fig.add_subplot(111) ax.triplot(tri) for idx, (xc, yc) in enumerate(zip(x_centroids, y_centroids)): ax.scatter(xc, yc) ax.annotate('xc_{}'.format(idx), xy=(xc, yc), xytext=(xc, yc)) # Plot for idx, (x, y) in enumerate(zip(x_nodes, y_nodes)): ax.scatter(x, y) ax.annotate('xn_{}'.format(idx), xy=(x, y), xytext=(x, y))