From 6dec20036d0d2b205e59d8e3366a3a9c72c27f51 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 26 Jun 2013 11:25:43 -0400 Subject: [PATCH 01/20] Added WCS API --- generalized_wcs/coordinate_systems_api.md | 140 +++++++++++++++++++ generalized_wcs/region_api.md | 163 ++++++++++++++++++++++ generalized_wcs/selector.md | 43 ++++++ generalized_wcs/wcs_api.md | 143 +++++++++++++++++++ 4 files changed, 489 insertions(+) create mode 100644 generalized_wcs/coordinate_systems_api.md create mode 100644 generalized_wcs/region_api.md create mode 100644 generalized_wcs/selector.md create mode 100644 generalized_wcs/wcs_api.md diff --git a/generalized_wcs/coordinate_systems_api.md b/generalized_wcs/coordinate_systems_api.md new file mode 100644 index 0000000..b579dad --- /dev/null +++ b/generalized_wcs/coordinate_systems_api.md @@ -0,0 +1,140 @@ +Coordinate Systems +------------------ + +The proposed API for coordinate systems is based on the +[STC document](http://www.ivoa.net/documents/PR/STC/STC-20050315.html) +and [WCS Paper III](http://fits.gsfc.nasa.gov/fits_wcs.html) +and is a very high level description of coordinate system classes. + +A coordinate system consists of one or more coordinate frames which +describe a reference position and a reference frame. + +The base class of all frames is `CoordinateFrame`. It is kept intentionally +very simple so that it can be easily extended. + + class CoordinateFrame(object): + """ + Base class for CoordinateFrames + + Parameters + ---------- + system : string + type of the frame + num_axes : int + axes_names : list of strings + units : list of units + """ + def __init__(self, system, num_axes, axes_names=None, units=None): + """ Initialize a frame""" + + def transform_to(self, other): + """ + Transform from the current reference system to other if + the system attribute of the two matches + """ + +Four basic frames are defined as subclasses of `CoordinateFrame`: + + class TimeFrame(CoordinateFrame): + """ + Time Frame + + Parameters + ---------- + time_scale : time scale + + reference_position :an instance of ReferencePosition + + reference_direction : (optional) + """ + + standard_time_scale = ["TT", "TDT", "ET", "TAI", "IAT", + "UTC", "GPS", "TDB", "TEB", "TCG", + "TCB", "LST"] + + def __init__(self, time_scale, reference_position, reference_direction=None, units="s"): + assert time_scale in standard_time_scale, "Unrecognized time scale" + + super("Time", numaxes=1, axes_names=['time'], units=[units]) + self._time_scale =time_scale + self._reference_position = reference_position + + class SkyFrame(CoordinateFrame): + """ + Space Frame Representation + """ + standart_ref_frame = ["FK4", "FK5", "ICRS", '...'] + + def __init__(self, reference_frame, reference_position, obstime, equinox=None, + projection="", axes_names=["", ""], units=["",""], offset_center=None): + + super(SkyFrame, self).__init__('Space', num_axes=2, axes_names=axes_names, units=units) + self._equinox = equinox + self._projection = projection + self._offset_center = offset_center + self._reference_frame = reference_frame + self._reference_position = reference_position + + class SpectralFrame(CoordinateFrame): + """ + Represents Spectral Frame + + Parameters + ---------- + reference_frame : string + one of spectral_ref_frame + reference_position : an instance of ReferencePosition + + """ + spectral_ref_frame = ["WAVE", "FREQ", "ENER", "WAVEN", "AWAV", "VRAD", + "VOPT", "ZOPT", "VELO", "BETA"] + def __init__(self, reference_frame, reference_pos, date_obs, rest_freq=None, rest_wave=None, + units=""): + + super(SpectralFrame, self).__init__('Spec', num_axes=1, axes_names=[reference_frame], units=[""]) + self._reference_frame = reference_frame + self._reference_position = reference_position + self.rest_freq = rest_freq + self.rest_wave = rest_wave + self.dateobs = dateobs + +A `CoordinateSystem` has one or more `CoordinateFrame` objects: + + class CoordinateSystem(object): + """ + A coordinate system has one or more frames. + + Parameters + ---------- + name : string + a user defined name + frames : list + list of frames [Time, Sky, Spectral] + """ + def __init__(self, frames, name="CompositeSystem"): + self.frames = frames + + + class ReferencePosition(object): + """ + Encapsulates a reference position for a CoordFrame + + Table 1 in the STC document. + + """ + standart_reference_positions = ["GEOCENTER", "BARYCENTER", "HELIOCENTER", + "TOPOCENTER", "LSR", "LSRK", "LSRD", + "GALACTIC_CENTER", "MOON", "LOCAL_GROUP_CENTER", + "EMBARYCENTER", "RELOCATABLE", "UNKNOWNRefPos"] + + def __init__(self, frame, name): + if self._validate(frame, name): + self._name = name + else: + raise ReferencePositionError + + def _validate_ref_pos(self, frame): + """ + validates that the reference position is allowed for the frame + """ + return True diff --git a/generalized_wcs/region_api.md b/generalized_wcs/region_api.md new file mode 100644 index 0000000..e8223c3 --- /dev/null +++ b/generalized_wcs/region_api.md @@ -0,0 +1,163 @@ +Regions +------- + +This file describes the region api. + +Regions are necessary to describe multiple WCSs in an observation, +for example IFUs. This proposal follows the Region definitions in the +[STC document](http://www.ivoa.net/documents/PR/STC/STC-20050315.html). + +* Note : This has some overlap with the aperture definitions in photutils. +Should we consider merging this work? + +A Region is defined in the context of a coordinate system. Subclasses should +define `__contains__` method and a `scan` method. + + class Region(object): + """ + Base class for regions. + + Parameters + ------------- + rid : int or string + region ID + coordinate_system : astropy.wcs.CoordinateSystem instance or a string + in the context of WCS this would be an instance of wcs.CoordinateSysem + """ + def __init__(self, rid, coordinate_system): + self._coordinate_system = coordinate_system + self._rid = rid + + def __contains__(self, x, y): + """ + Determines if a pixel is within a region. + + Parameters + ---------- + x,y : float + x , y values of a pixel + + Returns + ------- + True or False + + Subclasses must define this method. + """ + + def scan(self, mask): + """ + Sets mask values to region id for all pixels within the region. + Subclasses must define this method. + + Parameters + ---------- + mask : ndarray + a byte array with the shape of the observation to be used as a mask + + Returns + ------- + mask : array where the value of the elements is the region ID or 0 (for + pixels which are not included in any region). + """ + +An example of a Polygon region class + + class Polygon(Region): + """ + Represents a 2D polygon region with multiple vertices + + Parameters + ---------- + rid : string + polygon id + vertices : list of (x,y) tuples or lists + The list is ordered in such a way that when traversed in a + counterclockwise direction, the enclosed area is the polygon. + The last vertex must coincide with the first vertex, minimum + 4 vertices are needed to define a triangle + coord_system : string + coordinate system + + """ + def __init__(self, rid, vertices, coord_system="Cartesian"): + self._rid = rid + self._vertices = vertices + self.coord_system = coord_system + + def __contains__(self, x, y): + + def scan(mask): + + + + +`create_regions_mask` is a function which creates a byte array with regions labels + + def create_regions_mask(mask_shape, regions_def, regions_schema=None): + """ + Given a JSON file with regions definitions and a schema, this function + + - creates a byte array of shape mask_shape + - reads in and validates the regions definitions + - scans each region and marks each pixel in the output array with the region ID + - returns the mask + + Given 2 regions on a detector of size 10x10 px, the mask may look like this: + + 0 0 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 2 2 + 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 + 2 2 0 0 0 0 2 2 2 2 + 2 0 0 0 0 0 0 0 2 2 + + """ + +JSON is used for regions definitions. The schema for a Set of Regions and a Polygon region is +defined below. It will be expanded with other kinds of regions. + + {"$schema": "http://json-schema.org/draft-03/schema#", + "title": "A set of Regions", + "type": "array", + "items":{ + "type": "object", + "title": "Polygon Region", + "description": "A representation of a rectangular region on a detector", + "properties": { + "id": { + "type": ["integer", "string"], + "required": true, + "unique": true + }, + "coordinate_system": { + "type": "object", + "properties":{ + "name": { + "type": "string", + "enum": ["Cartesian", "Sky"] + } + }, + "required": true + }, + "vertices": { + "type": "array", + "description": "Array of vertices describing the Polygon", + "items": { + "type": "array", + "description": "Pairs of (x, y) coordinates, representing a vertex", + "items": { + "type": "integer" + }, + "minItems": 2, + "maxItems": 2 + }, + "minItems": 4, + "required": true + } + } + } + } diff --git a/generalized_wcs/selector.md b/generalized_wcs/selector.md new file mode 100644 index 0000000..916581e --- /dev/null +++ b/generalized_wcs/selector.md @@ -0,0 +1,43 @@ +SelectorModel +------------- + +The `SelectorModel` provides mappings between a transform and some other quantity. +The obvious case is an IFU detector where each region maps to a different transform. +However, the goal is for this to be general and allow for other use cases, for example +multiple orders, slitless spectroscopy. + +For this reason the base class defines only the mapping and additional functionality +is left for specific classes. + +The `__call__` method is defined by subclasses and implements the real work of +figuring out how to match input coordinates with a transform. + + class SelectorModel(model): + """ + Parameters + ---------- + labels : a list of strings or objects + transforms : a list of transforms + transforms match labels + """ + def __init__(self, labels, transforms): + self._selector = dict(labels, transforms) + + def __call__(self, label): + raise NotImplementedError + +An example of a selector of regions of an IFU is below. It has an additional attribute +`regions_map` which is a byte array with regions labels. The actual definitions of the +regions are read in from a JSON file, see the [Region API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/region_api.md) + + class RegionsSelector(SelectorModel): + def __init__(self, labels, transforms, regions): + super(RegionsSelector, self).__init__(labels, transforms) + #create_regions_mask_from_json is defined in the regions API. + self.regions_map = regions.create_regions_map_from_json(mask_shape, regions, schema) + + def __call__(self, x, y): + """ + Transforms x and y using self._selector and self.regions_map + + """ \ No newline at end of file diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md new file mode 100644 index 0000000..897adeb --- /dev/null +++ b/generalized_wcs/wcs_api.md @@ -0,0 +1,143 @@ +WCS data model +-------------- + +This document describes the WCS data model. WCS serialization is not discussed here. + +Motivation for this work was discussed [previously](https://mail.google.com/mail/u/1/?ui=2&shva=1#search/perrygreenfield/13efbb0f6b4b3932). + +Authors +------- +* Nadia Dencheva (@nden) +* Perry Greenfield (@perrygrienfield) + +Thanks for feedback from: + +* Mike Droettboom (@mdboom) + +The basic requirements for this data model are: + +* Perform the transformation from pixels to world coordinates and back. +* Handle multiple transforms ( IFU detectors but not limited to that). + +High level interface +--------------------- + +Create a WCS object: + + wcsobj = WCS(coordinate_system, transform) + +Transform pixel coordinates to world coordinates: + + ra, dec = wcsobj(x, y) + +Transform from world coordinates to pixels: + + x, y = wcsobj.invert(ra, dec) + +`transform` may be an instance of `SelectorModel` which maps transforms to other quantities, +for example regions on detector but not limited to this. In this case: + + wcsobj(x,y) + +should be able to transform the cordinates using the correct transform. +This is handled by the `SelectorModel` class. + + wcs_for_region_3 = wcsobj.select(label=3) + +returns the WCS object for region 3. + +If `transform` is an instance of `SelectorModel`, the `invert` method should map to the `invert()` +methods of all individual transforms. + +It should be possible to transform the output coordinates to a different coordinate system. The `~astropy.coordinates` package +is be used where possible. + + wcsobj.coordinate_system.to(ra, dec, other_system) + +The special case of FITS WCS is handled through the `FITSWCS` class which inherits from `WCS` +and uses `pywcs` to create the coordinate system object and the transforms. + + fwcs = FITSWCS(fits_file, ext, key=' ') + +In more detail +-------------- + +* [WCS API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/wcs_api.md#wcs-api) +* [Selector Object](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/selector.md) +* [Regions API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/region_api.md) +* [Coordinate Systems API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/coordinate_systems_api.md) + +WCS API +------- + + class WCS(object): + """ + WCS Data Model + + Parameters + ---------- + transform : astropy.modeling.Model or a callable + a callable which performs the transformation + + output_coordinate_system : astropy.wcs.CoordinateSystem + """ + + def __init__(self, transform, output_coordinate_system): + self.transform = transform + self.output_coordinate_system = output_coordinate_system + self.units = self.output_coordinate_system.units + + def select(self, label): + if isinstance(self.transform, SelectorModel): + return self.transform[label] + else: + raise Error + + def __call__(self, args): + """ + Performs the forward transformation pix --> world. + """ + return self.transform(x, y) + + def invert(self, args): + try: + inverse_transform = self.transform.inverse() + return inverse_transform(*args) + except NotImplementedError: + return self.transform.invert(*args) + +FITS WCS uses `~astropy.wcs`. This takes advantage of knowledge about FITS +specific keywords and parsing the FITS header. + + class FITSWCS(WCS): + """ + Implements FITS WCS + + Uses pywcs + + Parameters + ---------- + fits_file : string or fits.HDUList object + + ext : int + extension number + """ + def __init__(self, fits_file, ext=0): + """ + Creates an `~astropy.wcs.WCS` object and uses its `all_pix2world` + method as a transform. + Also constructs a `CoordSystem` object from it. + + regions mask is None in this case. + """ + + def __call__(self, args): + """ + The forward transform uses `all_pix2world` method of the object + """ + + def __invert(self, args): + """ + The inverse transform uses the `all_sky2pix` method. + """ + From bc39415682a1380bd278f951e861443d5c555b43 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 26 Jun 2013 11:34:30 -0400 Subject: [PATCH 02/20] Correct links --- generalized_wcs/selector.md | 2 +- generalized_wcs/wcs_api.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generalized_wcs/selector.md b/generalized_wcs/selector.md index 916581e..caf9395 100644 --- a/generalized_wcs/selector.md +++ b/generalized_wcs/selector.md @@ -28,7 +28,7 @@ figuring out how to match input coordinates with a transform. An example of a selector of regions of an IFU is below. It has an additional attribute `regions_map` which is a byte array with regions labels. The actual definitions of the -regions are read in from a JSON file, see the [Region API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/region_api.md) +regions are read in from a JSON file, see the [Region API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/region_api.md) class RegionsSelector(SelectorModel): def __init__(self, labels, transforms, regions): diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 897adeb..6c4b453 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -62,10 +62,10 @@ and uses `pywcs` to create the coordinate system object and the transforms. In more detail -------------- -* [WCS API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/wcs_api.md#wcs-api) -* [Selector Object](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/selector.md) -* [Regions API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/region_api.md) -* [Coordinate Systems API](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/coordinate_systems_api.md) +* [WCS API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/wcs_api.md#wcs-api) +* [Selector Object](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/selector.md) +* [Regions API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/region_api.md) +* [Coordinate Systems API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/coordinate_systems_api.md) WCS API ------- From 77e80c98903deb56543ccbc37cc7343fa02ad5b9 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 26 Jun 2013 11:37:50 -0400 Subject: [PATCH 03/20] Correct links --- generalized_wcs/selector.md | 2 +- generalized_wcs/wcs_api.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generalized_wcs/selector.md b/generalized_wcs/selector.md index caf9395..150c16a 100644 --- a/generalized_wcs/selector.md +++ b/generalized_wcs/selector.md @@ -28,7 +28,7 @@ figuring out how to match input coordinates with a transform. An example of a selector of regions of an IFU is below. It has an additional attribute `regions_map` which is a byte array with regions labels. The actual definitions of the -regions are read in from a JSON file, see the [Region API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/region_api.md) +regions are read in from a JSON file, see the [Region API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/region_api.md) class RegionsSelector(SelectorModel): def __init__(self, labels, transforms, regions): diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 6c4b453..ac5610c 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -63,9 +63,9 @@ In more detail -------------- * [WCS API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/wcs_api.md#wcs-api) -* [Selector Object](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/selector.md) -* [Regions API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/region_api.md) -* [Coordinate Systems API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs_api/coordinate_systems_api.md) +* [Selector Object](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/selector.md) +* [Regions API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/region_api.md) +* [Coordinate Systems API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/coordinate_systems_api.md) WCS API ------- From 21b0d36eb0677de254a5554a5cf9b28fdf7f6540 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Thu, 27 Jun 2013 14:40:36 -0400 Subject: [PATCH 04/20] minor improvements --- generalized_wcs/selector.md | 4 ++-- generalized_wcs/wcs_api.md | 15 +++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/generalized_wcs/selector.md b/generalized_wcs/selector.md index 150c16a..1897292 100644 --- a/generalized_wcs/selector.md +++ b/generalized_wcs/selector.md @@ -12,7 +12,7 @@ is left for specific classes. The `__call__` method is defined by subclasses and implements the real work of figuring out how to match input coordinates with a transform. - class SelectorModel(model): + class SelectorModel(object): """ Parameters ---------- @@ -27,7 +27,7 @@ figuring out how to match input coordinates with a transform. raise NotImplementedError An example of a selector of regions of an IFU is below. It has an additional attribute -`regions_map` which is a byte array with regions labels. The actual definitions of the +`regions_map` which is a byte array with region labels. The actual definitions of the regions are read in from a JSON file, see the [Region API](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/region_api.md) class RegionsSelector(SelectorModel): diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index ac5610c..d374104 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -1,20 +1,15 @@ WCS data model -------------- +Written by Nadia Dencheva (@nden) with ideas and feedback from +Perry Greenfield (@perrygrienfield) and Mike Droettboom (@mdboom) and taking into account +discussions at the latest astropy coordination meeting (Baltimore, 2012). + This document describes the WCS data model. WCS serialization is not discussed here. Motivation for this work was discussed [previously](https://mail.google.com/mail/u/1/?ui=2&shva=1#search/perrygreenfield/13efbb0f6b4b3932). -Authors -------- -* Nadia Dencheva (@nden) -* Perry Greenfield (@perrygrienfield) - -Thanks for feedback from: - -* Mike Droettboom (@mdboom) - -The basic requirements for this data model are: +The basic requirements for the data model are: * Perform the transformation from pixels to world coordinates and back. * Handle multiple transforms ( IFU detectors but not limited to that). From b06e01e74bf98a2c6bd0cf1ef0a5e50bd00312ae Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 02:20:58 -0500 Subject: [PATCH 05/20] Update document --- generalized_wcs/coordinate_systems_api.md | 165 +++++++++++++++------- generalized_wcs/wcs_api.md | 89 ++++++++---- 2 files changed, 180 insertions(+), 74 deletions(-) diff --git a/generalized_wcs/coordinate_systems_api.md b/generalized_wcs/coordinate_systems_api.md index b579dad..ace9cc0 100644 --- a/generalized_wcs/coordinate_systems_api.md +++ b/generalized_wcs/coordinate_systems_api.md @@ -4,7 +4,12 @@ Coordinate Systems The proposed API for coordinate systems is based on the [STC document](http://www.ivoa.net/documents/PR/STC/STC-20050315.html) and [WCS Paper III](http://fits.gsfc.nasa.gov/fits_wcs.html) -and is a very high level description of coordinate system classes. +and is a high level description of coordinate system classes. + +[Prototype implementation (incomplete)] ( https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/coordinate_systems.py) + +Note: Some of this may be replaced (or merged) with the high level coordinate class +being worked on although it may be that it is only a space coordinate class. A coordinate system consists of one or more coordinate frames which describe a reference position and a reference frame. @@ -18,22 +23,28 @@ very simple so that it can be easily extended. Parameters ---------- - system : string - type of the frame num_axes : int - axes_names : list of strings + number of axes + ref_system : str + reference system (see subclasses) + ref_pos : str or ``ReferencePosition`` + reference position or standard of rest units : list of units + unit for each axis + axes_names : list of str + names of the axes in this frame + name : str + name (alias) for this frame """ - def __init__(self, system, num_axes, axes_names=None, units=None): + def __init__(self, num_axes, ref_system=None, ref_pos=None, units=None, axes_names=None, name=None): """ Initialize a frame""" def transform_to(self, other): """ - Transform from the current reference system to other if - the system attribute of the two matches + Transform from the current reference system to other """ -Four basic frames are defined as subclasses of `CoordinateFrame`: +The following basic frames are defined as subclasses of `CoordinateFrame`: class TimeFrame(CoordinateFrame): """ @@ -41,39 +52,70 @@ Four basic frames are defined as subclasses of `CoordinateFrame`: Parameters ---------- - time_scale : time scale - - reference_position :an instance of ReferencePosition - - reference_direction : (optional) + scale : str + time scale, one of ``standard_time_scale`` + format : str + time representation + obslat : float or ``astropy.coordinates.Latitude`` + observer's latitude + obslon : float or ``astropy.coordinates.Longitude`` + observer's longitude + units : str or ``astropy.units.Unit`` + unit for each axis + axes_names : list of str + names of the axes in this frame """ - standard_time_scale = ["TT", "TDT", "ET", "TAI", "IAT", - "UTC", "GPS", "TDB", "TEB", "TCG", - "TCB", "LST"] + standard_time_scale = time.Time.SCALES + + time_format = time.Time.FORMATS - def __init__(self, time_scale, reference_position, reference_direction=None, units="s"): - assert time_scale in standard_time_scale, "Unrecognized time scale" + def __init__(self, scale, format, obslat=0., obslon=0., units="s", axes_names="Time", name="Time"): - super("Time", numaxes=1, axes_names=['time'], units=[units]) - self._time_scale =time_scale - self._reference_position = reference_position + + def transform_to(self, val, tosys, val2=None, precision=None, in_subfmt=None, + out_subfmt=None, copy=False): + """Transforms to a different scale/representation""" class SkyFrame(CoordinateFrame): """ - Space Frame Representation + Sky Frame Representation + + Parameters + ---------- + reference_system : str + one of standard_ref_frame + reference_position : str, ReferencePosition instance + obstime : time.Time instance + observation time + equinox : time.Time + equinox + ##TODO? List of supported projections per frame + projection : str + projection type + axes_names : iterable or str + axes labels + units : str or units.Unit instance or iterable of those + units on axes + distance : Quantity + distance from origin + see ``~astropy.coordinates.distance` + obslat : float or ~astropy.coordinates.Latitute` + observer's latitude + obslon : float or ~astropy.coordinates.Longitude + observer's longitude """ standart_ref_frame = ["FK4", "FK5", "ICRS", '...'] - def __init__(self, reference_frame, reference_position, obstime, equinox=None, - projection="", axes_names=["", ""], units=["",""], offset_center=None): + def __init__(self, reference_system, reference_position, obstime, equinox=None, + projection="", axes_names=["", ""], units=["",""], distance=None, + obslat=None, obslon=None, name=None): + + def transform_to(self, lat, lon, other, distance=None): + """ + Transform from the current reference system to other. + """ - super(SkyFrame, self).__init__('Space', num_axes=2, axes_names=axes_names, units=units) - self._equinox = equinox - self._projection = projection - self._offset_center = offset_center - self._reference_frame = reference_frame - self._reference_position = reference_position class SpectralFrame(CoordinateFrame): """ @@ -81,22 +123,52 @@ Four basic frames are defined as subclasses of `CoordinateFrame`: Parameters ---------- - reference_frame : string + reference_frame : str one of spectral_ref_frame - reference_position : an instance of ReferencePosition - + reference_position : ``ReferencePosition`` + obstime : time.Time instance + units : str or units.Unit instance + units for the spectral frame + axes_names : str + spectral axis name + If None, reference_system is used + rest_freq : float or Quantity (default None) + rest frequency + obslat : float or instance of `~astropy.coordinates.Latitude` + observer's latitude + obslon : float or instanceof `~astropy.coordinates.Longitude` + observer's longitude """ - spectral_ref_frame = ["WAVE", "FREQ", "ENER", "WAVEN", "AWAV", "VRAD", - "VOPT", "ZOPT", "VELO", "BETA"] - def __init__(self, reference_frame, reference_pos, date_obs, rest_freq=None, rest_wave=None, - units=""): - - super(SpectralFrame, self).__init__('Spec', num_axes=1, axes_names=[reference_frame], units=[""]) - self._reference_frame = reference_frame - self._reference_position = reference_position - self.rest_freq = rest_freq - self.rest_wave = rest_wave - self.dateobs = dateobs + + spectral_ref_frame = ["WAVE", "FREQ", "ENER", "WAVEN", "AWAV", "VRAD", + "VOPT", "ZOPT", "VELO", "BETA"] + + standard_reference_position = ["GEOCENTER", "BARYCENTER", "HELIOCENTER", + "TOPOCENTER", "LSR", "LSRK", "LSRD", + "GALACTIC_CENTER", "MOON", "LOCAL_GROUP_CENTER"] + + def __init__(self, reference_system, reference_position, units, axes_names=None, + obstime=None, rest_freq=None, obslat=None, obslon=None, name=None): + + def transform_to(self, coord, other): + """ Transforms to other spectral coordinate system""" + + class CartesianFrame(CoordinateFrame): + def __init__(self, num_axes, reference_position, units, projection=None, name=None, axes_names=None): + ##TODO: reference position + super(CartesianFrame, self).__init__(num_axes, ref_pos=reference_position, units=units, + axes_names=axes_names, name=name) + + def transform_to(self, other, *args): + #use affine transform + + + class DetectorFrame(CartesianFrame): + def __init__(self, reference_pixel, units=[u.pixel, u.pixel], name=None, reference_position="Local", + axes_names=None): + super(DetectorFrame, self).__init__(2, reference_position=reference_position, units=units, name=name, axes_names=axes_names) + self._reference_pixel = + A `CoordinateSystem` has one or more `CoordinateFrame` objects: @@ -133,8 +205,3 @@ A `CoordinateSystem` has one or more `CoordinateFrame` objects: else: raise ReferencePositionError - def _validate_ref_pos(self, frame): - """ - validates that the reference position is allowed for the frame - """ - return True diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index d374104..c57a6b9 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -1,25 +1,12 @@ WCS data model -------------- -Written by Nadia Dencheva (@nden) with ideas and feedback from -Perry Greenfield (@perrygrienfield) and Mike Droettboom (@mdboom) and taking into account -discussions at the latest astropy coordination meeting (Baltimore, 2012). - -This document describes the WCS data model. WCS serialization is not discussed here. - -Motivation for this work was discussed [previously](https://mail.google.com/mail/u/1/?ui=2&shva=1#search/perrygreenfield/13efbb0f6b4b3932). - -The basic requirements for the data model are: - -* Perform the transformation from pixels to world coordinates and back. -* Handle multiple transforms ( IFU detectors but not limited to that). - High level interface --------------------- Create a WCS object: - wcsobj = WCS(coordinate_system, transform) + wcsobj = WCS(transform, output_coordinate_system) Transform pixel coordinates to world coordinates: @@ -34,7 +21,7 @@ for example regions on detector but not limited to this. In this case: wcsobj(x,y) -should be able to transform the cordinates using the correct transform. +should be able to transform the coordinates using the correct transform. This is handled by the `SelectorModel` class. wcs_for_region_3 = wcsobj.select(label=3) @@ -44,13 +31,20 @@ returns the WCS object for region 3. If `transform` is an instance of `SelectorModel`, the `invert` method should map to the `invert()` methods of all individual transforms. -It should be possible to transform the output coordinates to a different coordinate system. The `~astropy.coordinates` package -is be used where possible. +It is possible to transform the output coordinates to a different coordinate system using other packages in astropy wcsobj.coordinate_system.to(ra, dec, other_system) +One can add additional coordinate systems and transformations between them + + wcsobj.add_transform(fromsys=self.input_coordinate_system, tosys=focal_plane, transform=pix2foc2) + +and later use them like this + + undistorted_coordinates = wcsobj.transform(fromsys=`detector`, tosys='focal_plane', x, y) + The special case of FITS WCS is handled through the `FITSWCS` class which inherits from `WCS` -and uses `pywcs` to create the coordinate system object and the transforms. +and uses the current `astropy.wcs` to create the coordinate system object and the transforms. fwcs = FITSWCS(fits_file, ext, key=' ') @@ -65,7 +59,11 @@ In more detail WCS API ------- - class WCS(object): +The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transfroms +between them. This allows one to specify multiple coordinate systems and the transformations between them. +(The [prototype](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/wcs.py) uses `networkx`.) + + class WCS(nx.DiGraph): """ WCS Data Model @@ -75,19 +73,56 @@ WCS API a callable which performs the transformation output_coordinate_system : astropy.wcs.CoordinateSystem + output system + input_coordinate_system : astropy.wcs.CoordinateSystem + input coordinate system + default is `wcs.DetectorFrame` """ - def __init__(self, transform, output_coordinate_system): + def __init__(self, transform, output_coordinate_system, input_coordinate_system=None): self.transform = transform self.output_coordinate_system = output_coordinate_system self.units = self.output_coordinate_system.units def select(self, label): + """ + If the transform is an instance of `SelectorModel` pick one of the available transforms + + Parameters + ---------- + label : int or str + + """ if isinstance(self.transform, SelectorModel): return self.transform[label] else: raise Error + def add_transform(self, fromsys, tosys, transform): + """ + Add new coordinate systems and transforms between them to this WCS + """ + ##TODO: check that name is unique + self.add_edge(fromsys, tosys, transform=transform) + + + def transform(self, fromsys, tosys, *args): + """ + Perform a transformation between any two systems registered with this WCS. + + Parameters + ---------- + fromsys : str + name of `fromsys` coordinate system + tosys : str + name of `tosys` coordinate system + """ + + @property + def coordinate_systems(self): + return self.nodes() + + def __call__(self, args): """ Performs the forward transformation pix --> world. @@ -101,6 +136,7 @@ WCS API except NotImplementedError: return self.transform.invert(*args) + FITS WCS uses `~astropy.wcs`. This takes advantage of knowledge about FITS specific keywords and parsing the FITS header. @@ -108,22 +144,25 @@ specific keywords and parsing the FITS header. """ Implements FITS WCS - Uses pywcs + Uses `astropy.wcs` Parameters ---------- fits_file : string or fits.HDUList object - ext : int extension number + key : str + alternate WCS key + """ - def __init__(self, fits_file, ext=0): + def __init__(self, fits_file, ext=0, key=""): """ Creates an `~astropy.wcs.WCS` object and uses its `all_pix2world` method as a transform. Also constructs a `CoordSystem` object from it. + If available, adds additional coordinate systems and transformations between them + based on `wcs.pix2foc` and similar methods. - regions mask is None in this case. """ def __call__(self, args): @@ -131,7 +170,7 @@ specific keywords and parsing the FITS header. The forward transform uses `all_pix2world` method of the object """ - def __invert(self, args): + def invert(self, args): """ The inverse transform uses the `all_sky2pix` method. """ From 8878e42fd2fcb7527f5494eeefe701777b992eb8 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 02:30:00 -0500 Subject: [PATCH 06/20] WIP --- generalized_wcs/wcs_api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index c57a6b9..7ffc604 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -1,4 +1,4 @@ -WCS data model +WCS data model - (WIP) -------------- High level interface From 2fa82bbbe2c0a9147cb3673061307aa39ec0eefb Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 03:41:48 -0500 Subject: [PATCH 07/20] correct typo --- generalized_wcs/wcs_api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 7ffc604..4ae6e6e 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -59,7 +59,7 @@ In more detail WCS API ------- -The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transfroms +The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transformations between them. This allows one to specify multiple coordinate systems and the transformations between them. (The [prototype](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/wcs.py) uses `networkx`.) From 72d7e9f77a2724e2bdc925d8846f392236b88757 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 13:17:58 -0500 Subject: [PATCH 08/20] Update wcs_api.md --- generalized_wcs/wcs_api.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 7ffc604..f643c38 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -1,6 +1,11 @@ WCS data model - (WIP) -------------- + +A [prototype](https://github.com/nden/code-experiments/tree/master/generalized_wcs_api/prototype) implementation and an +[example](https://github.com/nden/code-experiments/tree/master/generalized_wcs_api/prototype/jwst_example) of using this +proposal to construct JWST WCS. + High level interface --------------------- From 6605d140eb6ddbfd1715e3ebeb4ea27784eba85e Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 13:22:51 -0500 Subject: [PATCH 09/20] Update wcs_api.md --- generalized_wcs/wcs_api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index f643c38..6fe67fc 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -64,7 +64,7 @@ In more detail WCS API ------- -The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transfroms +The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transformations between them. This allows one to specify multiple coordinate systems and the transformations between them. (The [prototype](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/wcs.py) uses `networkx`.) From ca7c8484a69a10c30b756b5e384cfee787168307 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 14:09:28 -0500 Subject: [PATCH 10/20] Update wcs_api.md --- generalized_wcs/wcs_api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 6fe67fc..08dc230 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -6,8 +6,8 @@ A [prototype](https://github.com/nden/code-experiments/tree/master/generalized_w [example](https://github.com/nden/code-experiments/tree/master/generalized_wcs_api/prototype/jwst_example) of using this proposal to construct JWST WCS. -High level interface ---------------------- +User interface +-------------- Create a WCS object: From 9824aa61e57d979db774add403bc275345fd58bc Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 08:18:47 -0500 Subject: [PATCH 11/20] Update wcs_api.md --- generalized_wcs/wcs_api.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 08dc230..3d5b754 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -21,32 +21,37 @@ Transform from world coordinates to pixels: x, y = wcsobj.invert(ra, dec) -`transform` may be an instance of `SelectorModel` which maps transforms to other quantities, +`transform` may be an instance of [SelectorModel](https://github.com/nden/astropy-api/blob/generalized_wcs/generalized_wcs/selector.md) which maps transforms to other quantities, for example regions on detector but not limited to this. In this case: wcsobj(x,y) -should be able to transform the coordinates using the correct transform. +transforms the coordinates using the correct transform. This is handled by the `SelectorModel` class. - wcs_for_region_3 = wcsobj.select(label=3) +One can choose a specific transform, for example the transform for region 3 of an IFU: -returns the WCS object for region 3. + wcs_region_3 = wcsobj.select(label=3) -If `transform` is an instance of `SelectorModel`, the `invert` method should map to the `invert()` +If `transform` is an instance of `SelectorModel`, the `invert` method maps to the `invert()` methods of all individual transforms. It is possible to transform the output coordinates to a different coordinate system using other packages in astropy - wcsobj.coordinate_system.to(ra, dec, other_system) + wcsobj.output_coordinate_system.transform_to(ra, dec, other_system) One can add additional coordinate systems and transformations between them - wcsobj.add_transform(fromsys=self.input_coordinate_system, tosys=focal_plane, transform=pix2foc2) + focal = coordinate_systems.DetectorFrame(name="focal") + wcsobj.add_transform(fromsys=self.input_coordinate_system, tosys=focal, transform=pix2foc2) -and later use them like this +and later use their names to do a transformation - undistorted_coordinates = wcsobj.transform(fromsys=`detector`, tosys='focal_plane', x, y) + undistorted_coordinates = wcsobj.transform(fromsys=`detector`, tosys='focal', x, y) + +To see all coordinate systems defined by a WCS object: + + wcsobj.coordinate_systems The special case of FITS WCS is handled through the `FITSWCS` class which inherits from `WCS` and uses the current `astropy.wcs` to create the coordinate system object and the transforms. From 16b99b21039858b1ae1988f95f5a3e23ebf345ea Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 14:36:53 -0500 Subject: [PATCH 12/20] add examples --- generalized_wcs/design.md | 7 ++++ generalized_wcs/examples.md | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 generalized_wcs/design.md create mode 100644 generalized_wcs/examples.md diff --git a/generalized_wcs/design.md b/generalized_wcs/design.md new file mode 100644 index 0000000..af2ad6b --- /dev/null +++ b/generalized_wcs/design.md @@ -0,0 +1,7 @@ +The goal is to provide a framework for WCS transformations which is general and flexible enough that it is easy to extend by adding new transformations or coordinate classes. + +The WCS class is represented as a directed graph whose nodes are coordinate systems and edges are transformations +between them. This allows one to specify multiple coordinate systems and the transformations between them. +(The [prototype](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/wcs.py) uses [networkx](http://networkx.github.io).) + +Further advantage of this approach is that this can be extended by the transformations in the celestial coordinates package `astropy.coordinates` which is also represented by a graph and thus providing access to its claasses and transformations. diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md new file mode 100644 index 0000000..a7bdb4c --- /dev/null +++ b/generalized_wcs/examples.md @@ -0,0 +1,80 @@ +This contains examples of how an instrument scientist would use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization issues. + +Imaging WCS: + + class ImagingWCS(WCS): + def __init__(wcs_info, distortion_info): + dist = self.create_distortion_transformstion(distortion_info) + linear_trans = self.create_linear_wcs_transformation(wcs_info) + coord_sys = self.create_coordinate_system(wcs_info) + foc2sky = self.create_foc2sky(wcs_info) + trans = modeling.SerialCompositeModel([dist, linear_trans, foc2sky_trans]) + super(ImagingWCS, self).__init__(trans, coord_sys) + + def create_linear_wcs_transformation(self, wcs_info): + """Creates a composite transformation of a shift, rotation and scaling""" + return linear_trans + + def create_distortion_transformation(self, dist_info): + """ + Creates a distortion transformation. + + An example of a JSON representation. + """ + return dist_trans + + + def create_foc2sky(self, wcs_info): + """ Create a transformation from focal plane to sky - deprojection + celestial rotation""" + return foc2sky + + def create_coordinate_system(self, wcs_info): + """Construts an instance of wsc.CoordinateSystem""" + return coord_sys + + +Spectral WCS: + + class SpectralWCS(WCS): + + """ Example spec_info """ + + def __init__(self, spec_info): + trans = self.create_spectral_transform(spec_info) + coord_sys = self.create_coordinate_system(wcs_info) + super(SpectralWCS, self).__init__(trans, coord_sys) + + def create_coordinate_system(self, wcs_info): + """Construts an instance of wsc.CoordinateSystem""" + return coord_sys + + def create_spectral_transform(spec_info): + """ Constructs a transform from teh model(s) in sepc_info""" + return spec_model + +An examplel of a composite spectral transform + + class CompositeSpectralTransform(object): + + def __init__(self, wcs_info, spec_info, dist_info=None): + self.spatial_transform = ImagingTransform(wcs_info, dist_info) + self.spectral_transform = SpectralTransform(spec_info) + + def __call__(self, x, y): + alpha, delta = self.spatial_transform(x, y) + wave = self.spectral_transform(x) + return alpha, delta, wave + + +IFU Example: + + class IFUWCS(WCS): + """ Examples of JSON files """ + def __init__(self, regions_def, wcs_info, wcs_regions, spec_regions, dist_info): + trans = RegionsSelector(mask_shape, regions_def, wcs_info, wcs_regions, spec_regions, dist_info ) + coord_sys = self.create_coordinate_system(wcs_info) + super(IFUWCS, self).__init__(trans, coord_sys) + + def create_coordinate_system(self, wcs_info): + """Construts an instance of wsc.CoordinateSystem""" + return coord_sys \ No newline at end of file From c2c4ee980985f33f0bb35aaed22cf114f8f311da Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 09:42:37 -0500 Subject: [PATCH 13/20] Update examples.md --- generalized_wcs/examples.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md index a7bdb4c..83b46bb 100644 --- a/generalized_wcs/examples.md +++ b/generalized_wcs/examples.md @@ -1,8 +1,11 @@ -This contains examples of how an instrument scientist would use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization issues. - -Imaging WCS: - +ins examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization iCS: +) class ImagingWCS(WCS): + """ + An example [dist_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/distortion_image.json) JSON file. + wcs_info is a dict of basic FITS WCS keywords from the FITS header + + """ def __init__(wcs_info, distortion_info): dist = self.create_distortion_transformstion(distortion_info) linear_trans = self.create_linear_wcs_transformation(wcs_info) @@ -37,7 +40,7 @@ Spectral WCS: class SpectralWCS(WCS): - """ Example spec_info """ + """ Example [spec_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_wcs.json) """ def __init__(self, spec_info): trans = self.create_spectral_transform(spec_info) @@ -69,7 +72,14 @@ An examplel of a composite spectral transform IFU Example: class IFUWCS(WCS): - """ Examples of JSON files """ + """ + Examples of JSON reference files. + + [regions_def](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/regions_miri.json) + [wcs_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/wcs_regions.json) + [spec_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_regions.json) + + """ def __init__(self, regions_def, wcs_info, wcs_regions, spec_regions, dist_info): trans = RegionsSelector(mask_shape, regions_def, wcs_info, wcs_regions, spec_regions, dist_info ) coord_sys = self.create_coordinate_system(wcs_info) @@ -77,4 +87,4 @@ IFU Example: def create_coordinate_system(self, wcs_info): """Construts an instance of wsc.CoordinateSystem""" - return coord_sys \ No newline at end of file + return coord_sys From 49c51bbce57d91e13182c6f2d07d030fbdfd701d Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 09:43:24 -0500 Subject: [PATCH 14/20] Update examples.md --- generalized_wcs/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md index 83b46bb..453236d 100644 --- a/generalized_wcs/examples.md +++ b/generalized_wcs/examples.md @@ -1,4 +1,4 @@ -ins examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization iCS: +These are examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization iCS: ) class ImagingWCS(WCS): """ From 2056192d59ddde448fce6e6541ac8a87b78f4dcf Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 09:45:22 -0500 Subject: [PATCH 15/20] Update examples.md --- generalized_wcs/examples.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md index 453236d..039c1ef 100644 --- a/generalized_wcs/examples.md +++ b/generalized_wcs/examples.md @@ -1,5 +1,6 @@ -These are examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization iCS: -) +These are examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization issues.) + + class ImagingWCS(WCS): """ An example [dist_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/distortion_image.json) JSON file. From d4ae4ec3c1eea565d1880c0931b63d7a5233f525 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 09:53:32 -0500 Subject: [PATCH 16/20] Update examples.md --- generalized_wcs/examples.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md index 039c1ef..a57d7d3 100644 --- a/generalized_wcs/examples.md +++ b/generalized_wcs/examples.md @@ -1,9 +1,24 @@ -These are examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization issues.) +These are examples of how an instrument scientist can use the package to construct a WCS for an instrument. All examples assume the WCS information was already read in from somewhere (either a FITS header or a JSON file). This does not deal with WCS serialization issues. +JSON files used in the examples: + +[dist_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_regions.json) - coonstains models for distortion corrections + + +[spec_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_wcs.json) - contsains spectral models + + +[regions_def](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/regions_miri.json) - constains definitions of IFU regions as polygon vertices in pixel space + +[wcs_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/wcs_regions.json) - contains basic WCS for each IFU region as offsets from a primary region. The WCS for the primary region is in the FITS header + +[spec_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_regions.json) - contains spectral models for all regions + + + class ImagingWCS(WCS): """ - An example [dist_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/distortion_image.json) JSON file. wcs_info is a dict of basic FITS WCS keywords from the FITS header """ @@ -41,8 +56,6 @@ Spectral WCS: class SpectralWCS(WCS): - """ Example [spec_info](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_wcs.json) """ - def __init__(self, spec_info): trans = self.create_spectral_transform(spec_info) coord_sys = self.create_coordinate_system(wcs_info) @@ -73,16 +86,9 @@ An examplel of a composite spectral transform IFU Example: class IFUWCS(WCS): - """ - Examples of JSON reference files. - - [regions_def](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/regions_miri.json) - [wcs_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/wcs_regions.json) - [spec_regions](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/jwst_example/reference_files/spec_regions.json) - - """ + def __init__(self, regions_def, wcs_info, wcs_regions, spec_regions, dist_info): - trans = RegionsSelector(mask_shape, regions_def, wcs_info, wcs_regions, spec_regions, dist_info ) + trans = selector.RegionsSelector(mask_shape, regions_def, wcs_info, wcs_regions, spec_regions, dist_info ) coord_sys = self.create_coordinate_system(wcs_info) super(IFUWCS, self).__init__(trans, coord_sys) From f9bb445d6f31fdbefbfccd663618e7558f990a41 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Tue, 26 Nov 2013 15:04:10 -0500 Subject: [PATCH 17/20] Add README file --- generalized_wcs/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 generalized_wcs/README.md diff --git a/generalized_wcs/README.md b/generalized_wcs/README.md new file mode 100644 index 0000000..3552bfd --- /dev/null +++ b/generalized_wcs/README.md @@ -0,0 +1,11 @@ +Proposal for Generalized WCS. + +wcs_api.md contains the main class. + +coordinate_systems.md defines the coordinate systems. + +selector.md contains a definition of a SelectorModel (a subclass of `astropy.modeling.Model`, to be used when a WCS requires more than one transform based on a selection criteria, e.g. for IFUs. + +region_api.md explains the role of regions in WCS. + +example.md shows how an instrument scientist would use the API. \ No newline at end of file From 36f901197e2d382e48aefeb184256b320927bca8 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 10:02:26 -0500 Subject: [PATCH 18/20] Update README.md --- generalized_wcs/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generalized_wcs/README.md b/generalized_wcs/README.md index 3552bfd..0245ab4 100644 --- a/generalized_wcs/README.md +++ b/generalized_wcs/README.md @@ -1,11 +1,11 @@ -Proposal for Generalized WCS. +Proposal for a WCS package -wcs_api.md contains the main class. +*wcs_api.md* contains the main class. -coordinate_systems.md defines the coordinate systems. +*coordinate_systems.md* defines the coordinate systems. -selector.md contains a definition of a SelectorModel (a subclass of `astropy.modeling.Model`, to be used when a WCS requires more than one transform based on a selection criteria, e.g. for IFUs. +*selector.md* contains a definition of a SelectorModel (a subclass of `astropy.modeling.Model`, to be used when a WCS requires more than one transform based on a selection criteria, e.g. for IFUs. -region_api.md explains the role of regions in WCS. +*region_api.md* explains the role of regions in WCS. -example.md shows how an instrument scientist would use the API. \ No newline at end of file +*example.md* shows how an instrument scientist would use the API. From 6dd51acd703d8245956c50edc0ad38ed4bd684d6 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Wed, 27 Nov 2013 10:05:16 -0500 Subject: [PATCH 19/20] Update examples.md --- generalized_wcs/examples.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/generalized_wcs/examples.md b/generalized_wcs/examples.md index a57d7d3..eecffb5 100644 --- a/generalized_wcs/examples.md +++ b/generalized_wcs/examples.md @@ -93,5 +93,7 @@ IFU Example: super(IFUWCS, self).__init__(trans, coord_sys) def create_coordinate_system(self, wcs_info): - """Construts an instance of wsc.CoordinateSystem""" + """ + Construts an instance of wcs.CoordinateSystem which in this case is a composite systems of a SkyFrame and SpectralFrame. + """ return coord_sys From 680acb0ac90cd99a1a4a9ff114d2c6b6f7954a22 Mon Sep 17 00:00:00 2001 From: Nadia Dencheva Date: Fri, 29 Nov 2013 11:56:58 -0500 Subject: [PATCH 20/20] Update wcs_api.md --- generalized_wcs/wcs_api.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/generalized_wcs/wcs_api.md b/generalized_wcs/wcs_api.md index 3d5b754..e41d4bc 100644 --- a/generalized_wcs/wcs_api.md +++ b/generalized_wcs/wcs_api.md @@ -9,9 +9,15 @@ proposal to construct JWST WCS. User interface -------------- -Create a WCS object: +Create a WCS object which transforms from `input_coordinate_system` to `output_coordinate_system` using `transform`: - wcsobj = WCS(transform, output_coordinate_system) + wcsobj = WCS(transform, output_coordinate_system, input_coordinate_system) + +``input_cooridnate_system`` defaults to an instance of [DetectorFrame](https://github.com/nden/code-experiments/blob/master/generalized_wcs_api/prototype/coordinate_systems.py#L276) with units of `astropy.units.pixel`. To create a WCS which transforms from detector to sky coordinates: + + sky = coordinate_systems.SkyFrame('FK5', 'BARYCENTER', obstime, equinox, projection='TAN', + axes_names=['RA', 'DEC'], units=['deg', 'deg']) + wcsobj = WCS(transform, output_coordinate_system=sky, reference_pixel=CRPIX) Transform pixel coordinates to world coordinates: @@ -43,7 +49,7 @@ It is possible to transform the output coordinates to a different coordinate sys One can add additional coordinate systems and transformations between them focal = coordinate_systems.DetectorFrame(name="focal") - wcsobj.add_transform(fromsys=self.input_coordinate_system, tosys=focal, transform=pix2foc2) + wcsobj.add_transform(fromsys=self.input_coordinate_system, tosys=focal, transform=pix2foc) and later use their names to do a transformation @@ -116,7 +122,7 @@ between them. This allows one to specify multiple coordinate systems and the tra self.add_edge(fromsys, tosys, transform=transform) - def transform(self, fromsys, tosys, *args): + def transform_to(self, fromsys, tosys, *args): """ Perform a transformation between any two systems registered with this WCS.