Skip to content
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

Ensure FrameAttribute not on present frame are set on SkyCoord, not on its frame #5750

Merged
merged 3 commits into from Feb 17, 2017

Conversation

mhvk
Copy link
Contributor

@mhvk mhvk commented Jan 29, 2017

Currently, if one defines, e.g., a SkyCoord with an ICRS frame, one can set any existing frame attribute that is not on that frame. Oddly, this gets set on the frame, without any validation:

sc = SkyCoord(ra=0., dec=0., unit='deg')
sc.relative_humidity = 'bla'
sc.frame.relative_humidity
# 'bla'

This commit prevents one from setting any attribute that is a FrameAttribute of any frame [EDIT] ensures that possible frame attributes that are not on the present frame are stored on the SkyCoord instance.

EDIT: now went with alternative given that the setting is used in the wild (for sensible purposes).

@taldcroft, @eteq - please check this is in fact desired behaviour; the alternative would be to set the attribute on the SkyCoord itself, but my sense was that this violated the immutability.

@mhvk
Copy link
Contributor Author

mhvk commented Jan 29, 2017

p.s. I found this while working on #5751 -- if we do allow setting the attributes, I would suggest it to be once-only, i.e., once one sets, e.g., obstime on an ICRS SkyCoord, be it via the initializer or via assignment, sc.obstime becomes immutable.

@taldcroft
Copy link
Member

@mhvk - I'm worried that the ability to update non-frame attributes has been around since SkyCoord came into existence and it may be out there in use. This would break code like:

sc = yaml.load('icrs_skycoord.yaml')  # No control over initializer
sc.obstime = '2015:001'
sc_fk4 = sc_icrs.transform_to('fk4')

Yes, you can do this with transform_to(FK4(obstime='2015:001')), but probably if I were writing code without thinking too hard I would use the above. I like encapsulating the attribute in my object rather than making it a function of the transform. I'm not sure if SkyCoord is formally considered immutable so much as the data frame is immutable.

@mhvk
Copy link
Contributor Author

mhvk commented Jan 30, 2017

@taldcroft - yes, I worried about that too, hence my postscript about maybe relaxing this to allow an attribute to be set if it hasn't been set already. Shall I change it to work like that?

@taldcroft
Copy link
Member

@mhvk - OK, the immutable-once-set idea sounds fine.

@Cadair
Copy link
Member

Cadair commented Jan 30, 2017

I am heavily 👎 on this, either if it has been set or not, as changing the attributes of the solar frames is critical in allowing us to convert between systems with different observers. A full example of this is here: http://docs.sunpy.org/en/stable/generated/gallery/tutorials/SDO_to_STEREO_Coordinate_Conversion.html .

Basically what happens is an image might have an observer for a satellite and another might have an observer for the Earth, if we change out of an observer centric frame then change the observer location frame attributes on the frame where they are not being used, and then transform back we end up in a frame from a different place, which is critical for comparing locations from different view points.

@Cadair
Copy link
Member

Cadair commented Jan 30, 2017

I notice that this has been milestoned as 1.3.1, this change should not be in a bug fix release!!

@Cadair
Copy link
Member

Cadair commented Jan 30, 2017

