def test_obsgeo_cartesian(dkist_location): obstime = Time("2021-05-21T03:00:00") wcs = WCS(naxis=2) wcs.wcs.obsgeo = list(dkist_location.to_value(u.m).tolist()) + [0, 0, 0] wcs.wcs.dateobs = obstime.isot frame = obsgeo_to_frame(wcs.wcs.obsgeo, obstime) assert isinstance(frame, ITRS) assert frame.x == dkist_location.x assert frame.y == dkist_location.y assert frame.z == dkist_location.z
def test_obsgeo_spherical(dkist_location): obstime = Time("2021-05-21T03:00:00") dkist_location = dkist_location.get_itrs(obstime) loc_sph = dkist_location.spherical wcs = WCS(naxis=2) wcs.wcs.obsgeo = [0, 0, 0] + [ loc_sph.lon.value, loc_sph.lat.value, loc_sph.distance.value ] wcs.wcs.dateobs = obstime.isot frame = obsgeo_to_frame(wcs.wcs.obsgeo, obstime) assert isinstance(frame, ITRS) assert u.allclose(frame.x, dkist_location.x) assert u.allclose(frame.y, dkist_location.y) assert u.allclose(frame.z, dkist_location.z)
def test_obsgeo_invalid(obsgeo): with pytest.raises(ValueError): obsgeo_to_frame(obsgeo, None)
def solar_wcs_frame_mapping(wcs): """ This function registers the coordinates frames to their FITS-WCS coordinate type values in the `astropy.wcs.utils.wcs_to_celestial_frame` registry. Parameters ---------- wcs : astropy.wcs.WCS Returns ------- astropy.coordinates.BaseCoordinateFrame """ if hasattr(wcs, "coordinate_frame"): return wcs.coordinate_frame dateobs = wcs.wcs.dateobs or None # Get observer coordinate from the WCS auxillary information required_attrs = { HeliographicStonyhurst: ['hgln_obs', 'hglt_obs', 'dsun_obs'], HeliographicCarrington: ['crln_obs', 'hglt_obs', 'dsun_obs'] } # Get rsun from the WCS auxillary information rsun = wcs.wcs.aux.rsun_ref if rsun is not None: rsun *= u.m # TODO: remove these errors in sunpy 4.1 bad_attrs = [ f'.{attr}' for attr in ['rsun', 'heliographic_observer'] if hasattr(wcs, attr) ] if len(bad_attrs): raise ValueError( f"The {' and '.join(bad_attrs)} attribute(s) on a WCS " "are no longer supported.") observer = None for frame, attr_names in required_attrs.items(): attrs = [getattr(wcs.wcs.aux, attr_name) for attr_name in attr_names] if all([attr is not None for attr in attrs]): kwargs = {'obstime': dateobs} if rsun is not None: kwargs['rsun'] = rsun if issubclass(frame, HeliographicCarrington): kwargs['observer'] = 'self' observer = frame(attrs[0] * u.deg, attrs[1] * u.deg, attrs[2] * u.m, **kwargs) # Read the observer out of obsgeo for ground based observers if observer is None: try: observer = obsgeo_to_frame(wcs.wcs.obsgeo, dateobs) observer = SkyCoord(observer, rsun=rsun) except ValueError as e: # The helper function assumes you know the obsgeo coords you are # parsing are good, we are not sure, so catch the error. # This approach could lead to an invalid observer (i.e. one of the # coords being NaN), but only if the WCS has been constructed like that. log.debug(f"Could not parse obsgeo coordinates from WCS:\n{e}") # Collect all of the possible frame attributes, although some may be removed later frame_args = {'obstime': dateobs} if observer is not None: frame_args['observer'] = observer if rsun is not None: frame_args['rsun'] = rsun frame_class = _sunpy_frame_class_from_ctypes(wcs.wcs.ctype) if frame_class: if frame_class == HeliographicStonyhurst: frame_args.pop('observer', None) if frame_class == Heliocentric: frame_args.pop('rsun', None) return frame_class(**frame_args)
def solar_wcs_frame_mapping(wcs): """ This function registers the coordinates frames to their FITS-WCS coordinate type values in the `astropy.wcs.utils.wcs_to_celestial_frame` registry. Parameters ---------- wcs : astropy.wcs.WCS Returns ------- astropy.coordinates.BaseCoordinateFrame """ if hasattr(wcs, "coordinate_frame"): return wcs.coordinate_frame dateobs = wcs.wcs.dateobs or None # Get observer coordinate from the WCS auxillary information required_attrs = { HeliographicStonyhurst: ['hgln_obs', 'hglt_obs', 'dsun_obs'], HeliographicCarrington: ['crln_obs', 'hglt_obs', 'dsun_obs'] } # Get rsun from the WCS auxillary information rsun = wcs.wcs.aux.rsun_ref if rsun is not None: rsun *= u.m # This custom attribute was always used in sunpy < 2.1; these warnings # can be converted into errors in sunpy 3.1 if hasattr(wcs, 'rsun'): warnings.warn( 'Support for the .rsun attribute on a WCS is deprecated. ' 'Set observer keywords in the FITS header, or directly set the wcs.wcs.aux ' 'values instead.', SunpyUserWarning) if rsun is None: rsun = wcs.rsun else: warnings.warn( 'rsun information present in WCS auxillary information, ignoring ' '.rsun', SunpyUserWarning) observer = None for frame, attr_names in required_attrs.items(): attrs = [getattr(wcs.wcs.aux, attr_name) for attr_name in attr_names] if all([attr is not None for attr in attrs]): kwargs = {'obstime': dateobs} if rsun is not None: kwargs['rsun'] = rsun if issubclass(frame, HeliographicCarrington): kwargs['observer'] = 'self' observer = frame(attrs[0] * u.deg, attrs[1] * u.deg, attrs[2] * u.m, **kwargs) # Read the observer out of obsgeo for ground based observers if observer is None: try: observer = obsgeo_to_frame(wcs.wcs.obsgeo, dateobs) observer = SkyCoord(observer, rsun=rsun) except ValueError as e: # The helper function assumes you know the obsgeo coords you are # parsing are good, we are not sure, so catch the error. # This approach could lead to an invalid observer (i.e. one of the # coords being NaN), but only if the WCS has been constructed like that. log.debug(f"Could not parse obsgeo coordinates from WCS:\n{e}") # This custom attribute was always used in sunpy < 2.1; these warnings # can be converted into errors in sunpy 3.1 if hasattr(wcs, 'heliographic_observer'): warnings.warn( 'Support for the .heliographic_observer attribute on a WCS is deprecated. ' 'Set observer keywords in the FITS header, or directly set the wcs.wcs.aux ' 'values instead.', SunpyUserWarning) if observer is None: observer = wcs.heliographic_observer else: warnings.warn( 'Observer information present in WCS auxillary information, ignoring ' '.heliographic_observer', SunpyUserWarning) # Truncate the ctype to the first four letters ctypes = {c[:4] for c in wcs.wcs.ctype} if {'HPLN', 'HPLT'} <= ctypes: return Helioprojective(obstime=dateobs, observer=observer, rsun=rsun) if {'HGLN', 'HGLT'} <= ctypes: return HeliographicStonyhurst(obstime=dateobs) if {'CRLN', 'CRLT'} <= ctypes: return HeliographicCarrington(obstime=dateobs, observer=observer) if {'SOLX', 'SOLY'} <= ctypes: return Heliocentric(obstime=dateobs, observer=observer)