-
Notifications
You must be signed in to change notification settings - Fork 476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
checking for unit compatibility #988
Comments
Dimensionality was the intended way to compare this. Let's define: >>> u1 = ureg.meter ** 3
>>> u2 = ureg.liter
>>> q1 = 10 * u1
>>> q2 = 4 * u2 Using dimensionality works for quantities and units: >>> q1.dimensionality == q2.dimensionality # quantity to quantity
True
>>> q1.dimensionality == u2.dimensionality # quantity to units
True
>>> u1.dimensionality == u2.dimensionality # units to units
True I have also seen other things in the wild >>> (q1/q2).dimensionless. # quantity to quantity
True
>>> (q1/u2).dimensionless. # quantity to units
True
>>> (u1/u2).dimensionless. # units to units
True but this is not a good idea as it fails when one of the units is non-multiplicative.
>>> q1.check(u2) # Quantity to unit
True
>>> q1.check(q2) # Quantity to quantity
True but it does not work for units to units. Finally, we created In general, I would be in favour of adding a method (e.g. |
I was thinking about a top-level function like def is_compatible(obj1, obj2, unit_registry=pint._DEFAULT_REGISTRY):
def get_dimensionality(obj):
if isinstance(obj, (unit_registry.Quantity, unit_registry.Unit)):
unit_like = obj
else:
unit_like = unit_registry.dimensionless
return unit_like.dimensionality
return get_dimensionality(obj1) == get_dimensionality(obj2) but I have no idea how to make it context-aware or how to deal with units from different unit registries |
I would also agree with a top level function (I still think that a method for Quantity and Unit would be nice also). PS.- I think you have a bug in your code, Regearding making it unit aware, the easiest way is to add the folowing arguments to your function try:
quantity.to(new_unit, *contexts, **ctx_kwargs)
return True
except pint.errors.DimensionalityError:
return False It woud be nice to have a context aware |
the bug happens when not using the default registry: then the Regarding your proposed implementation: that could work, but only when quantities are involved (just like |
I think the implementation could go along the following lines: In Quantity def is_compatible(self, other, *contexts, **ctx_kwargs):
if contexts:
try:
self.to(other, *contexts, **ctx_kwargs)
return True
except pint.errors.DimensionalityError:
return False
if isinstance(other, (Quantity, Unit)):
return self.dimensionality == other.dimensionality
if isinstance(other, str):
return self.dimensionality == self._REGISTRY.parse_units(other).dimensionality
return self.dimensionless In Unit: def is_compatible(self, other, *contexts, **ctx_kwargs):
if contexts:
try:
(1 * quantity).to(other, *contexts, **ctx_kwargs)
return True
except pint.errors.DimensionalityError:
return False
if isinstance(other, (Quantity, Unit)):
return self.dimensionality == other.dimensionality
if isinstance(other, str):
return self.dimensionality == self._REGISTRY.parse_units(other).dimensionality
return self.dimensionless Top level function: def is_compatible(obj1, obj2, unit_registry=None, *contexts, **ctx_kwargs):
ureg = unit_registry or pint._DEFAULT_REGISTRY # or should be the APP registry????
if isintance(obj1, (ureg.Quantity, ureg.Unit)):
return obj1.is_compatible(obj2, *contexts, **ctx_kwargs)
if isinstance(obj1, str):
return unit_registry.parse_expression(obj1).is_compatible(obj2, *contexts, **ctx_kwargs)
return not isinstance(obj2, (ureg.Quantity, ureg.Unit)) |
This looks fine to me, but I'd make If it's fine with you I'd put in a PR so we can comment on the actual code (and documentation). Also, |
Agree
Regarding the name, for methods I usualy like using verbs. But |
What is the official way to check compatibility between units (or arrays and units)? Right now I'm using
but it took me some time to realize this was possible (it is not really obvious to me and I couldn't find it in the docs -- I might have missed it, though).
I usually put this in a function named something like
is_compatible
to make it a little bit more robust. If there is no such function yet, is there any interest in adding one?The text was updated successfully, but these errors were encountered: