def plot_matrix2(g): plt.figure(figsize=(9, 3)) azimuth = 137 altitude = 40 mat = g.mat plt.axis('off') ax = plt.subplot(131, projection='3d') light = LightSource(90, 45) green = np.array([0, 1.0, 0]) X, Y = np.meshgrid([m for m in range(len(mat[0]))], [n for n in range(len(mat))]) z = np.array(mat) ax.view_init(altitude, azimuth) illuminated_surface = light.shade(z, cmap=cm.coolwarm) rgb = np.ones((z.shape[0], z.shape[1], 3)) green_surface = light.shade_rgb(rgb * green, z) ax.plot_surface(X, Y, g.mat, rstride=1, cstride=1, linewidth=0, antialiased=True, facecolors=illuminated_surface) ax.set_zticks([]) ax.grid(False) sbplt = plt.subplot(132) plt.contour(g.mat, cmap=plt.get_cmap('gray'), origin='lower') # plotting the asymmetric gradient field plt.subplot(133) plt.quiver(g.gradient_asymmetric_dx, g.gradient_asymmetric_dy, scale=g.rows * g.cols / 2) plt.tight_layout() plt.show()
def vis_depth_matplotlib(img, Z, elevation=60, azimuth=45, stride=5): from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt from matplotlib.colors import LightSource fig = plt.figure() ax = fig.gca(projection='3d') # Create X and Y data x = np.arange(0, 512, 1) y = np.arange(0, 512, 1) X, Y = np.meshgrid(x, y) ls = LightSource(azdeg=0, altdeg=90) # shade data, creating an rgb array. img_c = np.concatenate((img.astype('float') / 255, np.ones((512, 512, 1))), axis=2) rgb = ls.shade_rgb(img.astype('float') / 255, Z, blend_mode='overlay') surf = ax.plot_surface(X, Y, Z, cstride=stride, rstride=stride, linewidth=0, antialiased=False, facecolors=rgb) ax.view_init(elev=elevation, azim=azimuth) # ax.view_init(elev=90., azim=90)` # Show the plot plt.show()
class LightFilter(BaseFilter): "simple gauss filter" def __init__(self, sigma, fraction=0.5): self.gauss_filter = GaussianFilter(sigma, alpha=1) self.light_source = LightSource() self.fraction = fraction #hsv_min_val=0.5,hsv_max_val=0.9, # hsv_min_sat=0.1,hsv_max_sat=0.1) def get_pad(self, dpi): return self.gauss_filter.get_pad(dpi) def process_image(self, padded_src, dpi): t1 = self.gauss_filter.process_image(padded_src, dpi) elevation = t1[:, :, 3] rgb = padded_src[:, :, :3] rgb2 = self.light_source.shade_rgb(rgb, elevation, fraction=self.fraction) tgt = np.empty_like(padded_src) tgt[:, :, :3] = rgb2 tgt[:, :, 3] = padded_src[:, :, 3] return tgt
def update_f(i, render=True): ax.clear() ax.set_xlim3d([0 - 1, M * interval_length + 1]) ax.set_xlabel('X') ax.set_ylim3d([0 - 1, N * interval_length + 1]) ax.set_ylabel('Y') ax.set_zlim3d([-10.0, 10.0]) ax.set_zlabel('Z') ax.set_title('3D Test') X, Y, Z = solutions[i][0], solutions[i][1], solutions[i][2] if render: grey = np.array([1, 1, 1]) light = LightSource(0, 0) rgb = np.ones((Z.shape[0], Z.shape[1], 3)) grey_surface = light.shade_rgb(rgb * grey, Z) ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0, antialiased=False, facecolors=grey_surface) else: ax.plot_wireframe(X, Y, Z, c='grey') ax.scatter(X, Y, Z, marker='o', c='grey', linewidths=0.02) return ax
class LightFilter(BaseFilter): "simple gauss filter" def __init__(self, sigma, fraction=0.5): self.gauss_filter = GaussianFilter(sigma, alpha=1) self.light_source = LightSource() self.fraction = fraction #hsv_min_val=0.5,hsv_max_val=0.9, # hsv_min_sat=0.1,hsv_max_sat=0.1) def get_pad(self, dpi): return self.gauss_filter.get_pad(dpi) def process_image(self, padded_src, dpi): t1 = self.gauss_filter.process_image(padded_src, dpi) elevation = t1[:,:,3] rgb = padded_src[:,:,:3] rgb2 = self.light_source.shade_rgb(rgb, elevation, fraction=self.fraction) tgt = np.empty_like(padded_src) tgt[:,:,:3] = rgb2 tgt[:,:,3] = padded_src[:,:,3] return tgt
def run_example_5(): print("Phenotypic phase analysis") model = cobra.test.create_test_model("textbook") glucose_upper_limit = 21 oxygen_upper_limit = 21 glucoses = np.arange(glucose_upper_limit) oxygens = np.arange(oxygen_upper_limit) glucoses, oxygens = np.meshgrid(glucoses, oxygens) growth_rates = calc_growth_rate(glucoses, oxygens, model) # TODO pretty graphics H = np.histogram(growth_rates, bins=5) plt.clf() light = LightSource(45, 60) white = np.ones((growth_rates.shape[0], growth_rates.shape[1], 3)) green = white * np.array([0, 1, 0]) illuminated_surface = light.shade_rgb(green, growth_rates) ax = plt.axes(projection='3d') ax.plot_surface(glucoses, oxygens, growth_rates, cstride=1, rstride=1, facecolors=illuminated_surface) plt.show() plt.clf() plt.imshow(growth_rates, cmap='hot', interpolation='nearest') plt.show() plt.clf()
def plot_matrix2(g): plt.figure(figsize=(15, 5)) #plt.suptitle("Ga: "+str(round(max(g.G2,g.G1,g.G3),3)),fontsize=18) azimuth = 137 altitude = 40 mat = g.mat plt.axis('off') ax = plt.subplot(131, projection='3d') #plt.title("3D") light = LightSource(90, 45) green = np.array([0, 1.0, 0]) X, Y = np.meshgrid([m for m in range(len(mat))], [n for n in range(len(mat))]) z = np.array(mat) ax.view_init(altitude, azimuth) illuminated_surface = light.shade(z, cmap=cm.coolwarm) rgb = np.ones((z.shape[0], z.shape[1], 3)) green_surface = light.shade_rgb(rgb * green, z) ax.plot_surface(X, Y, z, rstride=1, cstride=1, linewidth=0, antialiased=True, facecolors=illuminated_surface) # ax.plot_wireframe(X,Y,z) #plt.axis('off') ax.set_zticks([]) ax.grid(False) sbplt = plt.subplot(132) #plt.title("Contour") plt.contour(g.mat, cmap=plt.get_cmap('gray'), origin='lower') # plotting the asymmetric gradient field plt.subplot(133) plt.quiver(g.gradient_asymmetric_dx, g.gradient_asymmetric_dy, scale=1.0 / 0.1) #plt.title("Asymmetric Gradient Field") #plt.title("C",fontsize=20) # plotting the triangulation #if g.n_edges > 0: # plt.subplot(133) #plt.xlim(0,len(g.mat[0])) #plt.ylim(0,len(g.mat)) # plt.triplot(g.triangulation_points[:,0], g.triangulation_points[:,1], g.triangles.simplices.copy()) # plt.title("Triangulation") #plt.title("D",fontsize=20) plt.tight_layout() plt.show()
def shade_other_data(): """Demonstrates displaying different variables through shade and color.""" y, x = np.mgrid[-4:2:200j, -4:2:200j] z1 = np.sin(x**2) # Data to hillshade z2 = np.cos(x**2 + y**2) # Data to color norm = Normalize(z2.min(), z2.max()) cmap = plt.cm.RdBu ls = LightSource(315, 45) rgb = ls.shade_rgb(cmap(norm(z2)), z1) fig, ax = plt.subplots() ax.imshow(rgb) ax.set_title('Shade by one variable, color by another', size='x-large')
def shade_other_data(): """Demonstrates displaying different variables through shade and color.""" y, x = np.mgrid[-4:2:200j, -4:2:200j] z1 = np.sin(x**2) # Data to hillshade z2 = np.cos(x**2 + y**2) # Data to color norm = Normalize(z2.min(), z2.max()) cmap = plt.cm.jet ls = LightSource(315, 45) rgb = ls.shade_rgb(cmap(norm(z2)), z1) fig, ax = plt.subplots() ax.imshow(rgb) ax.set_title('Shade by one variable, color by another', size='x-large')
def plot_angular(self, popt, getxyz=False): #from mpl_toolkits.mplot3d import Axes3D #from matplotlib.colors import LightSource #: set grid theta, phi = np.linspace(0, np.pi, 40), np.linspace(0, 2.0 * np.pi, 40) #: get data on mesh grid fitted_data = np.zeros((len(theta), len(phi))) for itheta in range(theta.size): for iphi in range(phi.size): angles = (theta[itheta], phi[iphi]) fitted_data[iphi, itheta] = np.absolute(self.fit_func(angles, *popt)) #: get points to plot theta_mesh, phi_mesh = np.meshgrid(theta, phi) x = np.sqrt(fitted_data) * np.cos(phi_mesh) * np.sin(theta_mesh) y = np.sqrt(fitted_data) * np.sin(phi_mesh) * np.sin(theta_mesh) z = np.sqrt(fitted_data) * np.cos(theta_mesh) if getxyz: return x, y, z #: lighting source light = LightSource(270, 90) rgb = np.ones((z.shape[0], z.shape[1], 3)) pink = [219 / 255, 112 / 255, 147 / 255] illuminated_surface = light.shade_rgb(rgb * pink, z) #: plot plot plot plot fig = plt.figure() ax = plt.axes(projection='3d') ax.plot_surface(x, y, z, alpha=0.4, linewidth=0, antialiased=False, facecolors=illuminated_surface) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') #ax.set_axis_off() plt.show()
class LightFilter(BaseFilter): def __init__(self, sigma, fraction=0.5): self.gauss_filter = GaussianFilter(sigma, alpha=1) self.light_source = LightSource() self.fraction = fraction def get_pad(self, dpi): return self.gauss_filter.get_pad(dpi) def process_image(self, padded_src, dpi): t1 = self.gauss_filter.process_image(padded_src, dpi) elevation = t1[:, :, 3] rgb = padded_src[:, :, :3] alpha = padded_src[:, :, 3:] rgb2 = self.light_source.shade_rgb(rgb, elevation, fraction=self.fraction) return np.concatenate([rgb2, alpha], -1)
def shade_and_color(relief, data=None, az=315, alt=45, vmax='max', vmin='min', cmap='gist_earth', smooth=None, scale=None, blend_mode='multiply', contrast=1, brightness=1, method='matplotlib', normalize=False, return_shading_dict=False, **kwargs): """ Shade (relief) and color (relief or data). This is done using the :meth:`~matplotlib.colors.LightSource.shade` method of the :class:`~matplotlib.colors.LightSource` class. Parameters ---------- relief : 2d :class:`~numpy.ndarray` Contains elevation (usually) data. Used for calculating intensities. data : None or 2d :class:`~numpy.ndarray` Data to color (drape) over the intensity grid. If ``None``, relief is colored over the intensity grid az : int or float The azimuth (0-360, degrees clockwise from North) of the light source. Defaults to 315 degrees (from the northwest). alt : int or float The altitude (0-90, degrees up from horizontal) of the light source. Defaults to 45 degrees from horizontal. vmax, vmin : str or float Used to clip the coloring of the data at the set value. Default is 'max' and 'min' which used the extent of the data. If ``float``s, the colorscale saturates at the given values. Finally, if a string is passed (other than 'max' or 'min'), it is casted to float and used as an ``rms`` multiplier. For instance, if ``vmax='3'``, clipping is done at 3.0\*rms of the data. To force symmetric coloring around 0 set `vmin` to ``None`` or ``False``. This will cause `vmin` to equal -1 * `vmax`. cmap : str or :class:`~matplotlib.colors.Colormap` instance String of the name of the colormap, i.e. 'Greys', or a :class:`~matplotlib.colors.Colormap` instance. smooth : float Smooth the relief before calculating the intensity grid. This reduces noise. The overlaid relief is untouched. scale : float Scaling value of the data. Higher definition is achieved by scaling the elevation prior to the intensity calculation. This can be used either to correct for differences in units between the x, y coordinate system and the elevation coordinate system (e.g. decimal degrees vs meters). blend_mode : str or callable The type of blending used to combine the colormapped data values with the illumination intensity. For backwards compatibility, this defaults to 'hsv'. Note that for most topographic surfaces, 'overlay' or 'multiply' appear more visually realistic. If a user-defined function is supplied, it is expected to combine an MxNx3 RGB array of floats (ranging 0 to 1) with an MxNx1 hillshade array (also 0 to 1). (Call signature func(rgb, illum, \*\*kwargs)) Options are: **'hsv', 'overlay', 'soft'** - are achieved using the :meth:`~matplotlib.colors.LightSource.shade_rgb` method of the :class:`~matplotlib.colors.LightSource` class. **'multiply', 'hard', 'screen', 'pegtop'** - are achieved by image manipulation in RGB space. See :func:`~.multiply`, :func:`~.hard`, :func:`~.screen`, :func:`~.pegtop`. contrast : float Increases or decreases the contrast of the resulting image. If > 1 intermediate values move closer to full illumination or shadow (and clipping any values that move beyond 0 or 1). brightness : float Increases or decreases the brightness of the resulting image. Ignored for 'hsv', 'overlay', 'soft'. method : {'matplotlib', 'calc_intensity'} By default, matplotlib's :meth:`~matplotlib.colors.LightSource.hillshade` is used to calculate the illumination intensity of the relief. For better control, :func:`~.calc_intensity` can be used instead. normalize : bool or float By default the intensity is clipped to the [0,1] range. If set to ``True``, intensity is normalized to [0,1]. Otherwise, give a float value to normalize to [0,1] and then divide by the value. This is ignored if ``method`` is 'matplotlib'. return_shading_dict : bool False by default. If ``True``, a dictionary is returned that can be passed to :func:`~matplotlib.pyplot.imshow` and :func:`~.shade_colorbar` to preserve consistency. .. note:: It is assumed that relief and data have the same extent, origin and shape. Any resizing and reshaping must be done prior to this. Other parameters ---------------- kwargs : ``blend_mode`` options. """ if blend_mode in BLEND_MODES or callable(blend_mode): blend_func = BLEND_MODES[blend_mode] else: raise ValueError('"blend_mode" must be callable or one of {}'.format( BLEND_MODES.keys)) relief = relief.copy() data = data if data is not None else relief if scale is not None: relief = relief * scale if smooth: relief = uniform_filter(relief, size=smooth) # data if vmax is 'max': clip = np.nanmax(data) elif type(vmax) in INT_AND_FLOAT: clip = vmax else: clip = float(vmax) * np.nanstd(data) if vmin is 'min': vmin = np.nanmin(data) elif type(vmin) in INT_AND_FLOAT: pass elif vmin in [None, False]: vmin = -clip vmax = clip # matplotlib shade_rgb using hillshade intensity calculation if method == 'matplotlib': ls = LightSource(azdeg=az, altdeg=alt) # color and drape the data on top of the shaded relief rgb = ls.shade_rgb(data2rgb(data, cmap, vmin, vmax), relief, blend_mode=blend_func, fraction=contrast, **kwargs) # use calc_intensity with better control else: rgb = data2rgb(data, cmap, vmin, vmax) illumination = calc_intensity(relief, az, alt, normalize=normalize) illumination = illumination[..., np.newaxis] if blend_mode in BLEND_MODES: blend_func = BLEND_MODES[blend_mode] elif callable(blend_mode): blend_func = blend_mode else: raise ValueError( '"blend_mode" must be callable or one of {}'.format( BLEND_MODES.keys)) rgb = blend_func(rgb, illumination) if brightness != 1: rgb = adjust_brightness(rgb, brightness) if return_shading_dict: return rgb, dict(cmap=cmap, vmin=vmin, vmax=vmax, blend_mode=blend_func, brightness=brightness) return rgb
def show_plot(self, x_points: np.array, y_points: np.array, data: np.ndarray, map_plot: bool, **kwargs) -> bool: """ Displays the plot to the user. :param x_points: X co-ordinates for the data points. :param y_points: Y co-ordinates for the data points. :param data: The data points as a 1D grid, X-fast. :param map_plot: If set to true, the data is plotted on a map. If false, just generic data. :return: True, if plot was shown successfully. False if not. """ ranges = { "min_lon": np.amin(x_points), "max_lon": np.amax(x_points), "min_lat": np.amin(y_points), "max_lat": np.amax(y_points) } colormap = cm.RdBu norm = mcolors.Normalize(vmin=self.bounds[0], vmax=self.bounds[len(self.bounds) - 1]) faults = False save = False if "basic" in kwargs: basic = kwargs["basic"] else: basic = False if hasattr(self, "extras"): if "data" in self.extras: if "save" in self.extras["data"]: if str(self.extras["data"]["save"]).lower() == "y": save = os.path.join( self.extras["data"]["location"], self.extras["data"]["name"] + ".png") if "plot" in self.extras: if "save" in self.extras["plot"]: save = self.extras["plot"]["save"] if "features" in self.extras["plot"]: if "colormap" in self.extras["plot"]["features"]: try: colormap = getattr( cm, self.extras["plot"]["features"]["colormap"]) except AttributeError: colormap = getattr( basemapcm, self.extras["plot"]["features"]["colormap"]) if "scale" in self.extras["plot"]["features"]: if str(self.extras["plot"]["features"]["scale"]).lower().strip() \ == "discrete": colormap = self._cmapDiscretize( colormap, len(self.bounds) - 1) norm = mcolors.BoundaryNorm( self.bounds, colormap.N) if "faults" in self.extras["plot"]["features"]: if str(self.extras["plot"]["features"] ["faults"]).lower().strip() == "yes": faults = True if map_plot: colormap.set_bad("gray", 1) if not basic: plt.axes([0.15, 0.2, 0.70, 0.70]) # Check to see if we have pickled this particular basemap instance. m = basemap.Basemap(projection='cyl', llcrnrlat=ranges["min_lat"], urcrnrlat=ranges["max_lat"], llcrnrlon=ranges["min_lon"], urcrnrlon=ranges["max_lon"], resolution='f', anchor='C') if not basic: lat_ticks = np.arange(ranges["min_lat"], ranges["max_lat"], (ranges["max_lat"] - ranges["min_lat"]) / 2) lat_ticks = np.append(lat_ticks, [ranges["max_lat"]]) lon_ticks = np.arange(ranges["min_lon"], ranges["max_lon"], (ranges["max_lon"] - ranges["min_lon"]) / 2) lon_ticks = np.append(lon_ticks, [ranges["max_lon"]]) lat_ticks = [round(x, 2) for x in lat_ticks] lon_ticks = [round(x, 2) for x in lon_ticks] m.drawparallels(lat_ticks, linewidth=1.0, labels=[1, 0, 0, 0]) m.drawmeridians(lon_ticks, linewidth=1.0, labels=[0, 0, 0, 1]) data_cpy = np.ma.masked_invalid(data) if "topography" in kwargs and kwargs["topography"] is not None: # create light source object. ls = LightSource(azdeg=315, altdeg=45) # convert data to rgb array including shading from light source. # (must specify color map) low_indices = kwargs["topography"] < 0 kwargs["topography"][low_indices] = 0 rgb = ls.shade_rgb(colormap(norm(data_cpy)), kwargs["topography"], blend_mode="overlay", vert_exag=2) for y in range(len(rgb)): for x in range(len(rgb[0])): rgb[y][x][0] *= 0.90 rgb[y][x][1] *= 0.90 rgb[y][x][2] *= 0.90 t = m.imshow(rgb, cmap=colormap, norm=norm) else: t = m.pcolormesh(x_points, y_points, data_cpy, cmap=colormap, norm=norm) m.drawstates() m.drawcountries() m.drawcoastlines() # If we want the fault lines we need to plot them. if faults: for key, fault_coords in Fault().get_all_faults().items(): fault_lons = [] fault_lats = [] for x, y in fault_coords: fault_lons.append(x) fault_lats.append(y) m.plot(fault_lons, fault_lats, "k-", linewidth=1) if not basic: plt.xlabel(self.plot_xlabel if isinstance( self.plot_xlabel, str) else "", fontsize=14) plt.ylabel(self.plot_ylabel if isinstance( self.plot_ylabel, str) else "", fontsize=14) plt.title(self.plot_title if isinstance(self.plot_title, str ) else "") else: colormap.set_bad("gray", 1) data_cpy = np.ma.masked_invalid(data) data_cpy = np.ma.masked_less_equal(data_cpy, 0) plt.axes([0.1, 0.7, 0.8, 0.25]) ll_lat = kwargs["boundaries"]["sp"][1] if kwargs["boundaries"]["sp"][1] < \ kwargs["boundaries"]["ep"][1] else kwargs["boundaries"]["ep"][1] ll_lon = kwargs["boundaries"]["sp"][0] if kwargs["boundaries"]["sp"][0] < \ kwargs["boundaries"]["ep"][0] else kwargs["boundaries"]["ep"][0] ur_lat = kwargs["boundaries"]["sp"][1] if kwargs["boundaries"]["sp"][1] > \ kwargs["boundaries"]["ep"][1] else kwargs["boundaries"]["ep"][1] ur_lon = kwargs["boundaries"]["sp"][0] if kwargs["boundaries"]["sp"][0] > \ kwargs["boundaries"]["ep"][0] else kwargs["boundaries"]["ep"][0] m = basemap.Basemap(projection='cyl', llcrnrlat=ll_lat - 0.1 * ll_lat, urcrnrlat=ur_lat + 0.1 * ur_lat, llcrnrlon=ll_lon + 0.05 * ll_lon, urcrnrlon=ur_lon - 0.05 * ur_lon, resolution='f', anchor='C') m.etopo() m.plot( [kwargs["boundaries"]["sp"][0], kwargs["boundaries"]["ep"][0]], [kwargs["boundaries"]["sp"][1], kwargs["boundaries"]["ep"][1]], color="k", linewidth=2) plt.axes([0.15, 0.25, 0.7, 0.35]) plt.xlabel( self.plot_xlabel if isinstance(self.plot_xlabel, str) else "", fontsize=12) plt.ylabel( self.plot_ylabel if isinstance(self.plot_ylabel, str) else "", fontsize=12) plt.title( self.plot_title if isinstance(self.plot_title, str) else "") # If the aspect ratio is too extreme, set it to auto. if kwargs["yticks"][0][2] / kwargs["xticks"][0][2] < 1/8 or \ kwargs["yticks"][0][2] / kwargs["xticks"][0][2] > 8/1: t = plt.imshow(data_cpy, cmap=colormap, norm=norm, aspect="auto") else: t = plt.imshow(data_cpy, cmap=colormap, norm=norm) if "yticks" in kwargs: plt.yticks(kwargs["yticks"][0], kwargs["yticks"][1]) else: plt.yticks([], []) if "xticks" in kwargs: plt.xticks(kwargs["xticks"][0], kwargs["xticks"][1]) else: plt.xticks([], []) if "topography" in kwargs and kwargs["topography"] is not None: x = [y for y in range(len(kwargs["topography"]))] plt.gca().set_ylim(kwargs["yticks"][0][2], kwargs["yticks"][0][0]) plt.plot(x, kwargs["topography"], "k-", linewidth=0.75) if not basic: cax = plt.axes([0.05, 0.1, 0.90, 0.02]) cbar = plt.colorbar(t, cax=cax, orientation='horizontal', ticks=self.ticks) cbar.set_label(self.plot_cbar_label if isinstance( self.plot_cbar_label, str) else "") if not save: plt.show() else: plt.savefig(save) else: return t
class Texture(object): """Simple Matplotlib agg_filter textures Parameters ---------- style : string default 'noise' One of the following styles * 'noise' - strictly random points * 'hash' - small lines oriented randomly * 'shadow' - create background shadow block : int default 1 Size of the points, in pixels. Larger values give coarser textures. light : bool default False Use noise as a depth map and light the surface. Works best when ``block`` is at least 2. Other Options ------------- 'noise' : options to set amount and darkness of points * prob : float (0.0 - 1.0) - probability a point will be changed * dark : float (0.0 - 1.0) - how dark to make random points. Small values are better. 'hash' : options to set spacing and darkness of lines * space : int default 4 - roughly how far apart lines are * dark : float (0.0 - 1.0) - how dark to make random points. Small values are better. light : options passed to the matplotlib.colors.LightSource.rgb_shade method. * fraction : float (0.0 - 1.0) alpha value * vert_exag : float amount of vertical exaggeration. * blend_mode : string ['soft'|'overlay'|'hsv'] blending mode shadow : options to define the shadow. Supplied object becomes the shadow. * direction : ['up'|'all'] Use 'up' for upward shadows * width : float 0.5 How large to make the shadow (screen inches) * alpha : float 0.5 How dark to make the shadow * color : (0, 0, 0) Color to use for shadow * cut_figure : False Remove shape from shadow (use if main object is semi-transparent). * offset : (0, 0) Where to offset shadow (screen inches) * win : ['gaussian'|'hanning'] Shadow type. 'hanning' gives more spread-out shadow, 'gaussian' is more realistic. Usage ----- Create a Texture object with the desired options, then pass this object to the agg_filter keyword in matplotlib routines. Example ------- :: from Texture import Texture import matplotlib.pyplot as plt filt = Texture('noise', block=4, light=True) shadow = Texture('shadow', width=.5, offset=(-.25, .25)) fig = plt.figure() ax = fig.add_subplot(111) ax.fill_between([0,1], [1,1], agg_filter=shadow) # create shadow first ax.fill_between([0,1], [1,1], agg_filter=filt) plt.show() """ def __init__(self, style='noise', **kwargs): """Initialize object with values to be used when called. """ self.style = style if style == 'shadow': self.direction = kwargs.get('direction', 'up') self.width = kwargs.get('width', .5) self.alpha = kwargs.get('alpha', .5) self.color = kwargs.get('color', (0, 0, 0)) self.cut_figure = kwargs.get('cut_figure', False) self.offset = kwargs.get('offset', (0, 0)) self.win = kwargs.get('win', 'gaussian') return self.block = kwargs.get('block', 1) self.light = kwargs.get('light', False) if self.light: prob = kwargs.get('prob', .15) dark = kwargs.get('dark', .15) self.vert = kwargs.get('vert_exag', 2.) self.blend = kwargs.get('blend_mode', 'soft') self.fraction = kwargs.get('fraction', .5) self.light_source = LightSource() else: prob = kwargs.get('prob', .2) dark = kwargs.get('dark', .02) if style == 'hash': # hash spreads out points somewhat evenly, but random within # spaces. Up to 2 points are chosen per space. # Set up arrays and their probabilities if not self.light: dark = kwargs.get('dark', .04) self.dark = dark self.space = kwargs.get('space', 4) self.frac = kwargs.get('frac', .8) # fraction of spaces to fill self.clip = (1. - dark)**3 # clip limit (max darkness) # make list of directions and pairs of directions. # Directions are tuples of (dx, dy) for adding to indices dtns = [(1, 0), (-1, 0), (0, 1), (0, -1)] # directions self.pairs = [] # list of pairs of directions for i in range(3): for j in range(i+1,4): self.pairs.append([dtns[i], dtns[j]]) else: self.choice = list(1. - np.array([1,2,3]) * dark) + [1.] self.p = 3 * [prob] + [1. - 3 * prob] self.kwargs = kwargs def __call__(self, im, dpi=100): """Main call routine, which passes image to other routines for processing. """ if self.style == 'noise': return self._noise(im), 0, 0 if self.style == 'hash': return self._hash(im), 0, 0 if self.style == 'shadow': return self._shadow(im, dpi) return im, 0, 0 # Do nothing if style not found def _expand(self, small, large): """Expand small 2D array into large 2D array. Clipping not supported. small : 2D np.array large : 2D np.array must be n-times larger than small Note: Make sure to only supply 2D arrays, not 3D, ie self._expand(small, large[:, :, 0]) if necessary. """ n = self.block if n == 1: large[...] = small return nx, ny = large.shape dx = nx % n dy = ny % n for a in range(n): for b in range(n): large[a:nx-dx:n, b:ny-dy:n] = small def _combine(self, rgb, alpha): # return new array with rgb and alpha nx, ny = alpha.shape tgt = np.empty((nx, ny, 4)) tgt[..., :3] = rgb tgt[..., 3] = alpha return tgt def _light(self, rgb, elevation): """Shade the supplied rgb array with the 2D elevation array. Note: elevation must be 2D, ie use noise[:, :, 0] if necessary. """ rgb2 = self.light_source.shade_rgb(rgb, elevation, blend_mode=self.blend, fraction=self.fraction, vert_exag=self.vert) return rgb2 def _noise(self, im): """ Simple noise texture with block and light support. Points are one of three darkness levels. """ n = self.block rgb = im[...,:3] # (nx, ny, 3) alpha = im[...,3] # (nx, ny) nx, ny = alpha.shape shape = (nx//n + 1, ny//n + 1) # expand shape slightly small = rnd.choice(self.choice, shape, p=self.p) # (nx, ny) large = np.ones((shape[0]*n, shape[1]*n)) self._expand(small, large) noise = np.ones((nx, ny, 1)) # (nx, ny, 1) noise[..., 0] = large[:nx, :ny] if self.light: rgb = self._light(rgb, noise[..., 0]) else: rgb *= noise # (nx, ny, 3) = (nx, ny, 3) * (nx, ny, 1) return self._combine(rgb, alpha) def _hash(self, im): """Similar to 'noise', but using small lines instead of points """ n = self.block space = self.space rgb = im[...,:3] # (nx, ny, 3) alpha = im[...,3] # (nx, ny) nx, ny = alpha.shape # Expand image size so it takes multiples of block and space. # The buffers will be clipped later to fit into supplied size shape = (nx//n + 1, ny//n + 1) shape = ((shape[0]+(n+2)*space)//space * space, (shape[1]+(n+2)*space)//space * space) # calculate number of points to be plotted. px = shape[0]//space py = shape[1]//space plen = px * py p = np.arange(plen) ix = [] iy = [] for i in range(2): # Do this for each set of points # make the indices for the point array, spread out by space # if space==4, then ix goes up 0, 0, 0,... 0, 4, 4,... # and y goes up 0, 4, 8,..., 0, 4, 8,... ix.append((p//py) * space) iy.append((p % px) * space) # now put them randomly in the spaces ix[i] += rnd.randint(0, space, plen) iy[i] += rnd.randint(0, space, plen) # a[ix, iy] will be the locations of random but evenly spread points. # Next step is to randomly choose these points to be given one of # the 4 possible directions. p is already an index into the points, # so just scramble p up and divide into 4 groups. Choosing fewer # points will create blank spots. # But I want 2 points per space, and I don't want to repeat the # directions used. This makes 6 possible pairs of directions, so # create 2 sets of points and divide them into 6 groups by reshaping # the vectors into (n//6, 6) arrays. r = [] # This will hold arrays of randomized indices slen = int((plen * self.frac)//6) # length of subsets rlen = slen * 6 # total length of randomize indices for i in range(2): temp = rnd.choice(p, plen, replace=False) temp = temp[:rlen] # truncate to needed size r.append(temp.reshape((slen, 6))) # Now stamp the points onto a buffer buffer = np.ones(shape) bright = 1. - self.dark # brightness points = 3 # number of points in line for i in range(6): for j in range(2): dx, dy = self.pairs[i][j] x = ix[j][r[j][:,i]] y = iy[j][r[j][:,i]] # bright gets darker as you raise it to higher powers. buffer[x,y] = bright**points for k in range(points-1): x += dx y += dy # wrap indices around if they fall outside shape x %= shape[0] y %= shape[1] # add brightest points last buffer[x,y] = bright**(points-1-k) large = np.ones((shape[0]*n, shape[1]*n)) self._expand(buffer, large) noise = np.ones((nx, ny, 1)) noise[..., 0] = large[:nx, :ny] if self.light: rgb = self._light(rgb, noise[..., 0]) else: rgb *= noise # (nx, ny, 3) = (nx, ny, 3) * (nx, ny, 1) return self._combine(rgb, alpha) def _shadow(self, im, dpi): """Create a drop shadow from the supplied image """ def gaussian(n=50, lim=3): """ Gaussian window, with endpoints near 0. ``lim`` controls how narrow the peak is, and how 'tight' the shadow becomes. A larger value is narrower, with more of the shadow closer to the object. """ x = np.linspace(-lim, lim, n) s = -0.5 * x**2 y = np.exp(s) y -= y[0] - .01 y /= y.max() return y alpha = im[...,3] # (nx, ny) nx, ny = alpha.shape is_up = (self.direction == 'up') # Calculate and apply padding to image pix = int(self.width * dpi) if is_up == 'up': padded = np.zeros((nx, ny+pix)) xs = ys = 0 # image start location else: padded = np.zeros((nx + 2*pix, ny + 2*pix)) xs = ys = pix # padded starts with chart object shape which gets blurred (smoothed). # It will then become the alpha channel for the expanded image. padded[xs:nx+xs, ys:ny+ys] = alpha # Create window for smoothing # Hanning is used instead of Hamming to reduce abruptness at ends if self.win == 'gaussian': w = gaussian(2 * pix + 1) else: w = np.hanning(2 * pix + 1) + .01 if is_up: w[pix+1:] = 0 # just use beginning of window w /= w.sum() # normalize # Smoth image in appropriate directions # Note no extra padding is used on convolutions, so may cause # artifacts for edge cases. See arg_filter demo for example. if not is_up: for x in range(padded.shape[0]): # horizontal y = padded[x, :] # add some additional padding for the convolution yc = np.convolve(w, y, mode='same') padded[x, :] = yc for y in range(padded.shape[1]): # vertical x = padded[:, y] # add some additional padding for the convolution xc = np.convolve(w, x, mode='same') padded[:, y] = xc # Normalize padded so that it has uniform darkness between figures padded /= padded.max() # Cut out original figure if desired if self.cut_figure: reverse = 1. - alpha padded[xs:nx+xs, ys:ny+ys] *= reverse # Return image rgb = np.ones((padded.shape[0], padded.shape[1], 3)) * self.color padded *= self.alpha new_im = self._combine(rgb, padded) return (new_im, self.offset[0] * dpi - xs, self.offset[1] * dpi - ys)
def show_plot(self, x_points: np.array, y_points: np.array, data: np.ndarray, map_plot: bool, **kwargs) -> bool: """ Displays the plot to the user. :param x_points: X co-ordinates for the data points. :param y_points: Y co-ordinates for the data points. :param data: The data points as a 1D grid, X-fast. :param map_plot: If set to true, the data is plotted on a map. If false, just generic data. :return: True, if plot was shown successfully. False if not. """ ranges = { "min_lon": np.amin(x_points), "max_lon": np.amax(x_points), "min_lat": np.amin(y_points), "max_lat": np.amax(y_points) } colormap = cm.RdBu norm = mcolors.Normalize(vmin=self.bounds[0], vmax=self.bounds[len(self.bounds) - 1]) faults = False save = False if "basic" in kwargs: basic = kwargs["basic"] else: basic = False if hasattr(self, "extras"): if "data" in self.extras: if "save" in self.extras["data"]: if str(self.extras["data"]["save"]).lower() == "y": save = os.path.join(self.extras["data"]["location"], self.extras["data"]["name"] + ".png") if "plot" in self.extras: if "save" in self.extras["plot"]: save = self.extras["plot"]["save"] if "features" in self.extras["plot"]: if "colormap" in self.extras["plot"]["features"]: try: colormap = getattr( cm, self.extras["plot"]["features"]["colormap"] ) except AttributeError: colormap = getattr( basemapcm, self.extras["plot"]["features"]["colormap"] ) if "scale" in self.extras["plot"]["features"]: if str(self.extras["plot"]["features"]["scale"]).lower().strip() \ == "discrete": colormap = self._cmapDiscretize(colormap, len(self.bounds) - 1) norm = mcolors.BoundaryNorm(self.bounds, colormap.N) if "faults" in self.extras["plot"]["features"]: if str(self.extras["plot"]["features"]["faults"]).lower().strip() == "yes": faults = True if map_plot: colormap.set_bad("gray", 1) if not basic: plt.axes([0.15, 0.2, 0.70, 0.70]) # Check to see if we have pickled this particular basemap instance. m = basemap.Basemap(projection='cyl', llcrnrlat=ranges["min_lat"], urcrnrlat=ranges["max_lat"], llcrnrlon=ranges["min_lon"], urcrnrlon=ranges["max_lon"], resolution='f', anchor='C') if not basic: lat_ticks = np.arange(ranges["min_lat"], ranges["max_lat"], (ranges["max_lat"] - ranges["min_lat"]) / 2) lat_ticks = np.append(lat_ticks, [ranges["max_lat"]]) lon_ticks = np.arange(ranges["min_lon"], ranges["max_lon"], (ranges["max_lon"] - ranges["min_lon"]) / 2) lon_ticks = np.append(lon_ticks, [ranges["max_lon"]]) lat_ticks = [round(x, 2) for x in lat_ticks] lon_ticks = [round(x, 2) for x in lon_ticks] m.drawparallels(lat_ticks, linewidth=1.0, labels=[1, 0, 0, 0]) m.drawmeridians(lon_ticks, linewidth=1.0, labels=[0, 0, 0, 1]) data_cpy = np.ma.masked_invalid(data) if "topography" in kwargs and kwargs["topography"] is not None: # create light source object. ls = LightSource(azdeg=315, altdeg=45) # convert data to rgb array including shading from light source. # (must specify color map) low_indices = kwargs["topography"] < 0 kwargs["topography"][low_indices] = 0 rgb = ls.shade_rgb(colormap(norm(data_cpy)), kwargs["topography"], blend_mode="overlay", vert_exag=2) for y in range(len(rgb)): for x in range(len(rgb[0])): rgb[y][x][0] *= 0.90 rgb[y][x][1] *= 0.90 rgb[y][x][2] *= 0.90 t = m.imshow(rgb, cmap=colormap, norm=norm) else: t = m.pcolormesh(x_points, y_points, data_cpy, cmap=colormap, norm=norm) m.drawstates() m.drawcountries() m.drawcoastlines() # If we want the fault lines we need to plot them. if faults: for key, fault_coords in Fault().get_all_faults().items(): fault_lons = [] fault_lats = [] for x, y in fault_coords: fault_lons.append(x) fault_lats.append(y) m.plot(fault_lons, fault_lats, "k-", linewidth=1) if not basic: plt.xlabel(self.plot_xlabel if isinstance(self.plot_xlabel, str) else "", fontsize=14) plt.ylabel(self.plot_ylabel if isinstance(self.plot_ylabel, str) else "", fontsize=14) plt.title(self.plot_title if isinstance(self.plot_title, str) else "") else: colormap.set_bad("gray", 1) data_cpy = np.ma.masked_invalid(data) data_cpy = np.ma.masked_less_equal(data_cpy, 0) plt.axes([0.1, 0.7, 0.8, 0.25]) ll_lat = kwargs["boundaries"]["sp"][1] if kwargs["boundaries"]["sp"][1] < \ kwargs["boundaries"]["ep"][1] else kwargs["boundaries"]["ep"][1] ll_lon = kwargs["boundaries"]["sp"][0] if kwargs["boundaries"]["sp"][0] < \ kwargs["boundaries"]["ep"][0] else kwargs["boundaries"]["ep"][0] ur_lat = kwargs["boundaries"]["sp"][1] if kwargs["boundaries"]["sp"][1] > \ kwargs["boundaries"]["ep"][1] else kwargs["boundaries"]["ep"][1] ur_lon = kwargs["boundaries"]["sp"][0] if kwargs["boundaries"]["sp"][0] > \ kwargs["boundaries"]["ep"][0] else kwargs["boundaries"]["ep"][0] m = basemap.Basemap(projection='cyl', llcrnrlat=ll_lat - 0.1 * ll_lat, urcrnrlat=ur_lat + 0.1 * ur_lat, llcrnrlon=ll_lon + 0.05 * ll_lon, urcrnrlon=ur_lon - 0.05 * ur_lon, resolution='f', anchor='C') m.etopo() m.plot([kwargs["boundaries"]["sp"][0], kwargs["boundaries"]["ep"][0]], [kwargs["boundaries"]["sp"][1], kwargs["boundaries"]["ep"][1]], color="k", linewidth=2) plt.axes([0.15, 0.25, 0.7, 0.35]) plt.xlabel(self.plot_xlabel if isinstance(self.plot_xlabel, str) else "", fontsize=12) plt.ylabel(self.plot_ylabel if isinstance(self.plot_ylabel, str) else "", fontsize=12) plt.title(self.plot_title if isinstance(self.plot_title, str) else "") # If the aspect ratio is too extreme, set it to auto. if kwargs["yticks"][0][2] / kwargs["xticks"][0][2] < 1/8 or \ kwargs["yticks"][0][2] / kwargs["xticks"][0][2] > 8/1: t = plt.imshow(data_cpy, cmap=colormap, norm=norm, aspect="auto") else: t = plt.imshow(data_cpy, cmap=colormap, norm=norm) if "yticks" in kwargs: plt.yticks(kwargs["yticks"][0], kwargs["yticks"][1]) else: plt.yticks([], []) if "xticks" in kwargs: plt.xticks(kwargs["xticks"][0], kwargs["xticks"][1]) else: plt.xticks([], []) if "topography" in kwargs and kwargs["topography"] is not None: x = [y for y in range(len(kwargs["topography"]))] plt.gca().set_ylim(kwargs["yticks"][0][2], kwargs["yticks"][0][0]) plt.plot(x, kwargs["topography"], "k-", linewidth=0.75) if not basic: cax = plt.axes([0.05, 0.1, 0.90, 0.02]) cbar = plt.colorbar(t, cax=cax, orientation='horizontal', ticks=self.ticks) cbar.set_label(self.plot_cbar_label if isinstance(self.plot_cbar_label, str) else "") if not save: plt.show() else: plt.savefig(save) else: return t
def drawmol(mol, backgroundColor='k'): """ # DRAWMOL(MOL) # Render simple molecules. Large molecules will require # considerable computing power. # Colors: # White: hydrogen # Black: carbon # Red: oxygen # Blue: nitrogen # Yellow: sulphur # Grey: other. #Based on DRAWPDB by Joe Hicklin, September 2001. """ # creating size of the spheres if len(mol['x']) > 50: #X,Y,Z = sphere2(10) sphere_size = 10 else: #X,Y,Z = sphere2(20) sphere_size = 20 # Set view parameters for all subplots. azimuth = 90 altitude = 90 # preparing the canvas plt.close('all') plt.ion() fig = plt.figure(1, figsize=(8, 8)) ax = fig.add_subplot(1, 1, 1, projection='3d') ax.view_init(altitude, azimuth) # loop over the mols for ii in range(len(mol['x'])): if mol['element'][ii] == 'H': #colorBead='w' colorBead = (.9, 1, .9) r = 0.5 elif mol['element'][ii] == 'C': #colorBead='k' colorBead = (0.25, 0.25, 0.25) r = 0.85 elif mol['element'][ii] == 'O': #colorBead='r' colorBead = (1, 0, 0) r = 0.95 elif mol['element'][ii] == 'N': #colorBead='b' colorBead = (0, 0, 1) r = 0.9 elif mol['element'][ii] == 'S': #colorBead='y' colorBead = (1, 1, 0) r = 1.0 else: colorBead = (0.6, 0.6, 0.6) r = 0.9 # creating the sphere with radius value X, Y, Z = sphere2(sphere_size, radius=r) # preparing the light rgb = np.ones((Z.shape[0], Z.shape[1], 3)) light = LightSource(90, 45) # give the color to the shaded surface illuminatedSurface = light.shade_rgb(rgb * colorBead, Z) # adding beads with different color and radius to plots ax.plot_surface( mol['x'][ii] + X, mol['y'][ii] + Y, mol['z'][ii] + Z, rstride=1, cstride=1, linewidth=0, color=colorBead, #facecolors =illuminatedSurface, antialiased=False) if backgroundColor == 'black': ax.set_facecolor((0, 0, 0)) elif backgroundColor == 'white': ax.set_facecolor(( 1, 1, 1, )) elif backgroundColor == 'grey': ax.set_facecolor((0.5, 0.5, 0.5)) else: print('Background color not implement yet. Using black') ax.set_facecolor((0, 0, 0)) xmin, xmax, ymin, ymax = ax.axis() zmin = 0.8 * np.min((xmin, ymin)) zmax = 0.8 * np.max((xmax, ymax)) ax.set_xlabel('x [Angstrom]', fontsize=14) ax.set_ylabel('y [Angstrom]', fontsize=14) plt.tight_layout() ax.auto_scale_xyz([xmin, xmax], [ymin, ymax], [zmin, zmax]) #ax.set_axis_off() plt.show(block=False)
altitude = 60 # Create empty figure. fig = plt.figure(figsize=(18, 12)) # ------------------------------------------------------------------------- # Generate first subplot. # ------------------------------------------------------------------------- # Create a light source object for light from # 0 degrees azimuth, 0 degrees elevation. light = LightSource(0, 0) # Generate face colors for a shaded surface using either # a color map or the uniform rgb color specified above. illuminated_surface = light.shade_rgb(red, Z) # Create a subplot with 3d plotting capabilities. # This command will fail if Axes3D was not imported. ax = fig.add_subplot(2, 2, 1, projection='3d') ax.view_init(altitude, azimuth) ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0, antialiased=False, facecolors=illuminated_surface) # -------------------------------------------------------------------------
k = float(input()) frac = k u = np.linspace(0, 2 * np.pi, approx) v = np.linspace(0, np.pi, approx) X = np.outer(np.cos(u), np.sin(v)) Y = np.outer(np.sin(u), np.sin(v)) Z = np.outer(np.ones(np.size(u)), np.cos(v)) light = LightSource(azdeg=0, altdeg=60) rgb = np.ones((X.shape[0], X.shape[1], 3)) illuminated_surface = light.shade_rgb(rgb, X, fraction=frac) ax.plot_surface(X, Y, Z, linewidth=0.0, facecolors=illuminated_surface, shade=False) ax.set_aspect('equal') plt.show()
for j in xrange(0,i,1): if(np.linalg.norm(X[i]-X[j])<=1.3*d[i]): ax1.plot([ X[i][0],X[j][0] ], [ X[i][1],X[j][1] ], [ X[i][2],X[j][2] ],linewidth=3,alpha=0.7,color='black') X=np.transpose(X) ax1.scatter(X[0], X[1], X[2], s=600, marker='.',color='b') ax1.axis('off') #Make sphere r = 1.00 pi = np.pi cos = np.cos sin = np.sin phi, theta = np.mgrid[0.0:pi:100j, 0.0:2.0*pi:100j] x = r*sin(phi)*cos(theta) y = r*sin(phi)*sin(theta) z = r*cos(phi) white = np.ones((z.shape[0], z.shape[1], 3)) red = white * np.array([0.1,.1,.1]) green = white * np.array([0,1,0]) blue = white * np.array([0,0,1]) light = LightSource(60, 45) illuminated_surface = light.shade_rgb(red, z) ax1.plot_surface(x, y, z, rstride=1, cstride=1, antialiased=False, color='white', alpha=0.2, linewidth=0) #Show nearest neighbor distances #print("average dist: {}".format(np.average(d))) plt.show()
lons = ogrid[extent[0]:extent[1]:N] lats = ogrid[extent[2]:extent[3]:N] # mmidat = m.transform_scalar(resampled,lons,lats,nx,ny) mmidat = m.transform_scalar(resampled.T, lons, lats, nx, ny) print 'Getting colormap...' # get colormap cptfile = '../data/topo/haz.cpt' cmap, zvals = cpt2colormap(cptfile, 256) # make shading print 'Making map...' ls = LightSource(azdeg=180, altdeg=0) norm = mpl.colors.Normalize(vmin=0.0, vmax=1.4) #myb rgb = ls.shade_rgb(cmap(norm(mmidat)), topodat, blend_mode='hsv', vert_exag=1) im = m.imshow(rgb) ########################################################################################## # get land & lake polygons for masking ########################################################################################## polys = get_map_polygons(m) mask_outside_polygons(polys, 'lightskyblue', plt) # get lake ploygons polygons = [] for polygon in m.lakepolygons: poly = polygon.get_coords() plt.fill(poly[:, 0], poly[:, 1], 'lightskyblue') polygons.append(poly)
a = Arrow3D([0, 0], [-1, 1], [-1, -1], **arrowprops) ax.add_artist(a) # For surface illumination, see # http://physicalmodelingwithpython.blogspot.de/2015/08/illuminating-surface-plots.html # Get lighting object for shading surface plots. from matplotlib.colors import LightSource # Get colormaps to use with lighting object. from matplotlib import cm # Create an instance of a LightSource and use it to illuminate the surface. light = LightSource(70, -120) white = np.ones((zz.shape[0], zz.shape[1], 3)) illuminated_surface = light.shade_rgb(white * (0, 1, 0), zz) ax.plot_surface(tt, yy, zz, cstride=1, rstride=1, alpha=0.3, facecolors=illuminated_surface, linewidth=0) verts = [array([(-1, -1), (-1, 1), (1, 1), (1, -1), (-1, -1)])] poly = PolyCollection(verts, facecolors=c_plane) ax.add_collection3d(poly, zs=[0], zdir='x') poly = PolyCollection(verts, facecolors=c_plane)
def drape_plot(data, relief, extent, vmax='max', vmin='min', az=315, alt=45, cmap='hot_r', blend_mode='hsv', contrast=1, definition=1, origin='upper', ax=None, colorbar=True): """ Drape `data` over `relief`. This is done using the :meth:`~matplotlib.colors.LightSource.shade_rgb` method of the :class:`~matplotlib.colors.LightSource` class. Parameters ---------- data : a 2d :class:`~numpy.ndarray` Contains data to be draped over relief. relief : a 2d :class:`~numpy.ndarray` Contains elevation (usually). extent : array-like Extent of the domain plotted. (xmin,xmax,ymin,ymax) or (w,e,s,n) vmax, vmin : str or float Used to clip the coloring of the data at the set value. Default is 'max' and 'min' which used the extent of the data. If ``float``s, the colorscale saturates at the given values. Finally, if a string is passed (other than 'max' or 'min'), it is casted to float and used as an ``rms`` multiplier. For instance, if ``vmax='3'``, clipping is done at 3.0\*rms of the data. To force symmetric coloring around 0 set `vmin` to ``None`` or ``False``. This will cause `vmin` to equal `vmax`. az : int or float The azimuth (0-360, degrees clockwise from North) of the light source. Defaults to 315 degrees (from the northwest). alt : int or float The altitude (0-90, degrees up from horizontal) of the light source. Defaults to 45 degrees from horizontal. cmap : str or :class:`~matplotlib.colors.Colormap` instance String of the name of the colormap, i.e. 'Greys', or a :class:`~matplotlib.colors.Colormap` instance used for the data. blend_mode : {'hsv', 'overlay', 'soft', callable} The type of blending used to combine the colormapped data values with the illumination intensity. For backwards compatibility, this defaults to 'hsv'. Note that for most topographic surfaces, 'overlay' or 'soft' appear more visually realistic. If a user-defined function is supplied, it is expected to combine an MxNx3 RGB array of floats (ranging 0 to 1) with an MxNx1 hillshade array (also 0 to 1). (Call signature func(rgb, illum, \*\*kwargs)) contrast : int or float Increases or decreases the contrast of the hillshade. If > 1 intermediate values move closer to full illumination or shadow (and clipping any values that move beyond 0 or 1). Note that this is not visually or mathematically the same as definition. definition : int or float Higher definition is achieved by scaling the elevation prior to the illumination calculation. This can be used either to correct for differences in units between the x,y coordinate system and the elevation coordinate system (e.g. decimal degrees vs meters) or to exaggerate or de-emphasize topography. origin : {'upper', 'lower'} Places the origin at the 'upper' (default) or 'lower' left corner of the plot. ax : :class:`~matplotlib.axes.Axes` instance Plot to an existing axes. If None, a :class:`~matplotlib.figure.Figure` and :class:`~matplotlib.axes.Axes` are created and their instances are returned for further manipulation. colorbar : bool By default, a colorbar is drawn with the plot. If `colorbar` is a string, it is used for the label of the colorbar. Otherwise, the colorbar can be omitted by setting to False. :class:`~matplotlib.colorbar.Colorbar` instance is returned. .. note:: *All* grids must have the same extent and origin! """ if not ax: fig, ax = plt.subplots() ax.axis(extent) ax.set_aspect(1) # data if vmax is 'max': clip = np.nanmax(data) elif type(vmax) in INT_AND_FLOAT: clip = vmax else: clip = float(vmax) * np.nanstd(data) if vmin is 'min': vmin = np.nanmin(data) elif type(vmin) in [int, float]: pass elif vmin in [None, False]: vmin = -clip vmax = clip if vmin > data.min() and vmax < data.max(): extend = 'both' elif vmin > data.min(): extend = 'min' elif vmax < data.max(): extend = 'max' else: extend = 'neither' im = ax.imshow(data, cmap=cmap, vmin=vmin, vmax=vmax) im.remove() if data.size < relief.size: _, _, data = resample(data, extent, relief.shape) elif data.size > relief.size: _, _, relief = resample(relief, extent, data.shape) norm = Normalize(vmin, vmax) ls = LightSource(azdeg=az, altdeg=alt) if type(cmap) is str: cmap = plt.cm.get_cmap(cmap) rgba = ls.shade_rgb(cmap(norm(data)), relief, fraction=contrast, blend_mode=blend_mode, vert_exag=definition) ax.imshow(rgba, extent=extent, origin=origin) # make sure no offsets are introduced ax.ticklabel_format(useOffset=False) if colorbar: divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='3%', pad=0.1) cb = plt.colorbar(im, cax=cax, extend=extend) if type(colorbar) is str: cb.set_label(colorbar) cb.solids.set_edgecolor('face') cb.formatter.set_scientific(True) cb.formatter.set_powerlimits((-1, 4)) cb.update_ticks() else: cb = None try: return fig, ax, cb except NameError: return cb