Source code for flusstools.fuzzycorr.plotter

"""Plotting routines and classes for fuzzy comparison maps"""

import earthpy.plot as ep
import matplotlib.pyplot as plt
import numpy as np
import rasterio as rio
from matplotlib import colors, patches


[docs] def read_raster(raster_path): """Opens a raster using rasterio Args: raster_path (str): directory and name of a raster Returns: ``ndarray``: a numpy array of the raster """ with rio.open(raster_path) as src: raster_np = src.read(1, masked=True) nodatavalue = src.nodata # storing nodatavalue of raster meta = src.meta.copy() print( "Number of active cells (non-masked) of raster ", raster_path, ": ", np.ma.count(raster_np), ) return raster_np, nodatavalue, meta, meta["crs"], meta["dtype"]
[docs] class RasterDataPlotter: """Class of raster for plotting :param path (str): path of the raster to be plotted """ def __init__(self, path): self.path = path
[docs] def make_hist( self, legendx, legendy, fontsize, output_file, figsize, set_ylim=None, set_xlim=None ): """Creates a histogram of numerical raster :param legendx (str): legend of the x axis of he histogram :param legendy (str): legend of the y axis of he histogram :param fontsize (int): size of the font :param output_file (str): path for the output file :param figsize (tuple): of integers, size of the width x height of the figure :param set_ylim (float): set the maximum limit of the y axis :param set_ylim (float): set the maximum limit of the x axis :returns: saves the figure of the histogram """ plt.rcParams.update({"font.size": fontsize}) raster_np = read_raster(self.path) fig, ax = plt.subplots(figsize=figsize) _, bins, _ = ax.hist(raster_np[~raster_np.mask], bins=60) if set_ylim is not None: ax.set_ylim(set_ylim) if set_xlim is not None: ax.set_xlim(set_xlim) np.savetxt("trial.csv", raster_np[~raster_np.mask], delimiter=",") plt.xlabel(legendx) plt.ylabel(legendy) # plt.title(title) plt.grid(True) plt.subplots_adjust(left=0.17, bottom=0.15) # Plot line with data mean (Sfuzzy) plt.axvline(raster_np.mean(), color="k", linestyle="dashed", linewidth=1) min_ylim, max_ylim = plt.ylim() plt.text(raster_np.mean() * 0.70, max_ylim * 0.9, f"Sfuzzy: {raster_np.mean():.4f}") # Save fig plt.savefig(output_file, dpi=300) plt.clf()
[docs] def plot_continuous_w_window( self, output_file, xy, width, height, bounds, cmap=None, list_colors=None ): """Create a figure of a raster with a zoomed window :param output_file: path, file path of the figure :param xy (tuple): ``(x,y)`` origin of the zoomed window, the upper left corner :param width (int): width (number of cells) of the zoomed window :param height (int): height (number of cells) of the zoomed window :param bounds (list): of float, limits for each color of the colormap :param cmap (str): optional, colormap to plot the raster :param list_colors (list): of colors (str), optional, as alternative to using a colormap :returns None: saves the figure of the raster """ # xy: upper left corner from the lower left corner of the picture raster_np = read_raster(self.path) print("Raster has size: ", raster_np.shape) fig, ax = plt.subplots(1, 2, figsize=(10, 8)) fig.tight_layout() # Creates a colormap based on the given list_colors, if the cmap is not given if cmap is None and list_colors is not None: cmap = colors.ListedColormap(list_colors) elif cmap is not None and list_colors is None: pass else: print("Error: Insuficient number of arguments") norm = colors.BoundaryNorm(bounds, cmap.N) ax[0].imshow(raster_np, cmap=cmap, norm=norm) rectangle = patches.Rectangle(xy, width, height, fill=False) ax[0].add_patch(rectangle) plt.setp(ax, xticks=[], yticks=[]) # Plot Patch box_np = raster_np[xy[1] : xy[1] + height, xy[0] : xy[0] + width] im = ax[1].imshow(box_np, cmap=cmap, norm=norm) # ax[1].axis('off') cbar = ep.colorbar(im, pad=0.3, size="5%") cbar.ax.tick_params(labelsize=20) fig.savefig(output_file, dpi=600, bbox_inches="tight")
[docs] def plot_continuous_raster(self, output_file, cmap, vmax=np.nan, vmin=np.nan, box=True): """Creates a figure of a continuous valued raster :param output_file: path, file path of the figure :param cmap (str): colormap to plot the raster :param vmax (float): optional, value maximum of the scale, this value is used in the normalization of the colormap :param vmin (float): optional, value minimum of the scale, this value is used in the normalization of the colormap :param box: boolean, if False it sets off the frame of the picture :returns: saves the figure of the raster """ raster_np = read_raster(self.path) fig1, ax1 = plt.subplots(figsize=(6, 8), frameon=False) # norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N) if np.isfinite(vmax) and np.isfinite(vmin): im1 = ax1.imshow(raster_np, cmap=cmap, vmax=vmax, vmin=vmin) else: im1 = ax1.imshow(raster_np, cmap=cmap, vmax=raster_np.max(), vmin=raster_np.min()) fig1.tight_layout() plt.setp(ax1) cbar = ep.colorbar(im1, pad=0.3, size="5%") cbar.ax.tick_params(labelsize=15) if not box: ax1.axis("off") fig1.savefig(output_file, dpi=200, bbox_inches="tight")
[docs] def plot_categorical_raster(self, output_file, labels, cmap, box=True): """Creates a figure of a categorical raster :param output_file: path, file path of the figure :param labels (list): of strings, labels (i.e., titles)for the categories :param cmap (str): colormap to plot the raster :param box: boolean, if False it sets off the frame of the picture :returns: saves the figure of the raster """ raster_np = read_raster(self.path) print("Classes identified in the raster: ", np.unique(raster_np)) # cmap = matplotlib.colors.ListedColormap(list_colors) fig, ax = plt.subplots() im = ax.imshow(raster_np, cmap=cmap) ep.draw_legend(im, titles=labels) ax.set_axis_off() # plt.show() if not box: ax.axis("off") fig.savefig(output_file, dpi=200, bbox_inches="tight")
[docs] def plot_categorical_w_window(self, output_file, labels, cmap, xy, width, height, box=True): """Creates a figure of a categorical raster with a zoomed window :param output_file (str): file path of the figure :param labels (list): of strings, labels (i.e., titles)for the categories :param cmap (str): colormap to plot the raster :param xy (tuple): (x,y), origin of the zoomed window, the upper left corner :param width (int): width (number of cells) of the zoomed window :param height (int): height (number of cells) of the zoomed window :returns: saves the figure of the raster """ raster_np = read_raster(self.path) print("Classes identified in the raster: ", np.unique(raster_np)) # cmap = matplotlib.colors.ListedColormap(list_colors) fig, ax = plt.subplots(1, 2) ax[0].imshow(raster_np, cmap=cmap) rectangle = patches.Rectangle(xy, width, height, fill=False) ax[0].add_patch(rectangle) plt.setp(ax, xticks=[], yticks=[]) # Plot Patch box_np = raster_np[xy[1] : xy[1] + height, xy[0] : xy[0] + width] im = ax[1].imshow(box_np, cmap=cmap) cbar = ep.draw_legend(im, titles=labels) # cbar.ax[].tick_params(labelsize=20) if not box: ax.axis("off") fig.savefig(output_file, dpi=700, bbox_inches="tight")