135 lines
4.5 KiB
Python
135 lines
4.5 KiB
Python
"""UnitDblConverter module containing class UnitDblConverter."""
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.units as units
|
|
import matplotlib.projections.polar as polar
|
|
|
|
__all__ = ['UnitDblConverter']
|
|
|
|
|
|
# A special function for use with the matplotlib FuncFormatter class
|
|
# for formatting axes with radian units.
|
|
# This was copied from matplotlib example code.
|
|
def rad_fn(x, pos=None):
|
|
"""Radian function formatter."""
|
|
n = int((x / np.pi) * 2.0 + 0.25)
|
|
if n == 0:
|
|
return str(x)
|
|
elif n == 1:
|
|
return r'$\pi/2$'
|
|
elif n == 2:
|
|
return r'$\pi$'
|
|
elif n % 2 == 0:
|
|
return fr'${n//2}\pi$'
|
|
else:
|
|
return fr'${n}\pi/2$'
|
|
|
|
|
|
class UnitDblConverter(units.ConversionInterface):
|
|
""": A matplotlib converter class. Provides matplotlib conversion
|
|
functionality for the Monte UnitDbl class.
|
|
"""
|
|
# default for plotting
|
|
defaults = {
|
|
"distance": 'km',
|
|
"angle": 'deg',
|
|
"time": 'sec',
|
|
}
|
|
|
|
@staticmethod
|
|
def axisinfo(unit, axis):
|
|
""": Returns information on how to handle an axis that has Epoch data.
|
|
|
|
= INPUT VARIABLES
|
|
- unit The units to use for a axis with Epoch data.
|
|
|
|
= RETURN VALUE
|
|
- Returns a matplotlib AxisInfo data structure that contains
|
|
minor/major formatters, major/minor locators, and default
|
|
label information.
|
|
"""
|
|
# Delay-load due to circular dependencies.
|
|
import matplotlib.testing.jpl_units as U
|
|
|
|
# Check to see if the value used for units is a string unit value
|
|
# or an actual instance of a UnitDbl so that we can use the unit
|
|
# value for the default axis label value.
|
|
if unit:
|
|
label = unit if isinstance(unit, str) else unit.label()
|
|
else:
|
|
label = None
|
|
|
|
if label == "deg" and isinstance(axis.axes, polar.PolarAxes):
|
|
# If we want degrees for a polar plot, use the PolarPlotFormatter
|
|
majfmt = polar.PolarAxes.ThetaFormatter()
|
|
else:
|
|
majfmt = U.UnitDblFormatter(useOffset=False)
|
|
|
|
return units.AxisInfo(majfmt=majfmt, label=label)
|
|
|
|
@staticmethod
|
|
def convert(value, unit, axis):
|
|
""": Convert value using unit to a float. If value is a sequence, return
|
|
the converted sequence.
|
|
|
|
= INPUT VARIABLES
|
|
- value The value or list of values that need to be converted.
|
|
- unit The units to use for a axis with Epoch data.
|
|
|
|
= RETURN VALUE
|
|
- Returns the value parameter converted to floats.
|
|
"""
|
|
# Delay-load due to circular dependencies.
|
|
import matplotlib.testing.jpl_units as U
|
|
|
|
isNotUnitDbl = True
|
|
|
|
if np.iterable(value) and not isinstance(value, str):
|
|
if len(value) == 0:
|
|
return []
|
|
else:
|
|
return [UnitDblConverter.convert(x, unit, axis) for x in value]
|
|
|
|
# We need to check to see if the incoming value is actually a
|
|
# UnitDbl and set a flag. If we get an empty list, then just
|
|
# return an empty list.
|
|
if isinstance(value, U.UnitDbl):
|
|
isNotUnitDbl = False
|
|
|
|
# If the incoming value behaves like a number, but is not a UnitDbl,
|
|
# then just return it because we don't know how to convert it
|
|
# (or it is already converted)
|
|
if isNotUnitDbl and units.ConversionInterface.is_numlike(value):
|
|
return value
|
|
|
|
# If no units were specified, then get the default units to use.
|
|
if unit is None:
|
|
unit = UnitDblConverter.default_units(value, axis)
|
|
|
|
# Convert the incoming UnitDbl value/values to float/floats
|
|
if isinstance(axis.axes, polar.PolarAxes) and value.type() == "angle":
|
|
# Guarantee that units are radians for polar plots.
|
|
return value.convert("rad")
|
|
|
|
return value.convert(unit)
|
|
|
|
@staticmethod
|
|
def default_units(value, axis):
|
|
""": Return the default unit for value, or None.
|
|
|
|
= INPUT VARIABLES
|
|
- value The value or list of values that need units.
|
|
|
|
= RETURN VALUE
|
|
- Returns the default units to use for value.
|
|
Return the default unit for value, or None.
|
|
"""
|
|
|
|
# Determine the default units based on the user preferences set for
|
|
# default units when printing a UnitDbl.
|
|
if np.iterable(value) and not isinstance(value, str):
|
|
return UnitDblConverter.default_units(value[0], axis)
|
|
else:
|
|
return UnitDblConverter.defaults[value.type()]
|