-
Notifications
You must be signed in to change notification settings - Fork 153
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
Allow serializing and deserializing named astropy units #2475
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this should be functional for the basic use case. However one would run into problems as soon as any CompoundUnit
comes into play, which is not a subclass of NamedUnit
(or even Unit
).
Those two are probably the most relevant cases in practice, so one might also add just another saver for CompoundUnit
, but setting it up directly for UnitBase
seems to do the job just as well, and I currently see no risk in enabling serialisation for them all.
Note that for CompoundUnit
this does not guarantee exact identity (unit2 is unit
) and probably is not realistic to achieve, since to_str
will always reduce to a default form, but I think this should be sufficient for practical use?
glue/core/state.py
Outdated
@@ -65,6 +65,7 @@ def load(rec, context) | |||
import numpy as np | |||
from matplotlib.colors import Colormap | |||
from matplotlib import cm | |||
from astropy.units import NamedUnit, Unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from astropy.units import NamedUnit, Unit | |
from astropy.units import Unit, UnitBase |
glue/core/state.py
Outdated
@saver(NamedUnit) | ||
def _save_named_unit(unit, context): | ||
return dict(named_unit=unit.to_string()) | ||
|
||
|
||
@loader(NamedUnit) | ||
def _load_named_unit(rec, context): | ||
return Unit(rec["named_unit"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saver(NamedUnit) | |
def _save_named_unit(unit, context): | |
return dict(named_unit=unit.to_string()) | |
@loader(NamedUnit) | |
def _load_named_unit(rec, context): | |
return Unit(rec["named_unit"]) | |
@saver(UnitBase) | |
def _save_unit_base(unit, context): | |
return dict(unit_base=unit.to_string()) | |
@loader(UnitBase) | |
def _load_unit_base(rec, context): | |
return Unit(rec["unit_base"]) |
@dhomeier Thanks for the review! My main motivation for ensuring exact identity was making sure that unit conversions would work correctly. I wasn't really sure what sorts of unit classes were out there so I didn't want to overreach and cause something to break in the future on some unit class that I hadn't prepared for. I wasn't aware of |
9da2d78
to
72ed676
Compare
Admittedly I have not checked all examples of exotic units one might encounter here.
Currently those cases would probably simply fail on creating # Check that unit can be parsed back with default enabled systems
try:
with u.set_enabled_units([u.si, u.cgs, u.astrophys]):
saved_unit = u.Unit(unit.to_string())
except ValueError:
raise GlueSerializeError(f"Serializing units of '{unit}' is not yet supported") (a bit complicated since some custom system might already have been added in the saver context, but not be available when reading back). |
@dhomeier I think the sanity check is a good idea. I'm trying to imagine what it would look like for a plugin/config to overwrite this kind of behavior in a straightforward way. I'm wondering if it would be better to give a warning rather than raise an error. It seems like non-default units (e.g. the units in
and similarly in the saver. Regardless, I think it's going to be incumbent on anything that implements a custom saver to implement a custom loader, and vice versa. Or maybe I'm overthinking things and we should just raise an error as you suggested. |
@dhomeier I've updated this to make the changes that you suggested. |
Co-authored-by: Derek Homeier <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! I think raising an error is fine but let's revisit if this ends up causing issues.
This PR adds serialization support for astropy
NamedUnit
s. The immediate use case for this is storing the decay unit in glue-viz/glue-wwt#103. This seems to work well for me, and it looks like astropy will give the builtin instance after deserialization, e.g.However, if someone more astropy-savvy than myself knows of a better way that we should do this, please let me know!