Skip to content

Commit

Permalink
Make .to(other) return the result for a value with all ones.
Browse files Browse the repository at this point in the history
And fix .items() to directly return a tuple, for nicer interactive viewing.
  • Loading branch information
mhvk committed May 25, 2021
1 parent 37aea09 commit b723597
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions astropy/units/structured.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import numpy as np

from .core import Unit, UnitBase
from .core import Unit, UnitBase, UNITY


__all__ = ['StructuredUnit']
Expand Down Expand Up @@ -167,7 +167,7 @@ def keys(self):
return self._units.dtype.names

def items(self):
return zip(self._units.dtype.names, self._units.item())
return tuple(zip(self._units.dtype.names, self._units.item()))

def __iter__(self):
yield from self._units.dtype.names
Expand Down Expand Up @@ -203,11 +203,16 @@ def _recursively_get_dtype(self, value, enter_lists=True):
The routine does presume that the type of the first tuple is
representative of the rest. Used in ``_get_converter``.
For the special value of ``UNITY``, all fields are assumed to be 1.0,
and hence this will return an all-float dtype.
"""
if enter_lists:
while isinstance(value, list):
value = value[0]
if not isinstance(value, tuple) or len(self) != len(value):
if value is UNITY:
value = (UNITY,) * len(self)
elif not isinstance(value, tuple) or len(self) != len(value):
raise ValueError(f"cannot interpret value {value} for unit {self}.")
descr = []
for (name, unit), part in zip(self.items(), value):
Expand Down Expand Up @@ -311,23 +316,25 @@ def converter(value):
result = np.empty_like(value)
for name, converter_ in zip(result.dtype.names, converters):
result[name] = converter_(value[name])
return result
# Index with empty tuple to decay array scalars to numpy void.
return result if result.shape else result[()]

return converter

def to(self, other, value, equivalencies=[]):
def to(self, other, value=np._NoValue, equivalencies=[]):
"""Return values converted to the specified unit.
Parameters
----------
other : `~astropy.units.StructuredUnit`
The unit to convert to. If necessary, will be converted to
a `~astropy.units.StructuredUnit` using the dtype of ``value``.
value : array-like
value : array-like, optional
Value(s) in the current unit to be converted to the
specified unit. If a sequence, the first element must have
entries of the correct type to represent all elements (i.e.,
not have, e.g., a ``float`` where other elements have ``complex``).
If not given, assumed to have 1. in all fields.
equivalencies : list of tuple, optional
A list of equivalence pairs to try if the units are not
directly convertible. See :ref:`unit_equivalencies`.
Expand All @@ -345,6 +352,10 @@ def to(self, other, value, equivalencies=[]):
UnitsError
If units are inconsistent
"""
if value is np._NoValue:
# We do not have UNITY as a default, since then the docstring
# would list 1.0 as default, yet one could not pass that in.
value = UNITY
return self._get_converter(other, equivalencies=equivalencies)(value)

def to_string(self, format='generic'):
Expand Down

0 comments on commit b723597

Please sign in to comment.