UnitDblConverter.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """UnitDblConverter module containing class UnitDblConverter."""
  2. import numpy as np
  3. from matplotlib import cbook
  4. import matplotlib.units as units
  5. import matplotlib.projections.polar as polar
  6. __all__ = ['UnitDblConverter']
  7. # A special function for use with the matplotlib FuncFormatter class
  8. # for formatting axes with radian units.
  9. # This was copied from matplotlib example code.
  10. def rad_fn(x, pos=None):
  11. """Radian function formatter."""
  12. n = int((x / np.pi) * 2.0 + 0.25)
  13. if n == 0:
  14. return str(x)
  15. elif n == 1:
  16. return r'$\pi/2$'
  17. elif n == 2:
  18. return r'$\pi$'
  19. elif n % 2 == 0:
  20. return fr'${n//2}\pi$'
  21. else:
  22. return fr'${n}\pi/2$'
  23. class UnitDblConverter(units.ConversionInterface):
  24. """
  25. Provides Matplotlib conversion functionality for the Monte UnitDbl class.
  26. """
  27. # default for plotting
  28. defaults = {
  29. "distance": 'km',
  30. "angle": 'deg',
  31. "time": 'sec',
  32. }
  33. @staticmethod
  34. def axisinfo(unit, axis):
  35. """: Returns information on how to handle an axis that has Epoch data.
  36. = INPUT VARIABLES
  37. - unit The units to use for a axis with Epoch data.
  38. = RETURN VALUE
  39. - Returns a matplotlib AxisInfo data structure that contains
  40. minor/major formatters, major/minor locators, and default
  41. label information.
  42. """
  43. # Delay-load due to circular dependencies.
  44. import matplotlib.testing.jpl_units as U
  45. # Check to see if the value used for units is a string unit value
  46. # or an actual instance of a UnitDbl so that we can use the unit
  47. # value for the default axis label value.
  48. if unit:
  49. label = unit if isinstance(unit, str) else unit.label()
  50. else:
  51. label = None
  52. if label == "deg" and isinstance(axis.axes, polar.PolarAxes):
  53. # If we want degrees for a polar plot, use the PolarPlotFormatter
  54. majfmt = polar.PolarAxes.ThetaFormatter()
  55. else:
  56. majfmt = U.UnitDblFormatter(useOffset=False)
  57. return units.AxisInfo(majfmt=majfmt, label=label)
  58. @staticmethod
  59. def convert(value, unit, axis):
  60. """: Convert value using unit to a float. If value is a sequence, return
  61. the converted sequence.
  62. = INPUT VARIABLES
  63. - value The value or list of values that need to be converted.
  64. - unit The units to use for a axis with Epoch data.
  65. = RETURN VALUE
  66. - Returns the value parameter converted to floats.
  67. """
  68. # Delay-load due to circular dependencies.
  69. import matplotlib.testing.jpl_units as U
  70. if not cbook.is_scalar_or_string(value):
  71. return [UnitDblConverter.convert(x, unit, axis) for x in value]
  72. # If the incoming value behaves like a number,
  73. # then just return it because we don't know how to convert it
  74. # (or it is already converted)
  75. if units.ConversionInterface.is_numlike(value):
  76. return value
  77. # If no units were specified, then get the default units to use.
  78. if unit is None:
  79. unit = UnitDblConverter.default_units(value, axis)
  80. # Convert the incoming UnitDbl value/values to float/floats
  81. if isinstance(axis.axes, polar.PolarAxes) and value.type() == "angle":
  82. # Guarantee that units are radians for polar plots.
  83. return value.convert("rad")
  84. return value.convert(unit)
  85. @staticmethod
  86. def default_units(value, axis):
  87. """: Return the default unit for value, or None.
  88. = INPUT VARIABLES
  89. - value The value or list of values that need units.
  90. = RETURN VALUE
  91. - Returns the default units to use for value.
  92. Return the default unit for value, or None.
  93. """
  94. # Determine the default units based on the user preferences set for
  95. # default units when printing a UnitDbl.
  96. if cbook.is_scalar_or_string(value):
  97. return UnitDblConverter.defaults[value.type()]
  98. else:
  99. return UnitDblConverter.default_units(value[0], axis)