Source code for pyValEIA.plots.utils

# -*- coding: utf-8 -*-
#
# DISTRIBUTION STATEMENT A: Approved for public release. Distribution is
# unlimited.
# ----------------------------------------------------------------------------
"""Utility functions for formatting or creating plots."""

from matplotlib.lines import Line2D
import matplotlib.ticker as mticker
from matplotlib.patches import Patch


[docs] def format_latitude_labels(ax, xy='x'): """Format the latitude axis labels with degree symbols and N/S suffixes. Parameters ---------- ax : matplotlib.axes.Axes The Matplotlib axes object to format xy : str Specifies whether the x or y axis is being formatted (default='x') """ if xy.lower() == 'x': ax.xaxis.set_major_formatter(mticker.FuncFormatter(latitude_formatter)) elif xy.lower() == 'y': ax.yaxis.set_major_formatter(mticker.FuncFormatter(latitude_formatter)) elif xy.lower() == 'z': ax.zaxis.set_major_formatter(mticker.FuncFormatter(latitude_formatter)) else: raise ValueError('unknown axis requested: {:}'.format(xy)) return
[docs] def latitude_formatter(latitude, pos): """Format latitude ticks to include degrees and hemisphere, removing signs. Parameters ---------- latitude : float Latitude tick value in degrees from -90 to 90. pos : float Position, not used but required for use as FuncFormatter Returns ------- lat_str : str Formatted latitude string Notes ----- Designed for use within mpl.ticker.FuncFormatter """ if latitude > 0: lat_str = r"{:.0f}$^\circ$N".format(latitude) elif latitude < 0: lat_str = r"{:.0f}$^\circ$S".format(abs(latitude)) else: lat_str = r"0$^\circ$" return lat_str
[docs] def longitude_formatter(longitude, pos): """Format longitude ticks to include degrees and hemisphere, removing signs. Parameters ---------- longitude : float Longitude tick value in degrees from -180 to 360. pos : float Position, not used but required for use as FuncFormatter Returns ------- lon_str : str Formatted latitude string Notes ----- Designed for use within mpl.ticker.FuncFormatter """ if longitude > 0.0 and longitude <= 180.0: lon_str = r"{:.0f}$^\circ$E".format(longitude) elif longitude < 0.0 or longitude > 180.0: lon_str = r"{:.0f}$^\circ$W".format(abs(longitude)) else: lon_str = r"0$^\circ$" return lon_str
[docs] def format_longitude_labels(ax, xy='x'): """Format the longitude axis labels with degree symbols and E/W suffixes. Parameters ---------- ax : matplotlib.axes.Axes The Matplotlib axes object xy : str kwarg 'x', 'y', or 'z' depending on which axis you want to have the degree symbol with E/W formatting (default='x') Raises ------ ValueError If unknown axis supplied. """ if xy.lower() == 'x': ax.xaxis.set_major_formatter(mticker.FuncFormatter(longitude_formatter)) elif xy.lower() == 'y': ax.yaxis.set_major_formatter(mticker.FuncFormatter(longitude_formatter)) elif xy.lower() == 'z': ax.zaxis.set_major_formatter(mticker.FuncFormatter(latitude_formatter)) else: raise ValueError('unknown axis requested: {:}'.format(xy)) return
[docs] def make_legend(leg_ax, leg_labs, leg_cols, leg_styles, modes, **kwargs): """Create a custom legend on a given axis. Parameters ---------- leg_ax : matplotlib axis Axis to place the legend on. leg_labs : list of str Labels for the legend entries. leg_cols : list of str Colors for the legend entries. leg_styles : list of str Marker styles (if scatter) or line styles (if line). modes : list of str Type of legend entry for each label. Options: "line", "scatter", "shading", "line+shading". kwargs : dict Additional keyword arguments passed to ax.legend(). """ handles = [] for lab, col, style, mode in zip(leg_labs, leg_cols, leg_styles, modes): if mode == "line": h = Line2D([], [], color=col, linestyle=style, marker=None, label=lab) elif mode == "scatter": h = Line2D([], [], marker=style, linestyle="None", markerfacecolor=col, markeredgecolor=col, markersize=8, label=lab) elif mode == "shading": h = Patch(facecolor=col, edgecolor="none", alpha=0.5, label=lab) elif mode == "line+shading": line = Line2D([], [], color=col, linestyle=style) patch = Patch(facecolor=col, edgecolor="none", alpha=0.3) h = (line, patch) # composite handle else: raise ValueError(f"Unknown mode: {mode}") handles.append(h) leg_ax.legend(handles=handles, labels=leg_labs, **kwargs) leg_ax.axis("off") # hide axes completely) return
[docs] def daynight_label(model, LT_range=None): """Generate Label for local time day and night. Parameters ---------- model : pd.DataFrame model dataframe build by states_report_swarm LT_range : list-like or NoneType Range of day night local time, or None for default of [7, 19] (default=None) Returns ------- lab_day : string legend label for daytime lab_night : string legend label for nighttime """ if LT_range is None: LT_range = [7, 19] # Separate day and night model_day = model[((model['LT'] > LT_range[0]) & (model['LT'] < LT_range[1]))] model_night = model[((model['LT'] < LT_range[0]) | (model['LT'] > LT_range[1]))] # Day label form minimum LT to maximum LT day_lab = str(int(min(model_day['LT']))) + '-' + str( int(max(model_day['LT']))) + ' LT' # night label depends on what the max and min are max_night = max(model_night['LT']) min_night = min(model_night['LT']) if (min_night < 12) & (max_night > 12): # minimum is between 0 and 12 do max to min, i.e. 23 to 3 night_lab = str(int(max_night)) + '-' + str(int(min_night)) + ' LT' else: # minimum is greater than 12 do min to max, i.e. 20 to 23 or 1 to 5 night_lab = str(int(min_night)) + '-' + str(int(max_night)) + ' LT' return day_lab, night_lab