Repository navigation
Implement option in WCS class to preserve the original units - #18338
Conversation
|
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
|
👋 Thank you for your draft pull request! Do you know that you can use |
|
I'm seeing a test failure in |
|
@mcara - are you happy with this in general? If so, I will carry out extensive testing in different packages and can then write more tests and some documentation. |
|
Since it was in the draft mode I thought it was not yet ready for review. I'll take a look. |
|
@mcara - yes just to be clear it works, it's just in draft mode because there are no docs yet. |
|
@astrofrog While I review this, may I ask whether you had contacted Mark to see if this could be fixed in WCSLIB? It seems it would be a much more natural place for the fix as it would avoid unnecessary copying of Section 2.3 of Paper I says:
Although in Paper II (section 1) it says:
This is confusing (to me). So I looked at the Hanisch et al. 2001 paper, section 5.3, and it says:
recommended != required. I think it is worth asking why WCSLIB chose to behave like that and whether it is a bug and regardless of bug or not - can't this be handled there? While I think it is worth contacting Mark Calabretta about this, I think we can go ahead and implement this here. |
| // calling wcsp2s, but we need to call it ourselves using PyWcsprm_cset so that we can | ||
| // catch cases where the units might change if e.g. they are not in SI to start with. | ||
| /* Force a call to wcsset here*/ | ||
| if (self->preserve_units && PyWcsprm_cset(self, 1)) return NULL; |
There was a problem hiding this comment.
What is the performance cost for this for the case of a single coordinate transformation (a pair of coordinates) and for a large array of coordinates?
Again, { return NULL; }
There was a problem hiding this comment.
Fixed - I'll address the performance question shortly
|
I also wonder how this works with the |
I was in touch with Mark last year about this and this is what he said: Correct - internally, WCSLIB only deals with SI units plus degrees. It would overly complicate matters to try to do otherwise. Applications programmers see it when composing world coordinates to be transformed to pixel coordinates, or in the result of transforming pixel to world coordinates - I believe the documentation is clear enough on this. However, I feel applications programmers could protect higher-level users (i.e. the users of the applications) by doing unit conversions for them using the tools provided, namely wcsunitse(). This PR does pretty much that - we actually use In any case, thanks for the review! I will try and see if I can address these and wrap it up today or tomorrow. |
Using the 5-D WCS from the test added in this PR ( Before this PR With this PR Time times for With preserve units, it seems pix2world is a little slower for Script to reproduce: https://gist.github.com/astrofrog/a0c88718992029198b79245114469d81 |
…as far as the user is concerned rather than have them be converted to SI (for example converting nm to m, GHz to Hz, and arcsec to deg).
… after set() has been called
|
@mcara - I spent some time today working on making sure we can assign units to In any case, I was wondering if you could take this for another spin and see if you are happy with the behavior under different circumstances? |
|
@mhvk thank you for taking a look at this! Regarding the implementation i would prefer for now to keep the code paths reasonably separate for preserve_units False or True - mainly to avoid introducing bugs for regular users of the default WCS class - but we could always try and tighten up the implementation once it's had a good amount of real world testing? I would like to try and add a ScienceState to control the default behavior, but would prefer to keep this for a separate PR. |
Certainly fine, though I was thinking more about a configuration item. But given that, perhaps all the more reason to discuss separately. |
There was a problem hiding this comment.
Oooo... does this also simplify unit handling for Jdaviz downstream? cc @kecnry
|
Thanks for doing this @astrofrog this is something which has been a pain point for a long time. |
|
I dare say this might be a killer feature for the next release. 😆 😭 |
|
I'm sure if we turned it on by default nothing would break. |
Is that sarcasm? 😉 |
|
I think it would be important to have a method/property on the WCS object like |
|
Yes of course! |
|
@mcara - just to check, would it be better to simply have a Or would you prefer a method for this? |
|
+1 property which can't be set. |
From me?! Never. |
|
I like property |
|
For the record, |
|
With the default behaviour or opting into preserve units? 😉 |
Default as |
|
If we get a global switch, it'd certainly be good to check to see that there's no unexpected behaviour, even with SI units. |
|
I think a global switch is bound to have consequences on other packages. For example, a package that is expecting RA & DEC to be in degrees will not be aware that, due to a global switch, it now gets angles in arcsec (for example). |
|
Yeah, for sure, but it would be good to experiment with finding out where those assumptions are. Including inside astropy itself. |


Description
A common issue users run into when using the
astropy.wcsclass is that WCSLIB will convert units to SI. For instance, celestial WCS in arcseconds will be converted to degrees, and spectral axes in GHz and nm will be converted to m. There isn't much we can do to stop WCSLIB from doing this - however I have realized that since we never expose the WCSLIB objects directly, but instead have our own C wrapper class, we can make that wrapper class remember any initial units and do on-the-fly conversions for all appropriate methods/properties.As an example:
This is not yet complete but I am putting it up already so that people who are interested can try it out.
Remaining TODOs:
__str__and compare, unitfixThis will need to be rebased once #18231 is merged