casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Coordinates.h
Go to the documentation of this file.
00001 //# Coordinates.h : Classes to interconvert computation positions with physical
00002 //# Copyright (C) 1996,1997,1998,1999,2000,2001
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: Coordinates.h 20691 2009-07-14 03:13:54Z Malte.Marquarding $
00027 
00028 #ifndef COORDINATES_COORDINATES_H
00029 #define COORDINATES_COORDINATES_H
00030 
00031 //# Module includes
00032 #include <coordinates/Coordinates/Coordinate.h>
00033 #include <coordinates/Coordinates/CoordinateSystem.h>
00034 #include <coordinates/Coordinates/DirectionCoordinate.h>
00035 #include <coordinates/Coordinates/LinearCoordinate.h>
00036 #include <coordinates/Coordinates/LinearXform.h>
00037 #include <coordinates/Coordinates/Projection.h>
00038 #include <coordinates/Coordinates/SpectralCoordinate.h>
00039 #include <coordinates/Coordinates/StokesCoordinate.h>
00040 #include <coordinates/Coordinates/TabularCoordinate.h>
00041 #include <coordinates/Coordinates/CoordinateUtil.h>
00042 
00043 namespace casa { //# NAMESPACE CASA - BEGIN
00044 
00045 // <module>
00046 //
00047 // <summary>
00048 // Classes to interconvert pixel and world (physical) coordinates
00049 // </summary>
00050 
00051 // <prerequisite>
00052 //   <li> Knowledge of astronomical coordinate conversions in general. Probably the
00053 //        best documents are the papers by Mark Calabretta and Eric Greisen.
00054 //        The initial draft from 1996 can be found at 
00055 //        http://www.atnf.csiro.au/~mcalabre.  It is this draft that the
00056 //        Coordinate classes are based upon.  Since then, this paper has evolved 
00057 //        into three which can be found at the above address, and will be published in the
00058 //        Astronomy and Astrophysics Supplement Series (probably in 2000).
00059 //        The design has changed since the initial draft.  When these papers
00060 //        are finalized, and the IAU has ratified the new standards, WCSLIB
00061 //        (Mark Calabretta's implementation of these conventions) will be
00062 //        revised for the new designs.  At that time, the Coordinate classes
00063 //        may also be revised.
00064 //   <li> Generic AIPS++ classes; especially those in the 
00065 //        <linkto module=Arrays>Arrays</linkto> module.
00066 //   <li> The <linkto module=Measures>Measures</linkto> module.
00067 // </prerequisite>
00068 //
00069 
00070 // <reviewed reviewer="Peter Barnes" date="1999/12/24">
00071 // </reviewed>
00072 
00073 // <synopsis>
00074 // The primary notion is that a <linkto class=Coordinate>Coordinate</linkto>
00075 // can interconvert between a length "n" Vector<Double> (the
00076 // pixel coordinate) and a length "m" Vector<Double> (the
00077 // "world" coordinate). Note that "m" and "n" do not in 
00078 // principle have to be the same (so that one can get both the RA and DEC from
00079 // an image slice, for example), however in practice they currently always are.
00080 // Each Coordinate has the full mapping from pixel to world coordinates, i.e.
00081 // it has a reference value, reference pixel, increments, and an arbitrary
00082 // transformation matrix. To go from a pixel to a world coordinate the following
00083 // steps are applied:
00084 // <ol>
00085 //    <li> The reference pixel is subtracted from the pixel position.
00086 //    <li> The result is multiplied by the transformation matrix.
00087 //    <li> The result is multiplied by an increment per output axis to convert
00088 //         it into physical coordinates.
00089 //    <li> For some coordinate types (e.g., Direction), a non-linear function is
00090 //         applied to this result.
00091 // </ol>
00092 //
00093 // The classes are arranged as follows.  The base class is
00094 // <linkto class=Coordinate>Coordinate</linkto> which defines the
00095 // interface.  Classes derived from it are
00096 // <ol>
00097 //   <li> <linkto class=DirectionCoordinate>DirectionCoordinate</linkto> 
00098 //   <li> <linkto class=LinearCoordinate>LinearCoordinate</linkto> 
00099 //   <li> <linkto class=SpectralCoordinate>SpectralCoordinate</linkto> 
00100 //   <li> <linkto class=TabularCoordinate>TabularCoordinate</linkto> 
00101 //   <li> <linkto class=StokesCoordinate>StokesCoordinate</linkto> 
00102 //   <li> <linkto class=CoordinateSystem>CoordinateSystem</linkto> 
00103 // </ol>
00104 //
00105 // Other classes are <linkto class=Projection>Projection</linkto>  
00106 // which is used to specify an astronomical projection for 
00107 // DirectionCoordinates, and  <linkto class=LinearXform>LinearXform</linkto>  
00108 // a helper class which the application programmer  will not interact with.
00109 //
00110 // <linkto class=CoordinateSystem>CoordinateSystem</linkto> is
00111 // the class that application programmers will usually interact
00112 // with. A CoordinateSystem consists of a collection of the other 
00113 // classes derived from Coordinate.  Normally one group will be for
00114 // RA/DEC, another for a Stokes axis, and another group for the spectral axis.
00115 // The axes may be transposed arbitrarily, for example RA could be 
00116 // the first axis, and DEC the third. 
00117 //
00118 // Normally the CoordinateSystem being manipulated will be embedded in a PagedImage
00119 // or other object.    Note that the axes of the PagedImage do not
00120 // necessarily map directly to the axes in the CoordinateSystem.  Functionality
00121 // is provided to determine this mapping.
00122 //
00123 // One or more axes from the CoordinateSystem may be removed. Pixel axes and/or
00124 // world axes may be removed. You are encouraged to leave all the world axes
00125 // when you remove pixel axes.
00126 // <br>
00127 // If a world axis is removed, the corresponding pixel axis is also removed.
00128 // This means that one can be sure that a pixel axis always has a
00129 // corresponding world axis (it makes no sense otherwise).  The opposite is 
00130 // not necessarily true: a world axis can exist without a pixel axis.
00131 //
00132 // The linear transformation and sky projection computations are carried out in an
00133 // underlying library -- WCSLIB -- written by Mark Calabretta of the ATNF.
00134 //
00135 // </synopsis>
00136 //
00137 //
00138 // <note role=caution>
00139 // All pixels coordinates are zero relative.
00140 // </note>
00141 //
00142 // <example>
00143 // First, let's make a DirectionCoordinate --- used to represent a direction,
00144 // usually an RA/DEC, but it could also be, e.g., an AZ/EL pair.
00145 // <srcblock>
00146 //    Matrix<Double> xform(2,2);                                    // 1
00147 //    xform = 0.0; xform.diagonal() = 1.0;                          // 2
00148 //    Quantum<Double> refLon(135.0, "deg");
00149 //    Quantum<Double> refLat(60.0, "deg");
00150 //    Quantum<Double> incLon(-1.0, "deg");
00151 //    Quantum<Double> incLat(1.0, "deg");
00152 //    DirectionCoordinate radec(MDirection::J2000,                  // 3
00153 //                            Projection(Projection::SIN),          // 4
00154 //                            refLon, refLat,                       // 5
00155 //                            incLon, incLat,                       // 6
00156 //                            xform,                                // 7
00157 //                            128, 128);                            // 8
00158 // </srcblock>
00159 // <ul>
00160 //    <li> <i>1-2:</i>Here we set up a diagonal transformation matrix.
00161 //         Normally this matrix should be diagonal, however if you wanted
00162 //         to introduce a rotation or skew, you would do it through this
00163 //         matrix.
00164 //    <li> <i>3:</i>This defines the astronomical type of the world 
00165 //         coordinate. Most of the time it will probably be J2000
00166 //         or B1950, but there are many other possibilities as listed
00167 //         in the <linkto class=MDirection>MDirection</linkto> class
00168 //         header.
00169 //    <li> <i>4:</i>The <linkto class=Projection>Projection</linkto> class
00170 //         defines the "geometry" that is used to map <src>xy<-->world</src>. SIN
00171 //         is the most common projection for radio interferometers. Note that
00172 //         SIN can optionally take parameters as defined in Calabretta and Greisen.
00173 //         If not provided, they default to 0.0, which is the "old" SIN
00174 //         convention.
00175 //    <li> <i>5:</i>Set the reference position to RA=135, DEC=60 degrees.
00176 //         Note that the native units of a DirectionCoordinate is radians.
00177 //    <li> <i>6:</i> Set the increments to -1 degree in RA, and +1 degree
00178 //         in DEC.
00179 //    <li> <i>7:</i> Set the previously defined transformation matrix.
00180 //    <li> <i>8:</i> Set the zero-relative reference pixel. Note that it does
00181 //         not have to be incremental. At the reference pixel, the world 
00182 //         coordinate has the reference value.
00183 // </ul>
00184 //
00185 // Although we happeend to create our DirectionCoordinate with Quanta in degrees,
00186 // these have been converted to radians by the constructor.  We can set the native units
00187 // to degrees if we wish as follows:
00188 // <srcblock>
00189 //    Vector<String> units(2); units = "deg";                       //  9
00190 //    radec.setWorldAxisUnits(units);                               // 10
00191 // </srcblock>
00192 // The increment and reference value are updated appropriately.
00193 //
00194 // Set up a couple of vectors to use the world and pixel coordinate values.
00195 // <srcblock>
00196 //    Vector<Double> world(2), pixel(2);                            // 11
00197 //    pixel = 138.0;                                                // 12
00198 // </srcblock>
00199 // We use 138 as an abitrary pixel position which is near the reference pixel
00200 // so we can tell if the answers look foolish or not.
00201 //
00202 // We can actually perform a transformation like this as follows. If
00203 // it succeeds we print the value of the world coordinate.
00204 // <srcblock>
00205 //    Bool ok = radec.toWorld(world, pixel);                        // 13
00206 //    if (!ok) {                                                    // 14
00207 //      cout << "Error: " << radec.errorMessage() << endl;          // 15
00208 //      return 1;                                                   // 16
00209 //    }                                                             // 17
00210 //    cout << world << " <--- " << pixel << endl;         // 18
00211 // </srcblock>
00212 // There is an overloaded "toWorld" function that produces an MDirection
00213 // in case you want to, e.g., find out what the position in B1950 coordinates
00214 // would be.
00215 //
00216 // The reverse transformation takes place similarly:
00217 // <srcblock>
00218 //    ok = radec.toPixel(pixel, world);                             // 19
00219 // </srcblock>
00220 //
00221 // Suppose we have an image with a Stokes axis. It can be set up as follows:
00222 // <srcblock>
00223 //    Vector<Int> iquv(4);
00224 //    iquv(0) = Stokes::I; iquv(1) = Stokes::Q;                    // 21
00225 //    iquv(2) = Stokes::U; iquv(3) = Stokes::V;                    // 22
00226 //    StokesCoordinate stokes(iquv);                               // 23
00227 // </srcblock>
00228 // We create an integer array the same length as the Stokes axis, and place
00229 // the corresponding Stokes enum into each element of the array. The values
00230 // must be unique, e.g. there can only be one "I" plane.
00231 // Besides the generic <src>Vector<Double></src> toWorld/toPixel interface,
00232 // you can also directly interconvert between Stokes enum and and (zero-relative)
00233 // plane number:
00234 // <srcblock>
00235 //    Int plane;                                                   // 24
00236 //    ok = stokes.toPixel(plane, Stokes::Q);                       // 25
00237 // </srcblock>
00238 // Here it will return <src>True</src> and set plane to 1. On the other
00239 // hand, it would return <src>False</src> for:
00240 // <srcblock>
00241 //    ok = stokes.toPixel(plane, Stokes::XX);                      // 26
00242 // </srcblock>
00243 // since "XX" is not one of the Stokes enumerations we used to create this
00244 // coordinate.
00245 //
00246 // A Spectral ("frequency") coordinate may be created as follows:
00247 // <srcblock>
00248 //    SpectralCoordinate spectral(MFrequency::TOPO,               // 27
00249 //                                1.4E+9,                         // 28
00250 //                                2.0E+4,                         // 29
00251 //                                0,                              // 30
00252 //                                1420.40575E+6);                 // 31
00253 // </srcblock>
00254 // The default frequency units of a spectral coordinate are Hz, although they
00255 // may be changed to whatever is convenient. The first line (27) defines the
00256 // type of frequency we have -- topocentric here. The second (28) line
00257 // defines the frequency at the reference pixel, 0 (28) here. The channel
00258 // increment is defined on line 29. A rest frequency of the spectral may
00259 // be provided. It is useful in calculating doppler velocities. These calculations
00260 // are carried out by the <linkto class=MFrequency>MFrequency</linkto> and
00261 // <linkto class=MDoppler>MDoppler</linkto> classes of the Measures system.
00262 // </example>
00263 //
00264 // <motivation>
00265 // The primary motivation is to provide support for converting pixel locations in an
00266 // image to physical ("world") positions.
00267 // </motivation>
00268 
00269 // <todo asof="2000/01/01">
00270 // <li> Add measures interfaces that handle reference frame conversions
00271 // <li> offset coordinates
00272 // </todo>
00273 
00274 // </module>
00275 
00276 
00277 } //# NAMESPACE CASA - END
00278 
00279 #endif