We could modify our internal transformation code (https://github.com/sunpy/sunpy/blob/master/sunpy/coordinates/transformations.py#L192) to use @taldcroft's (transform_to(HelioprojectiveFrame(L0=..., B0=,...)) example. However, we have advertised this as functionality of sunpy.coordinates so I think it needs to be thought about a bit more. (I am not really sure what you are trying to prevent with this patch).

@mhvk
Copy link
Contributor Author

mhvk commented Jan 30, 2017

@Cadair - To see why something like this is necessary, see #5751. But this really is two things: a frame should not have attributes that are not part of its regular definition (while a SkyCoord can), and, should a SkyCoord be immutable.

I think from the above, the consensus certainly is that one should be able to initialise other-frame attributes on an existing SkyCoord instance. From what you say, it sounds like you have existing code that relies on also changing such attributes, correct? If so, I think the correct thing to do is to still allow that. @taldcroft - what do you think?

If we go that route, then this PR would only ensure that attributes get stored in the correct location, and #5751 would add that, whenever they get set, they also get validated.

@mhvk
Copy link
Contributor Author

mhvk commented Jan 30, 2017

p.s. @taldcroft, @Cadair - if you both think it is OK, it is perhaps easier to just do this in the context of #5751 (I don't really know any more why I had the two PRs...).

@Cadair
Copy link
Member

Cadair commented Jan 30, 2017

Yes, we use the fact you can change existing attributes on a SkyCoord to swap observers. (Which is a transformation from one frame into another and out to the same frame with a different attribute).

I think limiting the setting of SkyCoord attributes to only ones that exist on frames is ok, as long as it's not a massive performance hit. I think we should keep the ability for the attributes to be modified if they are not the active frame though, as that's what we are using (exploiting?!) to do this observer switch-eroo.

@mhvk mhvk changed the title Ensure no existing FrameAttribute can be set on a SkyCoord. Ensure FrameAttribute not on present frame are set on SkyCoord, not on its frame Feb 1, 2017
@mhvk
Copy link
Contributor Author

mhvk commented Feb 1, 2017

@taldcroft, @Cadair - I now reversed the logic, and made this PR set any frame attribute that is not on its present frame on the SkyCoord instance (instead of its frame).

Combining this with #5751 will ensure it will also be validated.

Does this make sense?

@mhvk
Copy link
Contributor Author

mhvk commented Feb 7, 2017

@Cadair - I think the present PR would not break anything, could you have a check?
@taldcroft - any objections to this?

@eteq
Copy link
Member

eteq commented Feb 16, 2017

@mhvk - I like the present solution in this PR, if I'm understanding correctly... I actually thought this was the current behavior until seeing this PR and the associated issues. So in that sense I'm fine with calling this a bug fix (especially given #5751) But I would like to hear from @Cadair if this is compatible with the Sunpy use case before merging.

@Cadair
Copy link
Member

Cadair commented Feb 16, 2017

I will try and test this tomorrow.

Copy link
Member

@taldcroft taldcroft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished my review. In its current state this doesn't seem controversial. I honestly don't know why I put "non-frame" attributes into the frame instance instead of the SkyCoord instance, but I agree this wasn't the best choice.

(not attr.startswith('_') and
hasattr(self._sky_coord_frame, attr))):
if not attr.startswith('_') and hasattr(self._sky_coord_frame,
attr):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think this is a nice example of where a strict 80 character line length limit makes the code less readable, not more. The existing style in this module is up to 100 characters, so in the future please feel free to let lines go somewhat past 80 if that avoids an awkward line break.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively the previous version had a bit more logical line break

CHANGES.rst Outdated
@@ -185,6 +185,12 @@ Bug Fixes
- Fixed a bug where ``get_transform`` could sometimes produce confusing errors
because of a typo in the input validation. [#5645]

- Ensured that frame attributes cannot be set on ``SkyCoord`` if the current
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty confusing, and I think the first part was already true. What about:

Changed SkyCoord so that frame attributes which are not valid for the current frame (but are valid for other frames) are stored on the SkyCoord instance instead of the underlying frame instance. An example is setting relative_humidity on an ICRS SkyCoord instance.

Currently, if one defines, e.g., a SkyCoord with an ICRS frame,
one can set any existing frame attribute that is not on that
frame. Oddly, this gets set on the frame, without any validation:
```
sc = SkyCoord(ra=0., dec=0., unit='deg')
sc.relative_humidity = 'bla'
sc.frame.relative_humidity
```
This commit prevents one from setting any attribute that is
a FrameAttribute of any frame.
Discussions showed that this is actually useful, so unlike in
the previous commit, we should not forbid such setting. However,
it still makes no sense to store those non-frame attributes on
the frame; instead, they are now stored on the SkyCoord instance.
(Validation of these is deferred to further commits.)
@mhvk
Copy link
Contributor Author

mhvk commented Feb 17, 2017

@taldcroft - OK, done both (much better text indeed). Rebased for good measure.

Copy link
Member

@Cadair Cadair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to break anything in release SunPy. I have another problem that I discovered while testing this but it seems to be unrelated to this.

@mhvk
Copy link
Contributor Author

mhvk commented Feb 17, 2017

OK, I'll merge so that I can get my follow-up PR rebased on master, and it will be clearer what is new.

@mhvk mhvk merged commit 9d64f44 into astropy:master Feb 17, 2017
@mhvk mhvk deleted the skycoord-setattr-bug branch February 17, 2017 14:38
bsipocz pushed a commit that referenced this pull request Feb 22, 2017
Ensure FrameAttribute not on present frame are set on SkyCoord, not on its frame
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants