Skip to content

Latest commit

 

History

History
242 lines (180 loc) · 11.1 KB

SEP-0005.md

File metadata and controls

242 lines (180 loc) · 11.1 KB

SEP-0005 - Coordinates Module

SEP 5
title Coordinates Module
author(s) Pritish Chakraborty, Stuart Mumford
contact email [email protected], [email protected]
date-creation 2014-05-18
type standard
discussion https://groups.google.com/forum/m/#!topic/sunpy-gsoc-2014/hKWRYe1ND00
status accepted

Introduction

This SEP describes the implementation of a new SunPy submodule sunpy.coordinates. This submodule will provide objects to represent spatial coordinates in all of the common solar physics coordinate systems. This submodule will utilize the Astropy coordinates submodule and integrate heavily with that module. This new submodule will replace most of the functionality currently present in sunpy.wcs.

Detailed Description

Astropy's new coordinates submodule (released as part of Astropy v0.4.0) provides a well designed and appropriate framework for implementing solar physics coordinate transformations. The details of this framework are described below.

The coordinates package is designed to provide transformations between physical spatial coordinates, it does not provide the pixel to world coordinate transformation framework. This is handled via astropy.wcs.

Definitions

The following provide some definitions used in this document with regards to coordinates. These are based on the definitions in APE5.

  1. Coordinate Representation: It is a particular way of describing a unique point in a vector space (usually 3D space). Some examples of significance to SunPy are the Cartesian and Cylindrical representations.

  2. Reference System: It is a scheme used to orient points in a space. It is used to describe how a point is transformed from system to system. Examples from the Astropy codebase are the ICRS and equitorial coordinates (mean equinox) systems.

  3. Coordinate Frame: This is a specific realization of a reference system. Some systems may have only one meaningful frame while yet others may have several different frames. A tentative example in the proposed SunPy subpackage would be that of the heliographic coordinates, with Stonyhurst and Carrington realizations.

The astropy.coordinates Sub-Package

The Astropy coordinate submodule has three sets of classes:

  1. Data Representation: The representation of the coordinate point in 3D space. The representation can be considered as the coordinate vector, for example, in Cartesian, Cylindrical or Spherical systems. These classes are generally not used by the user, apart from in advanced use cases. These representations hold their data in Quantity objects or subclasses.

  2. Low-Level Frames: These classes are the objects that describe the coordinate system, origin, default representation etc. They also can hold the coordinate data (in a representation object), however, a frame does not have to hold coordinate information and can just represent the reference system.

  3. High-Level Object: The high level object is the astropy.coordinates.SkyCoord object which provides the primary interface to both Astropy's coordinates submodule and SunPy's. This class can handle a wider variety of input and will sanitize this input and create a CoordinateFrame class.

The Proposed sunpy.coordinates Sub-Package

The four primary coordinate systems, i.e., heliographic (Stonyhurst and Carrington), heliocentric and helioprojective systems will be implemented. These will take the form of low-level frame classes - HelioGraphicStonyhurst, HelioGraphicCarrington, HelioCentric and HelioProjective. These will be made to subclass from astropy.coordinates.BaseCoordinateFrame.

To facilitate the convention of both helioprojective and heliographic coordinate systems of wrapping Longitude at 180° a custom SphericalWarp180Representation object will be created as a subclass of astropy.coordinates.SphericalRepresentation to set the Longitude wrapping to 180°.

No modification to or subclassing of SkyCoord will occur to maintain maximum possible compatibility and interoperability with Astropy and other packages which use its coordinates framework.

Basic Core API Examples

Creating a helioprojective SkyCoord object::

import astropy.units as u
from astropy.coordinates import SkyCoord
import sunpy.coordinates

sc1 = SkyCoord(230*u.arcsec, 120*u.arcsec, frame='helioprojective')

Transforming this object to heliographic Stonyhurst:

sc2 = sc1.transform_to('heliographicstonyhurst')

Creation of an object from astropy Quantity objects:

Tx = np.random.random([10])*100 * u.arcsec
Ty = np.random.random([10])*100 * u.arcsec

sc3 = SkyCoord(Tx, Ty, frame='helioprojective')

Helioprojective Coordinate Assumptions

Because the helioprojective coordinate system is a projective system, where it is unusual to have information on the third spatial dimension of a coordinate, some assumptions are normally made when transforming from helioprojective to heliocentric coordinates.

This assumption (as currently implemented in sunpy.wcs) is that during transformation, if no helioprojective radial coordinate was specified then the radial coordinate is calculated as if the coordinate point is on the solar surface.

The third coordinate can be specified explicitly upon construction:

sc = SkyCoord(230*u.arcsec, 120*u.arcsec, 1*u.au, frame='helioprojective')

or will be calculated to facilitate transformations to other frames.

