casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
TabularCoordinate.h
Go to the documentation of this file.
00001 //# TabularCoordinate.h: Table lookup 1-D coordinate, with interpolation
00002 //# Copyright (C) 1997,1998,1999,2000,2001,2003,2004
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 //#
00027 //# $Id: TabularCoordinate.h 18823 2005-07-07 20:36:33Z ddebonis $
00028 
00029 
00030 #ifndef COORDINATES_TABULARCOORDINATE_H
00031 #define COORDINATES_TABULARCOORDINATE_H
00032 
00033 #include <casa/aips.h>
00034 #include <casa/Arrays/ArrayMath.h>
00035 #include <casa/Arrays/Vector.h>
00036 #include <coordinates/Coordinates/Coordinate.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 template<class Domain, class Range> class Interpolate1D;
00041 template<class T> class Quantum;
00042 class LogIO;
00043 
00044 
00045 
00046 // <summary>
00047 // Table lookup 1-D coordinate, with interpolation.
00048 // </summary>
00049 
00050 // <use visibility=export>
00051 
00052 // <reviewed reviewer="Peter Barnes" date="1999/12/24" tests="tTabularCoordinate">
00053 // </reviewed>
00054 
00055 // <prerequisite>
00056 //   <li> <linkto class=Coordinate>Coordinate</linkto>
00057 // </prerequisite>
00058 //
00059 // <synopsis>
00060 // This class is used where the world and pixel values are determined by a
00061 // lookup table. For fractional pixel values, a linear interpolation is used. 
00062 // The values returned for, e.g., the increment, are based on 
00063 // the average of the whole table.  At present,
00064 // the values must either increase or decrease monotonically.
00065 // </synopsis>
00066 //
00067 // <note role=caution>
00068 // All pixels coordinates are zero relative.
00069 // </note>
00070 //
00071 // <example>
00072 // Let's make a non-linear TabularCoordinate  and convert a pixel
00073 // value to world (which will use linear interpolation)
00074 // <srcblock>
00075 //    Vector<Double> pixelValues(3); 
00076 //    Vector<Double> worldValues(3); 
00077 //    pixelValues(0) = 122.0;
00078 //    pixelValues(1) = 300.0;
00079 //    pixelValues(2) = 6524.0;
00080 //    worldValues(0) = 1.1e6;
00081 //    worldValues(1) = 2.1e6;
00082 //    worldValues(2) = 2.2e6;
00083 //
00084 //    String unit("km");
00085 //    String axisName("length");
00086 //
00087 //    TabularCoordinate tc(pixelValues, worldValues, unit, axisName);
00088 //
00089 //    Double world, pixel;
00090 //    pixel = 200.12;
00091 //    if (!tc.toWorld(world, pixel)) {
00092 //      cerr << "Error : " << tc.errorMessage() << endl;
00093 //    } else {
00094 //      cerr << "pixel, world = " << pixel << ", " << world << endl;
00095 //    }
00096 // </srcblock>
00097 // </example>
00098 //
00099 // <motivation>
00100 // This class was motivated by the need for an irregular axis, such as a collection
00101 // of frequencies.    For example, the SpectralCoordinate class contains a TabularCoordinate.
00102 // </motivation>
00103 //
00104 //
00105 // <thrown>
00106 //   <li>  AipsError
00107 // </thrown>
00108 //
00109 // <todo asof="1997/07/12">
00110 // <li> Allow interpolations other than linear.
00111 // </todo>
00112 
00113 
00114 class TabularCoordinate : public Coordinate
00115 {
00116 public:
00117     // Default constructor.  It is equivalent to 
00118     // TabularCoordinate(0,1,0, "", "Tabular");
00119     TabularCoordinate();
00120 
00121     // Create a linear TabularCoordinate where 
00122     // <src>world = refval + inc*(pixel-refpix)</src>
00123     TabularCoordinate(Double refval, Double inc, Double refpix,
00124                       const String &unit, const String &axisName);
00125 
00126     // Create a linear TabularCoordinate with a Quantum-based interface where 
00127     // <src>world = refval + inc*(pixel-refpix)</src>.  The units of the 
00128     // increment (<src>inc</src>) will be converted to
00129     // those of the reference value (<src>refVal</src>) which will
00130     // then serve as the units of the Coordinate.
00131     TabularCoordinate(const Quantum<Double>& refval, 
00132                       const Quantum<Double>& inc, 
00133                       Double refpix, const String& axisName);
00134 
00135     // Construct a TabularCoordinate with the specified world values. The
00136     // increments and related functions return the average values
00137     // calculated from the first and last world values. The number of pixel
00138     // and world values must be the same. Normally the pixel values will be
00139     // 0,1,2,..., but this is not required.
00140     //
00141     // A linear interpolation/extrapolation is used for channels which are not
00142     // supplied. The reference channel (pixel) is chosen to be 0.  The
00143     // frequencies must increase or decrease monotonically (otherwise the
00144     // toPixel lookup would not be possible).
00145     TabularCoordinate(const Vector<Double> &pixelValues,
00146                       const Vector<Double> &worldValues,
00147                       const String &unit, const String &axisName);
00148 
00149     // Construct a TabularCoordinate with the specified world values
00150     // via the Quantum-based interface.  All comments for the
00151     // previous constructor apply
00152     TabularCoordinate(const Vector<Double>& pixelValues,
00153                       const Quantum<Vector<Double> >& worldValues,
00154                       const String &axisName);
00155 
00156     // Copy constructor (copy semantics).
00157     TabularCoordinate(const TabularCoordinate &other);
00158 
00159     // Assignment (copy semantics).
00160     TabularCoordinate &operator=(const TabularCoordinate &other);
00161 
00162     // Destructor.
00163     virtual ~TabularCoordinate();
00164 
00165     // Returns Coordinate::TABULAR.
00166     virtual Coordinate::Type type() const;
00167 
00168     // Always returns the String "Tabular".
00169     virtual String showType() const;
00170 
00171     // Always returns 1.
00172     // <group>
00173     virtual uInt nPixelAxes() const;
00174     virtual uInt nWorldAxes() const;
00175     // </group>
00176 
00177     // Convert a pixel position to a world position or vice versa. Returns True
00178     // if the conversion succeeds, otherwise it returns False and method
00179     // errorMessage contains an error message.  The output
00180     // vectors are appropriately resized.
00181     // <group>
00182     virtual Bool toWorld(Vector<Double> &world, 
00183                          const Vector<Double> &pixel) const;
00184     virtual Bool toPixel(Vector<Double> &pixel, 
00185                          const Vector<Double> &world) const;
00186     Bool toWorld(Double &world, Double pixel) const;
00187     Bool toPixel(Double &pixel, Double world) const;
00188     // </group>
00189 
00190     // Batch up a lot of transformations. The first (most rapidly varying) axis
00191     // of the matrices contain the coordinates. Returns False if any conversion
00192     // failed  and  <src>errorMessage()</src> will hold a message.
00193     // The <src>failures</src> array (True for fail, False for success)
00194     // is the length of the number of conversions and
00195     // holds an error status for each conversion.  
00196     // <group>
00197     virtual Bool toWorldMany(Matrix<Double> &world,
00198                              const Matrix<Double> &pixel,
00199                              Vector<Bool>& failures) const;
00200     virtual Bool toPixelMany(Matrix<Double>& pixel,
00201                              const Matrix<Double>& world,
00202                              Vector<Bool>& failures) const;
00203     // </group>
00204 
00205 
00206     // Make absolute coordinates relative and vice-versa (with
00207     // respect to the referencfe value).
00208     // Vectors must be length <src>nPixelAxes()</src> or
00209     // <src>nWorldAxes()</src> or memory access errors will occur
00210     // <group>
00211     virtual void makePixelRelative (Vector<Double>& pixel) const {pixel -= crpix_p;};
00212     virtual void makePixelAbsolute (Vector<Double>& pixel) const {pixel += crpix_p;};
00213     virtual void makeWorldRelative (Vector<Double>& world) const {world -= crval_p;};
00214     virtual void makeWorldAbsolute (Vector<Double>& world) const {world += crval_p;};
00215     // </group>
00216 
00217     // Return the requested attribute.
00218     // <group>
00219     virtual Vector<String> worldAxisNames() const;
00220     virtual Vector<Double> referencePixel() const;
00221     virtual Matrix<Double> linearTransform() const;
00222     virtual Vector<Double> increment() const;
00223     virtual Vector<Double> referenceValue() const;
00224     // </group>
00225 
00226     // Set the value of the requested attribute.  Note that these just
00227     // change the internal values, they do not cause any recomputation.
00228     // <group>
00229     virtual Bool setWorldAxisNames(const Vector<String> &names);
00230     virtual Bool setReferencePixel(const Vector<Double> &refPix);
00231     virtual Bool setLinearTransform(const Matrix<Double> &xform);
00232     virtual Bool setIncrement(const Vector<Double> &inc) ;
00233     virtual Bool setReferenceValue(const Vector<Double> &refval);
00234     // </group>
00235 
00236     // Set/get the axis unit. Adjust the increment and
00237     // reference value by the ratio of the old and new units.
00238     // The unit must be compatible with the current units.
00239     // <group>
00240     virtual Bool setWorldAxisUnits(const Vector<String> &units);
00241     virtual Vector<String> worldAxisUnits() const;
00242     // </group>
00243 
00244     // Overwrite the world axis units with no compatibility
00245     // checks or adjustment.
00246     Bool overwriteWorldAxisUnits(const Vector<String> &units);
00247 
00248     // Get the table, i.e. the pixel and world values. The length of these
00249     // Vectors will be zero if this axis is pure linear.
00250     // <group>
00251     Vector<Double> pixelValues() const;
00252     Vector<Double> worldValues() const;
00253     // </group>
00254 
00255     // Comparison function. Any private Double data members are compared    
00256     // with the specified fractional tolerance.  Don't compare on the specified     
00257     // axes in the Coordinate.  If the comparison returns False, method
00258     // errorMessage() contains a message about why.
00259     // <group>
00260     virtual Bool near(const Coordinate& other, 
00261                       Double tol=1e-6) const;
00262     virtual Bool near(const Coordinate& other, 
00263                       const Vector<Int>& excludeAxes,
00264                       Double tol=1e-6) const;
00265     // </group>
00266 
00267     // Find the Coordinate for when we Fourier Transform ourselves.  This pointer
00268     // must be deleted by the caller. Axes specifies which axes of the Coordinate
00269     // you wish to transform.   Shape specifies the shape of the image
00270     // associated with all the axes of the Coordinate.   Currently the
00271     // output reference pixel is always shape/2. If the pointer returned is 0, 
00272     // it failed with a message in <src>errorMessage</src>
00273     virtual Coordinate* makeFourierCoordinate (const Vector<Bool>& axes,
00274                                                const Vector<Int>& shape) const;
00275 
00276     // Save the TabularCoordinate into the supplied record using the supplied field name.
00277     // The field must not exist, otherwise <src>False</src> is returned.
00278     virtual Bool save(RecordInterface &container, const String &fieldName) const;
00279 
00280     // Recover the TabularCoordinate from a record.
00281     // A null pointer means that the restoration did not succeed - probably 
00282     // because fieldName doesn't exist or doesn't contain a CoordinateSystem.
00283     static TabularCoordinate *restore(const RecordInterface &container,
00284                                    const String &fieldName);
00285 
00286     // Make a copy of the TabularCoordinate using new. The caller is responsible for calling
00287     // delete.
00288     virtual Coordinate *clone() const;
00289 
00290 private:
00291     Double crval_p, cdelt_p, crpix_p;
00292     Double matrix_p;
00293     String unit_p;
00294     String name_p;
00295 
00296     // Channel_True = channel_corrections_p(Channel_average).
00297     // <group>
00298     Interpolate1D<Double,Double> *channel_corrector_p;
00299     Interpolate1D<Double,Double> *channel_corrector_rev_p;
00300     // </group>
00301 
00302     // Common for assignment operator and destructor.
00303     void clear_self();
00304 
00305     // Common code for copy ctor and assignment operator.
00306     void copy(const TabularCoordinate &other);
00307 
00308     void makeNonLinearTabularCoordinate(const Vector<Double> &pixelValues,
00309                                         const Vector<Double> &worldValues);
00310 };
00311 
00312 } //# NAMESPACE CASA - END
00313 
00314 
00315 #endif