Source code for canopy.visualization.map.simple_map

"""Simple map visualization."""

from typing import Optional, List

import matplotlib.pyplot as plt
import numpy as np

import canopy as cp
from canopy.visualization.multiple_figs import create_wrapper_from_locals
from canopy.visualization.visualization_helpers import handle_figure_output

from .map_helpers import (
    get_metadata,
    safe_make_raster,
    calculate_bins,
    plot_map
)

[docs] def make_simple_map( field: cp.Field, layer: str, categorical: bool = False, output_file: Optional[str] = None, timeop: str = 'av', cb_label: Optional[str] = None, title: Optional[str] = None, unit: Optional[str] = None, n_classes: int = 4, classification: List[float] | str = "linear", palette: Optional[str] = None, custom_palette: Optional[str] = None, orientation: str = 'horizontal', cb_label_rotation: float = 0, extend: str = "neither", proj: str = "Robinson", force_zero: bool = False, dark_mode: bool = False, transparent: bool = False, stats_annotation: bool = False, x_fig: float = 10, y_fig: float = 10, subfig=None, return_fig: bool = False, ) -> Optional[plt.Figure]: """ Create a map from a given Field object (apply time reduction) and save it to a file. Parameters ---------- field : cp.Field Field object. layer : str Layer name to display. categorical : bool, optional Set to True for categorical data mapping. Default False. output_file : str, optional File path for saving the plot. timeop : str, optional The reduction operation. Either 'sum' or 'av'. Default is 'av'. cb_label : str, optional Label of the colour bar, if not provided canopy will try to retrieve the name of the variable in the metadata. unit : str, optional Unit of the variable, if not provided canopy will try to retrieve the unit of the variable in the metadata. title : str, optional Title of the map. n_classes : int, optional Number of discrete color classes to use. Default is 4. classification : List[float] | str, optional Method to classify the data into different classes. One of 'linear', 'quantile', 'jenks', 'std' (https://gisgeography.com/choropleth-maps-data-classification/) or a list, e.g. [0,2,4,8]. Default is 'linear'. palette : str, optional Seaborn color palette to use for the line colors (https://seaborn.pydata.org/tutorial/color_palettes.html, recommended palette are in https://colorbrewer2.org). custom_palette : str, optional Path of custom color palette .txt file to use. orientation: str, optional Orientation of the legend. Either 'horizontal' or 'vertical'. Default is 'horizontal'. cb_label_rotation : float, optional Rotation angle in degrees for the colorbar tick labels. Default is 0. extend : str, optional Extend colourbar to maximum and minimum value. One of 'neither', 'min', 'max' or 'both'. Default is 'neither'. proj : str, optional Cartopy projection to use for the map (https://scitools.org.uk/cartopy/docs/v0.15/crs/projections.html). Default is 'Robinson'. force_zero : bool, optional If True, force the first (or the closest in diff_map) bin to zero. Default is False. dark_mode : bool, optional If True, apply dark mode styling. Default is False. transparent: bool, optional If True, make the figure transparent. Default is False. stats_annotation : bool, optional If True, adds a text box annotation on the bottom-left of the map displaying the mean and standard deviation of the raster values over the entire domain. Default is False. x_fig : float, optional Width of the figure in inches. Default is 10. y_fig : float, optional Height of the figure in inches. Default is 10. subfig : matplotlib.figure.SubFigure, optional If provided, the plot will be created in this subfigure instead of creating a new figure. This is used by multiple_figs() to combine multiple plots. User can also provide a plt.figure.subfigure object (https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subfigures.html) return_fig : bool, optional If True, return a callable wrapper function instead of creating the plot immediately. This wrapper can be used with multiple_figs(). Default is False. """ # If return_fig is True, create a wrapper function and return it if return_fig: return create_wrapper_from_locals(make_simple_map, locals()) if field.grid.is_reduced("lat") and field.grid.is_reduced("lon"): raise ValueError( "Field has reduced latitude and longitude. Map requires unreduced spatial dimensions." ) # Retrieve metadata cb_label, unit = get_metadata(field, cb_label, unit) # If classification is provided as a list, update n_classes to match its length minus one if isinstance(classification, list) and len(classification)-1 != n_classes: n_classes = len(classification) - 1 if categorical: raster = safe_make_raster(field, layer, timeop=timeop) n_classes = len(raster.keys) if raster.keys else 0 bins = np.arange(n_classes + 1) keys = raster.keys else: raster = safe_make_raster(field, layer, timeop=timeop) bins = calculate_bins(raster.vmap, n_classes, classification, force_zero) keys = False fig = plot_map(raster.x, raster.y, raster.vmap, categorical, keys, output_file, cb_label, title, unit, n_classes, bins, palette, custom_palette, orientation, cb_label_rotation, extend, proj, dark_mode, stats_annotation, x_fig, y_fig, nonsig_mask=None, hist=not categorical, subfig=subfig) return handle_figure_output(fig, output_file=output_file, transparent=transparent, subfig=subfig)