casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
TwoSidedShape.h
Go to the documentation of this file.
00001 //# TwoSidedShape.h:
00002 //# Copyright (C) 1998,1999,2000,2002
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: TwoSidedShape.h 21130 2011-10-18 07:39:05Z gervandiepen $
00028 
00029 #ifndef COMPONENTS_TWOSIDEDSHAPE_H
00030 #define COMPONENTS_TWOSIDEDSHAPE_H
00031 
00032 #include <casa/aips.h>
00033 #include <components/ComponentModels/ComponentShape.h>
00034 #include <components/ComponentModels/ComponentType.h>
00035 #include <casa/BasicSL/Complex.h>
00036 #include <casa/Quanta/Unit.h>
00037 #include <casa/Quanta/Quantum.h>
00038 
00039 namespace casa { //# NAMESPACE CASA - BEGIN
00040 
00041 class DirectionCoordinate;
00042 class MDirection;
00043 class MVAngle;
00044 class RecordInterface;
00045 class String;
00046 template <class T> class Vector;
00047 
00048 // <summary>Base class for component shapes with two sides</summary>
00049 
00050 // <use visibility=export> 
00051 
00052 // <reviewed reviewer="" date="yyyy/mm/dd" tests="tTwoSidedShape" demos="dTwoSidedShape">
00053 // </reviewed>
00054 
00055 // <prerequisite>
00056 //   <li> <linkto class=ComponentShape>ComponentShape</linkto>
00057 //   <li> <linkto class=Quantum>Quantum</linkto>
00058 // </prerequisite>
00059 
00060 // <synopsis> 
00061 
00062 // This base class adds a common interface for component shapes that have two
00063 // sides. These shapes can be parameterised as having a major-axis width,
00064 // minor-axis width and a position angle (as well as the reference direction).
00065 // Currently there are two shapes which use this parameterisation, the 
00066 // <linkto class=GaussianShape>Gaussian</linkto> shape and the 
00067 // <linkto class=DiskShape>disk</linkto> shape. Shapes which do not have this
00068 // parameterisation, such as the <linkto class=PointShape>point</linkto> shape,
00069 // are derived directly from the 
00070 // <linkto class=ComponentShape>ComponentShape</linkto> class.
00071 
00072 // Functions in this class implement a more convenient way of setting the
00073 // parameters associated with two-sided shapes than the very flexible, but
00074 // clumsy, <src>parameters</src> functions. The width parameters can be set
00075 // using the <src>setWidth</src> functions. These functions enforce the rule
00076 // that the major-axis width must not be smaller than the minor-axis
00077 // width. Hence the axial ratio, which is the minor-axis width divided by the
00078 // major-axis width, must always be greater than zero and less than or equal to
00079 // one.
00080 
00081 // The functions in this class also free derived classes from the having to
00082 // deal with units. Any angular unit can be used to specify the width of the
00083 // shape. The widths returned by the majoraxis, minoraxis & the positionAngle
00084 // functions are in the same units as they where specified in, unless the
00085 // convertUnit function has been used to specify another unit.
00086 
00087 // For maximum speed the <src>*InRad</src> functions are provided. These
00088 // functions bypass all the computation involving units.
00089 
00090 // The toRecord and fromRecord functions in this class standardise the record
00091 // representation of classes derived from this one. In addition to the type and
00092 // direction fields all records, discussed in the 
00093 // <linkto class=ComponentShape>ComponentShape</linkto> class, there are three
00094 // more mandatory fields called; majoraxis, minoraxis & positionangle. These
00095 // fields are record representation of Quantum<Double> objects and hence
00096 // contain a value and unit. eg., A typical record for any of the shapes
00097 // derived from this class might be:
00098 // <srcblock>
00099 // c := [type = 'gaussian',
00100 //       direction = [type = 'direction',
00101 //                    refer = 'b1950',
00102 //                    m0 = [value = .1, unit = 'rad']
00103 //                    m1 = [value = -.1, unit = 'rad']
00104 //                   ],
00105 //       majoraxis = [value=.5, unit='arcmin'],
00106 //       minoraxis = [value=1, unit='arcsec'],
00107 //       positionangle = [value=10, unit='deg']
00108 //      ]
00109 // </srcblock>
00110 // </synopsis>
00111 //
00112 // <example>
00113 
00114 // Because this is an abstract base class, an actual instance of this class
00115 // cannot be constructed. However the interface it defines can be used inside a
00116 // function. This allows functions which have TwoSidedShapes as arguments to
00117 // work for any derived class. Hence the printShape function shown below will
00118 // work for GaussianShapes and DiskShapes but not for PointShapes.
00119 
00120 // In this example the printShape function prints out the type of model it is
00121 // working with, the reference direction of that model, the major-axis width,
00122 // minor-axis width and the position angle. This example is also available in
00123 // the <src>dTwoSidedShape.cc</src> file.
00124 // <srcblock>
00125 //  void printShape(const TwoSidedShape& theShape) {
00126 //    cout << "This is a " << ComponentType::name(theShape.type())
00127 //         << " shape " << endl 
00128 //         << "with a reference direction of "
00129 //         << theShape.refDirection().getAngle("deg") << " ("
00130 //         << theShape.refDirection().getRefString() << ")" << endl
00131 //         << "and a major axis of " << theShape.majorAxis() << endl
00132 //         << "      minor axis of " << theShape.minorAxis() << endl
00133 //         << "and   position angle of " << theShape.positionAngle() << endl;
00134 //  }
00135 // </srcblock>
00136 // </example>
00137 //
00138 
00139 // <motivation>
00140 // This base class was created to allow the reuse of a number of common
00141 // functions by all derived classes.
00142 // </motivation>
00143 
00144 // <todo asof="1999/110/12">
00145 //   <li> Use Measures & Quanta in the interface to the visibility functions.
00146 // </todo>
00147 
00148 // <linkfrom anchor="TwoSidedShape" classes="ComponentShape">
00149 //  <here>TwoSidedShape</here> - a base class for shapes with two sides
00150 // </linkfrom>
00151 
00152 class TwoSidedShape: public ComponentShape
00153 {
00154 public:
00155 
00156   // a virtual destructor is needed so that the actual destructor in the
00157   // derived class will be used.
00158   virtual ~TwoSidedShape();
00159 
00160   // return the actual component type.
00161   virtual ComponentType::Shape type() const = 0;
00162 
00163   // set/get the width and orientation of the Shape. The width of the major
00164   // must be larger than the width of the minor axes. The position angle is
00165   // measured North through East ie a position angle of zero degrees means
00166   // that the major axis is North-South and a position angle of 10 degrees
00167   // moves the Northern edge to the East. The axial ratio is the ratio of the
00168   // minor to major axes widths. Hence it is always between zero and one.
00169   // <group>
00170   void setWidth(const Quantum<Double>& majorAxis,
00171                 const Quantum<Double>& minorAxis, 
00172                 const Quantum<Double>& positionAngle);
00173   void setWidth(const Quantum<Double>& majorAxis,
00174                 const Double axialRatio, 
00175                 const Quantum<Double>& positionAngle);
00176   Quantum<Double> majorAxis() const;
00177   Quantum<Double> minorAxis() const;
00178   Quantum<Double> positionAngle() const;
00179   Double axialRatio() const;
00180   // </group>
00181 
00182   // set/get the errors on the shape parameters. 
00183   // <group>
00184   void setErrors(const Quantum<Double>& majorAxisError,
00185                  const Quantum<Double>& minorAxisError, 
00186                  const Quantum<Double>& positionAngleError);
00187   const Quantum<Double>& majorAxisError() const;
00188   const Quantum<Double>& minorAxisError() const;
00189   const Quantum<Double>& positionAngleError() const;
00190   Double axialRatioError() const;
00191   // </group>
00192 
00193   // set/get the width and orientation of the Shape. These are the same as the
00194   // above functions except that all widths are in radians.
00195   // <group>
00196   virtual void setWidthInRad(const Double majorAxis,
00197                              const Double minorAxis, 
00198                              const Double positionAngle) = 0;
00199   virtual Double majorAxisInRad() const = 0;
00200   virtual Double minorAxisInRad() const = 0;
00201   virtual Double positionAngleInRad() const = 0;
00202   // </group>
00203 
00204   // Calculate the proportion of the flux that is in a pixel of specified size
00205   // centered in the specified direction. The returned value will always be
00206   // between zero and one (inclusive).
00207   virtual Double sample(const MDirection& direction, 
00208                         const MVAngle& pixelLatSize,
00209                         const MVAngle& pixelLongSize) const = 0;
00210 
00211   // Same as the previous function except that many directions can be sampled
00212   // at once. The reference frame and pixel size must be the same for all the
00213   // specified directions. A default implementation of this function is
00214   // available that uses the single pixel sample function described above.
00215   // However customised versions of this function will be more efficient as
00216   // intermediate values only need to be computed once.
00217   virtual void sample(Vector<Double>& scale, 
00218                       const Vector<MDirection::MVType>& directions, 
00219                       const MDirection::Ref& refFrame,
00220                       const MVAngle& pixelLatSize,
00221                       const MVAngle& pixelLongSize) const = 0;
00222 
00223   // Return the Fourier transform of the component at the specified point in
00224   // the spatial frequency domain. The point is specified by a 3-element vector
00225   // (u,v,w) that has units of meters and the frequency of the observation, in
00226   // Hertz. These two quantities can be used to derive the required spatial
00227   // frequency <src>(s = uvw*freq/c)</src>. The w component is not used in
00228   // these functions.  The scale factor returned by this function can be used
00229   // to scale the flux at the origin of the Fourier plane in order to determine
00230   // the visibility at the specified point.
00231 
00232   // The "origin" of the transform is the reference direction of the
00233   // component. This means for symmetric components, where the reference
00234   // direction is at the centre, that the Fourier transform will always be
00235   // real.
00236   virtual DComplex visibility(const Vector<Double>& uvw,
00237                               const Double& frequency) const = 0;
00238 
00239   // Same as the previous function except that many (u,v,w) points can be
00240   // sampled at once. The observation frequency is the same for all the
00241   // specified points. The uvw Matrix must have first dimension of three and
00242   // the second dimension must match the length of the scale vector. A default
00243   // implementation of this function is available that uses the single point
00244   // visibility function described above.  However customised versions of this
00245   // function may be more efficient as intermediate values only need to be
00246   // computed once.
00247   virtual void visibility(Vector<DComplex>& scale, const Matrix<Double>& uvw,
00248                           const Double& frequency) const = 0;
00249 
00250   // same as above but with many frequencies
00251  virtual void visibility(Matrix<DComplex>& scale, const Matrix<Double>& uvw,
00252                           const Vector<Double>& frequency) const = 0; 
00253 
00254   // determine whether the shape is symmetric or not. Always returns True.
00255   virtual Bool isSymmetric() const;
00256 
00257   // Return a pointer to a copy of this object upcast to a ComponentShape
00258   // object. The class that uses this function is responsible for deleting the
00259   // pointer. This is used to implement a virtual copy constructor.
00260   virtual ComponentShape* clone() const = 0;
00261 
00262   // set/get the shape parameters associated with this shape. There are always
00263   // three these being in order: the major-axis, the minor-axis and the
00264   // position angle. All these angular quantities are specified and returned in
00265   // radians. The Vector supplied to the <src>setParameters</src> and
00266   // <src>setErrors</src> functions must have three elements and the Vector
00267   // returned by the <src>parameters</src> and <src>errors</src> functions will
00268   // have three elements. The errors are nominally 1-sigma in an implicit
00269   // Gaussian distribution.
00270   // <group>
00271   virtual uInt nParameters() const;
00272   virtual void setParameters(const Vector<Double>& newParms);
00273   virtual Vector<Double> parameters() const;
00274   virtual void setErrors(const Vector<Double>& newParms);
00275   virtual Vector<Double> errors() const;
00276   virtual Vector<Double> optParameters() const;
00277   virtual void setOptParameters(const Vector<Double>& newOptParms);
00278   // </group>
00279 
00280   // This functions convert between a Record and a shape derived from this
00281   // class. These functions define how the object is represented in glish and
00282   // this is detailed in the synopsis above.  They return False if the record
00283   // is malformed and append an error message to the supplied string giving the
00284   // reason.
00285   // <group>
00286   virtual Bool fromRecord(String& errorMessage,
00287                           const RecordInterface& record);
00288   virtual Bool toRecord(String& errorMessage,
00289                         RecordInterface& record) const;
00290   // </group>
00291 
00292   // Convert the parameters of the component to the specified units. The
00293   // supplied record must have three fields, namely 'majoraxis', 'minoraxis' &
00294   // 'positionangle'. These fields must contains strings that are angular units
00295   // and this function will convert the corresponding parameters to the
00296   // specified units. This will have no effect on the shape of this class but
00297   // will affect the format of the record returned by the toRecord function,
00298   // and the units used in the the Quanta returned by the majoraxis, minoraxis
00299   // & positionangle functions.
00300   virtual Bool convertUnit(String& errorMessage,
00301                            const RecordInterface& record);
00302 
00303   // Function which checks the internal data of this class for correct
00304   // dimensionality and consistent values. Returns True if everything is fine
00305   // otherwise returns False.
00306   virtual Bool ok() const;
00307 
00308   // Convert component shape to absolute pixels (longitude, latitude, major axis, 
00309   // minor axis, position angle [positive +x -> +y ; rad])
00310   virtual Vector<Double> toPixel (const DirectionCoordinate& dirCoord) const;
00311 
00312   // Fill the shape from the vector (longitude, latitude, major axis, 
00313   // minor axis, position angle [positive +x -> +y ; rad]).  The return
00314   // is True if the input major axis (in pixels) became the minor 
00315   // axis (in world coordinates), else False.
00316   virtual Bool fromPixel (const Vector<Double>& parameters,
00317                           const DirectionCoordinate& dirCoord);
00318 
00319   // Get the string containing the various size quantities of a component.
00320   virtual String sizeToString() const = 0;
00321 
00322   // Format the string containing the various size quantities of a component.
00323   static String sizeToString(
00324         Quantity major, Quantity minor, Quantity posangle,
00325         Bool includeUncertainties = True, Quantity majorErr = 0,
00326         Quantity minorErr = 0, Quantity posanErr = 0);
00327 
00328 protected:
00329   // The constructors and assignment operator are protected as only derived
00330   // classes should use them.
00331   // <group>
00332   //# The default TwoSidedShape is at the J2000 North Pole.
00333   TwoSidedShape();
00334 
00335   //# Construct a TwoSidedShape at the specified direction, and return all all
00336   //# widths using the specified units.
00337   TwoSidedShape(const MDirection& direction, const Unit& majorAxisUnit, const
00338                 Unit& minorAxisUnit, const Unit& paUnit);
00339 
00340   //# The copy constructor uses copy semantics.
00341   TwoSidedShape(const TwoSidedShape& other);
00342 
00343   //# The assignment operator uses copy semantics.
00344   TwoSidedShape& operator=(const TwoSidedShape& other);
00345   // </group>
00346 
00347 private:
00348   Unit itsMajUnit;
00349   Unit itsMinUnit;
00350   Unit itsPaUnit;
00351   Quantum<Double> itsMajErr;
00352   Quantum<Double> itsMinErr;
00353   Quantum<Double> itsPaErr;
00354 //
00355   Vector<Double> widthToCartesian (const Quantum<Double>& width,
00356                                    const Quantum<Double>& pa, 
00357                                    const MDirection& dirRef,
00358                                    const DirectionCoordinate& dirCoord,
00359                                    const Vector<Double>& pixelCen) const;
00360 //
00361   MDirection directionFromCartesian (Double width, Double pa,
00362                                      const DirectionCoordinate& dirCoord,
00363                                      const Vector<Double>& pixelCen) const;
00364 
00365 };
00366 
00367 } //# NAMESPACE CASA - END
00368 
00369 #endif