Allow units to have multiple physical types
See original GitHub issueDescription
The physical_type
attribute for UnitBase
instances currently returns a string that describes what a particular unit measures:
>>> import astropy.units as u
>>> (u.barn * u.Mpc).physical_type
'volume'
However, sometimes a set of units corresponds to multiple physical types. For example, a 1 Pa ≡ 1 J · m-3, so a pascal can represent both pressure and energy density. In addition, a kessel run can be retconned from distance to time.
Units to physical type is not a one-to-one mapping. Each set of units can map to multiple physical types. Each physical type should usually map to one set of units, though there can be some exceptions to this (for example, the temperature_energy
equivalency that lets eV represent energy as well as temperature).
I propose that we enable each unit to correspond to multiple physical types instead of limiting them to a single physical type. This would change backward compatibility.
Draft design and brainstorm for the API
A possibility would be to create a PhysicalType
class. Instances of PhysicalType
could be created for each set of units and become the physical_type
attribute, and contain a collection of all of the possible physical types that each set of units could have.
Essential behavior of physical_type
attribute
I’d like to allow the following behavior.
>>> import astropy.units as u
>>> u.Pa.physical_type
"pressure, energy density"
>>> u.Pa.physical_type # not sure if this should be a list or str
["pressure", "energy density"]
>>> u.Pa.physical_type == "pressure"
True
>>> u.Pa.physical_type == "energy_density"
True
The last two lines would require defining PhysicalType.__eq__
to be able to handle multiple physical types (e.g., by making sure "pressure"
or "energy"
is in the collection of physical types).
Handling equivalencies
The physical type will also depend on which equivalencies are enabled.
>>> u.eV.physical_type == "temperature"
False
>>> u.set_enabled_equivalencies(u.temperature_energy())
>>> u.eV.physical_type == "temperature"
True
Allowing users to specify the physical type for units or quantities
It would also be helpful for users to be able to specify the physical type in more detail. I’m not sure if this would be best done for units or quantities, and I have a feeling this could be more difficult to implement. A possible API for the unit approach would be:
>>> specific_pressure_unit = create_unit_with_specific_physical_type(u.Pa, physical_type="pressure")
>>> specific_pressure_unit.physical_type = "pressure"
>>> specific_pressure_unit.physical_type == "energy density"
False
>>> u.Pa.physical_type == "energy density" # we don't want to change the physical type of the original unit
True
For a Quantity
instance, this could be something like
>>> pressure = u.Quantity(1.0, u.Pa, physical_type="pressure")
>>> pressure.physical_type == "pressure"
True
>>> pressure.physical_type == "energy density"
False
It appears that Quantity
does not have a physical_type
attribute so this would be particularly new.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
p.s. I also like the idea of equivalencies working. In that case, equality should really be more like
(where
.unit
can re-infer the unit from the physical type ID if necessary)One suggestion would be to have only a master dict from
physical_type
to unit (or physical type ID). We could then still have aPhysicalType
class, but equality would be something likeWe might then not have a
dict
keyed by unit, but rather letget_physical_type
filter keys whose values are the correct unit/physical-type-ID. (One might return aset
.)