Source code for planetary_coverage.ticks.ticks

"""Maps ticks helpers."""

from matplotlib.dates import AutoDateLocator, ConciseDateFormatter
from matplotlib.ticker import Formatter, FuncFormatter


# Datetime ticker
date_ticks = ConciseDateFormatter(AutoDateLocator(maxticks=24))

# Astronomical unit
AU = 149_597_870.7  # km


[docs]class UnitFormatter(Formatter): """Format numbers with a unit. Parameters ---------- unit: str, optional A string that will be appended to the label. It may be ``None`` or empty to indicate that no unit should be used. LaTeX special characters are escaped in ``unit`` whenever latex mode is enabled, unless `is_latex` is ``True``. sep: str, optional Separator used between the value and the unit. Default is a ``space`` but it can be remove with empty value. scale: float, optional Scaling factor (default: ``1``). offset: float, optional Base offset (default: ``0``). fmt: str, optional Number formatter (default: ``',g'``). """ def __init__(self, unit='', sep=' ', scale=1, offset=0, fmt=',g'): self.unit = unit self.sep = sep self.scale = scale self.offset = offset self.fmt = fmt def __repr__(self): return ( f'<{self.__class__.__name__}> Unit: `{self.unit}` | ' f'Sep: `{self.sep}` | Scale: {self.scale} | Offset: {self.offset} | ' f'Format: `{self.fmt}`' ) def __call__(self, x, pos=None): """Format the tick as a number with the appropriate scaling and a unit.""" s = f'{x * self.scale + self.offset:{self.fmt}}{self.sep}{self.unit}' if self.sep and s.endswith(self.sep): s = s[:-len(self.sep)] return self.fix_minus(s) def __add__(self, other): """Add offset factor.""" new_offset = self.offset + other return self.__class__(unit=self.unit, sep=self.sep, scale=self.scale, offset=new_offset, fmt=self.fmt) def __radd__(self, other): """Add offset factor.""" return self + other def __sub__(self, other): """Subtract offset factor.""" new_offset = self.offset - other return self.__class__(unit=self.unit, sep=self.sep, scale=self.scale, offset=new_offset, fmt=self.fmt) def __rsub__(self, other): """Subtract offset factor.""" return -self + other def __mul__(self, other): """Multiplication scaling factor.""" new_scale = self.scale * other return self.__class__(unit=self.unit, sep=self.sep, scale=new_scale, offset=self.offset, fmt=self.fmt) def __rmul__(self, other): """Multiplication scaling factor.""" return self * other def __neg__(self): """Negative factor.""" return self * -1 def __truediv__(self, other): """Divide scaling factor.""" new_scale = self.scale / other return self.__class__(unit=self.unit, sep=self.sep, scale=new_scale, offset=self.offset, fmt=self.fmt) def __matmul__(self, tick): """Reverse ticks location.""" if isinstance(tick, list): return [self @ t for t in tick] return (tick - self.offset) / self.scale
km_ticks = UnitFormatter('km', fmt=',.10g') au_ticks = UnitFormatter('AU', scale=1 / AU) # Input in [km] km_s_ticks = UnitFormatter('km/s') m_s_ticks = UnitFormatter('m/s', scale=1_000) # Input in [km] deg_ticks = UnitFormatter('°', sep='') hr_ticks = UnitFormatter('h') km_pix_ticks = UnitFormatter('km/pix') m_pix_ticks = UnitFormatter('m/pix', scale=1_000, fmt=',.0f') # Input in [km/pix] @FuncFormatter def lat_ticks(lat, pos=None): # pylint: disable=unused-argument """Latitude ticks formatter.""" if lat == 90: return 'N.P.' if lat == 0: return 'Eq.' if lat == -90: return 'S.P.' if lat < 0: return f'{-lat}°S' return f'{lat}°N' @FuncFormatter def lon_e_ticks(lon_e, pos=None): # pylint: disable=unused-argument """East longitude ticks formatter.""" if lon_e % 180 == 0: return f'{lon_e % 360}°' return f'{lon_e % 360}°E' @FuncFormatter def lon_w_ticks(lon_w, pos=None): # pylint: disable=unused-argument """West longitude ticks formatter.""" if lon_w % 180 == 0: return f'{lon_w % 360}°' return f'{lon_w % 360}°W' @FuncFormatter def lon_west_ticks(lon_e, pos=None): # pylint: disable=unused-argument """West longitude ticks formatter with East longitude input.""" return lon_w_ticks(-lon_e % 360)