def _get_shaded(ptopo, contour_colormap): """Get hill-shaded topo with topo colormap. Args: ptopo (ndarray): Projected topography numpy array. contour_colormap (ColorPalette): Topography color palette object. Returns: ndarray: Hill-shaded topography RGB image. """ maxvalue = contour_colormap.vmax ls1 = LightSource(azdeg=300, altdeg=45) if np.allclose(ptopo, 0): intensity = np.full_like(ptopo, 1.0) else: maxvalue = contour_colormap.vmax ls2 = LightSource(azdeg=45, altdeg=45) intensity1 = ls1.hillshade(ptopo, fraction=0.25, vert_exag=VERT_EXAG) intensity2 = ls2.hillshade(ptopo, fraction=0.25, vert_exag=VERT_EXAG) intensity = intensity1 * 0.5 + intensity2 * 0.5 del intensity1, intensity2 ptoposc = ptopo / maxvalue rgba = contour_colormap.cmap(ptoposc) del ptoposc rgb = np.squeeze(rgba) del rgba draped_hsv = ls1.blend_hsv(rgb, np.expand_dims(intensity, 2)) return draped_hsv
def _getDraped(self, data, topodata): """Get array of data "draped" on topography. Args: data (ndarray): 2D Numpy array. topodata (ndarray): 2D Numpy array. Returns: ndarray: Numpy array of data draped on topography. """ maxvalue = self.intensity_colormap.vmax mmisc = data / maxvalue rgba_img = self.intensity_colormap.cmap(mmisc) rgb = np.squeeze(rgba_img[:, :, 0:3]) # use lightsource class to make our shaded topography ls = LightSource(azdeg=135, altdeg=45) # intensity = ls.hillshade(ptopo,fraction=0.25,vert_exag=1.0) ls1 = LightSource(azdeg=120, altdeg=45) ls2 = LightSource(azdeg=225, altdeg=45) intensity1 = ls1.hillshade( topodata, fraction=0.25, vert_exag=VERT_EXAG) intensity2 = ls2.hillshade( topodata, fraction=0.25, vert_exag=VERT_EXAG) intensity = intensity1 * 0.5 + intensity2 * 0.5 draped_hsv = ls.blend_hsv(rgb, np.expand_dims(intensity, 2)) return draped_hsv
def _get_draped(data, topodata, colormap): """Get array of data "draped" on topography. Args: data (ndarray): 2D Numpy array. topodata (ndarray): 2D Numpy array. colormap (ColorPalette): MMI color palette object. Returns: ndarray: Numpy array of data draped on topography. """ maxvalue = colormap.vmax mmisc = data / maxvalue rgba_img = colormap.cmap(mmisc) del mmisc rgb = np.squeeze(rgba_img[:, :, 0:3]) del rgba_img if np.allclose(topodata, 0): intensity = np.full_like(topodata, 0.5) else: # use lightsource class to make our shaded topography ls1 = LightSource(azdeg=300, altdeg=45) ls2 = LightSource(azdeg=45, altdeg=45) intensity1 = ls1.hillshade( topodata, fraction=0.25, vert_exag=VERT_EXAG) intensity2 = ls2.hillshade( topodata, fraction=0.25, vert_exag=VERT_EXAG) intensity = intensity1 * 0.5 + intensity2 * 0.5 del intensity1, intensity2 ls = LightSource(azdeg=315, altdeg=45) draped_hsv = ls.blend_hsv(rgb, np.expand_dims(intensity, 2)) return draped_hsv
def _getShaded(self,ptopo): maxvalue = self.contour_colormap.vmax ls1 = LightSource(azdeg = 120, altdeg = 45) ls2 = LightSource(azdeg = 225, altdeg = 45) intensity1 = ls1.hillshade(ptopo, fraction = 0.25, vert_exag = VERT_EXAG) intensity2 = ls2.hillshade(ptopo, fraction = 0.25, vert_exag = VERT_EXAG) intensity = intensity1*0.5 + intensity2*0.5 ptoposc = ptopo/maxvalue rgba = self.contour_colormap.cmap(ptoposc) rgb = np.squeeze(rgba) draped_hsv = ls1.blend_hsv(rgb,np.expand_dims(intensity,2)) return draped_hsv
def plot_data(xi,yi,z,label,clabel,shaded=False): # #Plotting data from xyz file fig = plt.figure(figsize=(14, 6)) ax1 = fig.add_subplot('111') if shaded: ls = LightSource(azdeg=315, altdeg=45) ve = 0.1 #rgb = ls.shade(z,cmap=plt.cm.rainbow, blend_mode = 'overlay', vert_exag=1000, fraction = 0.3, dx = 200, dy = 200) plt.imshow(ls.hillshade(z,vert_exag=ve),cmap='gray') rgb = ls.shade(z,cmap=plt.cm.rainbow, blend_mode = 'hsv',vert_exag=ve) #pcm = plt.imshow(z,cmap=plt.cm.rainbow) plt.imshow(rgb,extent=[xi.min(),xi.max(),yi.min(),yi.max()]) #if you want to normalize in log > e.g. norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,vmin=z.min(), vmax=z.max()) else: #pcm = plt.contourf(xi, yi, z,50,vmin=z.min(), vmax=z.max(),cmap=plt.cm.rainbow) pcm = plt.imshow(z,extent=[xi.min(),xi.max(),yi.min(),yi.max()],cmap=plt.cm.rainbow,vmin = -300, vmax = 300) cbar = plt.colorbar(pcm,orientation='horizontal',fraction=0.046, pad=0.1) cbar.set_label(clabel,fontsize = 12) ax1.set_xlabel('x (m)',fontsize = 12) ax1.set_ylabel('y (m)',fontsize = 12) ax1.set_title(label,fontsize = 16,style='italic') plt.axis('scaled') plt.xlim(xi.min(),xi.max()) plt.ylim(yi.min(),yi.max()) plt.tight_layout()
def _generate_hill_shade(self, topo, root=1, azdeg=275, altdeg=145): """ Generate image with hill shading. """ ls = LightSource(azdeg=azdeg, altdeg=altdeg) bumps = ls.hillshade(topo)**root # Taking a root backs it off a bit. return bumps
def _getDraped(self,data,topodata): maxvalue = self.intensity_colormap.vmax mmisc = data/maxvalue rgba_img = self.intensity_colormap.cmap(mmisc) rgb = np.squeeze(rgba_img[:,:,0:3]) #use lightsource class to make our shaded topography ls = LightSource(azdeg=135,altdeg=45) # intensity = ls.hillshade(ptopo,fraction=0.25,vert_exag=1.0) ls1 = LightSource(azdeg = 120, altdeg = 45) ls2 = LightSource(azdeg = 225, altdeg = 45) intensity1 = ls1.hillshade(topodata, fraction = 0.25, vert_exag = VERT_EXAG) intensity2 = ls2.hillshade(topodata, fraction = 0.25, vert_exag = VERT_EXAG) intensity = intensity1*0.5 + intensity2*0.5 draped_hsv = ls.blend_hsv(rgb,np.expand_dims(intensity,2)) return draped_hsv
def plot_map(dem, valdf, aff): """ Function to plot hillshade map of dem and checkpoints colored by residual. args: dem: numpy array of dem. Returned by dem_validation function. valdf: dataframe with gps_z, dem_z, and residual at each checkpoint. Returned by dem_validation function. aff: affine transformation. Returned by dem_validation function. returns: fig_map: handle on plot object """ # reset seaborn sns.reset_orig() ltsrc = LightSource(azdeg=315, altdeg=45) fig_map = plt.figure(figsize=(9, 9)) plt.imshow(ltsrc.hillshade(dem, vert_exag=1.5, dx=0.1, dy=0.1), cmap='gray') # plot points, using img coords, colors as abs(resid) plt.scatter(x=valdf['demcol'], y=valdf['demrow'], c=valdf['resid'].abs(), cmap=plt.cm.jet, s=12, alpha=0.5) ax = plt.gca() # set ticklabels to easting, northing instead of image coords el = [] nl = [] for col in ax.get_xticks(): e, _ = aff * (col, 0) el.append(int(round(e))) for row in ax.get_yticks(): _, n = aff * (0, row) nl.append(int(round(n))) #set top y ticklabel to '' nl[0], nl[1] = '', '' ax.set_xticklabels(el) ax.set_yticklabels(nl) #set tick label formats plt.yticks(fontsize=8, rotation=90, verticalalignment='center') plt.xticks(fontsize=8) cbar = plt.colorbar(aspect=45, pad=0.04, label='residual [m]') cbar.set_label('residual [m]', fontsize=8) cbar.ax.tick_params(labelsize=8) plt.show() return fig_map
def calc_hillshade(self, azimuth, elevation_angle, scale=1.): """ Compute hillshading :param azimuth: float, azimuth of light source in degrees :param elevation_angle: float, elevation angle of light source in degrees :param scale: float, multiplication factor to apply (default: 1.) """ """ ## Source: http://rnovitsky.blogspot.com.es/2010/04/using-hillshade-image-as-intensity.html az = np.radians(azimuth) elev = np.radians(elevation_angle) data = self.values[::-1] ## Gradient in x and y directions dx, dy = np.gradient(data * float(scale)) slope = 0.5 * np.pi - np.arctan(np.hypot(dx, dy)) aspect = np.arctan2(dx, dy) shade = np.sin(elev) * np.sin(slope) + np.cos(elev) * np.cos(slope) * np.cos(-az - aspect - 0.5*np.pi) ## Normalize shade = (shade - np.nanmin(shade))/(np.nanmax(shade) - np.nanmin(shade)) shade = shade[::-1] """ from matplotlib.colors import LightSource ls = LightSource(azimuth, elevation_angle) # TODO: look into vertical exaggeration with true dx and dy if hasattr(self, 'dx'): shade = ls.hillshade(self.values, dx=np.sign(self.dx), dy=-np.sign(self.dy)) else: shade = ls.hillshade(self.values, dx=np.sign(self.dlon), dy=-np.sign(self.dlat)) ## Eliminate nan values, they result in black when blended # TODO: maybe these values should be masked or made transparent shade[np.isnan(shade)] = 0.5 return shade
def plot_strm(x, y, e): # Se declara el tamaño de la ventana fig = plt.figure(figsize=(15, 5)) # Se extraen latitud y longitud minimas y maximas xmin, xmax, ymin, ymax = x[0], x[-1], y[0], y[-1] #Se declara fuente de luz con azimut y grado de elevacion ls = LightSource(LGT_AZIMUT, LGT_ELEVATION) #Se crea subplot para graficar DEM en 3D ax1 = fig.add_subplot(1, 2, 1, projection='3d') ax1.set_title("Proyeccion en 3D", y=1.08) ax1.set_zlim(0, np.amax(e)) x, y = np.meshgrid(x, y) rgb = ls.shade(e, cmap=cm.gray, vert_exag=VER_EXAGERATION, blend_mode='soft') sup = ax1.plot_surface(x, y, e, facecolors=rgb, linewidth=0, antialiased=False, shade=False) #Se crea 2do subplot para graficar DEM en 2D ax2 = fig.add_subplot(1, 2, 2) ax2.set_title("Vista 2D", y=1) # Se transforma el DEM a hillshade utilizando el LighSource # vert_exag es la exageracion vertical l = ls.hillshade(e, vert_exag=10) # Permite vizualizar el DEM con sombras aplicadas, ademas de su ejes de latitud y longitud ax2.imshow(l, cmap='gray', extent=[xmin, xmax, ymin, ymax]) # Funcion que permite ver el DEM sin hillshade # ax2.matshow(e, interpolation="bilinear", origin="lower",cmap=cm.cividis, extent=[xmin, xmax, ymin, ymax]) # Se define el titulo de ventana plt.suptitle("Vistas de STRM", fontsize=18) # Permite rotar la imagen 3D en 360 # for angle in range(0, 360): # ax1.view_init(30, angle) # plt.draw() # plt.pause(.01) plt.show() fig.savefig(save_name_file(DATA_DIR, FILE), bbox_inches='tight')
def repairDEM( topoC ) : """ This function removes artefacts from a DEM by finding gradients of the elevation above a certain threshold. Input paramters: topoC : DEM object of class Topo """ print('\n Repairing ... ') ls = LightSource(azdeg=225, altdeg=45) fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True) # Plot original DEM extent = [ topoC.E0, topoC.E0+topoC.Nx*topoC.dx, topoC.N0, topoC.N0+topoC.Ny*topoC.dy ] ax1.set_title('Original DEM') ax1.imshow(ls.hillshade(topoC.topo,vert_exag=1,dx=topoC.dx,dy=topoC.dy), extent=extent, cmap='gray', origin='lower') ax1.set(xlabel='Easting (m)', ylabel='Northing (m)') # Repair DEM n_iter = 20 # maximum number of recursive iterations threshold = 2. # threshold of gradient to repair repairX( topoC, n_iter, threshold ) # Plot repaired DEM ax2.set_title('Repaired DEM') ax2.imshow(ls.hillshade(topoC.topo,vert_exag=1,dx=topoC.dx,dy=topoC.dy), extent=extent, cmap='gray', origin='lower') ax2.set(xlabel='Easting (m)') plt.show() return()
def _getShaded(self, ptopo): """Get shaded topography. Args: ptopo (ndarray): Numpy array of projected topography data. Returns: ndarray: Numpy array of light-shaded topography. """ maxvalue = self.contour_colormap.vmax ls1 = LightSource(azdeg=120, altdeg=45) ls2 = LightSource(azdeg=225, altdeg=45) intensity1 = ls1.hillshade(ptopo, fraction=0.25, vert_exag=VERT_EXAG) intensity2 = ls2.hillshade(ptopo, fraction=0.25, vert_exag=VERT_EXAG) intensity = intensity1 * 0.5 + intensity2 * 0.5 ptoposc = ptopo / maxvalue rgba = self.contour_colormap.cmap(ptoposc) rgb = np.squeeze(rgba) draped_hsv = ls1.blend_hsv(rgb, np.expand_dims(intensity, 2)) return draped_hsv
def plot_initial_floodplain(zFP, nX, nY, grid): # Plot 2D domain topography fig = plt.figure(figsize=(14, 8)) plt.subplot(1, 2, 1) ls = LightSource(azdeg=315, altdeg=45) plt.imshow(ls.hillshade(np.reshape(zFP, [nX, nY]), vert_exag=10), cmap='gray') plt.title('initial floodplain topography') #Plot 2D domain hydraulic cond. plt.subplot(1, 2, 2) imshow_grid(grid, 'hydraulic_conductivity', plot_name="Hydraulic Conductivity", cmap="winter") fig.show()
def draw_hillshade(self, axes): ''' Draw hillshade from the elevation data on *axes*. The :meth:`generate_elevation_grid` must be called before this method. ''' if self.ele is None: raise TypeError( 'Elevation grid is not initialised, call generate_elevation_grid before this method' ) else: ls = LightSource(azdeg=30, altdeg=60) shade = ls.hillshade(self.ele, vert_exag=1, fraction=1.0).T axes.imshow(shade, origin='lower', extent=self.im_extent, interpolation='bilinear', cmap='gray', alpha=self.style.hillshade_alpha)
def plot_hillshade(file, index): grid = from_netcdf(file) elev_plt = grid.at_node['topographic__elevation'] y = np.arange(grid.shape[0] + 1) * grid.dy - grid.dy * 0.5 x = np.arange(grid.shape[1] + 1) * grid.dx - grid.dx * 0.5 ls = LightSource(azdeg=135, altdeg=45) fig = plt.figure(figsize=(8,6)) plt.imshow(ls.hillshade(elev_plt.reshape(grid.shape).T, vert_exag=2, dx=grid.dx, dy=grid.dy), origin="lower", extent=(x[0], x[-1], y[0], y[-1]), cmap='gray') plt.tight_layout() fig.canvas.draw() # draw the canvas, cache the renderer image = np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8') image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,)) plt.close() return image
def plot_floodplain(grid, zFP, nX, nY, elapsed_time, filepath=""): fig = plt.figure(figsize=(14, 8)) ls = LightSource(azdeg=315, altdeg=45) plt.imshow(ls.hillshade(np.reshape(zFP, [nX, nY]), vert_exag=10), cmap='gist_earth', origin="lower") imshow_grid(grid, 'surface_water__depth', limits=(0, 1), colorbar_label="Water depth (m)", cmap=mycmap, plot_name="Time = %i" % elapsed_time) if len(filepath) > 0: fig.savefig(filepath + "floodplain/" + str(int(elapsed_time)).zfill(5) + ".png", dpi=150) plt.close(fig) else: plt.show()
def plotDEM(topoC, title): ls = LightSource(azdeg=225, altdeg=45) extent = [ topoC.E0, topoC.E0 + topoC.Nx * topoC.dx, topoC.N0, topoC.N0 + topoC.Ny * topoC.dy ] fig = plt.figure() ax = fig.add_subplot(111) ax.set_title(title) ax.imshow(ls.hillshade(topoC.topo, vert_exag=1, dx=topoC.dx, dy=topoC.dy), extent=extent, cmap='gray', origin='lower') ax.set_xlabel('Easting (m)') ax.set_ylabel('Northing (m)') plt.show() return ()
def plot_age_model(lons, lats, resolution='i', cpt='/projects/howa1663/Code/ToolKit/Models/Age_Ocean_Crust/age1.cpt'): """ Not finished """ #mycm=pycpt.load.gmtColormap(cpt) try: etopo1 = Dataset('/work2/wang/Code/ToolKit/ETOPO1_Ice_g_gmt4.grd','r') # read in the etopo1 file which was used as the basemap llons = etopo1.variables["x"][:] west = llons<0 # mask array with negetive longitudes west = 360.*west*np.ones(len(llons)) llons = llons+west llats = etopo1.variables["y"][:] zz = etopo1.variables["z"][:] etopoz = zz[(llats>(lats[0]-2))*(llats<(lats[1]+2)), :] etopoz = etopoz[:, (llons>(lons[0]-2))*(llons<(lons[1]+2))] llats = llats[(llats>(lats[0]-2))*(llats<(lats[1]+2))] llons = llons[(llons>(lons[0]-2))*(llons<(lons[1]+2))] etopoZ = m.transform_scalar(etopoz, llons-360*(llons>180)*np.ones(len(llons)), llats, etopoz.shape[0], etopoz.shape[1]) # tranform the altitude grid into the projected coordinate ls = LightSource(azdeg=315, altdeg=45) m.imshow(ls.hillshade(etopoZ, vert_exag=0.05),cmap='gray') except IOError: print("Couldn't read etopo data or color map file! Check file directory!") return
def calculate_hillshades(self, array, **kwargs): """Calculate Hillshades based on digital elevation model Args: array: ndarray - array containing the elevation data Kwargs: azdeg: float - light source direction altdeg: float - light source height Return: hillshades: ndarray - array with hillshade values """ azdeg = kwargs.get('azdeg', 225) altdeg = kwargs.get('altdeg', 45) # Calculate hillshades ls = LightSource(azdeg=azdeg, altdeg=altdeg) hillshades = ls.hillshade(array) hillshades = hillshades * 255 return hillshades
def shade(heights, filename, az=90, alt=45, ve=1, mode=None,cmap='jet'): ls = LightSource(azdeg=az, altdeg=alt) sizes = np.shape(heights) height = float(sizes[0]) width = float(sizes[1]) fig = plt.figure() fig.set_size_inches(width/height, 1, forward=False) ax = plt.Axes(fig, [0., 0., 1., 1.]) ax.set_axis_off() fig.add_axes(ax) if mode == None: # plot hillshade intensity image shaded = ls.hillshade(heights.astype('float'), vert_exag=ve) ax.imshow(shaded, cmap='gray') plt.savefig(filename, dpi = height) else: #blend hillshaded intensity rgb = ls.shade(heights.astype('float'), cmap=cmap, blend_mode=mode,vert_exag=ve) ax.imshow(rgb) plt.savefig(filename, dpi = height)
def compare(z, cmap, ve=1): # Create subplots and hide ticks fig, axes = plt.subplots(ncols=2, nrows=2) for ax in axes.flat: ax.set(xticks=[], yticks=[]) # Illuminate the scene from the northwest ls = LightSource(azdeg=315, altdeg=45) axes[0, 0].imshow(z, cmap=cmap) axes[0, 0].set(xlabel='Colormapped Data') axes[0, 1].imshow(ls.hillshade(z, vert_exag=ve), cmap='gray') axes[0, 1].set(xlabel='Illumination Intensity') rgb = ls.shade(z, cmap=cmap, vert_exag=ve, blend_mode='hsv') axes[1, 0].imshow(rgb) axes[1, 0].set(xlabel='Blend Mode: "hsv" (default)') rgb = ls.shade(z, cmap=cmap, vert_exag=ve, blend_mode='overlay') axes[1, 1].imshow(rgb) axes[1, 1].set(xlabel='Blend Mode: "overlay"') return fig
def modelMap(grids, shakefile=None, suptitle=None, inventory_shapefile=None, plotorder=None, maskthreshes=None, colormaps=None, boundaries=None, zthresh=0, scaletype='continuous', lims=None, logscale=False, ALPHA=0.7, maproads=True, mapcities=True, isScenario=False, roadfolder=None, topofile=None, cityfile=None, oceanfile=None, roadcolor='#6E6E6E', watercolor='#B8EEFF', countrycolor='#177F10', outputdir=None, savepdf=True, savepng=True, showplots=False, roadref='unknown', cityref='unknown', oceanref='unknown', printparam=False, ds=True, dstype='mean', upsample=False): """ This function creates maps of mapio grid layers (e.g. liquefaction or landslide models with their input layers) All grids must use the same bounds TO DO change so that all input layers do not have to have the same bounds, test plotting multiple probability layers, and add option so that if PDF and PNG aren't output, opens plot on screen using plt.show() :param grids: Dictionary of N layers and metadata formatted like: maplayers['layer name']={ 'grid': mapio grid2D object, 'label': 'label for colorbar and top line of subtitle', 'type': 'output or input to model', 'description': 'detailed description of layer for subtitle'}. Layer names must be unique. :type name: Dictionary or Ordered dictionary - import collections; grids = collections.OrderedDict() :param shakefile: optional ShakeMap file (url or full file path) to extract information for labels and folder names :type shakefile: Shakemap Event Dictionary :param suptitle: This will be displayed at the top of the plots and in the figure names :type suptitle: string :param plotorder: List of keys describing the order to plot the grids, if None and grids is an ordered dictionary, it will use the order of the dictionary, otherwise it will choose order which may be somewhat random but it will always put a probability grid first :type plotorder: list :param maskthreshes: N x 1 array or list of lower thresholds for masking corresponding to order in plotorder or order of OrderedDict if plotorder is None. If grids is not an ordered dict and plotorder is not specified, this will not work right. If None (default), nothing will be masked :param colormaps: List of strings of matplotlib colormaps (e.g. cm.autumn_r) corresponding to plotorder or order of dictionary if plotorder is None. The list can contain both strings and None e.g. colormaps = ['cm.autumn', None, None, 'cm.jet'] and None's will default to default colormap :param boundaries: None to show entire study area, 'zoom' to zoom in on the area of action (only works if there is a probability layer) using zthresh as a threshold, or a dictionary defining lats and lons in the form of boundaries.xmin = minlon, boundaries.xmax = maxlon, boundaries.ymin = min lat, boundaries.ymax = max lat :param zthresh: threshold for computing zooming bounds, only used if boundaries = 'zoom' :type zthresh: float :param scaletype: Type of scale for plotting, 'continuous' or 'binned' - will be reflected in colorbar :type scaletype: string :param lims: None or Nx1 list of tuples or numpy arrays corresponding to plotorder defining the limits for saturating the colorbar (vmin, vmax) if scaletype is continuous or the bins to use (clev) if scaletype if binned. The list can contain tuples, arrays, and Nones, e.g. lims = [(0., 10.), None, (0.1, 1.5), np.linspace(0., 1.5, 15)]. When None is specified, the program will estimate the limits, when an array is specified but the scale type is continuous, vmin will be set to min(array) and vmax will be set to max(array) :param lims: None or Nx1 list of Trues and Falses corresponding to plotorder defining whether to use a linear or log scale (log10) for plotting the layer. This will be reflected in the labels :param ALPHA: Transparency for mapping, if there is a hillshade that will plot below each layer, it is recommended to set this to at least 0.7 :type ALPHA: float :param maproads: Whether to show roads or not, default True, but requires that roadfile is specified and valid to work :type maproads: boolean :param mapcities: Whether to show cities or not, default True, but requires that cityfile is specified and valid to work :type mapcities: boolean :param isScenario: Whether this is a scenario (True) or a real event (False) (default False) :type isScenario: boolean :param roadfolder: Full file path to folder containing road shapefiles :type roadfolder: string :param topofile: Full file path to topography grid (GDAL compatible) - this is only needed to make a hillshade if a premade hillshade is not specified :type topofile: string :param cityfile: Full file path to Pager file containing city & population information :type cityfile: string :param roadcolor: Color to use for roads, if plotted, default #6E6E6E :type roadcolor: Hex color or other matplotlib compatible way of defining color :param watercolor: Color to use for oceans, lakes, and rivers, default #B8EEFF :type watercolor: Hex color or other matplotlib compatible way of defining color :param countrycolor: Color for country borders, default #177F10 :type countrycolor: Hex color or other matplotlib compatible way of defining color :param outputdir: File path for outputting figures, if edict is defined, a subfolder based on the event id will be created in this folder. If None, will use current directory :param savepdf: True to save pdf figure, False to not :param savepng: True to save png figure, False to not :param ds: True to allow downsampling for display (necessary when arrays are quite large, False to not allow) :param dstype: What function to use in downsampling, options are 'min', 'max', 'median', or 'mean' :param upsample: True to upsample the layer to the DEM resolution for better looking hillshades :returns: * PDF and/or PNG of map * Downsampled and trimmed version of input grids. If no modification was needed for plotting, this will be identical to grids but without the metadata """ if suptitle is None: suptitle = ' ' plt.ioff() defaultcolormap = cm.jet if shakefile is not None: edict = ShakeGrid.load(shakefile, adjust='res').getEventDict() temp = ShakeGrid.load(shakefile, adjust='res').getShakeDict() edict['eventid'] = temp['shakemap_id'] edict['version'] = temp['shakemap_version'] else: edict = None # Get output file location if outputdir is None: print('No output location given, using current directory for outputs\n') outputdir = os.getcwd() if edict is not None: outfolder = os.path.join(outputdir, edict['event_id']) else: outfolder = outputdir if not os.path.isdir(outfolder): os.makedirs(outfolder) # Get plotting order, if not specified if plotorder is None: plotorder = list(grids.keys()) # Get boundaries to use for all plots cut = True if boundaries is None: cut = False keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() elif boundaries == 'zoom': # Find probability layer (will just take the maximum bounds if there is # more than one) keytemp = list(grids.keys()) key1 = [key for key in keytemp if 'model' in key.lower()] if len(key1) == 0: print('Could not find model layer to use for zoom, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() else: lonmax = -1.e10 lonmin = 1.e10 latmax = -1.e10 latmin = 1.e10 for key in key1: # get lat lons of areas affected and add, if no areas affected, # switch to shakemap boundaries temp = grids[key]['grid'] xmin, xmax, ymin, ymax = temp.getBounds() lons = np.linspace(xmin, xmax, temp.getGeoDict().nx) lats = np.linspace(ymax, ymin, temp.getGeoDict().ny) # backwards so it plots right row, col = np.where(temp.getData() > float(zthresh)) lonmin = lons[col].min() lonmax = lons[col].max() latmin = lats[row].min() latmax = lats[row].max() # llons, llats = np.meshgrid(lons, lats) # make meshgrid # llons1 = llons[temp.getData() > float(zthresh)] # llats1 = llats[temp.getData() > float(zthresh)] # if llons1.min() < lonmin: # lonmin = llons1.min() # if llons1.max() > lonmax: # lonmax = llons1.max() # if llats1.min() < latmin: # latmin = llats1.min() # if llats1.max() > latmax: # latmax = llats1.max() boundaries1 = {'dx': 100, 'dy': 100., 'nx': 100., 'ny': 100} # dummy fillers, only really care about bounds if xmin < lonmin-0.15*(lonmax-lonmin): boundaries1['xmin'] = lonmin-0.1*(lonmax-lonmin) else: boundaries1['xmin'] = xmin if xmax > lonmax+0.15*(lonmax-lonmin): boundaries1['xmax'] = lonmax+0.1*(lonmax-lonmin) else: boundaries1['xmax'] = xmax if ymin < latmin-0.15*(latmax-latmin): boundaries1['ymin'] = latmin-0.1*(latmax-latmin) else: boundaries1['ymin'] = ymin if ymax > latmax+0.15*(latmax-latmin): boundaries1['ymax'] = latmax+0.1*(latmax-latmin) else: boundaries1['ymax'] = ymax boundaries = GeoDict(boundaries1, adjust='res') else: # SEE IF BOUNDARIES ARE SAME AS BOUNDARIES OF LAYERS keytemp = list(grids.keys()) tempgdict = grids[keytemp[0]]['grid'].getGeoDict() if np.abs(tempgdict.xmin-boundaries['xmin']) < 0.05 and \ np.abs(tempgdict.ymin-boundaries['ymin']) < 0.05 and \ np.abs(tempgdict.xmax-boundaries['xmax']) < 0.05 and \ np.abs(tempgdict.ymax - boundaries['ymax']) < 0.05: print('Input boundaries are almost the same as specified boundaries, no cutting needed') boundaries = tempgdict cut = False else: try: if boundaries['xmin'] > boundaries['xmax'] or \ boundaries['ymin'] > boundaries['ymax']: print('Input boundaries are not usable, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() cut = False else: # Build dummy GeoDict boundaries = GeoDict({'xmin': boundaries['xmin'], 'xmax': boundaries['xmax'], 'ymin': boundaries['ymin'], 'ymax': boundaries['ymax'], 'dx': 100., 'dy': 100., 'ny': 100., 'nx': 100.}, adjust='res') except: print('Input boundaries are not usable, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() cut = False # Pull out bounds for various uses bxmin, bxmax, bymin, bymax = boundaries.xmin, boundaries.xmax, boundaries.ymin, boundaries.ymax # Determine if need a single panel or multi-panel plot and if multi-panel, # how many and how it will be arranged fig = plt.figure() numpanels = len(grids) if numpanels == 1: rowpan = 1 colpan = 1 # create the figure and axes instances. fig.set_figwidth(5) elif numpanels == 2 or numpanels == 4: rowpan = np.ceil(numpanels/2.) colpan = 2 fig.set_figwidth(13) else: rowpan = np.ceil(numpanels/3.) colpan = 3 fig.set_figwidth(15) if rowpan == 1: fig.set_figheight(rowpan*6.0) else: fig.set_figheight(rowpan*5.3) # Need to update naming to reflect the shakemap version once can get # getHeaderData to work, add edict['version'] back into title, maybe # shakemap id also? fontsizemain = 14. fontsizesub = 12. fontsizesmallest = 10. if rowpan == 1.: fontsizemain = 12. fontsizesub = 10. fontsizesmallest = 8. if edict is not None: if isScenario: title = edict['event_description'] else: timestr = edict['event_timestamp'].strftime('%b %d %Y') title = 'M%.1f %s v%i - %s' % (edict['magnitude'], timestr, edict['version'], edict['event_description']) plt.suptitle(title+'\n'+suptitle, fontsize=fontsizemain) else: plt.suptitle(suptitle, fontsize=fontsizemain) clear_color = [0, 0, 0, 0.0] # Cut all of them and release extra memory xbuff = (bxmax-bxmin)/10. ybuff = (bymax-bymin)/10. cutxmin = bxmin-xbuff cutymin = bymin-ybuff cutxmax = bxmax+xbuff cutymax = bymax+ybuff if cut is True: newgrids = collections.OrderedDict() for k, layer in enumerate(plotorder): templayer = grids[layer]['grid'] try: newgrids[layer] = {'grid': templayer.cut(cutxmin, cutxmax, cutymin, cutymax, align=True)} except Exception as e: print(('Cutting failed, %s, continuing with full layers' % e)) newgrids = grids continue del templayer gc.collect() else: newgrids = grids tempgdict = newgrids[list(grids.keys())[0]]['grid'].getGeoDict() # Upsample layers to same as topofile if desired for better looking hillshades if upsample is True and topofile is not None: try: topodict = GDALGrid.getFileGeoDict(topofile) if topodict.dx >= tempgdict.dx or topodict.dy >= tempgdict.dy: print('Upsampling not possible, resolution of results already smaller than DEM') pass else: tempgdict1 = GeoDict({'xmin': tempgdict.xmin-xbuff, 'ymin': tempgdict.ymin-ybuff, 'xmax': tempgdict.xmax+xbuff, 'ymax': tempgdict.ymax+ybuff, 'dx': topodict.dx, 'dy': topodict.dy, 'nx': topodict.nx, 'ny': topodict.ny}, adjust='res') tempgdict2 = tempgdict1.getBoundsWithin(tempgdict) for k, layer in enumerate(plotorder): newgrids[layer]['grid'] = newgrids[layer]['grid'].subdivide(tempgdict2) except: print('Upsampling failed, continuing') # Downsample all of them for plotting, if needed, and replace them in # grids (to save memory) tempgrid = newgrids[list(grids.keys())[0]]['grid'] xsize = tempgrid.getGeoDict().nx ysize = tempgrid.getGeoDict().ny inchesx, inchesy = fig.get_size_inches() divx = int(np.round(xsize/(500.*inchesx))) divy = int(np.round(ysize/(500.*inchesy))) xmin, xmax, ymin, ymax = tempgrid.getBounds() gdict = tempgrid.getGeoDict() # Will be replaced if downsampled del tempgrid gc.collect() if divx <= 1: divx = 1 if divy <= 1: divy = 1 if (divx > 1. or divy > 1.) and ds: if dstype == 'max': func = np.nanmax elif dstype == 'min': func = np.nanmin elif dstype == 'med': func = np.nanmedian else: func = np.nanmean for k, layer in enumerate(plotorder): layergrid = newgrids[layer]['grid'] dat = block_reduce(layergrid.getData().copy(), block_size=(divy, divx), cval=float('nan'), func=func) if k == 0: lons = block_reduce(np.linspace(xmin, xmax, layergrid.getGeoDict().nx), block_size=(divx,), func=np.mean, cval=float('nan')) if math.isnan(lons[-1]): lons[-1] = lons[-2] + (lons[1]-lons[0]) lats = block_reduce(np.linspace(ymax, ymin, layergrid.getGeoDict().ny), block_size=(divy,), func=np.mean, cval=float('nan')) if math.isnan(lats[-1]): lats[-1] = lats[-2] + (lats[1]-lats[0]) gdict = GeoDict({'xmin': lons.min(), 'xmax': lons.max(), 'ymin': lats.min(), 'ymax': lats.max(), 'dx': np.abs(lons[1]-lons[0]), 'dy': np.abs(lats[1]-lats[0]), 'nx': len(lons), 'ny': len(lats)}, adjust='res') newgrids[layer]['grid'] = Grid2D(dat, gdict) del layergrid, dat else: lons = np.linspace(xmin, xmax, xsize) lats = np.linspace(ymax, ymin, ysize) # backwards so it plots right side up #make meshgrid llons1, llats1 = np.meshgrid(lons, lats) # See if there is an oceanfile for masking bbox = PolygonSH(((cutxmin, cutymin), (cutxmin, cutymax), (cutxmax, cutymax), (cutxmax, cutymin))) if oceanfile is not None: try: f = fiona.open(oceanfile) oc = next(f) f.close shapes = shape(oc['geometry']) # make boundaries into a shape ocean = shapes.intersection(bbox) except: print('Not able to read specified ocean file, will use default ocean masking') oceanfile = None if inventory_shapefile is not None: try: f = fiona.open(inventory_shapefile) invshp = list(f.items(bbox=(bxmin, bymin, bxmax, bymax))) f.close() inventory = [shape(inv[1]['geometry']) for inv in invshp] except: print('unable to read inventory shapefile specified, will not plot inventory') inventory_shapefile = None # # Find cities that will be plotted if mapcities is True and cityfile is not None: try: mycity = BasemapCities.loadFromGeoNames(cityfile=cityfile) bcities = mycity.limitByBounds((bxmin, bxmax, bymin, bymax)) #bcities = bcities.limitByPopulation(40000) bcities = bcities.limitByGrid(nx=4, ny=4, cities_per_grid=2) except: print('Could not read in cityfile, not plotting cities') mapcities = False cityfile = None # Load in topofile if topofile is not None: try: topomap = GDALGrid.load(topofile, resample=True, method='linear', samplegeodict=gdict) except: topomap = GMTGrid.load(topofile, resample=True, method='linear', samplegeodict=gdict) topodata = topomap.getData().copy() # mask oceans if don't have ocean shapefile if oceanfile is None: topodata = maskoceans(llons1, llats1, topodata, resolution='h', grid=1.25, inlands=True) else: print('no hillshade is possible\n') topomap = None topodata = None # Load in roads, if needed if maproads is True and roadfolder is not None: try: roadslist = [] for folder in os.listdir(roadfolder): road1 = os.path.join(roadfolder, folder) shpfiles = glob.glob(os.path.join(road1, '*.shp')) if len(shpfiles): shpfile = shpfiles[0] f = fiona.open(shpfile) shapes = list(f.items(bbox=(bxmin, bymin, bxmax, bymax))) for shapeid, shapedict in shapes: roadslist.append(shapedict) f.close() except: print('Not able to plot roads') roadslist = None val = 1 for k, layer in enumerate(plotorder): layergrid = newgrids[layer]['grid'] if 'label' in list(grids[layer].keys()): label1 = grids[layer]['label'] else: label1 = layer try: sref = grids[layer]['description']['name'] except: sref = None ax = fig.add_subplot(rowpan, colpan, val) val += 1 clat = bymin + (bymax-bymin)/2.0 clon = bxmin + (bxmax-bxmin)/2.0 # setup of basemap ('lcc' = lambert conformal conic). # use major and minor sphere radii from WGS84 ellipsoid. m = Basemap(llcrnrlon=bxmin, llcrnrlat=bymin, urcrnrlon=bxmax, urcrnrlat=bymax, rsphere=(6378137.00, 6356752.3142), resolution='l', area_thresh=1000., projection='lcc', lat_1=clat, lon_0=clon, ax=ax) x1, y1 = m(llons1, llats1) # get projection coordinates axsize = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) if k == 0: wid, ht = axsize.width, axsize.height if colormaps is not None and \ len(colormaps) == len(newgrids) and \ colormaps[k] is not None: palette = colormaps[k] else: # Find preferred default color map for each type of layer if 'prob' in layer.lower() or 'pga' in layer.lower() or \ 'pgv' in layer.lower() or 'cohesion' in layer.lower() or \ 'friction' in layer.lower() or 'fs' in layer.lower(): palette = cm.jet elif 'slope' in layer.lower(): palette = cm.gnuplot2 elif 'precip' in layer.lower(): palette = cm2.s3pcpn else: palette = defaultcolormap if topodata is not None: if k == 0: ptopo = m.transform_scalar( np.flipud(topodata), lons+0.5*gdict.dx, lats[::-1]-0.5*gdict.dy, np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=1, masked=False) #use lightsource class to make our shaded topography ls = LightSource(azdeg=135, altdeg=45) ls1 = LightSource(azdeg=120, altdeg=45) ls2 = LightSource(azdeg=225, altdeg=45) intensity1 = ls1.hillshade(ptopo, fraction=0.25, vert_exag=1.) intensity2 = ls2.hillshade(ptopo, fraction=0.25, vert_exag=1.) intensity = intensity1*0.5 + intensity2*0.5 #hillshm_im = m.transform_scalar(np.flipud(hillshm), lons, lats[::-1], np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=0, masked=False) #m.imshow(hillshm_im, cmap='Greys', vmin=0., vmax=3., zorder=1, interpolation='none') # vmax = 3 to soften colors to light gray #m.pcolormesh(x1, y1, hillshm, cmap='Greys', linewidth=0., rasterized=True, vmin=0., vmax=3., edgecolors='none', zorder=1); # plt.draw() # Get the data dat = layergrid.getData().copy() # mask out anything below any specified thresholds # Might need to move this up to before downsampling...might give illusion of no hazard in places where there is some that just got averaged out if maskthreshes is not None and len(maskthreshes) == len(newgrids): if maskthreshes[k] is not None: dat[dat <= maskthreshes[k]] = float('NaN') dat = np.ma.array(dat, mask=np.isnan(dat)) if logscale is not False and len(logscale) == len(newgrids): if logscale[k] is True: dat = np.log10(dat) label1 = r'$log_{10}$(' + label1 + ')' if scaletype.lower() == 'binned': # Find order of range to know how to scale order = np.round(np.log(np.nanmax(dat) - np.nanmin(dat))) if order < 1.: scal = 10**-order else: scal = 1. if lims is None or len(lims) != len(newgrids): clev = (np.linspace(np.floor(scal*np.nanmin(dat)), np.ceil(scal*np.nanmax(dat)), 10))/scal else: if lims[k] is None: clev = (np.linspace(np.floor(scal*np.nanmin(dat)), np.ceil(scal*np.nanmax(dat)), 10))/scal else: clev = lims[k] # Adjust to colorbar levels dat[dat < clev[0]] = clev[0] for j, level in enumerate(clev[:-1]): dat[(dat >= clev[j]) & (dat < clev[j+1])] = clev[j] # So colorbar saturates at top dat[dat > clev[-1]] = clev[-1] #panelhandle = m.contourf(x1, y1, datm, clev, cmap=palette, linewidth=0., alpha=ALPHA, rasterized=True) vmin = clev[0] vmax = clev[-1] else: if lims is not None and len(lims) == len(newgrids): if lims[k] is None: vmin = np.nanmin(dat) vmax = np.nanmax(dat) else: vmin = lims[k][0] vmax = lims[k][-1] else: vmin = np.nanmin(dat) vmax = np.nanmax(dat) # Mask out cells overlying oceans or block with a shapefile if available if oceanfile is None: dat = maskoceans(llons1, llats1, dat, resolution='h', grid=1.25, inlands=True) else: #patches = [] if type(ocean) is PolygonSH: ocean = [ocean] for oc in ocean: patch = getProjectedPatch(oc, m, edgecolor="#006280", facecolor=watercolor, lw=0.5, zorder=4.) #x, y = m(oc.exterior.xy[0], oc.exterior.xy[1]) #xy = zip(x, y) #patch = Polygon(xy, facecolor=watercolor, edgecolor="#006280", lw=0.5, zorder=4.) ##patches.append(Polygon(xy, facecolor=watercolor, edgecolor=watercolor, zorder=500.)) ax.add_patch(patch) ##ax.add_collection(PatchCollection(patches)) if inventory_shapefile is not None: for in1 in inventory: if 'point' in str(type(in1)): x, y = in1.xy x = x[0] y = y[0] m.scatter(x, y, c='m', s=50, latlon=True, marker='^', zorder=100001) else: x, y = m(in1.exterior.xy[0], in1.exterior.xy[1]) xy = list(zip(x, y)) patch = Polygon(xy, facecolor='none', edgecolor='k', lw=0.5, zorder=10.) #patches.append(Polygon(xy, facecolor=watercolor, edgecolor=watercolor, zorder=500.)) ax.add_patch(patch) palette.set_bad(clear_color, alpha=0.0) # Plot it up dat_im = m.transform_scalar( np.flipud(dat), lons+0.5*gdict.dx, lats[::-1]-0.5*gdict.dy, np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=0, masked=True) if topodata is not None: # Drape over hillshade #turn data into an RGBA image cmap = palette #adjust data so scaled between vmin and vmax and between 0 and 1 dat1 = dat_im.copy() dat1[dat1 < vmin] = vmin dat1[dat1 > vmax] = vmax dat1 = (dat1 - vmin)/(vmax-vmin) rgba_img = cmap(dat1) maskvals = np.dstack((dat1.mask, dat1.mask, dat1.mask)) rgb = np.squeeze(rgba_img[:, :, 0:3]) rgb[maskvals] = 1. draped_hsv = ls.blend_hsv(rgb, np.expand_dims(intensity, 2)) m.imshow(draped_hsv, zorder=3., interpolation='none') # This is just a dummy layer that will be deleted to make the # colorbar look right panelhandle = m.imshow(dat_im, cmap=palette, zorder=0., vmin=vmin, vmax=vmax) else: panelhandle = m.imshow(dat_im, cmap=palette, zorder=3., vmin=vmin, vmax=vmax, interpolation='none') #panelhandle = m.pcolormesh(x1, y1, dat, linewidth=0., cmap=palette, vmin=vmin, vmax=vmax, alpha=ALPHA, rasterized=True, zorder=2.); #panelhandle.set_edgecolors('face') # add colorbar cbfmt = '%1.1f' if vmax is not None and vmin is not None: if (vmax - vmin) < 1.: cbfmt = '%1.2f' elif vmax > 5.: # (vmax - vmin) > len(clev): cbfmt = '%1.0f' #norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) if scaletype.lower() == 'binned': cbar = fig.colorbar(panelhandle, spacing='proportional', ticks=clev, boundaries=clev, fraction=0.036, pad=0.04, format=cbfmt, extend='both') #cbar1 = ColorbarBase(cbar.ax, cmap=palette, norm=norm, spacing='proportional', ticks=clev, boundaries=clev, fraction=0.036, pad=0.04, format=cbfmt, extend='both', extendfrac='auto') else: cbar = fig.colorbar(panelhandle, fraction=0.036, pad=0.04, extend='both', format=cbfmt) #cbar1 = ColorbarBase(cbar.ax, cmap=palette, norm=norm, fraction=0.036, pad=0.04, extend='both', extendfrac='auto', format=cbfmt) if topodata is not None: panelhandle.remove() cbar.set_label(label1, fontsize=10) cbar.ax.tick_params(labelsize=8) parallels = m.drawparallels(getMapLines(bymin, bymax, 3), labels=[1, 0, 0, 0], linewidth=0.5, labelstyle='+/-', fontsize=9, xoffset=-0.8, color='gray', zorder=100.) m.drawmeridians(getMapLines(bxmin, bxmax, 3), labels=[0, 0, 0, 1], linewidth=0.5, labelstyle='+/-', fontsize=9, color='gray', zorder=100.) for par in parallels: try: parallels[par][1][0].set_rotation(90) except: pass #draw roads on the map, if they were provided to us if maproads is True and roadslist is not None: try: for road in roadslist: try: xy = list(road['geometry']['coordinates']) roadx, roady = list(zip(*xy)) mapx, mapy = m(roadx, roady) m.plot(mapx, mapy, roadcolor, lw=0.5, zorder=9) except: continue except Exception as e: print(('Failed to plot roads, %s' % e)) #add city names to map if mapcities is True and cityfile is not None: try: fontname = 'Arial' fontsize = 8 if k == 0: # Only need to choose cities first time and then apply to rest fcities = bcities.limitByMapCollision( m, fontname=fontname, fontsize=fontsize) ctlats, ctlons, names = fcities.getCities() cxis, cyis = m(ctlons, ctlats) for ctlat, ctlon, cxi, cyi, name in zip(ctlats, ctlons, cxis, cyis, names): m.scatter(ctlon, ctlat, c='k', latlon=True, marker='.', zorder=100000) ax.text(cxi, cyi, name, fontname=fontname, fontsize=fontsize, zorder=100000) except Exception as e: print('Failed to plot cities, %s' % e) #draw star at epicenter plt.sca(ax) if edict is not None: elat, elon = edict['lat'], edict['lon'] ex, ey = m(elon, elat) plt.plot(ex, ey, '*', markeredgecolor='k', mfc='None', mew=1.0, ms=15, zorder=10000.) m.drawmapboundary(fill_color=watercolor) m.fillcontinents(color=clear_color, lake_color=watercolor) m.drawrivers(color=watercolor) ##m.drawcoastlines() #draw country boundaries m.drawcountries(color=countrycolor, linewidth=1.0) #add map scale m.drawmapscale((bxmax+bxmin)/2., (bymin+(bymax-bymin)/9.), clon, clat, np.round((((bxmax-bxmin)*111)/5)/10.)*10, barstyle='fancy', zorder=10) # Add border autoAxis = ax.axis() rec = Rectangle((autoAxis[0]-0.7, autoAxis[2]-0.2), (autoAxis[1]-autoAxis[0])+1, (autoAxis[3]-autoAxis[2])+0.4, fill=False, lw=1, zorder=1e8) rec = ax.add_patch(rec) rec.set_clip_on(False) plt.draw() if sref is not None: label2 = '%s\nsource: %s' % (label1, sref) # '%s\n' % label1 + r'{\fontsize{10pt}{3em}\selectfont{}%s}' % sref # else: label2 = label1 plt.title(label2, axes=ax, fontsize=fontsizesub) #draw scenario watermark, if scenario if isScenario: plt.sca(ax) cx, cy = m(clon, clat) plt.text(cx, cy, 'SCENARIO', rotation=45, alpha=0.10, size=72, ha='center', va='center', color='red') #if ds: # Could add this to print "downsampled" on map # plt.text() if k == 1 and rowpan == 1: # adjust single level plot axsize = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) ht2 = axsize.height fig.set_figheight(ht2*1.6) else: plt.tight_layout() # Make room for suptitle - tight layout doesn't account for it plt.subplots_adjust(top=0.92) if printparam is True: try: fig = plt.gcf() dictionary = grids['model']['description']['parameters'] paramstring = 'Model parameters: ' halfway = np.ceil(len(dictionary)/2.) for i, key in enumerate(dictionary): if i == halfway and colpan == 1: paramstring += '\n' paramstring += ('%s = %s; ' % (key, dictionary[key])) print(paramstring) fig.text(0.01, 0.015, paramstring, fontsize=fontsizesmallest) plt.draw() except: print('Could not display model parameters') if edict is not None: eventid = edict['eventid'] else: eventid = '' time1 = datetime.datetime.utcnow().strftime('%d%b%Y_%H%M') outfile = os.path.join(outfolder, '%s_%s_%s.pdf' % (eventid, suptitle, time1)) pngfile = os.path.join(outfolder, '%s_%s_%s.png' % (eventid, suptitle, time1)) if savepdf is True: print('Saving map output to %s' % outfile) plt.savefig(outfile, dpi=300) if savepng is True: print('Saving map output to %s' % pngfile) plt.savefig(pngfile) if showplots is True: plt.show() else: plt.close(fig) return newgrids
def plot_topography(ax, geo_model, extent_val, **kwargs): """ Args: ax: geo_model: extent_val: **kwargs: Returns: """ hillshade = kwargs.pop('show_hillshade', True) contour = kwargs.pop('show_contour', False) fill_contour = kwargs.pop('show_fill_contour', False) azdeg = kwargs.pop('azdeg', 0) altdeg = kwargs.pop('altdeg', 0) cmap = kwargs.pop('cmap', 'terrain') super = kwargs.pop('super_res', False) colorbar = kwargs.pop("show_colorbar", False) topo = geo_model._grid.topography if super: import skimage topo_super_res = skimage.transform.resize(topo.values_2d, (1600, 1600), order=3, mode='edge', anti_aliasing=True, preserve_range=False) values = topo_super_res[..., 2] else: values = topo.values_2d[..., 2] if contour is True: CS = ax.contour(values, extent=extent_val, colors='k', linestyles='solid', origin='lower') ax.clabel(CS, inline=1, fontsize=10, fmt='%d') if fill_contour is True: CS2 = ax.contourf(values, extent=extent_val, cmap=cmap) if colorbar: from gempy.plot.helpers import add_colorbar add_colorbar(axes=ax, label='elevation [m]', cs=CS2) if hillshade is True: from matplotlib.colors import LightSource # Note: 180 degrees are subtracted because visualization in Sandbox is upside-down ls = LightSource(azdeg=azdeg - 180, altdeg=altdeg) # TODO: Is is better to use ls.hillshade or ls.shade?? hillshade_topography = ls.hillshade(values) # vert_exag=0.3, # blend_mode='overlay') global hill hill = ax.imshow(hillshade_topography, cmap=plt.cm.gray, origin='lower', extent=extent_val, alpha=0.4, zorder=11, aspect='auto')
sparse_ok=True, blockxsize=DST_BLOCK_SIZE, blockysize=DST_BLOCK_SIZE, height=DST_TILE_HEIGHT, width=DST_TILE_WIDTH, ) # Get the bounds of the tile. ulx, uly = mercantile.xy(*mercantile.ul(tile.x, tile.y, tile.z)) lrx, lry = mercantile.xy(*mercantile.ul(tile.x + 1, tile.y + 1, tile.z)) meta["affine"] = src.window_transform(window) ls = LightSource() hs = ls.hillshade(data, dx=dx, dy=dy, ) hs = (255.0 * hs).astype(np.uint8) with rasterio.open("windowed.tif", "w", **meta) as dst: # ignore the border pixels when writing dst.write(hs[BUFFER:-BUFFER, BUFFER:-BUFFER], 1) cdict = { "red": [(0.0, 60 / 255.0, 60 / 255.0), (1.0, 220 / 255.0, 220 / 255.0)], "green": [(0.0, 75 / 255.0, 75 / 255.0), (1.0, 1.0, 1.0)], "blue": [(0.0, 80 / 255.0, 80 / 255.0), (1.0, 100 / 255.0, 100 / 255.0)], "alpha": [(0.0, 0.4, 0.4),
start = timer() hs_array = hillshade(arr, 315, 45) end = timer() print "naive hillshade took %dms" % (end - start) dst.write(hs_array.astype(rasterio.int32), 1) profile = src.profile profile.update( dtype=rasterio.uint8, predictor=1, nodata=None, ) with rasterio.open("gt.tif", "w", **profile) as dst: start = timer() hs = gt_hillshade(arr, 315, 45, 0.05) end = timer() print "hillshade took %dms" % (end - start) dst.write(hs, 1) with rasterio.open("plt.tif", "w", **profile) as dst: start = timer() ls = LightSource() hs = ls.hillshade(arr, dx=dx, dy=dy, ) hs = (255.0 * hs).astype(np.uint8) end = timer() print "hillshade took %dms" % (end - start) dst.write(hs, 1)
dx, dy = dem['dx'], dem['dy'] dy = 111200 * dy dx = 111200 * dx * np.cos(np.radians(dem['ymin'])) #----------------------------------------------------------------------------- # Shade from the northwest, with the sun 45 degrees from horizontal ls = LightSource(azdeg=315, altdeg=45) cmap = plt.cm.gist_earth fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(8, 9)) plt.setp(axes.flat, xticks=[], yticks=[]) # Vary vertical exaggeration and blend mode and plot all combinations for col, ve in zip(axes.T, [0.1, 1, 10]): # Show the hillshade intensity image in the first row col[0].imshow(ls.hillshade(z, vert_exag=ve, dx=dx, dy=dy), cmap='gray') # Place hillshaded plots with different blend modes in the rest of the rows for ax, mode in zip(col[1:], ['hsv', 'overlay', 'soft']): rgb = ls.shade(z, cmap=cmap, blend_mode=mode, vert_exag=ve, dx=dx, dy=dy) ax.imshow(rgb) # Label rows and columns for ax, ve in zip(axes[0], [0.1, 1, 10]): ax.set_title('{0}'.format(ve), size=18) for ax, mode in zip(axes[:, 0], ['Hillshade', 'hsv', 'overlay', 'soft']):
se = morphology.disk(5) filtDem = cv2.morphologyEx(filtDem, cv2.MORPH_ERODE, se) # filtDem = cv2.medianBlur(dem, 5) # 5 is the biggest size for use with float32 # filtDem = cv2.bilateralFilter(dem, 13, 150, 150) pylab.figure() ax1 = pylab.subplot(211) pylab.imshow(dem) pylab.subplot(212, sharex=ax1, sharey=ax1) pylab.imshow(filtDem) ls = LightSource(azdeg=315, altdeg=45) pylab.figure() ax1 = pylab.subplot(311) pylab.imshow(ls.hillshade(dem, vert_exag=1., dx=.5, dy=.5), cmap='gray') pylab.subplot(312, sharex=ax1, sharey=ax1) pylab.imshow(ls.hillshade(filtDem, vert_exag=1., dx=.5, dy=.5), cmap='gray') pylab.subplot(313, sharex=ax1, sharey=ax1) pylab.imshow(ls.hillshade(dem - filtDem, vert_exag=1., dx=.5, dy=.5), cmap='gray') ########################################################################################### # write filtered DEM & plant height files filtDemDs = gdal.GetDriverByName('GTiff').CreateCopy( filtDemFile, demDs, options=["TILED=YES", "COMPRESS=DEFLATE"]) filtDemDs.GetRasterBand(1).WriteArray(filtDem) # Writes my array to the raster filtDemDs.FlushCache() filtDemDs = None
fig = plt.figure(figsize=(32, 24)) ax = plt.subplot(projection=proj) cmappa = cm.get_cmap('gist_earth') cbar_range = None clevels = [ -10000, -7000, -5000, -4000, -3000, -2000, -1000, -500, 0, 500, 1000, 1500, 2000, 3000, 4000, 6000, 7000 ] ax.set_global() ax.coastlines(linewidth=2) # Shade from the northwest, with the sun 45 degrees from horizontal ls = LightSource(azdeg=315, altdeg=45) hillsh = ls.hillshade(elev, vert_exag=100, dx=10000, dy=10000) ax.pcolormesh(lon, lat, hillsh, cmap='gray', transform=ccrs.PlateCarree(), alpha=1.0) map = ctl.plot_mapc_on_ax(ax, elev, lat, lon, proj, cmappa, cbar_range, clevels=clevels,
scaled.append(new_value) #set scaled colour values cmap_dem = make_colormap([ c('#010071'), scaled[0], c('#010071'), c('#1f78b4'), scaled[1], c('#1f78b4'), c("#89e2ff"), scaled[2], c("#0b6e24"), c("#dfc485"), scaled[3], c("#dfc485"), c('#8d7c58'), scaled[4], c("#8d7c58"), c("#a49fa3"), scaled[5], c("#a49fa3") ]) im = Image.fromarray(np.uint8(cmap_dem(rs_dem) * 255)) #create hillshade ls = LightSource(azdeg=315, altdeg=45) hs = ls.hillshade(read_dem, vert_exag=0.04, fraction=1.35) hsimg = Image.fromarray(np.uint8(cm.gray(hs) * 255)) #blend hillshade to RGB image using multiplication blend = ImageChops.multiply(im, hsimg) #write image to disc blend.save('OUTFILEPATH.tif')
def _get_basemap(self, projection='lambert', geopolygons=None, resolution='i', bound=True, hillshade=False): """Get basemap for plotting results """ # fig=plt.figure(num=None, figsize=(12, 12), dpi=80, facecolor='w', edgecolor='k') minlat = self.attrs['minlat'] maxlat = self.attrs['maxlat'] minlon = self.attrs['minlon'] maxlon = self.attrs['maxlon'] lat_centre = (maxlat+minlat)/2.0 lon_centre = (maxlon+minlon)/2.0 if projection=='merc': m=Basemap(projection='merc', llcrnrlat=minlat-5., urcrnrlat=maxlat+5., llcrnrlon=minlon-5., urcrnrlon=maxlon+5., lat_ts=20, resolution=resolution) # m.drawparallels(np.arange(minlat,maxlat,dlat), labels=[1,0,0,1]) # m.drawmeridians(np.arange(minlon,maxlon,dlon), labels=[1,0,0,1]) m.drawparallels(np.arange(-80.0,80.0,2.0), dashes=[2,2], labels=[1,0,0,0], fontsize=12) m.drawmeridians(np.arange(-170.0,170.0,2.0), dashes=[2,2], labels=[0,0,1,0], fontsize=12) m.drawstates(color='g', linewidth=2.) elif projection=='global': m=Basemap(projection='ortho',lon_0=lon_centre, lat_0=lat_centre, resolution=resolution) # m.drawparallels(np.arange(-80.0,80.0,10.0), labels=[1,0,0,1]) # m.drawmeridians(np.arange(-170.0,170.0,10.0), labels=[1,0,0,1]) elif projection=='regional_ortho': m1 = Basemap(projection='ortho', lon_0=minlon, lat_0=minlat, resolution='l') m = Basemap(projection='ortho', lon_0=minlon, lat_0=minlat, resolution=resolution,\ llcrnrx=0., llcrnry=0., urcrnrx=m1.urcrnrx/mapfactor, urcrnry=m1.urcrnry/3.5) m.drawparallels(np.arange(-80.0,80.0,10.0), labels=[1,0,0,0], linewidth=2, fontsize=20) # m.drawparallels(np.arange(-90.0,90.0,30.0),labels=[1,0,0,0], dashes=[10, 5], linewidth=2, fontsize=20) # m.drawmeridians(np.arange(10,180.0,30.0), dashes=[10, 5], linewidth=2) m.drawmeridians(np.arange(-170.0,170.0,10.0), linewidth=2) elif projection=='lambert': distEW, az, baz=obspy.geodetics.gps2dist_azimuth(minlat, minlon, minlat, maxlon) # distance is in m distNS, az, baz=obspy.geodetics.gps2dist_azimuth(minlat, minlon, maxlat+2., minlon) # distance is in m m = Basemap(width=distEW, height=distNS, rsphere=(6378137.00,6356752.3142), resolution='l', projection='lcc',\ lat_1=minlat, lat_2=maxlat, lon_0=lon_centre, lat_0=lat_centre) m.drawparallels(np.arange(-80.0,80.0,2.0), linewidth=1, dashes=[2,2], labels=[1,0,0,0], fontsize=12) m.drawmeridians(np.arange(-170.0,170.0,2.0), linewidth=1, dashes=[2,2], labels=[0,0,1,0], fontsize=12) # m.drawparallels(np.arange(-80.0,80.0,10.0), linewidth=0.5, dashes=[2,2], labels=[1,0,0,0], fontsize=5) # m.drawmeridians(np.arange(-170.0,170.0,10.0), linewidth=0.5, dashes=[2,2], labels=[0,0,0,1], fontsize=5) m.drawcoastlines(linewidth=1.0) m.drawcountries(linewidth=1.0) m.drawstates(linewidth=1.0) # m.drawmapboundary(fill_color=[1.0,1.0,1.0]) # m.fillcontinents(lake_color='#99ffff',zorder=0.2) # m.drawlsmask(land_color='0.8', ocean_color='#99ffff') m.drawmapboundary(fill_color="white") if bound: try: # m.readshapefile('/projects/howa1663/Code/ToolKit/Models/Plates/PB2002_boundaries', name='PB2002_boundaries', drawbounds=True, linewidth=1, color='orange') # draw plate boundary on basemap #m.readshapefile('/work3/wang/code_bkup/AgeJdF/Plates/PB2002_boundaries', name='PB2002_boundaries', drawbounds=True, \ # linewidth=1, color='orange') m.readshapefile('/work3/wang/code_bkup/ToolKit/Models/UT_Plates/ridge',name='ridge',drawbounds=True, linewidth=1, color='orange') m.readshapefile('/work3/wang/code_bkup/ToolKit/Models/UT_Plates/trench',name='trench',drawbounds=True, linewidth=1, color='orange') m.readshapefile('/work3/wang/code_bkup/ToolKit/Models/UT_Plates/transform',name='transform',drawbounds=True, linewidth=1, color='orange') except IOError: print("Couldn't read shape file! Continue without drawing plateboundaries") try: geopolygons.PlotPolygon(inbasemap=m) except: pass if hillshade: from netCDF4 import Dataset from matplotlib.colors import LightSource etopo1 = Dataset('/work2/wang/Code/ToolKit/ETOPO1_Ice_g_gmt4.grd','r') zz = etopo1.variables["z"][:] llons = etopo1.variables["x"][:] west = llons<0 # mask array with negetive longitudes west = 360.*west*np.ones(len(llons)) llons = llons+west llats = etopo1.variables["y"][:] etopoz = zz[(llats>(minlat-2))*(llats<(maxlat+2)), :] etopoz = etopoz[:, (llons>(minlon-2))*(llons<(maxlon+2))] llats = llats[(llats>(minlat-2))*(llats<(maxlat+2))] llons = llons[(llons>(minlon-2))*(llons<(maxlon+2))] ls = LightSource(azdeg=315, altdeg=45) etopoZ = m.transform_scalar(etopoz, llons-360*(llons>180)*np.ones(len(llons)), llats, etopoz.shape[0], etopoz.shape[1]) ls = LightSource(azdeg=315, altdeg=45) m.imshow(ls.hillshade(etopoZ, vert_exag=1.),cmap='gray') return m
def plot_topography(self, ax, fill_contour=False, contour=True, section_name=None, cell_number=None, direction='y', block=None, **kwargs): hillshade = kwargs.get('hillshade', True) azdeg = kwargs.get('azdeg', 0) altdeg = kwargs.get('altdeg', 0) cmap = kwargs.get('cmap', 'terrain') self.update_colot_lot() section_name, cell_number, direction = self._check_default_section(ax, section_name, cell_number, direction) if section_name is not None and section_name != 'topography': p1 = self.model._grid.sections.df.loc[section_name, 'start'] p2 = self.model._grid.sections.df.loc[section_name, 'stop'] x, y, z = self._slice_topo_4_sections(p1, p2, self.model._grid.topography.resolution[0]) pseudo_x = np.linspace(0, self.model._grid.sections.df.loc[section_name, 'dist'], z.shape[0]) a = np.vstack((pseudo_x, z)).T xy = np.append(a, ([self.model._grid.sections.df.loc[section_name, 'dist'], a[:, 1][-1]], [self.model._grid.sections.df.loc[section_name, 'dist'], self.model._grid.regular_grid.extent[5]], [0, self.model._grid.regular_grid.extent[5]], [0, a[:, 1][0]])).reshape(-1, 2) ax.fill(xy[:, 0], xy[:, 1], 'k', zorder=10) elif section_name == 'topography': import skimage from gempy.plot.helpers import add_colorbar topo = self.model._grid.topography topo_super_res = skimage.transform.resize( topo.values_2d, (1600, 1600), order=3, mode='edge', anti_aliasing=True, preserve_range=False) values = topo_super_res[:, :, 2].T if contour is True: CS = ax.contour(values, extent=(topo.extent[:4]), colors='k', linestyles='solid', origin='lower') ax.clabel(CS, inline=1, fontsize=10, fmt='%d') if fill_contour is True: CS2 = ax.contourf(values, extent=(topo.extent[:4]), cmap=cmap) add_colorbar(axes=ax, label='elevation [m]', cs=CS2) if hillshade is True: from matplotlib.colors import LightSource ls = LightSource(azdeg=azdeg, altdeg=altdeg) hillshade_topography = ls.hillshade(values) ax.imshow(hillshade_topography, origin='lower', extent=topo.extent[:4], alpha=0.5, zorder=11, cmap='gray') elif cell_number is not None or block is not None: p1, p2 = self.calculate_p1p2(direction, cell_number) resx = self.model._grid.regular_grid.resolution[0] resy = self.model._grid.regular_grid.resolution[1] x, y, z = self._slice_topo_4_sections(p1, p2, resx) if direction == 'x': a = np.vstack((y, z)).T ext = self.model._grid.regular_grid.extent[[2, 3]] elif direction == 'y': a = np.vstack((x, z)).T ext = self.model._grid.regular_grid.extent[[0, 1]] else: raise NotImplementedError a = np.append(a, ([ext[1], a[:, 1][-1]], [ext[1], self.model._grid.regular_grid.extent[5]], [ext[0], self.model._grid.regular_grid.extent[5]], [ext[0], a[:, 1][0]])) line = a.reshape(-1, 2) ax.fill(line[:, 0], line[:, 1], color='k')
plt.show() t=np.arange(-10,10.01,0.01) x=np.cosh(t) y=np.sin(t) plt.fill_between(x,y, facecolor='y',linestyle='--') plt.show() x=np.arange(0.1,10.1,0.1) y=np.arange(0.1,10.1,0.1) X, Y = np.meshgrid(x, y) Z=np.cos(X)*np.sin(Y)-np.log(X**2+Y**2) plt.contour(X,Y,Z) plt.show() ls = LightSource(azdeg=0, altdeg=0) plt.imshow(ls.hillshade(Z), cmap='gray') plt.show() fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_surface(X, Y, Z,rstride=1, cstride=1, cmap=cm.coolwarm,linewidth=0, antialiased=False) plt.show() x=np.arange(-10,11,1) y=np.arange(-10,11,1) X, Y = np.meshgrid(x, y) plt.streamplot(x, y, -1+np.cos(X)+Y**2, np.sin(Y)-X**2) plt.show() u=np.arange(-10,10.1,0.1) v=np.arange(-10,10.1,0.1) U, V = np.meshgrid(u, v)
from kustom.arpys import dataloaders as dl from kustom.arpys import postprocessing as pp import kustom.plotting from matplotlib.colors import LightSource filename = \ '/home/kevin/Documents/qmap/materials/LSCO22/170702_psi/LSCO22_1_0017.h5' #'/home/kevin/Documents/qmap/materials/LSCO22/170702_psi/LSCO22_1_0040_reduced.p' ddict = dl.load_data(filename) data = ddict['data'] d = data[0] ls = LightSource(azdeg=270, altdeg=80) shaded = ls.hillshade(d, vert_exag=d.max()) #shaded = ls.shade(d, cmap=cmap, vert_exag=d.max()) cmap = plt.get_cmap('viridis') fig = plt.figure() ax1 = fig.add_subplot(121) ax1.pcolormesh(d, cmap=cmap) ax2 = fig.add_subplot(122) #ax2.pcolormesh(data[0], cmap='rainbow_light') #ax2.pcolormesh(shaded, cmap=cmap) ax2.imshow(shaded) plt.show() """ colors1 = [(255,255,255), (235,204,255),
def interpDEM(topoC, dxout, dyout): """ This function allows down- or up-sample a DEM file. Input parameters topoC : DEM object of class Topo dxout : Nre resolution step size in x-direction (East) dyout : New resolution step size in y-direction (North) """ print('\n Interpolating ... ') # Dimensions of DEM Lx = (topoC.Nx - 1) * topoC.dx Ly = (topoC.Ny - 1) * topoC.dy # New number of grid points Nxout = np.int(Lx / dxout) + 1 Nyout = np.int(Ly / dyout) + 1 print('New grid dimension and resolution.') print('Nxout: ', Nxout, ', Nyout: ', Nyout) print('dxout: ', dxout, ', dyout: ', dyout) # Define coordinate arrays xi = np.arange(0., Lx + topoC.dx, topoC.dx) yi = np.arange(0., Ly + topoC.dy, topoC.dy) xo = np.arange(0., Lx + dxout, dxout) yo = np.arange(0., Ly + dyout, dyout) # Interpolation on new grid coordinates f_interp = RectBivariateSpline(yi, xi, topoC.topo) topo = f_interp(yo, xo) # Plotting ls = LightSource(azdeg=225, altdeg=45) fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True) extent = [ topoC.E0, topoC.E0 + topoC.Nx * topoC.dx, topoC.N0, topoC.N0 + topoC.Ny * topoC.dy ] # Plot original DEM ax1.set_title('Original DEM: '+\ 'dx='+str(topoC.dx)+'m, dy='+str(topoC.dy)+'m') ax1.imshow(ls.hillshade(topoC.topo, vert_exag=1, dx=topoC.dx, dy=topoC.dy), extent=extent, cmap='gray', origin='lower') ax1.set(xlabel='Easting (m)', ylabel='Northing (m)') # Save new properties to DEM object topoC.topo = topo topoC.Nx = Nxout topoC.Ny = Nyout topoC.dx = dxout topoC.dy = dyout # Plot cropped DEM ax2.set_title('Interpolated DEM: '+\ 'dx='+str(topoC.dx)+'m, dy='+str(topoC.dy)+'m') ax2.imshow(ls.hillshade(topoC.topo, vert_exag=1, dx=topoC.dx, dy=topoC.dy), extent=extent, cmap='gray', origin='lower') ax2.set(xlabel='Easting (m)') plt.show() return ()
dx, dy = dem['dx'], dem['dy'] dy = 111200 * dy dx = 111200 * dx * np.cos(np.radians(dem['ymin'])) #----------------------------------------------------------------------------- # Shade from the northwest, with the sun 45 degrees from horizontal ls = LightSource(azdeg=315, altdeg=45) cmap = plt.cm.gist_earth fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(8, 9)) plt.setp(axes.flat, xticks=[], yticks=[]) # Vary vertical exaggeration and blend mode and plot all combinations for col, ve in zip(axes.T, [0.1, 1, 10]): # Show the hillshade intensity image in the first row col[0].imshow(ls.hillshade(z, vert_exag=ve, dx=dx, dy=dy), cmap='gray') # Place hillshaded plots with different blend modes in the rest of the rows for ax, mode in zip(col[1:], ['hsv', 'overlay', 'soft']): rgb = ls.shade(z, cmap=cmap, blend_mode=mode, vert_exag=ve, dx=dx, dy=dy) ax.imshow(rgb) # Label rows and columns for ax, ve in zip(axes[0], [0.1, 1, 10]): ax.set_title('{}'.format(ve), size=18) for ax, mode in zip(axes[:, 0], ['Hillshade', 'hsv', 'overlay', 'soft']): ax.set_ylabel(mode, size=18) # Group labels... axes[0, 1].annotate('Vertical Exaggeration', (0.5, 1), xytext=(0, 30),
def plot_mapview( self, show_lith: bool = True, # show_boundary: bool = True, show_hillshade: bool = True, show_contour: bool = False, show_only_faults: bool = False, **kwargs): cmap_type = kwargs.pop('cmap', 'YlOrRd') if 'ax' in kwargs: # append plot to existing axis ax = kwargs.pop('ax') else: figsize = kwargs.pop("figsize", (10, 6)) fig, ax = plt.subplots(figsize=figsize) if show_lith: image = self.vertices_mapview[:, 2].reshape(self.model_resolution[:2]) self.lith = ax.imshow( image, origin='lower', zorder=-10, extent=self.model_extent[:4], cmap=cmap_type, #norm=norm, aspect='auto') fill_contour = kwargs.pop('show_fill_contour', False) azdeg = kwargs.pop('azdeg', 0) altdeg = kwargs.pop('altdeg', 0) super = kwargs.pop('super_res', False) colorbar = kwargs.pop("show_colorbar", False) topo = self.grid.depth_grid[:, 2].reshape(self.model_resolution[:2]) #if super: # import skimage # topo_super_res = skimage.transform.resize( # topo, # (1600, 1600), # order=3, # mode='edge', # anti_aliasing=True, preserve_range=False) # values = topo_super_res[..., 2] #else: # values = topo.values_2d[..., 2] if show_contour is True: CS = ax.contour(topo, extent=self.model_extent[:4], colors='k', linestyles='solid', origin='lower') ax.clabel(CS, inline=1, fontsize=10, fmt='%d') if fill_contour is True: CS2 = ax.contourf(topo, extent=self.model_extent[:4], cmap=cmap) if colorbar: from gempy.plot.helpers import add_colorbar add_colorbar(axes=ax, label='elevation [m]', cs=CS2) if show_hillshade: from matplotlib.colors import LightSource # Note: 180 degrees are subtracted because visualization in Sandbox is upside-down ls = LightSource(azdeg=azdeg - 180, altdeg=altdeg) # TODO: Is it better to use ls.hillshade or ls.shade?? hillshade_topography = ls.hillshade(topo) # vert_exag=0.3, # blend_mode='overlay') self.hill = ax.imshow(hillshade_topography, cmap=plt.cm.gray, origin='lower', extent=self.model_extent[:4], alpha=0.4, zorder=11, aspect='auto')