The third coordinate above is distance to the point from the observer, i.e. radial distance in a spherical coordinate system. Optionally, the third coordinate can be specified as zeta = Dsun - distance, thus:

sc = SkyCoord(230*u.arcsec, 120*u.arcsec, zeta=695.5e3*u.km,
              frame='helioprojective')

Observer Location and Frame Attributes

Fundamental to the coordinate transformations in solar physics is the position of the observer. To pass this information to the coordinate frame objects, the FrameAttribute classes are used. These classes provide immutable attributes of the frame class, where default values can be selected and values can be passed into either the frame constructors or the SkyCoordconstructor.

All of the frames have all the attributes needed for any frame transformation defined, this way if all the attribute values are specified or take their default values all the transformations can be performed on the data.

The frame attributes are:

  • D0: Distance to solar center from the observer [default: 1 AU].
  • L0: Heliographic longitude of the observer [default: 0°].
  • B0: Heliographic latitude of the observer [default: 0°].
  • dateobs: Date and time of the observation [no default].

Transformations Between Frames

The transformations between the frame classes are defined on a bi-directional transformation graph which is specified in astropy.coordinates. The SunPy frames can register their transformations on this graph and are therefore detected by astropy.coordinates and each solar coordinate system can be transformed to any other, even if no direct route between the nodes exists on the graph.

This implementation also allows the possibility of defining a transformation from a solar frame to an astronomical frame in the future and therefore allowing the transformation of any solar coordinate to any astronomical coordinate via the transformation graph.

Advanced API Examples

from sunpy.coordinates.frames import HelioGraphicStonyhurst, HelioCentric, HelioProjective
from astropy.coordinates import SkyCoord, UnitSphericalRepresentation                                
from astropy import units as u                                              

# Some ways to initialize a `SkyCoord` object.                              
# In Heliographic Stonyhurst frames, one can declare so -:                  
sc = SkyCoord(                                                              
    1*u.deg, 1*u.deg, 1*u.km, frame='heliographicstonyhurst',               
    dateobs='2011/01/01T00:00:45'                                           
)                                                                           
print(sc)      
<SkyCoord (HelioGraphicStonyhurst): B0=0.0 deg, dateobs=2011-01-01 00:00:45, L0=0.0 deg, hlon=1.0 deg, hlat=1.0 deg, rad=1.0 km>                                                             

# We can transform the data to another frame.                               
print(sc.transform_to('heliocentric'))       
<SkyCoord (HelioCentric): D0=149597870.7 km, B0=0.0 deg, dateobs=2011-01-01 00:00:45, L0=0.0 deg, x=0.0174497483513 km, y=0.0174524064373 km, z=0.99969541351 km>                               

# One could also not give the distance/radius input, and it will            
# default to solar radius.                                                  
sc = SkyCoord(                                                              
    1*u.deg, 1*u.deg, frame='heliographicstonyhurst',                       
    dateobs='2011/01/01T00:00:45'                                           
)                                                                           
print(sc)         
<SkyCoord (HelioGraphicStonyhurst): B0=0.0 deg, dateobs=2011-01-01 00:00:45, L0=0.0 deg, hlon=1.0 deg, hlat=1.0 deg, rad=695508.0 km>                                                          

# It is also possible to provide the representation-specific args as a      
# `BaseRepresentation` object.                                              
from sunpy.coordinates.representation import SphericalWrap180Representation
sc = SkyCoord(                                                              
    SphericalWrap180Representation(1*u.deg, 1*u.deg, 1*u.km),               
    frame='helioprojective', dateobs='2011/01/01T00:00:45'                  
)                                                                           
print(sc)                                                                   
<SkyCoord (HelioProjective): L0=0.0 deg, B0=0.0 deg, dateobs=2011-01-01 00:00:45, D0=149597870.7 km, Tx=3600.0 arcsec, Ty=3600.0 arcsec, distance=1.0 km>

# It is also possible to create a frame object directly
fr = HelioProjective(L0=10*u.deg, B0=-1.*u.deg, dateobs='2011/01/01T00:00:45')
print(fr)
<HelioProjective Frame: L0=10.0 deg, B0=-1.0 deg, dateobs=2011-01-01 00:00:45, D0=149597870.7 km>

# You can then realise this frame to get another frame with data:
print(fr.realize_frame(UnitSphericalRepresentation(230*u.arcsec, 10*u.arcsec)))
<HelioProjective Coordinate: L0=10.0 deg, B0=-1.0 deg, dateobs=2011-01-01 00:00:45, D0=149597870.7 km, Tx=230.0 arcsec, Ty=10.0 arcsec, distance=148922609.068 km>

References / Links

  1. APE 5
  2. Implementation PR #1069
  3. Astropy Coordinates Package

Decision Rationale

Accepted at the board meeting on 2014-10-17 by a vote of 6-0.