//# ComponentShape.h: Base class for component shapes //# Copyright (C) 1998,1999,2000,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: ComponentShape.h 21130 2011-10-18 07:39:05Z gervandiepen $ #ifndef COMPONENTS_COMPONENTSHAPE_H #define COMPONENTS_COMPONENTSHAPE_H #include <casacore/casa/aips.h> #include <casacore/casa/BasicSL/Complexfwd.h> #include <casacore/measures/Measures/MDirection.h> #include <casacore/casa/Quanta/Quantum.h> #include <casacore/casa/Utilities/RecordTransformable.h> #include <components/ComponentModels/ComponentType.h> #include <casacore/casa/Arrays/ArrayFwd.h> namespace casacore{ class DirectionCoordinate; class MVAngle; class RecordInterface; class String; template <class T> class MeasRef; } namespace casa { //# NAMESPACE CASA - BEGIN // <summary>Base class for component shapes</summary> // <use visibility=export> // <reviewed reviewer="" date="yyyy/mm/dd" tests="tComponentShape" demos="dPointShape"> // </reviewed> // <prerequisite> // <li> <linkto class=casacore::MDirection>MDirection</linkto> // </prerequisite> // // <synopsis> // This abstract base class defines the interface for classes which // define the shape of a component. The most fundamental derived class is the // <linkto class=PointShape>point</linkto> shape class but the // <linkto class=GaussianShape>Gaussian</linkto> shape, // <linkto class=DiskShape>disk</linkto> shape and // <linkto class=LimbDarkenedDiskShape>limbdarkeneddisk classes are also // available. These classes model the spatial distribution of emission from the // sky. // Classes derived from the <linkto class=SpectralModel>SpectralModel</linkto> // class are used to model the spectral characteristics and the // <linkto class=Flux>Flux</linkto> class is used to model the flux. The // <linkto class=SkyComponent>SkyComponent</linkto> class incorporates these // three characteristics (flux, shape & spectrum) and the // <linkto class=ComponentList>ComponentList</linkto> class handles groups of // SkyComponent objects. // This base class parameterises shapes with two quantities. // <dl> // <dt><em> A reference direction.</em> // <dd> This is specified using an <linkto class=casacore::MDirection>MDirection</linkto> // object and indicates the direction on a defined reference point // within the shape. Usually this reference point is the centre of the // shape. // <dt> <em>A casacore::Vector of parameters.</em> // <dd> This contains other parameters that the are defined differently for // different shapes. The length of the vector may vary for different // component shapes. // </dl> // // The basic operation of classes using this interface is to model the flux as // a function of direction on the sky. Classes derived from this one do not // know what the flux of the component. Instead the sample and visibility // functions return factors that are used to scale the flux and calculate the // amount of flux at a specified point on the sky or on the (u,v) plane. // Any allowed direction reference frame can be used. However the reference // frame must be adequately specified in order to allow conversions to other // reference frames. For example if the reference frame code for a component is // casacore::MDirection::AZEL then the reference frame must also contain the time and // position, on the earth, that the specified azimuth and elevation to refer // to. This way the sample functions can convert the direction to a value in // the J2000 reference frame (if you specify the sample direction in the J2000 // frame). // </synopsis> // <example> // Because this is an abstract base class, an actual instance of this class // cannot be constructed. However the interface it defines can be used inside a // function. This is always recommended as it allows functions which have // ComponentShapes as arguments to work for any derived class. // In this example the printShape function prints out the type of model it is // working with and the reference direction of that model. This example is also // available in the <src>dPointShape.cc</src> file. // <srcblock> // void printShape(const ComponentShape& theShape) { // cout << "This is a " << ComponentType::name(theShape.type()) // << " shape " << endl // << "with a reference direction of " // << theShape.refDirection() << endl; // } // </srcblock> // </example> // <motivation> // The Shape base class was split from the SkyCompRep base class so that mixing // components with different spatial and spectral shapes did not result in a // combinatorial explosion in the number of classes required. // </motivation> // // <todo asof="1999/11/11"> // <li> Use Measures & Quanta in the interface to the visibility functions. // </todo> class ComponentShape: public casacore::RecordTransformable { public: // a virtual destructor is needed so that the actual destructor in the // derived class will be used. virtual ~ComponentShape(); // return the actual shape. The ident function returns it as a String. // <group> virtual ComponentType::Shape type() const = 0; virtual const casacore::String& ident() const; // </group> // set/get the reference direction // <group> void setRefDirection(const casacore::MDirection& newRefDir); const casacore::MDirection& refDirection() const; // </group> // set/get the error in the reference direction. Values must be positive // angular quantities otherwise an casacore::AipsError exception is thrown. The errors // are usually interpreted as the 1-sigma bounds in latitude/longitude and // implicitly assume a Gaussian distribution. // <group> void setRefDirectionError(const casacore::Quantum<casacore::Double>& newRefDirErrLat, const casacore::Quantum<casacore::Double>& newRefDirErrLong); const casacore::Quantum<casacore::Double>& refDirectionErrorLat() const; const casacore::Quantum<casacore::Double>& refDirectionErrorLong() const; // </group> // copy direction info from that object to this object void copyDirectionInfo(const ComponentShape& that); // Calculate the proportion of the flux that is in a pixel of specified size // centered in the specified direction. The returned value will always be // between zero and one (inclusive). virtual casacore::Double sample(const casacore::MDirection& direction, const casacore::MVAngle& pixelLatSize, const casacore::MVAngle& pixelLongSize) const = 0; // Same as the previous function except that many directions can be sampled // at once. The reference frame and pixel size must be the same for all the // specified directions. A default implementation of this function is // available that uses the single pixel sample function described above. // However customised versions of this function will be more efficient as // intermediate values only need to be computed once. virtual void sample(casacore::Vector<casacore::Double>& scale, const casacore::Vector<casacore::MDirection::MVType>& directions, const casacore::MDirection::Ref& refFrame, const casacore::MVAngle& pixelLatSize, const casacore::MVAngle& pixelLongSize) const = 0; // Return the Fourier transform of the component at the specified point in // the spatial frequency domain. The point is specified by a 3-element vector // (u,v,w) that has units of meters and the frequency of the observation, in // Hertz. These two quantities can be used to derive the required spatial // frequency <src>(s = uvw*freq/c)</src>. The w component is not used in // these functions. The scale factor returned by this function can be used // to scale the flux at the origin of the Fourier plane in order to determine // the visibility at the specified point. // The "origin" of the transform is the reference direction of the // component. This means for symmetric components, where the reference // direction is at the centre, that the Fourier transform will always be // real. virtual casacore::DComplex visibility(const casacore::Vector<casacore::Double>& uvw, const casacore::Double& frequency) const = 0; // Same as the previous function except that many (u,v,w) points can be // sampled at once. The observation frequency is the same for all the // specified points. The uvw casacore::Matrix must have first dimension of three and // the second dimension must match the length of the scale vector. A default // implementation of this function is available that uses the single point // visibility function described above. However customised versions of this // function may be more efficient as intermediate values only need to be // computed once. virtual void visibility(casacore::Vector<casacore::DComplex>& scale, const casacore::Matrix<casacore::Double>& uvw, const casacore::Double& frequency) const = 0; //Same as above except for lots of frequencies too...scale rows is uvw points, columns // is frequency values virtual void visibility(casacore::Matrix<casacore::DComplex>& scale, const casacore::Matrix<casacore::Double>& uvw, const casacore::Vector<casacore::Double>& frequency) const = 0; // determine whether the shape is symmetric or not. If it is then all the // scale factors returned by the visibility functions will be real numbers. virtual casacore::Bool isSymmetric() const = 0; // Return a pointer to a copy of the derived object upcast to a // ComponentShape object. The class that uses this function is responsible // for deleting the pointer. This is used to implement a virtual copy // constructor. virtual ComponentShape* clone() const = 0; // return the number of parameters in this shape and set/get them. The error // functions provide a way to set/get the error (nominally 1-sigma in an // implicit Gaussian distribution) in the corresponding parameter. // <group> virtual casacore::uInt nParameters() const = 0; virtual void setParameters(const casacore::Vector<casacore::Double>& newParms) = 0; virtual casacore::Vector<casacore::Double> parameters() const = 0; virtual void setErrors(const casacore::Vector<casacore::Double>& newErrs) = 0; virtual casacore::Vector<casacore::Double> errors() const = 0; virtual casacore::Vector<casacore::Double> optParameters() const = 0; virtual void setOptParameters(const casacore::Vector<casacore::Double>& newOptParms) = 0; // </group> // These functions convert between a record and a ComponentShape. This way // derived classes can interpret fields in the record in a class specific // way. They return false if the record is malformed and append an error // message to the supplied string giving the reason. These functions define // how the shape is represented in glish. All records should have 'type' & // 'direction' fields which contain respectively; a string indicating which // shape is actually used, and a record representation of a direction // measure. The interpretation of all other fields depends on the specific // component shape used. // <group> virtual casacore::Bool fromRecord(casacore::String& errorMessage, const casacore::RecordInterface& record) = 0; virtual casacore::Bool toRecord(casacore::String& errorMessage, casacore::RecordInterface& record) const = 0; // </group> // Convert the parameters of the shape to the specified units. The Record // must contain the same fields that the to/from casacore::Record functions have (with // the exception of the direction & type fields). These fields will contain // strings (and not record representations of Quantums) that specify the new // units for these parameters. The new units must have the same dimensions as // the existing ones. If there is any problem parsing the record then an // error message is appended to the supplied string and the function returns // false. virtual casacore::Bool convertUnit(casacore::String& errorMessage, const casacore::RecordInterface& record) = 0; // Return the shape that the supplied record represents. The // shape is determined by parsing a 'type' field in the supplied // record. Returns ComponentType::UNKNOWN_SHAPE if the type field // (which contains a string) could not be translated into a known // shape. It then appends an appropriate error message to the errorMessage // String. static ComponentType::Shape getType(casacore::String& errorMessage, const casacore::RecordInterface& record); // Convert component shape to absolute pixels. The returned // vector is the longitude and latitude location in absolute pixels. virtual casacore::Vector<casacore::Double> toPixel (const casacore::DirectionCoordinate& dirCoord) const; // Fill the shape direction from the vector (longitude and latitude // in absolute pixels). The return value is always true. virtual casacore::Bool fromPixel (const casacore::Vector<casacore::Double>& parameters, const casacore::DirectionCoordinate& dirCoord); // casacore::Function which checks the internal data of this class for correct // dimensionality and consistant values. Returns true if everything is fine // otherwise returns false. virtual casacore::Bool ok() const; // Return a pointer to the object. All subclasses must implement. virtual const ComponentShape* getPtr() const = 0; // Return a nicely formatted string describing the component's size. // All subclasses must implement. virtual casacore::String sizeToString() const = 0; protected: // The constructors and assignment operator are protected as only derived // classes should use them. // <group> //# The default ComponentShape direction is at the J2000 North Pole. ComponentShape(); //# Construct a ComponentShape at the specified direction. ComponentShape(const casacore::MDirection& direction); //# The copy constructor uses copy semantics. ComponentShape(const ComponentShape& other); //# The assignment operator uses copy semantics. ComponentShape& operator=(const ComponentShape& other); // </group> //# Try and decide if the two reference directions are different, as the //# casacore::MeasRef<T>::operator== function is too restrictive. static casacore::Bool differentRefs(const casacore::MeasRef<casacore::MDirection>& ref1, const casacore::MeasRef<casacore::MDirection>& ref2); // returns true if the quantum is not a non-negative angular quantity static casacore::Bool badError(const casacore::Quantum<casacore::Double>& quantum); // Turns the specified field in the specified record into an casacore::Quantum // with angular units static casacore::Bool fromAngQRecord(casacore::Quantum<casacore::Double>& returnValue, casacore::String& errorMessage, const casacore::String& fieldString, const casacore::RecordInterface& record); private: //# The reference direction of the component casacore::MDirection itsDir; //# The errors in the reference direction of the component in radians casacore::Quantum<casacore::Double> itsDirErrLat; casacore::Quantum<casacore::Double> itsDirErrLong; }; } //# NAMESPACE CASA - END #endif