casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SpectralModel.h
Go to the documentation of this file.
00001 //# SpectralModel.h: Base class for Spectral Models
00002 //# Copyright (C) 1998,1999,2000,2003
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: SpectralModel.h 18093 2004-11-30 17:51:10Z ddebonis $
00027 
00028 #ifndef COMPONENTS_SPECTRALMODEL_H
00029 #define COMPONENTS_SPECTRALMODEL_H
00030 
00031 #include <casa/aips.h>
00032 #include <components/ComponentModels/ComponentType.h>
00033 #include <casa/Utilities/RecordTransformable.h>
00034 #include <measures/Measures/MFrequency.h>
00035 #include <casa/Quanta/Unit.h>
00036 #include <casa/Quanta/Quantum.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 class RecordInterface;
00041 class String;
00042 template <class T> class Vector;
00043 
00044 // <summary>Base class for spectral models</summary>
00045 
00046 // <use visibility=export>
00047 
00048 // <reviewed reviewer="" date="yyyy/mm/dd" tests="tConstantSpectrum" demos="dSpectralModel">
00049 // </reviewed>
00050 
00051 // <prerequisite>
00052 //   <li> <linkto class=MFrequency>MFrequency</linkto>
00053 // </prerequisite>
00054 //
00055 // <synopsis>
00056 
00057 // This abstract base class defines the interface for different classes which
00058 // model the spectrum of a component. The most fundamental derived class is the
00059 // <linkto class=ConstantSpectrum>ConstantSpectrum</linkto> class but the
00060 // <linkto class=SpectralIndex>SpectralIndex</linkto> class is also
00061 // available. These classes model the spectrum of emission from the sky.
00062 
00063 // Classes derived from the 
00064 // <linkto class=ComponentShape>ComponentShape</linkto> class are used to model
00065 // the shape and the <linkto class=Flux>Flux</linkto> class is used to model
00066 // the flux. The <linkto class=SkyComponent>SkyComponent</linkto> class
00067 // incorporates these three characteristics (flux, shape & spectrum) and the
00068 // <linkto class=ComponentList>ComponentList</linkto> class handles groups of
00069 // SkyComponent objects.
00070 
00071 // This class parameterises spectral models with two quantities.
00072 // <dl>
00073 // <dt><em> A reference frequency.</em>
00074 // <dd> This is specified using an <linkto class=MFrequency>MFrequency</linkto>
00075 //      object and defines a frequency where the model
00076 //      is interesting. See the description of derived classes for the
00077 //      specific interpretation of the reference frequency.
00078 // <dt> <em>A Vector of parameters.</em>
00079 // <dd> This contains other parameters that the are defined differently for
00080 //      different spectral models. The length of the vector may vary for
00081 //      different spectral models.
00082 // </dl>
00083 // 
00084 
00085 // The basic operation of classes using this interface is to model the flux as
00086 // a function of frequency. Classes derived from this one do not know what the
00087 // flux is at the reference frequency. Instead the sample functions return
00088 // factors that are used to scale the flux and calculate the amount of flux at
00089 // a specified frequency.
00090 
00091 // Any allowed frequency reference frame can be used. However the reference
00092 // frame must be adequately specified in order to allow conversions to other
00093 // reference frames. For example if the reference frame code for the frequency
00094 // is MFrequency::TOPO then the reference frame must also contain the time,
00095 // position on the earth, and direction of the observation that corresponds to
00096 // the specified frequency. This way the sample functions can convert the
00097 // frequency to a value in the LSR reference frame (if you specify the sample
00098 // frequency in the LSR frame).
00099 
00100 // </synopsis>
00101 //
00102 // <example>
00103 // Because this is an abstract base class, an actual instance of this class
00104 // cannot be constructed. However the interface it defines can be used inside a
00105 // function. This is always recommended as it allows functions which have
00106 // SpectralModels as arguments to work for any derived class.
00107 
00108 // In this example the plotSpectrum function prints out the type of spectral
00109 // model it is working with and the reference frequency of that model. It then
00110 // uses the model to calculate the proportion of the flux at other
00111 // frequencies. This example is coded in the dSpectralModel.cc file.
00112 
00113 // <srcblock>
00114 // void plotSpectrum(const SpectralModel& modelSpectrum) {
00115 //   cout << "This is a "
00116 //        << ComponentType::name(modelSpectrum.type())
00117 //        << " spectrum with a reference frequency of: "
00118 //        << setprecision(4) << modelSpectrum.refFrequency().get("GHz") << " ("
00119 //        << modelSpectrum.refFrequency().getRefString() << ")"
00120 //        << endl;
00121 //   const MVFrequency step(Quantity(100.0, "MHz"));
00122 //   MVFrequency sampleFreq(Quantity(1, "GHz"));
00123 //   MeasFrame obsFrame;
00124 //   {
00125 //     Quantity obsRa; MVAngle::read(obsRa, "19:39:");
00126 //     Quantity obsDec; MVAngle::read(obsDec, "-63.43.");
00127 //     Quantity obsDay; MVTime::read(obsDay, "1996/11/20/5:20");
00128 //     obsFrame.set(MEpoch(obsDay, MEpoch::UTC),
00129 //                  MDirection(obsRa, obsDec, MDirection::J2000));
00130 //   }
00131 //   MFrequency::Ref obsRef(MFrequency::GEO, obsFrame);
00132 //   cout << "Frequency\t scale\n";
00133 //   for (uInt i = 0; i < 11; i++) {
00134 //      cout << setprecision(7) << sampleFreq.get("GHz")
00135 //        << "\t\t " << modelSpectrum.sample(MFrequency(sampleFreq, obsRef))
00136 //        << endl;
00137 //      sampleFreq += step;
00138 //   }
00139 // }
00140 // </srcblock>
00141 // </example>
00142 //
00143 // <motivation>
00144 // The SpectralModel base class was seperated from the ComponentShape base
00145 // class so that mixing components with different spatial and spectral shapes
00146 // did not result in a combinatorial explosion in the number of classes
00147 // required.
00148 // </motivation>
00149 //
00150 // <todo asof="1999/11/23">
00151 //   <li> I would not be surprised if the base class will need to be updated
00152 //        when classes modelling spectral lines are written.
00153 // </todo>
00154 
00155 class SpectralModel: public RecordTransformable
00156 {
00157 public:
00158   // a virtual destructor is needed so that the actual destructor in the
00159   // derived class will be used.
00160   virtual ~SpectralModel();
00161 
00162   // return the actual spectral type. The ident function returns it as a
00163   // String. 
00164   // <group>
00165   virtual ComponentType::SpectralShape type() const = 0;
00166   virtual const String& ident() const;
00167   // </group>
00168 
00169   // set/get the reference frequency
00170   // <group>
00171   void setRefFrequency(const MFrequency& newRefFreq);
00172   const MFrequency& refFrequency() const;
00173   // </group>
00174 
00175   // get the frequency unit, and change the default frequency unit to the
00176   // specified one. This will only affect the units used in the Record returned
00177   // by the toRecord function.
00178   // <group>
00179   const Unit& frequencyUnit() const;
00180   void convertFrequencyUnit(const Unit& freqUnit);
00181   // </group>
00182 
00183   // set/get the error in the reference frequency. Values must be positive
00184   // angular quantities otherwise an AipsError exception is thrown. The errors
00185   // are usually interpreted as the 1-sigma bounds in latitude/longitude and
00186   // implicitly assume a Gaussian distribution. They must have units with the
00187   // same dimensions as the Hz.
00188   // <group>
00189   void setRefFrequencyError(const Quantum<Double>& newRefFreqErr);
00190   const Quantum<Double>& refFrequencyError() const;
00191   // </group>
00192 
00193   // Return the scaling factor that indicates what proportion of the flux is at
00194   // the specified frequency. ie. if the centreFrequency argument is the
00195   // reference frequency then this function will always return one. At other
00196   // frequencies it will return a non-negative number.
00197   virtual Double sample(const MFrequency& centerFrequency) const = 0;
00198 
00199   // Same as the previous function except that many frequencies can be sampled
00200   // at once. The reference frame must be the same for all the specified
00201   // frequencies. A default implementation of this function is available that
00202   // uses the sample function described above.  However customised versions of
00203   // this function will be more efficient as intermediate values only need to
00204   // be computed once.
00205   virtual void sample(Vector<Double>& scale, 
00206                       const Vector<MFrequency::MVType>& frequencies, 
00207                       const MFrequency::Ref& refFrame) const = 0;
00208 
00209   // Return a pointer to a copy of the derived object upcast to a SpectralModel
00210   // object. The class that uses this function is responsible for deleting the
00211   // pointer. This is used to implement a virtual copy constructor.
00212   virtual SpectralModel* clone() const = 0;
00213 
00214   // return the number of parameters in this spectral shape and set/get them.
00215   // <group>
00216   virtual uInt nParameters() const = 0;
00217   virtual void setParameters(const Vector<Double>& newParms) = 0;
00218   virtual Vector<Double> parameters() const = 0;
00219   virtual void setErrors(const Vector<Double>& newErrors) = 0;
00220   virtual Vector<Double> errors() const = 0;
00221   // </group>
00222 
00223   // These functions convert between a record and a SpectralModel. This way
00224   // derived classes can interpret fields in the record in a class specific
00225   // way. They return False if the record is malformed and append an error
00226   // message to the supplied string giving the reason.  These functions define
00227   // how a spectral model is represented in glish. All records should have
00228   // 'type' & 'frequency' fields which contain respectively; a string
00229   // indicating which spectral model is actually used, and a record
00230   // representation of a frequency measure.  The interpretation of all other
00231   // fields depends on the specific spectral model used.
00232   // <group>
00233   virtual Bool fromRecord(String& errorMessage, 
00234                           const RecordInterface& record) = 0;
00235   virtual Bool toRecord(String& errorMessage,
00236                         RecordInterface& record) const = 0;
00237   // </group>
00238 
00239   // Convert the parameters of the spectral model to the specified units. The
00240   // Record must contain the same fields that the to/from Record functions have
00241   // (with the exception of the frequency & type fields). These fields will
00242   // contain strings (and not Quantums) that specify the new units for these
00243   // parameters. The new units must have the same dimensions as the existing
00244   // ones. If there is any problem parsing the record then an error message is
00245   // appended to the supplied string and the function returns False. 
00246   virtual Bool convertUnit(String& errorMessage,
00247                            const RecordInterface& record) = 0;
00248 
00249   // Return the spectral shape that the supplied record represents. The
00250   // spectral shape is determined by parsing a 'type' field in the supplied
00251   // record. Returns ComponentType::UNKNOWN_SPECTRAL_SHAPE if the type field
00252   // (which contains a string) could not be translated into a known spectral
00253   // shape. It then appends an appropriate error message to the errorMessage
00254   // String.
00255   static ComponentType::SpectralShape getType(String& errorMessage,
00256                                               const RecordInterface& record);
00257 
00258   // Function which checks the internal data of this class for correct
00259   // dimensionality and consistant values. Returns True if everything is fine
00260   // otherwise returns False.
00261   virtual Bool ok() const;
00262 
00263 protected:
00264   // The constructors and assignment operator are protected as only derived
00265   // classes should use them.
00266   // <group>
00267   //# The default reference frequency is at 1 GHz in the LSR frame
00268   SpectralModel();
00269 
00270   //# Construct a SpectralModel at the specified reference frequency.
00271   SpectralModel(const MFrequency& refFreq, const Unit& = Unit("GHz"));
00272 
00273   //# The copy constructor uses copy semantics.
00274   SpectralModel(const SpectralModel& other);
00275 
00276   //# The assignment operator uses copy semantics.
00277   SpectralModel& operator=(const SpectralModel& other);
00278   // </group>
00279 
00280   // returns True if the quantum is not a non-negative quantity with units
00281   // dimensionally identical to the Hz
00282   static Bool badError(const Quantum<Double>& quantum);
00283 
00284 private:
00285   //# The reference frequency of the spectral model
00286   MFrequency itsRefFreq;
00287   //# the units (Hz, GHz etc.) that the record functions should use for the
00288   //# reference frequency. 
00289   Unit itsFreqUnit;
00290   Quantity itsFreqErr;
00291 };
00292 
00293 } //# NAMESPACE CASA - END
00294 
00295 #endif