casa
$Rev:20696$
|
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