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