def test_light_source_planar_hillshading(): """Ensure that the illumination intensity is correct for planar surfaces.""" def plane(azimuth, elevation, x, y): """Create a plane whose normal vector is at the given azimuth and elevation.""" theta, phi = _azimuth2math(azimuth, elevation) a, b, c = _sph2cart(theta, phi) z = -(a * x + b * y) / c return z def angled_plane(azimuth, elevation, angle, x, y): """Create a plane whose normal vector is at an angle from the given azimuth and elevation.""" elevation = elevation + angle if elevation > 90: azimuth = (azimuth + 180) % 360 elevation = (90 - elevation) % 90 return plane(azimuth, elevation, x, y) y, x = np.mgrid[5:0:-1, :5] for az, elev in itertools.product(range(0, 390, 30), range(0, 105, 15)): ls = mcolors.LightSource(az, elev) # Make a plane at a range of angles to the illumination for angle in range(0, 105, 15): z = angled_plane(az, elev, angle, x, y) h = ls.hillshade(z) assert_array_almost_equal(h, np.cos(np.radians(angle)))
def test_light_source_topo_surface(): """Shades a DEM using different v.e.'s and blend modes.""" fname = cbook.get_sample_data('jacksboro_fault_dem.npz', asfileobj=False) dem = np.load(fname) elev = dem['elevation'] # Get the true cellsize in meters for accurate vertical exaggeration # Convert from decimal degrees to meters dx, dy = dem['dx'], dem['dy'] dx = 111320.0 * dx * np.cos(dem['ymin']) dy = 111320.0 * dy dem.close() ls = mcolors.LightSource(315, 45) cmap = cm.gist_earth fig, axes = plt.subplots(nrows=3, ncols=3) for row, mode in zip(axes, ['hsv', 'overlay', 'soft']): for ax, ve in zip(row, [0.1, 1, 10]): rgb = ls.shade(elev, cmap, vert_exag=ve, dx=dx, dy=dy, blend_mode=mode) ax.imshow(rgb) ax.set(xticks=[], yticks=[])
def test_light_source_hillshading(): """Compare the current hillshading method against one that should be mathematically equivalent. Illuminates a cone from a range of angles.""" def alternative_hillshade(azimuth, elev, z): illum = _sph2cart(*_azimuth2math(azimuth, elev)) illum = np.array(illum) dy, dx = np.gradient(-z) dy = -dy dz = np.ones_like(dy) normals = np.dstack([dx, dy, dz]) dividers = np.zeros_like(z)[..., None] for i, mat in enumerate(normals): for j, vec in enumerate(mat): dividers[i, j, 0] = np.linalg.norm(vec) normals /= dividers # once we drop support for numpy 1.7.x the above can be written as # normals /= np.linalg.norm(normals, axis=2)[..., None] # aviding the double loop. intensity = np.tensordot(normals, illum, axes=(2, 0)) intensity -= intensity.min() intensity /= intensity.ptp() return intensity y, x = np.mgrid[5:0:-1, :5] z = -np.hypot(x - x.mean(), y - y.mean()) for az, elev in itertools.product(range(0, 390, 30), range(0, 105, 15)): ls = mcolors.LightSource(az, elev) h1 = ls.hillshade(z) h2 = alternative_hillshade(az, elev, z) assert_array_almost_equal(h1, h2)
def test_light_source_shading_default(): """Array comparison test for the default "hsv" blend mode. Ensure the default result doesn't change without warning.""" y, x = np.mgrid[-1.2:1.2:8j, -1.2:1.2:8j] z = 10 * np.cos(x**2 + y**2) cmap = plt.cm.copper ls = mcolors.LightSource(315, 45) rgb = ls.shade(z, cmap) # Result stored transposed and rounded for for more compact display... expect = np.array( [[[0.00, 0.45, 0.90, 0.90, 0.82, 0.62, 0.28, 0.00], [0.45, 0.94, 0.99, 1.00, 1.00, 0.96, 0.65, 0.17], [0.90, 0.99, 1.00, 1.00, 1.00, 1.00, 0.94, 0.35], [0.90, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.49], [0.82, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.41], [0.62, 0.96, 1.00, 1.00, 1.00, 1.00, 0.90, 0.07], [0.28, 0.65, 0.94, 1.00, 1.00, 0.90, 0.35, 0.01], [0.00, 0.17, 0.35, 0.49, 0.41, 0.07, 0.01, 0.00]], [[0.00, 0.28, 0.59, 0.72, 0.62, 0.40, 0.18, 0.00], [0.28, 0.78, 0.93, 0.92, 0.83, 0.66, 0.39, 0.11], [0.59, 0.93, 0.99, 1.00, 0.92, 0.75, 0.50, 0.21], [0.72, 0.92, 1.00, 0.99, 0.93, 0.76, 0.51, 0.18], [0.62, 0.83, 0.92, 0.93, 0.87, 0.68, 0.42, 0.08], [0.40, 0.66, 0.75, 0.76, 0.68, 0.52, 0.23, 0.02], [0.18, 0.39, 0.50, 0.51, 0.42, 0.23, 0.00, 0.00], [0.00, 0.11, 0.21, 0.18, 0.08, 0.02, 0.00, 0.00]], [[0.00, 0.18, 0.38, 0.46, 0.39, 0.26, 0.11, 0.00], [0.18, 0.50, 0.70, 0.75, 0.64, 0.44, 0.25, 0.07], [0.38, 0.70, 0.91, 0.98, 0.81, 0.51, 0.29, 0.13], [0.46, 0.75, 0.98, 0.96, 0.84, 0.48, 0.22, 0.12], [0.39, 0.64, 0.81, 0.84, 0.71, 0.31, 0.11, 0.05], [0.26, 0.44, 0.51, 0.48, 0.31, 0.10, 0.03, 0.01], [0.11, 0.25, 0.29, 0.22, 0.11, 0.03, 0.00, 0.00], [0.00, 0.07, 0.13, 0.12, 0.05, 0.01, 0.00, 0.00]], [[1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00]] ]).T if (V(np.__version__) == V('1.9.0')): # Numpy 1.9.0 uses a 2. order algorithm on the edges by default # This was changed back again in 1.9.1 expect = expect[1:-1, 1:-1, :] rgb = rgb[1:-1, 1:-1, :] assert_array_almost_equal(rgb, expect, decimal=2)
def lighting(M, upsample, cmap='gnuplot2'): light = colors.LightSource(180, 10) M = light.shade(M, cmap=plt.cm.get_cmap(cmap), vert_exag=1.25, norm=colors.PowerNorm(0.3), blend_mode='hsv', dx=int(upsample), dy=int(upsample)) return M
def test_light_source_masked_shading(): """ Array comparison test for a surface with a masked portion. Ensures that we don't wind up with "fringes" of odd colors around masked regions. """ y, x = np.mgrid[-1.2:1.2:8j, -1.2:1.2:8j] z = 10 * np.cos(x**2 + y**2) z = np.ma.masked_greater(z, 9.9) cmap = plt.cm.copper ls = mcolors.LightSource(315, 45) rgb = ls.shade(z, cmap) # Result stored transposed and rounded for more compact display... expect = np.array( [[[0.00, 0.46, 0.91, 0.91, 0.84, 0.64, 0.29, 0.00], [0.46, 0.96, 1.00, 1.00, 1.00, 0.97, 0.67, 0.18], [0.91, 1.00, 1.00, 1.00, 1.00, 1.00, 0.96, 0.36], [0.91, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 0.51], [0.84, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 0.44], [0.64, 0.97, 1.00, 1.00, 1.00, 1.00, 0.94, 0.09], [0.29, 0.67, 0.96, 1.00, 1.00, 0.94, 0.38, 0.01], [0.00, 0.18, 0.36, 0.51, 0.44, 0.09, 0.01, 0.00]], [[0.00, 0.29, 0.61, 0.75, 0.64, 0.41, 0.18, 0.00], [0.29, 0.81, 0.95, 0.93, 0.85, 0.68, 0.40, 0.11], [0.61, 0.95, 1.00, 0.78, 0.78, 0.77, 0.52, 0.22], [0.75, 0.93, 0.78, 0.00, 0.00, 0.78, 0.54, 0.19], [0.64, 0.85, 0.78, 0.00, 0.00, 0.78, 0.45, 0.08], [0.41, 0.68, 0.77, 0.78, 0.78, 0.55, 0.25, 0.02], [0.18, 0.40, 0.52, 0.54, 0.45, 0.25, 0.00, 0.00], [0.00, 0.11, 0.22, 0.19, 0.08, 0.02, 0.00, 0.00]], [[0.00, 0.19, 0.39, 0.48, 0.41, 0.26, 0.12, 0.00], [0.19, 0.52, 0.73, 0.78, 0.66, 0.46, 0.26, 0.07], [0.39, 0.73, 0.95, 0.50, 0.50, 0.53, 0.30, 0.14], [0.48, 0.78, 0.50, 0.00, 0.00, 0.50, 0.23, 0.12], [0.41, 0.66, 0.50, 0.00, 0.00, 0.50, 0.11, 0.05], [0.26, 0.46, 0.53, 0.50, 0.50, 0.11, 0.03, 0.01], [0.12, 0.26, 0.30, 0.23, 0.11, 0.03, 0.00, 0.00], [0.00, 0.07, 0.14, 0.12, 0.05, 0.01, 0.00, 0.00]], [[1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00]], ]).T assert_array_almost_equal(rgb, expect, decimal=2)
def test_light_source_shading_empty_mask(): y, x = np.mgrid[-1.2:1.2:8j, -1.2:1.2:8j] z0 = 10 * np.cos(x**2 + y**2) z1 = np.ma.array(z0) cmap = plt.cm.copper ls = mcolors.LightSource(315, 45) rgb0 = ls.shade(z0, cmap) rgb1 = ls.shade(z1, cmap) assert_array_almost_equal(rgb0, rgb1)
def test_light_source_masked_shading(): """Array comparison test for a surface with a masked portion. Ensures that we don't wind up with "fringes" of odd colors around masked regions.""" y, x = np.mgrid[-1.2:1.2:8j, -1.2:1.2:8j] z = 10 * np.cos(x**2 + y**2) z = np.ma.masked_greater(z, 9.9) cmap = plt.cm.copper ls = mcolors.LightSource(315, 45) rgb = ls.shade(z, cmap) # Result stored transposed and rounded for for more compact display... expect = np.array([[[1.00, 0.95, 0.96, 0.94, 0.86, 0.67, 0.40, 0.03], [0.95, 0.99, 1.00, 1.00, 1.00, 0.98, 0.67, 0.19], [0.96, 1.00, 1.00, 1.00, 1.00, 1.00, 0.78, 0.36], [0.94, 1.00, 1.00, 0.00, 0.00, 1.00, 0.55, 0.32], [0.86, 1.00, 1.00, 0.00, 0.00, 1.00, 0.27, 0.14], [0.67, 0.98, 1.00, 1.00, 1.00, 1.00, 0.07, 0.03], [0.40, 0.67, 0.78, 0.55, 0.27, 0.07, 0.00, 0.01], [0.03, 0.19, 0.36, 0.32, 0.14, 0.03, 0.01, 0.00]], [[1.00, 0.93, 0.93, 0.88, 0.72, 0.50, 0.28, 0.03], [0.93, 0.97, 0.99, 0.96, 0.87, 0.70, 0.42, 0.11], [0.93, 0.99, 0.74, 0.78, 0.78, 0.74, 0.45, 0.20], [0.88, 0.96, 0.78, 0.00, 0.00, 0.78, 0.32, 0.16], [0.72, 0.87, 0.78, 0.00, 0.00, 0.78, 0.14, 0.06], [0.50, 0.70, 0.74, 0.78, 0.78, 0.74, 0.03, 0.01], [0.28, 0.42, 0.45, 0.32, 0.14, 0.03, 0.00, 0.00], [0.03, 0.11, 0.20, 0.16, 0.06, 0.01, 0.00, 0.00]], [[1.00, 0.91, 0.91, 0.84, 0.64, 0.39, 0.21, 0.03], [0.91, 0.96, 0.98, 0.93, 0.77, 0.53, 0.27, 0.06], [0.91, 0.98, 0.47, 0.50, 0.50, 0.47, 0.25, 0.10], [0.84, 0.93, 0.50, 0.00, 0.00, 0.50, 0.13, 0.06], [0.64, 0.77, 0.50, 0.00, 0.00, 0.50, 0.03, 0.01], [0.39, 0.53, 0.47, 0.50, 0.50, 0.47, 0.00, 0.00], [0.21, 0.27, 0.25, 0.13, 0.03, 0.00, 0.00, 0.00], [0.03, 0.06, 0.10, 0.06, 0.01, 0.00, 0.00, 0.00]], [[1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 0.00, 0.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00]]]).T assert_array_almost_equal(rgb, expect, decimal=2)
def test_light_source_shading_default(): """Array comparison test for the default "hsv" blend mode. Ensure the default result doesn't change without warning.""" y, x = np.mgrid[-1.2:1.2:8j, -1.2:1.2:8j] z = 10 * np.cos(x**2 + y**2) cmap = plt.cm.copper ls = mcolors.LightSource(315, 45) rgb = ls.shade(z, cmap) # Result stored transposed and rounded for for more compact display... expect = np.array([[[0.87, 0.85, 0.90, 0.90, 0.82, 0.62, 0.34, 0.00], [0.85, 0.94, 0.99, 1.00, 1.00, 0.96, 0.62, 0.17], [0.90, 0.99, 1.00, 1.00, 1.00, 1.00, 0.71, 0.33], [0.90, 1.00, 1.00, 1.00, 1.00, 0.98, 0.51, 0.29], [0.82, 1.00, 1.00, 1.00, 1.00, 0.64, 0.25, 0.13], [0.62, 0.96, 1.00, 0.98, 0.64, 0.22, 0.06, 0.03], [0.34, 0.62, 0.71, 0.51, 0.25, 0.06, 0.00, 0.01], [0.00, 0.17, 0.33, 0.29, 0.13, 0.03, 0.01, 0.00]], [[0.87, 0.79, 0.83, 0.80, 0.66, 0.44, 0.23, 0.00], [0.79, 0.88, 0.93, 0.92, 0.83, 0.66, 0.38, 0.10], [0.83, 0.93, 0.99, 1.00, 0.92, 0.75, 0.40, 0.18], [0.80, 0.92, 1.00, 0.99, 0.93, 0.75, 0.28, 0.14], [0.66, 0.83, 0.92, 0.93, 0.87, 0.44, 0.12, 0.06], [0.44, 0.66, 0.75, 0.75, 0.44, 0.12, 0.03, 0.01], [0.23, 0.38, 0.40, 0.28, 0.12, 0.03, 0.00, 0.00], [0.00, 0.10, 0.18, 0.14, 0.06, 0.01, 0.00, 0.00]], [[0.87, 0.75, 0.78, 0.73, 0.55, 0.33, 0.16, 0.00], [0.75, 0.85, 0.90, 0.86, 0.71, 0.48, 0.23, 0.05], [0.78, 0.90, 0.98, 1.00, 0.82, 0.51, 0.21, 0.08], [0.73, 0.86, 1.00, 0.97, 0.84, 0.47, 0.11, 0.05], [0.55, 0.71, 0.82, 0.84, 0.71, 0.20, 0.03, 0.01], [0.33, 0.48, 0.51, 0.47, 0.20, 0.02, 0.00, 0.00], [0.16, 0.23, 0.21, 0.11, 0.03, 0.00, 0.00, 0.00], [0.00, 0.05, 0.08, 0.05, 0.01, 0.00, 0.00, 0.00]], [[1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00], [1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00]]]).T assert_array_almost_equal(rgb, expect, decimal=2)
def write_matrix(X: np.array, path: str = None) -> None: assert path is not None, "name required" M = X.copy() fig = plt.figure(figsize=(10, 10), dpi=200) ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1) # Shaded rendering light = colors.LightSource(azdeg=315, altdeg=10) M = light.shade(M, cmap=pom, vert_exag=1.5, norm=colors.PowerNorm(0.3), blend_mode="hsv") ax.imshow(M, interpolation="bicubic") ax.set_xticks([]) ax.set_yticks([]) plt.savefig(path)
def plotcomplex(function,height): norm = mcolors.Normalize(0,height) magnitudeplot = abs(function) print(magnitudeplot) phaseplot = (angle(-function)+np.pi)/2/np.pi #phaseplot-= min(min(x) for x in phaseplot) print(phaseplot.shape,magnitudeplot.shape) z_data_rgb = rgb((phaseplot)) print('max,min',max(max(x) for x in phaseplot),min(min(x) for x in phaseplot)) print(z_data_rgb.shape) intensity = norm(magnitudeplot) print(intensity.shape) ls = mcolors.LightSource() datap=ls.blend_hsv(z_data_rgb, intensity)*np.minimum(magnitudeplot[:,:,np.newaxis],1) #datap=ls.blend_hsv(z_data_rgb, intensity)*mag[:,:,np.newaxis] print (datap.shape,datap[:,:,0].max()) plt.imshow(datap,origin = 'lower',extent=[tre[0],tre[len(tre)-1],tim[0],tim[len(tim)-1]],interpolation='none') #plt.savefig('J0.png') plt.show()
def show_graphical(self): xmin, xmax, xn = -2.25, +0.75, 3000 / 2 ymin, ymax, yn = -1.25, +1.25, 2500 / 2 maxiter = 200 horizon = 2.0**40 log_horizon = np.log(np.log(horizon)) / np.log(2) Z, N = Mandelbrot.mandelbrot_set(self, xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon) with np.errstate(invalid='ignore'): M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z))) / np.log(2) + log_horizon) dpi = 72 width = 10 height = 10 * yn / xn fig = plt.figure(figsize=(width, height), dpi=dpi) ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) light = colors.LightSource(azdeg=315, altdeg=10) M = light.shade(M, cmap=plt.cm.hot, vert_exag=1.5, norm=colors.PowerNorm(0.3), blend_mode='hsv') plt.imshow(M, extent=[xmin, xmax, ymin, ymax], interpolation="bicubic") ax.set_xticks([]) ax.set_yticks([]) text = "The Mandelbrot fractal" ax.text(xmin + .025, ymin + .025, text, color="white", fontsize=12, alpha=0.5) plt.show()
def plot(): xmin, xmax, xn = -2.25, 0.75, 1500 ymin, ymax, yn = -1.25, 1.25, 1250 maxiter, horizon = 200, 2**40 log_horizon = np.log(np.log(horizon)) / np.log(2) z, n = mandelbrot(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon) with np.errstate(invalid='ignore'): m = np.nan_to_num(n + 1 - np.log(np.log(abs(z))) / np.log(2) + log_horizon) dpi = 72 width = 10 height = 10 * yn / xn fig = plt.figure(figsize=(width, height), dpi=dpi) ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) # Shaded rendering light = colors.LightSource(azdeg=315, altdeg=10) m = light.shade(m, cmap=plt.cm.hot, vert_exag=1.5, norm=colors.PowerNorm(0.3), blend_mode='hsv') plt.imshow(m, extent=[xmin, xmax, ymin, ymax], interpolation="bicubic") ax.set_xticks([]) ax.set_yticks([]) text = ("The Mandelbrot fractal set\n") ax.text(xmin + .025, ymin + .025, text, color="white", fontsize=12, alpha=0.5) plt.show()
def feature32_bar3d(): """ Create slide for feature highlight of bar3d light source. """ fig = new_slide() slide_heading(fig, '3.2 Feature: bar3d light source') # Plot two different light source angles. for i, angle in [(1, 90), (2, 0)]: # This example comes from the Pull Request adding this support: # https://github.com/matplotlib/matplotlib/pull/15099#issuecomment-523981989 ax = fig.add_subplot(1, 2, i, projection="3d") ls = mcolors.LightSource(azdeg=45, altdeg=angle) cmap = plt.get_cmap("coolwarm") length, width = 3, 4 area = length * width norm = mcolors.Normalize(0, area-1) x, y = np.meshgrid(np.arange(length), np.arange(width)) x = x.ravel() y = y.ravel() dz = x + y color = cmap(norm(np.arange(area))) ax.bar3d(x=x, y=y, z=0, dx=1, dy=1, dz=dz, color=color, shade=True, lightsource=ls) annotate_pr_author(fig, 'fourpoints', pr=15099) return fig
def update(self, sb_params: dict): active = sb_params.get('active_cmap') active_shade = sb_params.get('active_shading') ax = sb_params.get('ax') data = sb_params.get('frame') cmap = sb_params.get('cmap') norm = sb_params.get('norm') extent = sb_params.get('extent') self.vmin = extent[-2] self.vmax = extent[-1] set_cbar = sb_params.get("set_colorbar") set_cbar(self.vmin, self.vmax, cmap, norm) if active_shade and self.relief_shading: if len(data.shape) > 2: # 3 Then is an image already active_shade = False else: # Note: (Not really) 180 degrees are subtracted because visualization in Sandbox is upside-down ls = mcolors.LightSource(azdeg=self.light_source.azimuth, altdeg=self.light_source.altitude) data = ls.shade(data, cmap=self.cmap, vert_exag=self.light_source.ve, blend_mode='overlay') if active and self.active: if self._col is not None and self._col() not in ax.images: self.col = None if self.col is None: self.render_frame(data, ax, vmin=self.vmin, vmax=self.vmax, extent=extent[:4]) else: self.set_data(data) self.set_cmap(cmap, 'k', 'k', 'k') self.set_norm(norm) self.set_extent(extent) sb_params['cmap'] = self.cmap elif active_shade and self.relief_shading: cmap = plt.cm.gray if self._col is not None and self._col() not in ax.images: self.col = None if self.col is None: self.render_frame(data, ax, vmin=self.vmin, vmax=self.vmax, extent=extent[:4]) else: self.set_data(data) self.set_cmap(cmap, 'k', 'k', 'k') self.set_norm(norm) self.set_extent(extent) else: if self.col is not None: self.col.remove() self.col = None if self._col is not None and self._col() in ax.images: ax.images.remove(self._col) return sb_params
def ccs4_map(cfg_set_tds, figsize_x=12, figsize_y=12, hillshade=True, radar_loc=True, radar_vis=True): """Print map of TRT cells.""" ## Load DEM and Swiss borders shp_path_CH = os.path.join( cfg_set_tds["root_path"], u"data/shapefile/swissBOUNDARIES3D_1_3_TLM_LANDESGEBIET.shp") shp_path_Kantone = os.path.join( cfg_set_tds["root_path"], u"data/shapefile/swissBOUNDARIES3D_1_3_TLM_KANTONSGEBIET.shp") shp_path_count = os.path.join( cfg_set_tds["root_path"], u"data/shapefile/CCS4_merged_proj_clip_G05_countries.shp") dem_path = os.path.join(cfg_set_tds["root_path"], u"data/DEM/ccs4.png") visi_path = os.path.join(cfg_set_tds["root_path"], u"data/radar/radar_composite_visibility.npy") dem = Image.open(dem_path) dem = np.array(dem.convert('P')) sf_CH = shapefile.Reader(shp_path_CH) sf_KT = shapefile.Reader(shp_path_Kantone) sf_ct = shapefile.Reader(shp_path_count) ## Setup figure fig_extent = (255000, 965000, -160000, 480000) fig, axes = plt.subplots(1, 1) fig.set_size_inches(figsize_x, figsize_y) ## Plot altitude / hillshading if hillshade: ls = colors.LightSource(azdeg=315, altdeg=45) axes.imshow(ls.hillshade(-dem, vert_exag=0.05), extent=fig_extent, cmap='gray', alpha=0.5) else: axes.imshow(dem * 0.6, extent=fig_extent, cmap='gray', alpha=0.5) ## Get borders of Cantons try: shapes_KT = sf_KT.shapes() except UnicodeDecodeError: print(" *** Warning: No country shape plotted (UnicodeDecodeErrror)") else: for KT_i, shape in enumerate(shapes_KT): x = np.array([i[0] for i in shape.points[:]]) y = np.array([i[1] for i in shape.points[:]]) endpoint = np.where(x == x[0])[0][1] x = x[:endpoint] y = y[:endpoint] axes.plot(x, y, color='darkred', linewidth=0.5, zorder=5) ## Get borders of neighbouring countries try: shapes_ct = sf_ct.shapes() except UnicodeDecodeError: print(" *** Warning: No country shape plotted (UnicodeDecodeErrror)") else: for ct_i, shape in enumerate(shapes_ct): if ct_i in [0, 1]: continue x = np.array([i[0] for i in shape.points[:]]) y = np.array([i[1] for i in shape.points[:]]) x[x <= 255000] = 245000 x[x >= 965000] = 975000 y[y <= -159000] = -170000 y[y >= 480000] = 490000 if ct_i in [3]: axes.plot(x[20:170], y[20:170], color='black', linewidth=0.5) if ct_i in [2]: ## Delete common border of FR and CH: x_south = x[y <= 86000] y_south = y[y <= 86000] x_north = x[np.logical_and( np.logical_and(y >= 270577, y <= 491000), x > 510444)] #x_north = x[np.logical_and(y>=270577,y<=491000)] y_north = y[np.logical_and( np.logical_and(y >= 270577, y <= 491000), x > 510444)] #y_north = y[np.logical_and(y>=270577,y<=491000)] axes.plot(x_south, y_south, color='black', linewidth=0.5, zorder=4) axes.plot(x_north, y_north, color='black', linewidth=0.5, zorder=4) if ct_i in [4]: ## Delete common border of AT and CH: x_south = x[np.logical_and(x >= 831155, y < 235000)] y_south = y[np.logical_and(x >= 831155, y < 235000)] #x_north1 = x[np.logical_and(x>=756622,y>=260466)] x_north1 = x[np.logical_and( np.logical_and(x >= 758622, y >= 262466), x <= 794261)] #y_north1 = y[np.logical_and(x>=756622,y>=260466)] y_north1 = y[np.logical_and( np.logical_and(x >= 758622, y >= 262466), x <= 794261)] y_north2 = y[np.logical_and( np.logical_and(x >= 774261, y >= 229333), x <= 967000)] x_north2 = x[np.logical_and( np.logical_and(x >= 774261, y >= 229333), x <= 967000)] y_north2 = np.concatenate([ y_north2[np.argmin(x_north2):], y_north2[:np.argmin(x_north2)] ]) x_north2 = np.concatenate([ x_north2[np.argmin(x_north2):], x_north2[:np.argmin(x_north2)] ]) x_LI = x[np.logical_and( np.logical_and(x <= 773555, y >= 214400), y <= 238555)] y_LI = y[np.logical_and( np.logical_and(x <= 773555, y >= 214400), y <= 238555)] axes.plot(x_south, y_south, color='black', linewidth=0.5, zorder=4) axes.plot(x_north1, y_north1, color='black', linewidth=0.5, zorder=4) axes.plot(x_north2, y_north2, color='black', linewidth=0.5, zorder=4) axes.plot(x_LI, y_LI, color='black', linewidth=0.5, zorder=4) else: continue #axes.plot(x,y,color='black',linewidth=1,zorder=4) ## Get Swiss borders try: #shp_records = sf_CH.shapeRecords() shapes_CH = sf_CH.shapes() except UnicodeDecodeError: print(" *** Warning: No country shape plotted (UnicodeDecodeErrror)") else: for ct_i, shape in enumerate(shapes_CH): #sf_CH.shapeRecords(): if ct_i != 0: continue x = np.array([i[0] - 2000000 for i in shape.points[:]]) y = np.array([i[1] - 1000000 for i in shape.points[:]]) endpoint = np.where(x == x[0])[0][1] x = x[:endpoint] y = y[:endpoint] ## Convert to swiss coordinates #x,y = lonlat2xy(lon, lat) axes.plot(x, y, color='darkred', linewidth=1, zorder=3) ## Add weather radar locations: if radar_loc: weather_radar_y = [237000, 142000, 100000, 135000, 190000] weather_radar_x = [681000, 497000, 708000, 604000, 780000] axes.scatter( weather_radar_x, weather_radar_y, marker="D", #s=2, color='orange', edgecolor='black', zorder=10) ## Add radar visibility: if radar_vis: arr_visi = np.load(visi_path) arr_visi[arr_visi < 9000] = 0 arr_visi2 = morph.binary_opening(morph.binary_erosion( arr_visi, structure=np.ones((4, 4))), structure=np.ones((4, 4))) arr_visi[arr_visi < 9000] = np.nan axes.imshow(arr_visi, cmap="gray", alpha=0.2, extent=fig_extent) arr_visi[np.isnan(arr_visi)] = 1 #axes.contour(arr_visi[::-1,:], levels=[2], cmap="gray", linewidths=2, # linestyle="solid", alpha=0.5, extent=fig_extent) #arr_visi = arr_visi[::4, ::4] #ys, xs = np.mgrid[arr_visi.shape[0]:0:-1, # 0:arr_visi.shape[1]] #axes.scatter(xs.flatten(), ys.flatten(), s=4, # c=arr_visi.flatten().reshape(-1, 3), edgecolor='face') ## Add further elements: axes.set_xlim([255000, 965000]) axes.set_ylim([-160000, 480000]) axes.grid() axes.set_ylabel("CH1903 Northing") axes.set_xlabel("CH1903 Easting") axes.get_xaxis().set_major_formatter( \ ticker.FuncFormatter(lambda x, p: format(int(x), ",").replace(',', "'"))) axes.get_yaxis().set_major_formatter( \ ticker.FuncFormatter(lambda x, p: format(int(x), ",").replace(',', "'"))) plt.yticks(rotation=90, verticalalignment="center") return fig, axes, fig_extent
def imshow_hs(source, ax=None, cmap='geosoft', cmap_norm='equalize', hs=True, zf=10, azdeg=45, altdeg=45, dx=1, dy=1, hs_contrast=1.5, cmap_brightness=1.0, blend_mode='alpha', alpha=0.7, contours=False, colorbar=True, cb_contours=False, cb_ticks='linear', std_range=1, figsize=(8, 8), title=None, **kwargs): ''' Display an array or a grid with optional hillshading and contours. The data representation is controlled by the colormap and two types of normalisation can be applied to balance an uneven distribution of values. Contrary to the standard method available in `plt.imshow`, it is the colormap, not the data, that is modified. This allows the true distribution of the data to be displayed on the colorbar. The two options are equalisation (default) or clipping extremes (autolevels). Parameters ---------- source : 2D array or interpies grid object Grid to plot. Arrays with NaNs and masked arrays are supported. ax : matplotlib Axes instance This indicates where to make the plot. Create new figure if absent. cmap : string or colormap object Colormap or name of the colormap to use to display the array. The default is 'geosoft' and corresponds to the blue to pink clra colormap from Geosoft Oasis Montaj. cmap_norm : string Type of normalisation of the colormap. Possible values are: 'equalize' (or 'equalization') Increases contrast by distributing intensities across all the possible colours. The distribution is calculated from the data and applied to the colormap. 'auto' (or 'autolevels') Stretches the histogram of the colormap so that dark colours become darker and the bright colours become brighter. The extreme values are calculated with percentiles: min_percent (defaults to 2%) and max_percent (defaults to 98%). 'none' or any other value The colormap is not normalised. The data can still be normalised in the usual way using the 'norm' keyword argument and a Normalization instance defined in matplotlib.colors(). hs : boolean If True, the array is displayed in colours over a grey hillshaded version of the data. zf : float Vertical exaggeration (Z factor) for hillshading. azdeg : float The azimuth (0-360, degrees clockwise from North) of the light source. altdeg : float The altitude (0-90, degrees up from horizontal) of the light source. dx : float, optional cell size in the x direction dy : float, optional cell size in the y direction hs_contrast : float Increase or decrease the contrast of the hillshade. This is directly passed to the fraction argument of the matplotlib hillshade function. cmap_brightness : float Increase or decrease the brightness of the image by adjusting the gamma of the colorbar. Default value is 1.0 meaning no effect. Values greater than 1.0 make the image brighter, less than 1.0 darker. Useful when the presence of the hillshade makes the result a little too dark. blend_mode : {'alpha', 'hsv', 'overlay', 'soft'} The type of blending used to combine the colormapped data values with the illumination intensity. Default is 'alpha' and the effect is controlled by the alpha parameter. alpha : float Controls the transparency of the data overlaid over the hillshade. 1.0 is fully opaque while 0.0 is fully transparent. contours : Boolean or integer If True, add contours to the map, the number of them being the default value, i.e. 32. If an integer is given instead, use this value as the number of contours levels. colorbar : Boolean If True, draw a colorbar on the right-hand side of the map. The colorbar shows the distribution of colors, as modified by the normalization algorithm. cb_ticks : string If left as default ('linear') the ticks and labels on the colorbar are spaced linearly in the standard way. Otherwise (any other keyword, for example 'stats'), the mean and two ticks at + and - std_range*(standard deviation) are shown instead. std_range : integer (default is 1) Extent of the range from the mean as a multiple of the standard deviation. cb_contours : Boolean Add lines corresponding to contours values on the colorbar. figsize: tuple Dimensions of the figure: width, height in inches. If not provided, the default is (8, 8). title: string String to display as a title above the plot. If the source is a grid object, the title is taken by default from the name of the grid. kwargs : other optional arguments Can be used to pass other arguments to `plt.imshow()`, such as 'origin' and 'extent', or to the colorbar('shrink'), the title ('fontweight' and 'fontsize'), or the contours ('colors'). Returns ------- ax : Matplotlib Axes instance. Notes ----- This function exploits the hillshading capabilities implemented in matplotlib.colors.LightSource. A new blending mode is added (alpha compositing, see https://en.wikipedia.org/wiki/Alpha_compositing). ''' # get extra information if input data is grid object (grid.grid) # `extent` is added to the kwargs of the imshow function if isinstance(source, interpies.Grid): kwargs['extent'] = source.extent data = source.data if title is None: if source.name != 'Unknown': title = source.name else: data = source.copy() ## Extract keywords - using pop() also removes the key from the dictionary # keyword for the colorbar cb_kwargs = dict(shrink=kwargs.pop('shrink', 0.6)) # keywords for the title title_kwargs = dict(fontweight=kwargs.pop('fontweight', None), fontsize=kwargs.pop('fontsize', 'large')) # keyword arguments that can be passed to ls.shade shade_kwargs = dict(norm=kwargs.get('norm'), vmin=kwargs.get('vmin'), vmax=kwargs.get('vmax')) # keywords for cmap normalisation min_percent = kwargs.pop('min_percent', 2) max_percent = kwargs.pop('max_percent', 98) # keywords for contours ct_colors = kwargs.pop('ct_colors', 'k') ct_cmap = kwargs.pop('ct_cmap', None) # modify colormap if required if cmap_norm in ['equalize', 'equalise', 'equalization', 'equalisation']: # equalisation my_cmap = equalize_colormap(cmap, data) elif cmap_norm in ['auto', 'autolevels']: # clip colormap my_cmap = modify_colormap(cmap, data, modif='autolevels', min_percent=min_percent, max_percent=max_percent) else: # colormap is loaded unchanged from the input name my_cmap = load_cmap(cmap) # raise error if name is not recognised # apply brightness control if cmap_brightness != 1.0: my_cmap = modify_colormap(my_cmap, modif='brightness', brightness=cmap_brightness) # create figure or retrieve the one already defined if ax: fig = ax.get_figure() else: fig, ax = plt.subplots(figsize=figsize) # convert input data to a masked array data = np.ma.masked_array(data, np.isnan(data)) # add array to figure with hillshade or not if hs: # flip azimuth upside down if grid is also flipped if 'origin' in kwargs: if kwargs['origin'] == 'lower': azdeg = 180 - azdeg # create light source ls = mcolors.LightSource(azdeg, altdeg) # calculate hillshade and combine the colormapped data with the intensity if alpha == 0: # special case when only the shaded relief is needed without blending rgb = ls.hillshade(data, vert_exag=zf, dx=dx, dy=dy, fraction=hs_contrast) kwargs['cmap'] = 'gray' elif blend_mode == 'alpha': # transparency blending rgb = ls.shade(data, cmap=my_cmap, blend_mode=alpha_blend, vert_exag=zf, dx=dx, dy=dy, fraction=hs_contrast, alpha=alpha, **shade_kwargs) else: # other blending modes from matplotlib function rgb = ls.shade(data, cmap=my_cmap, blend_mode=blend_mode, vert_exag=zf, dx=dx, dy=dy, fraction=hs_contrast, **shade_kwargs) # finally plot the array ax.imshow(rgb, **kwargs) else: # display data without hillshading im = ax.imshow(data, cmap=my_cmap, **kwargs) # add contours levels = None if isinstance(contours, bool): if contours: levels = 32 else: levels = contours contours = True if levels is not None: # remove cmap keyword that might have been added earlier _ = kwargs.pop('cmap', None) conts = plt.contour(data, levels, linewidths=0.5, colors=ct_colors, linestyles='solid', cmap=ct_cmap, **kwargs) # add colorbar if colorbar and alpha != 0: if hs: # Use a proxy artist for the colorbar im = ax.imshow(data, cmap=my_cmap, **kwargs) im.remove() # draw colorbar if cb_ticks == 'linear': # normal equidistant ticks on a linear scale cb1 = plt.colorbar(im, ax=ax, **cb_kwargs) else: # show ticks at min, max, mean and standard deviation interval new_ticks = stats_boundaries(data, std_range, std_range) cb1 = plt.colorbar(im, ax=ax, ticks=new_ticks, **cb_kwargs) # add optional contour lines on colorbar if contours and cb_contours: cb1.add_lines(conts) cb1.update_normal(im) # add title if title: ax.set_title(title, **title_kwargs) # return Axes instance for re-use return ax
def plot_output(d, which='elevation', filename=None, time=None, hillshade=False, resize_factor=1, **kwargs): ''' Plot the output of the Badlands model. Parameters: d: the output from grid.remap_TIN ''' try: which = which.lower() except AttributeError as e: raise TypeError("Invalid 'which' parameter: {}".format(which)) from e if which not in ['elevation', 'elev_discharge', 'erodep']: raise ValueError("Invalid 'which' parameter: {}".format(which)) z = d['z'] dz = d['cumdiff'] discharge = d['discharge'] discharge = np.nan_to_num(discharge, nan=1.0) # Resize if desired if resize_factor != 1: if 'resize_order' in kwargs: resize_order = kwargs['resize_order'] else: resize_order = 3 if resize_factor < 1: anti_aliasing = True else: anti_aliasing = False ny, nx = z.shape new_ny = int(np.around(ny * resize_factor)) new_nx = int(np.around(nx * resize_factor)) z = transform.resize( z, (new_ny, new_nx), order=resize_order, preserve_range=True, anti_aliasing=anti_aliasing, ) ny, nx = dz.shape new_ny = int(np.around(ny * resize_factor)) new_nx = int(np.around(nx * resize_factor)) dz = transform.resize( dz, (new_ny, new_nx), order=resize_order, preserve_range=True, anti_aliasing=anti_aliasing, ) ny, nx = discharge.shape new_ny = int(np.around(ny * resize_factor)) new_nx = int(np.around(nx * resize_factor)) discharge = transform.resize( discharge, (new_ny, new_nx), order=resize_order, preserve_range=True, anti_aliasing=anti_aliasing, ) # Draw and configure figure and axes figsize = kwargs.get('figsize', (8, 12)) fig = plt.figure(figsize=figsize) ax = fig.add_axes([0.2, 0.2, 0.6, 0.6]) ax.tick_params( **{i: False for i in ['bottom', 'labelbottom', 'left', 'labelleft']}) if 'font_size' in kwargs: font_size = kwargs['font_size'] else: font_size = FONT_SIZE title_size = int(font_size * 2.5) tick_size = int(font_size * 0.75) disp = 0.04 * (font_size / 16) width = 0.03 * (font_size / 16) cax1 = fig.add_axes([1 - (disp + width), 0.214, width, 0.572 / 2]) # Hillshade parameters if hillshade: azdeg = kwargs.get('azdeg', 180 - 135) altdeg = kwargs.get('altdeg', 70) vert_exag = kwargs.get('vert_exag', 0.5) blend_mode = kwargs.get('blend_mode', 'soft') ls = colors.LightSource(azdeg=azdeg, altdeg=altdeg) else: azdeg, altdeg, vert_exag, blend_mode, ls = (None, None, None, None, None) if which == 'elev_discharge': cax2 = fig.add_axes([disp, 0.214, width, 0.572 / 2]) # Discharge plotting parameters if 'dmax' in kwargs: dmax = kwargs['dmax'] else: dmax = 1.e12 if 'dmin' in kwargs: dmin = kwargs['dmin'] else: dmin = 1. if 'cmap_discharge' in kwargs: cmap_discharge = kwargs['cmap_discharge'] else: cmap_discharge = 'Blues' alphas = discharge.copy() alphas[alphas > dmax] = dmax alphas[alphas < dmin] = dmin alphas -= alphas.min() alphas /= alphas.max() # Plot discharge and colourbar plot_discharge( discharge=discharge, ax=ax, cmap_discharge=cmap_discharge, norm='log', alpha='linear', cax=cax2, fig=fig, dmin=dmin, dmax=dmax, cbar_orientation='vertical', ) if which in ['elevation', 'elev_discharge']: # Plot elevation and colourbar plot_terrain( z, ax, fig=fig, cax=cax1, ls=ls, vert_exag=vert_exag, blend_mode=blend_mode, cbar_orientation='vertical', ) if which == 'erodep': cmap_erodep = kwargs.get('cmap_erodep', 'coolwarm') dzmin = kwargs.get('dzmin', -2000) dzmax = kwargs.get('dzmax', 2000) plot_erodep( dz=dz, ax=ax, cmap_erodep=cmap_erodep, cax=cax1, fig=fig, z=z, ls=ls, dzmin=dzmin, dzmax=dzmax, vert_exag=vert_exag, blend_mode=blend_mode, cbar_orientation='vertical', ) # Contour elevation contour_interval = kwargs.get('contour_interval', None) if contour_interval is not None: contour_interval = float(contour_interval) if contour_interval > 0: contour_interval = kwargs['contour_interval'] d_contours = { i: kwargs[i] for i in kwargs if '_' in i and (i[:4] == 'zero' or i[:7] == 'contour') and i != 'contour_interval' } if 'contour_linestyles' not in kwargs: d_contours['contour_linestyles'] = 'solid' if 'contour_linewidths' not in kwargs: d_contours['contour_linewidths'] = 0.7 if 'contour_colors' not in kwargs: if which != 'erodep': d_contours['contour_colors'] = 'white' else: d_contours['contour_colors'] = 'grey' if 'zero_linestyles' not in kwargs: d_contours['zero_linestyles'] = None if 'zero_linewidths' not in kwargs: d_contours['zero_linewidths'] = None if 'zero_colors' not in kwargs: d_contours['zero_colors'] = 'k' contour_elevation( z=z, ax=ax, contour_interval=contour_interval, zero_zorder=50, contour_zorder=50, **d_contours, ) elif contour_interval == 0: ax.contour(np.flipud(z), [0.0], linewidths=1.4, linestyles='solid', colors='black') else: raise ValueError( 'contour_interval < 0: {}'.format(contour_interval)) # Adjust colourbars if which == 'elev_discharge': caxs = [cax1, cax2] else: caxs = [cax1] for cax in caxs: cax.tick_params( **{ i: False for i in [ 'bottom', 'labelbottom', 'right', 'labelright', 'top', 'labeltop', ] }) cax.tick_params(**{i: True for i in ['left', 'labelleft']}) cax.yaxis.set_tick_params(labelsize=tick_size) cax.yaxis.set_label_coords(0.5, 1.2 * (font_size / 16)) cax1.tick_params(**{ 'left': False, 'labelleft': False, 'right': True, 'labelright': True, }) # Add and configure labels if 'title' in kwargs: title = kwargs['title'] elif time is not None: time_decimals = kwargs.get('time_decimals', 1) title = ('{:.' + str(time_decimals) + 'f} Ma').format(time) else: title = None title = fig.suptitle(title, y=0.2 - (0.03 * font_size / 16), fontsize=title_size) if which in ['elevation', 'elev_discharge']: if contour_interval is not None: cbarlabel1 = ( 'Elevation (m)\n({}m contours)'.format(contour_interval)) else: cbarlabel1 = 'Elevation (m)' cbarlabel1 = cax1.set_ylabel( cbarlabel1, fontsize=font_size, rotation=0, ) elif which == 'erodep': cbarlabel1 = '\n' + r'$\mathrm{\Delta Z (m)}$' cbarlabel1 = cax1.set_ylabel( cbarlabel1, fontsize=font_size, rotation=0, ) if which == 'elev_discharge': cbarlabel2 = r'Discharge ($\mathrm{m^3\,{yr}^{-1}}$)' cbarlabel2 = cax2.set_ylabel( cbarlabel2, fontsize=font_size, rotation=0, ) # Save to file if filename is not None: dpi = kwargs.get('dpi', 300) fig.savefig(filename, dpi=dpi, bbox_inches='tight') plt.close(fig)
def section(section='', timerange=[], tracerange=[], fold=True, cm='gray', hillshade=False, type='twt', hscale=5000, vscale=5000, output='root'): ''' Display section ''' # transpose data and get sample depths, fold data = section.data.T twt = section.stats['twt'] fold_data = section.trace_header['NStackedTraces'] # Check CDP orientation, reverse if cdp are reverse-ordered cdp_id = list(section.trace_header['CDP']) if cdp_id[0] > cdp_id[-1]: data = data[:, ::-1] # Cut time region if timerange != []: dd = (twt > timerange[0]) & (twt < timerange[1]) data = data[dd, :] twt = twt[dd] # Cut trace region ntraces = np.shape(data)[1] cdp_range = range(0, ntraces) if tracerange != []: if tracerange[1] > np.shape(data)[1]: tracerange[1] = np.shape(data)[1] data = data[:, tracerange[0]:tracerange[1]] cdp_range = range(tracerange[0], tracerange[1]) ntraces = len(cdp_range) fold_data = fold_data.iloc[tracerange[0] - 1:tracerange[1] - 1] # Get fold curve for relevant CDPs if fold: fold_x = list(fold_data.index) fold_y = list(fold_data.values) # Validate colormap if cm not in plt.colormaps(): cm = 'gray' # Change labels if depth section if type != 'twt': ylabel = 'Depth under datum [m]' else: ylabel = 'Two-way time [ms]' # Compute figure dimensions # Adjust image dimension to hscale and vscale (adjust if twt or depth) figsize = (18, 10) # Initialize figure if fold: pass # SET PLOT STYLES else: fig, ax = plt.subplots(figsize=figsize) # Plot image if hillshade: # Create light source ls = mcolors.LightSource(0, 80) # Get color map cmap = plt.get_cmap(cm) # Normalize sc = robust_scale(data, axis=1, with_centering=False, with_scaling=True, quantile_range=(0.2, 0.9), ) # Create HS hs = ls.hillshade(sc) size = int(50 / section.stats['sample_rate']) hs = uniform_filter1d(hs, size, axis=0) hs = robust_scale(hs, axis=1, with_centering=True, with_scaling=False, quantile_range=(0.01, 0.99), ) clip_val = abs(np.percentile(data, 0.999)) ax.imshow(data, interpolation='bilinear', aspect='auto', cmap=cm, extent=(0, ntraces, twt[-1], twt[0]), vmin=-clip_val, vmax=clip_val) ax.imshow(hs, cmap='binary', norm=None, aspect='auto', interpolation=None, alpha=0.2, extent=(0, ntraces, twt[-1], twt[0])) else: clip_val = abs(np.percentile(data, 0.999)) im = ax.imshow(data, interpolation='bilinear', aspect='auto', cmap=cm, extent=(0, ntraces, twt[-1], twt[0]), vmin=-clip_val, vmax=clip_val) # Set tick number to CDP range n_ticks = 20 round_to = 10 x_step = int(round_to * round(float(ntraces / n_ticks) / round_to)) # pixel count at label position x_positions = np.arange(0, ntraces, x_step) x_labels = cdp_range[::x_step] # labels you want to see ax.set_xticks(x_positions) ax.set_xticklabels(x_labels) # Set labels ax.set_xlabel('CDP no.') ax.set_ylabel(ylabel) ax.set_title(section.stats['filename']) # Resolve output filename filename = section.stats['filename'] if output == 'root': out = filename.parent else: out = filename.parent.joinpath('Sections') out.mkdir(parents=True, exist_ok=True) # Save image outfile = out.joinpath(f'{filename.stem}_section.jpg') fig.savefig(outfile) plt.close(fig)
fig = plt.figure() ax = fig.gca(projection='3d') r = 1 # Make data u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) x = r * np.outer(np.cos(u), np.sin(v)) y = r * np.outer(np.sin(u), np.sin(v)) zss = r * np.outer(np.ones(np.size(u)), np.cos(v)) zss = [[z if z >= 0 else 0 for z in zs] for zs in zss] # Remove all negative z z = np.array(zss) light = cls.LightSource(azdeg=0, altdeg=45) #z = zs # Define an arbitrary point acting as a light cue, if lighting can't be done in mpl # could draw a Gaussian around it to create an intensity pattern. radius = 1 gamma = np.pi / 8 # 45deg, also should be phi theta = np.pi / 4 # 90deg # Define cartesian coordinates (lists to make life easy with ax.plot) light_x = [radius * np.sin(theta) * np.cos(gamma)] light_y = [radius * np.sin(theta) * np.sin(gamma)] light_z = [radius * np.cos(theta)] # Plot the surface and the axes vectors ax.plot(light_x,
def imshow_hs(source, ax=None, cmap='geosoft', cmap_norm='equalize', hs=True, zf=10, azdeg=45, altdeg=45, dx=1, dy=1, fraction=1.5, blend_mode='alpha', alpha=0.7, contours=False, levels=32, colorbar=True, cb_contours=False, cb_ticks='linear', nSigma=1, figsize=(8,8), title=None, **kwargs): ''' Display an array with optional hillshading and contours. Mapping of the data to the colormap is done linearly by default. Instead the colormap is normalised by equalisation (default) or by clipping extremes (autolevels). This allows the true distribution of the data to be displayed on the colorbar. Parameters ---------- source : 2D array or interpies grid object Grid to plot. Arrays with NaNs and masked arrays are supported. ax : matplotlib Axes instance This indicates where to make the plot. Create new figure if absent. cmap : string or colormap object Colormap or name of the colormap to use to display the array. The default is 'geosoft' and corresponds to the blue to pink clra colormap from Geosoft Oasis Montaj. cmap_norm : string Type of normalisation of the colormap. Possible values are: 'equalize' (or 'equalization') Increases contrast by distributing intensities across all the possible colours. With this option, it is not the data that is normalised but the colormap, based on the data. 'auto' (or 'autolevels') Stretches the histogram of the colormap so that dark colours become darker and the bright colours become brighter. Two extra parameters control the amount of clipping at the extremes: minPercent (default to 10%) and maxPercent (default to 90%) 'none' or any other value The colormap is not normalised. The data can still be normalised in the usual way using the 'norm' keyword argument and a Normalization instance defined in matplotlib.colors(). hs : boolean If True, the array is displayed in colours over a grey hillshaded version of the data. zf : number Vertical exaggeration (Z factor) for hillshading. azdeg : number The azimuth (0-360, degrees clockwise from North) of the light source. altdeg : number The altitude (0-90, degrees up from horizontal) of the light source. dx : number, optional cell size in the x direction dy : number, optional cell size in the y direction fraction : number Increase or decrease the contrast of the hillshade. blend_mode : {'alpha', 'hsv', 'overlay', 'soft'} The type of blending used to combine the colormapped data values with the illumination intensity. Default is 'alpha' and the effect is controlled by the alpha parameter. alpha : float Controls the transparency of the data overlaid over the hillshade. 1.0 is fully opaque while 0.0 is fully transparent. contours : Boolean If True, add contours to the map. The number of calculated contours is defined by: levels : integer Number of contour levels. colorbar : Boolean If True, draw a colorbar on the right-hand side of the map. The colorbar shows the distribution of colors, as modified by the normalization algorithm. cb_ticks : string If left as default ('linear') the ticks and labels on the colorbar are spaced linearly in the standard way. Otherwise (any other keyword, for example 'stats'), the mean and two ticks at + and - nSigma*(standard deviation) are shown instead. nSigma : integer (default is 1) Size of the interval to show between ticks on the colorbar. cb_contours : Boolean Add lines corresponding to contours on the colorbar. figsize: tuple Dimensions of the figure: width, height in inches. If not provided, the default is (8,8). title: string String to display as a title above the plot. If the source is a grid object, the title is taken by default from the name of the grid. kwargs : other optional arguments Can be used to pass other arguments to imshow, such as 'origin' and 'extent', or for the colorbar('shrink'), or the title ('fontweight' and 'fontsize'). Returns ------- ax : Matplotlib Axes instance. Notes ----- This function exploits the hillshading capabilities implemented in matplotlib.colors.LightSource. A new blending mode is added (alpha compositing, see https://en.wikipedia.org/wiki/Alpha_compositing). ''' # get extra information if input data is grid object (transforms.grid) # `extent` is added to the kwargs of the imshow function if isinstance(source, grid.grid): kwargs['extent'] = source.extent data = source.data if title is None: title = source.name else: data = source.copy() # extract keyword for the colorbar cb_kwargs = dict(shrink=kwargs.pop('shrink', 0.6)) # extract keywords for the title title_kwargs = dict(fontweight=kwargs.pop('fontweight', None), fontsize=kwargs.pop('fontsize', 'large')) # extract keyword arguments that can be passed to ls.shade shade_kwargs = dict(norm=kwargs.get('norm'), vmin=kwargs.get('vmin'), vmax=kwargs.get('vmax')) # modify colormap if required if cmap_norm in ['equalize', 'equalization', 'equalisation']: # equalisation my_cmap = equalizeColormap(cmap, data) elif cmap_norm in ['auto','autolevels']: # autolevels minP = kwargs.pop('minPercent',10) # also removes the key from the dictionary maxP = kwargs.pop('maxPercent',90) my_cmap = normalizeColormap(cmap, norm='autolevels', minPercent=minP, maxPercent=maxP) else: # colormap is loaded unchanged from the input name my_cmap = load_cmap(cmap) # raises error if name is not recognised # create figure or retrieve the one already defined if ax: fig = ax.get_figure() else: fig, ax = plt.subplots(figsize=figsize) # convert input data to a masked array data = np.ma.masked_array(data, np.isnan(data)) # add array to figure with hillshade or not if hs: # flip azimuth upside down if grid is also flipped if 'origin' in kwargs: if kwargs['origin'] == 'lower': azdeg = 180 - azdeg # create light source ls = mcolors.LightSource(azdeg, altdeg) # calculate hillshade and combine the colormapped data with the intensity if alpha == 0: # special case when only the shaded relief is needed without blending rgb = ls.hillshade(data, vert_exag=zf, dx=dx, dy=dy, fraction=fraction) kwargs['cmap'] = 'gray' elif blend_mode == 'alpha': # transparency blending rgb = ls.shade(data, cmap=my_cmap, blend_mode=alpha_blend, vert_exag=zf, dx=dx, dy=dy, fraction=fraction, alpha=alpha, **shade_kwargs) else: # other blending modes from matplotlib function rgb = ls.shade(data, cmap=my_cmap, blend_mode=blend_mode, vert_exag=zf, dx=dx, dy=dy, fraction=fraction, **shade_kwargs) # finally plot the array ax.imshow(rgb, **kwargs) else: # display data without hillshading im = ax.imshow(data, cmap=my_cmap, **kwargs) # add contours if contours: ct = plt.contour(data, levels, linewidths=0.5, colors='k', linestyles='solid', **kwargs) # add colorbar if colorbar and alpha!=0: if hs: # Use a proxy artist for the colorbar im = ax.imshow(data, cmap=my_cmap, **kwargs) im.remove() # draw colorbar if cb_ticks=='linear': # normal equidistant ticks on a linear scale cb1 = plt.colorbar(im, ax=ax, **cb_kwargs) else: # show ticks at min, max, mean and standard deviation interval newTicks = stats_boundaries(data, nSigma, nSigma) cb1 = plt.colorbar(im, ax=ax, ticks=newTicks, **cb_kwargs) # add optional contour lines on colorbar if contours and cb_contours: cb1.add_lines(ct) cb1.update_normal(im) # add title if title: ax.set_title(title, **title_kwargs) # final show (better without as it gives the handle of the axis back) #plt.show() # return Axes instance for re-use return ax
# This line will generate warnings for null values but it is faster to # process them afterwards using the nan_to_num with np.errstate(invalid='ignore'): M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z))) / np.log(2) + log_horizon) dpi = 72 width = 10 height = 10 * yn / xn fig = plt.figure(figsize=(width, height), dpi=dpi) #canvas dimensions ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) # Shaded rendering light = colors.LightSource(azdeg=315, altdeg=10) # change the colouring system M = light.shade(M, cmap=plt.cm.hot, vert_exag=1.5, norm=colors.PowerNorm(0.3), blend_mode='hsv') plt.imshow(M, extent=[xmin, xmax, ymin, ymax], interpolation="bicubic") ax.set_xticks([]) ax.set_yticks([]) # Some advertisement for matplotlib year = time.strftime("%Y") major, minor, micro = matplotlib.__version__.split('.', 2) text = ("The Mandelbrot fractal set\n" "Rendered with matplotlib %s.%s, %s - http://matplotlib.org" % (major, minor, year))
def get_lightsource(self): s = mcolors.LightSource(azdeg=self.azimuth, altdeg=self.altitude) return s
# https://linas.org/art-gallery/escape/smooth.html # https://www.ibm.com/developerworks/community/blogs/jfp/entry/My_Christmas_Gift # This line will generate warnings for null values but it is faster to # process them afterwards using the nan_to_num with np.errstate(invalid='ignore'): M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z))) / np.log(2) + log_horizon) dpi = 72 width = 10 height = 10 * yn / xn fig = plt.figure(figsize=(width, height), dpi=dpi) ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) # Shaded rendering light = colors.LightSource(azdeg=315, altdeg=10) M = light.shade(M, cmap=plt.cm.hot, vert_exag=1.5, norm=colors.PowerNorm(0.3), blend_mode='hsv') plt.imshow(M, extent=[xmin, xmax, ymin, ymax], interpolation="bicubic") ax.set_xticks([]) ax.set_yticks([]) # Some advertisement for matplotlib year = time.strftime("%Y") major, minor, micro = matplotlib.__version__.split('.', 2) text = ("The Mandelbrot fractal set\n" "Rendered with matplotlib %s.%s, %s - http://matplotlib.org" % (major, minor, year))
def createMap(ll=None, ur=None, figsize=None, margin=None, ax=None, dict_basemap=None, countries=True, lw=1, coastlines=True, mapboundary=True, grid=False, grid_labels=True, watercolor='#ADD8E6', fillcontinents='coral', use_lsmask=False, stations=None, cities=None, trench=None, earthquake=None, slip=None, elevation=None, elevation_args=(7000, 500, True), elevation_offset=None, shaded=True, shaded_args=(315, 45, 0.2), colormap=None, title=None, show=True, save=None, station_markersize=4, elev_oceans=True, grid_lw=None, spines_lw=None, dpi=None, station_labelsize='small', loffset=None): if figsize: fig = plt.figure(figsize=figsize) if margin: ax = fig.add_axes(margin) else: fig = None if dict_basemap is None: dict_basemap = dict(llcrnrlon=-180, llcrnrlat=-60, urcrnrlon=180, urcrnrlat=60, lat_0=0, lon_0=0, projection='hammer', resolution='l') elif ll is not None: print dict_basemap up_dict = dict(llcrnrlon=ll[1], llcrnrlat=ll[0], urcrnrlon=ur[1], urcrnrlat=ur[0]) dict_basemap.update(up_dict) m = Basemap(ax=ax, **dict_basemap) if fillcontinents and use_lsmask: m.drawlsmask(land_color=fillcontinents, ocean_color='white') elif fillcontinents: m.fillcontinents(color=fillcontinents, lake_color=watercolor, zorder=0) if countries: m.drawcountries(linewidth=lw) if coastlines: m.drawcoastlines(linewidth=lw) if mapboundary: m.drawmapboundary(fill_color=watercolor, zorder=-10) print 1 if grid or grid_labels: if not grid_lw: grid_lw = lw if grid is True: grid = 1. #JGR if grid and grid_labels: m.drawparallels(np.arange(-90., 90., grid), labels=[True, True, False, False], linewidth=grid_lw, xoffset=loffset, yoffset=loffset, size='small') m.drawmeridians(np.arange(0., 390., grid), labels=[False, False, True, True], linewidth=grid_lw, xoffset=loffset, yoffset=loffset, size='small') elif grid: m.drawparallels(np.arange(-90., 90., grid), labels=[False, False, False, False], linewidth=grid_lw) m.drawmeridians(np.arange(0., 390., grid), labels=[False, False, False, False], linewidth=grid_lw) if stations: stations.plot(m, mfc='b', ms=station_markersize, zorder=10, lsize=station_labelsize) if slip: if len(slip) == 4: x, y, z, levels = slip colors_slip = None else: x, y, z, levels, colors_slip = slip x, y = zip(*[m(lon, lat) for lon, lat in zip(x, y)]) if len(np.shape(z)) == 2: grid_x = x grid_y = y else: grid_x = np.arange( min(x), max(x) - 0.15 * (max(x) - min(x)), 100) #VERY dirty hack to cut of parts of the slip model grid_y = np.arange(min(y), max(y), 100) #grid_x, grid_y = np.mgrid[min(x):max(x):100j, min(y):max(y):100j] z = scipy.interpolate.griddata((x, y), z, (grid_x[None, :], grid_y[:, None]), method='cubic') plt.gca().contour(grid_x, grid_y, z, levels, colors=colors_slip, lw=lw) if earthquake == 'Tocopilla': x, y = m(-70.06, -22.34) x2, y2 = m(-69.5, -24.2) #x2, y2 = m(-70.4, -21.5) m.plot((x, x2), (y, y2), 'k-', lw=lw) #line m.plot((x), (y), 'r*', ms=2 * station_markersize, zorder=10) #epicenter b = Beach([358, 26, 109], xy=(x2, y2), width=50000, linewidth=lw) b.set_zorder(10) plt.gca().add_collection(b) plt.annotate( '14 Nov. 2007\n M 7.7', (x2, y2), xytext=(15, 0), # 22 textcoords='offset points', va='center', size=station_labelsize) elif earthquake == 'Tocopilla_beachball': #x, y = m(-70.06, -22.34) x2, y2 = m(-69.5, -24.2) #x2, y2 = m(-70.4, -21.5) b = Beach([358, 26, 109], xy=(x2, y2), width=50000, linewidth=lw) b.set_zorder(10) plt.gca().add_collection(b) plt.annotate('14 Nov. 2007\n M 7.6', (x2, y2), xytext=(22, 0), textcoords='offset points', va='center') elif earthquake == 'Tocopilla_position': x, y = m(-70.06, -22.34) m.plot((x), (y), 'r*', ms=15, zorder=10) #epicenter elif earthquake: xs, ys = zip(*[m(lon, lat) for lon, lat in zip(*earthquake[:2])]) m.plot(xs, ys, 'r*', ms=15, zorder=10) #epicenters if len(earthquake) == 3: for i in range(len(xs)): x, y, mag = xs[i], ys[i], earthquake[2][i] plt.annotate('M%.1f' % mag, xy=(x, y), xytext=(-5, -15), textcoords='offset points', va='center') elif len(earthquake) > 3: for i in range(len(xs)): x, y, mag, date = xs[i], ys[i], earthquake[2][i], earthquake[ 3][i] plt.annotate('M%.1f\n%s' % (mag, date.date), xy=(x, y), xytext=(10, 0), textcoords='offset points', va='center') print 2 if elevation: vmax, resol, bar = elevation_args geo = gdal.Open(elevation) topoin = geo.ReadAsArray() if elevation_offset: topoin[topoin > 0] += elevation_offset coords = geo.GetGeoTransform() nlons = topoin.shape[1] nlats = topoin.shape[0] delon = coords[1] delat = coords[5] lons = coords[0] + delon * np.arange(nlons) lats = coords[3] + delat * np.arange(nlats)[::-1] # reverse lats # create masked array, reversing data in latitude direction # (so that data is oriented in increasing latitude, # as transform_scalar requires). topoin = np.ma.masked_less(topoin[::-1, :], -11000) #topoin = gaussian_filter(topoin, 1) #topoin = array[::-1, :] # transform DEM data to a 250m native projection grid # if True: # x, y = m(*np.meshgrid(lons, lats)) # m.contourf(x, y, topoin, 100, cm=colormap) # if save: # plt.savefig(save) # return if resol: if resol < 25: nx = resol * len(lons) ny = resol * len(lats) else: nx = int((m.xmax - m.xmin) / resol) + 1 ny = int((m.ymax - m.ymin) / resol) + 1 else: nx = len(lons) ny = len(lats) topodat = m.transform_scalar(topoin, lons, lats, nx, ny, masked=True) if elevation == 'CleanTopo2_nchile.tif': # -10,701m(0) to 8,248m(18948) topodat = topodat - 10701 if (isinstance(colormap, basestring) and os.path.isfile(colormap) and colormap.endswith('.gpf')): colormap = createColormapFromGPF(colormap) if shaded: azdeg, altdeg, fraction = shaded_args ls = colors.LightSource(azdeg=azdeg, altdeg=altdeg) # convert data to rgb array including shading from light source. if elev_oceans: rgb = colormap(0.5 * topodat / vmax + 0.5) else: rgb = colormap(topodat / vmax) rgb1 = ls.shade_rgb(rgb, elevation=topodat, fraction=fraction) rgb[:, :, 0:3] = rgb1 m.imshow(rgb, zorder=1) else: if elev_oceans: m.imshow(topodat, interpolation='bilinear', cmap=colormap, zorder=1, vmin=-vmax, vmax=vmax) else: m.imshow(topodat, interpolation='bilinear', cmap=colormap, zorder=1, vmin=0, vmax=vmax) if bar: ax = plt.gca() fig = plt.gcf() #cb_ax = fig.add_axes([0.8, 0.3, 0.02, 0.4]) cb_ax = fig.add_axes([0.82, 0.3, 0.02, 0.4]) cb = colorbar.ColorbarBase(cb_ax, cmap=colormap, norm=colors.Normalize(vmin=-vmax, vmax=vmax)) #cb.set_label('elevation and bathymetry') ticks = (np.arange(20) - 10) * 1000 ticks = ticks[np.abs(ticks) <= vmax] cb.set_ticks(ticks) tls = ['%dm' % i if i % 2000 == 0 else '' for i in ticks] cb.set_ticklabels(tls) plt.axes(ax) # make the original axes current again if cities == 'ipoc': cities = 'Antofagasta Tocopilla Iquique Calama Pisagua Arica'.split() lons = [-70.4, -70.2, -70.1525, -68.933333, -70.216667, -70.333333] lats = [-23.65, -22.096389, -20.213889, -22.466667, -19.6, -18.483333] x, y = m(lons[:len(cities)], lats[:len(cities)]) m.plot(x, y, 'o', ms=station_markersize, mfc='w', mec='k', zorder=10) for i in range(len(cities)): if 'Anto' in cities[i]: plt.annotate(cities[i], (x[i], y[i]), xytext=(5, 0), textcoords='offset points', va='top', size=station_labelsize) else: plt.annotate(cities[i], (x[i], y[i]), xytext=(-5, 0), textcoords='offset points', ha='right', size=station_labelsize) elif cities == 'Tocopilla': lons = [-70.2] lats = [-22.096389] x, y = m(lons, lats) m.plot(x, y, 'o', ms=station_markersize, mfc='w', mec='k', zorder=10) plt.annotate('Tocopilla', (x[0], y[0]), xytext=(5, 0), textcoords='offset points', size=station_labelsize) if trench == 'ipoc': coords = np.transpose( np.loadtxt('/home/richter/Data/map/' 'nchile_trench.txt')) import matplotlib as mpl # hack JGR mpl.rcParams.update({'lines.linewidth': 1}) plotTrench(m, coords[0, :], coords[1, :], facecolors='k', edgecolors='k') if spines_lw: for l in plt.gca().spines.values(): l.set_linewidth(spines_lw) if title: plt.title(title, y=1.05) if save: plt.savefig(save, dpi=dpi) if show: plt.show() return m
def imshow_hs(data, ax=None, cmap='geosoft', cmap_norm='equalize', hs=True, zf=10, azdeg=45, altdeg=45, dx=1, dy=1, fraction=1.5, blend_mode='alpha', alpha=0.7, contours=False, levels=32, colorbar=True, cb_contours=False, cb_ticks='linear', nSigma=1, **kwargs): ''' Display an array with optional hillshading and contours. The colormap can be normalised by equalisation or by clipping extremes (autolevels). Parameters ---------- data : 2D array Grid to plot. Arrays with NaNs and masked arrays are supported. ax : matplotlib axes instance This indicates where to draw the figure. Create new figure if absent. cmap : string Name of the colormap to use to display the array. The default 'geosoft' is the blue to pink clra colormap from Geosoft Oasis Montaj. cmap_norm : string Type of normalisation of the colormap. Possible values are: 'equalize' (or 'equalization') Increases contrast by distributing intensities across all the possible colours. With this option, it is not the data that is normalised but the colormap, based on the data. 'auto' (or 'autolevels') Stretches the histogram of the colormap so that dark colours become darker and the bright colours become brighter. Two extra parameters control the amount of clipping at the extremes: minPercent (default to 10%) and maxPercent (default to 90%) hs : boolean If True, the array is displayed in colours over a grey hillshaded version of the data. zf : number Vertical exaggeration (Z factor) for hillshading. azdeg : number The azimuth (0-360, degrees clockwise from North) of the light source. altdeg : number The altitude (0-90, degrees up from horizontal) of the light source. dx : number, optional cell size in the x direction dy : number, optional cell size in the y direction fraction : number Increases or decreases the contrast of the hillshade. blend_mode : {'alpha', 'hsv', 'overlay', 'soft'} The type of blending used to combine the colormapped data values with the illumination intensity. Default is 'alpha' and the effect is controlled by the alpha parameter. alpha : float Controls the transparency of the data overlaid over the hillshade. 1.0 is fully opaque while 0.0 is fully transparent. contours : Boolean If True, adds contours to the map. The number of calculated contours is defined by: levels : integer Number of contour levels. colorbar : Boolean If True, draw a colorbar on the right-hand side of the map. The colorbar shows the distribution of colors, as modified by the normalization algorithm. cb_ticks : string If left as default ('linear') the ticks and labels on the colorbar are spaced linearly in the standard way. Otherwise (any other keyword, for example 'stats'), the mean and two ticks at + and - nSigma*(standard deviation) are shown instead. nSigma : integer (default is 1) Size of the interval to show between ticks on the colorbar. cb_contours : Boolean Add lines corresponding to contours on the colorbar. kwargs : other optional arguments Can be used to pass other arguments to imshow, such as 'origin' and 'extent'. Notes ----- This function exploits the hillshading capabilities implemented in matplotlib.colors.LightSource. It adds additional blending mode (alpha compositing, see https://en.wikipedia.org/wiki/Alpha_compositing) and normalising functions for the data (equalization). ''' # modify colormap if required if cmap_norm in ['equalize', 'equalization']: # histogram equalization cdf, bins = exposure.cumulative_distribution( data[~np.isnan(data)].flatten(), nbins=256) my_cmap = equalizeColormap(cmap, bins, cdf) elif cmap_norm in ['auto', 'autolevels']: # autolevels minP = kwargs.pop('minPercent', 10) # also removes the key from the dictionary maxP = kwargs.pop('maxPercent', 90) my_cmap = normalizeColormap(cmap, norm='autolevels', minPercent=minP, maxPercent=maxP) elif cmap in plt.colormaps(): # colormap defined as string (recognised name) my_cmap = plt.get_cmap(cmap) else: # colormap is one of the extra ones added by the colors module my_cmap = load_cmap(cmap) # raises error if not recognised # create figure or retrieve the one already there if ax: fig = ax.get_figure() else: fig, ax = plt.subplots(figsize=(8, 8)) # convert input data to masked array data = np.ma.masked_array(data, np.isnan(data)) # add array to figure with hillshade or not if hs: # flip azimuth upside down if grid is also flipped if 'origin' in kwargs: if kwargs['origin'] == 'lower': azdeg = 180 - azdeg # extract keyword arguments that can be passed to ls.shade kwargs_norm = {} kwargs_norm['norm'] = kwargs.get('norm') kwargs_norm['vmin'] = kwargs.get('vmin') kwargs_norm['vmax'] = kwargs.get('vmax') # create light source ls = mcolors.LightSource(azdeg, altdeg) # calculate hillshade and combine the colormapped data with the intensity if alpha == 0: # special case when only the shaded relief is needed without blending rgb = ls.hillshade(data, vert_exag=zf, dx=dx, dy=dy, fraction=fraction) kwargs['cmap'] = 'gray' elif blend_mode == 'alpha': # transparency blending rgb = ls.shade(data, cmap=my_cmap, blend_mode=alpha_blend, vert_exag=zf, dx=dx, dy=dy, fraction=fraction, alpha=alpha, **kwargs_norm) else: # other blending modes from matplotlib function rgb = ls.shade(data, cmap=my_cmap, blend_mode=blend_mode, vert_exag=zf, dx=dx, dy=dy, fraction=fraction, **kwargs_norm) ax.imshow(rgb, **kwargs) else: # display data without hillshading im = ax.imshow(data, cmap=my_cmap, **kwargs) # add contours if contours: ct = plt.contour(data, levels, linewidths=0.5, colors='k', linestyles='solid', **kwargs) # add colorbar if colorbar and alpha != 0: if hs: # Use a proxy artist for the colorbar im = ax.imshow(data, cmap=my_cmap, **kwargs) im.remove() if cb_ticks == 'linear': # normal equidistant ticks on a linear scale cb1 = fig.colorbar(im, shrink=0.8) else: # show ticks at min, max, mean and standard deviation interval newTicks = stats_boundaries(data, nSigma, nSigma) cb1 = fig.colorbar(im, shrink=0.8, ticks=newTicks) # add optional contour lines on colorbar if contours and cb_contours: cb1.add_lines(ct) cb1.update_normal(im) # final show plt.show()
log_horizon = np.log(np.log(horizon)) / np.log(2) Z, N = mandelbrot_set(xmin, xmax, ymin, ymax, zmin, zmax, xn, yn, zn, maxiter, horizon) with np.errstate(invalid='ignore'): M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z))) / np.log(3.1415) + log_horizon) Ra = fourleaf(math.e) #Rx = M*Ra dpi = 800 width = 6 * xn / yn height = 6 * yn / xn #depth = 6 fig = plt.figure(dpi=dpi) fig.set_size_inches(width, height) #, forward=True) #ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=True, aspect=1.5) light = colors.LightSource(azdeg=92, altdeg=22) M = light.shade(M, cmap=plt.cm.inferno, vert_exag=0.0, norm=colors.PowerNorm(1.1)) plt.imshow(M, extent=[xmin, xmax, ymin, ymax], aspect='auto', interpolation="Bessel") #fig = plt.figure(dpi=dpi) #this line is correct and essential. #ax = plt.axes(projection='3d') #this line is essential for a 3d graph #ax.scatter(M[0],M[1],M[2], cmap='seismic') #ax.set_xlim(-5, 5); ax.set_ylim(-5, 5); ax.set_zlim(-5, 5); #ax.set_xlabel('x') #ax.set_ylabel('y') #ax.set_zlabel('z');
# This line will generate warnings for null values but it is faster to # process them afterwards using the nan_to_num with np.errstate(invalid='ignore'): M = np.nan_to_num(N + 1 - np.log(np.log(abs(Z)))/np.log(3.1415) + log_horizon) dpi = 1200 width = 5 height = 5*yn/xn fig = plt.figure(figsize=(width, height), dpi=dpi) ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1) # Shaded rendering light = colors.LightSource(azdeg=180, altdeg=15) M = light.shade(data=M[:], cmap=plt.cm.seismic, blend_mode="overlay", vmin=None, vmax=None, vert_exag=0, dx=0.001, dy=0.001, fraction=1.15) plt.imshow(M, extent=[xmin, xmax, ymin, ymax], interpolation="gaussian") ax.set_xticks([]) ax.set_yticks([]) # Some advertisement for matplotlib #year = time.strftime("%Y") #major, minor, micro = matplotlib.__version__.split('.', 2) #text = ("The Mandelbrot fractalset\n" "Rendered with matplotlib %s.%s, %s - http://matplotlib.org" #% (major, minor, year)) #ax.text(xmin+.025, ymin+.025, text,color="white", fontsize=12, alpha=0.5) fig.savefig('mbot.tiff') plt.subplot_tool(targetfig=fig)