//# SpectralIndex.h: Models the spectral variation with a spectral index //# Copyright (C) 1998-2014 //# 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: SpectralIndex.h 21229 2012-04-02 12:00:20Z gervandiepen $ #ifndef COMPONENTS_SPECTRALINDEX_H #define COMPONENTS_SPECTRALINDEX_H #include <casacore/casa/aips.h> #include <components/ComponentModels/ComponentType.h> #include <components/ComponentModels/SpectralModel.h> #include <casacore/casa/Arrays/ArrayFwd.h> namespace casacore{ class MFrequency; class RecordInterface; class String; } namespace casa { //# NAMESPACE CASA - BEGIN // <summary>Models the spectral variation with a spectral index</summary> // <use visibility=export> // <reviewed reviewer="" date="yyyy/mm/dd" tests="tSpectralIndex" demos="dSpectralModel"> // </reviewed> // <prerequisite> // <li> <linkto class="SpectralModel">SpectralModel</linkto> // </prerequisite> // // <synopsis> // This class models the spectral variation of a component with a spectral // index. // This class like the other spectral models becomes more useful when used // through the <linkto class=SkyComponent>SkyComponent</linkto> class, which // incorporates the flux and spatial variation of the emission, or through the // <linkto class=ComponentList>ComponentList</linkto> class, which handles // groups of SkyComponent objects. // A spectral index is the exponent in a power law model for the variation flux // with frequency. It is mathematically is defined as: // <srcblock> // (nu / nu_0)^alpha // </srcblock> // Where: // <dl compact> // <dt><src>nu_0</src><dd> is the reference frequency // <dt><src>alpha</src><dd> is the spectral index // <dt><src>nu</src><dd> is the user specified frequency // </dl> // As with all classes derived from SpectralModel the basic operation of this // class is to model the flux as a function of frequency. This class does not // know what the flux is at the reference frequency. Instead the sample // functions return factors that are used to scale the flux and calculate the // amount of flux at a specified frequency. // Besides the reference frequency this class has one parameter; the spectral // index. This parameter can be set & queried using the general purpose // <src>parameters</src> functions or the class specific <src>index</src> // functions. //<Dec-2013> Have added a full stokes spectral variation ... // This is done via setting setStokesIndex. // If setIndex is used then only the first element of 4 parameters is set // The 4 elements are // 0) alpha for stokes I ..such that // 1) alpha for linear pol fraction i.e make sure that Q and U is such that sqrt(Q_0^2+U_0^2)/I_0 * (nu/nu_0)^alpha(1)) is obeyed. // 2) Rot measure (RM=alpha(2)) value to rotate linear pol by angle RM*(lambda^2- lambda_0^2) // 3) alpha for circular pol fraction i.e to make V such that V/I=V_0/I_0 *(nu/nu_0)^alpha(3) //</Dec-2013> // This class also contains functions (<src>toRecord</src> & // <src>fromRecord</src>) which perform the conversion between Records and // SpectralIndex objects. These functions define how a SpectralIndex // object is represented in glish. The format of the record that is generated // and accepted by these functions is: // <srcblock> // c := [type = 'spectral index', // frequency = [type = 'frequency', // refer = 'lsr', // m0 = [value = 1, unit = 'GHz'] // ], // index = 0.7 // ] // </srcblock> // The frequency field contains a record representation of a frequency measure // and its format is defined in the Measures module. Its refer field defines // the reference frame for the direction and the m0 field defines the value of // the reference frequency. The parsing of the type field is case // insensitive. The index field contains the spectral index. // </synopsis> // // <example> // These examples are coded in the tSpectralModel.h file. // <h4>Example 1:</h4> // In this example a SpectralIndex object is created and used to calculate the // flux at a number of frequencies. // <srcblock> //<Dec-2013> The example below was NEVER implemented... // Could well have written the following and call it documentation: // Sous un arbre, vos laitues naissent-elles ? // Si vos laitues naissent, vos navets aussi naissent ! // Leaving it as is for archeological purposes // </Dec-2013> // SpectralIndex siModel; // siModel.setRefFrequency(casacore::MFrequency(casacore::Quantity(1.0, "GHz"))); // siModel.setIndex(1.0, casacore::Stokes::I); // siModel.setIndex(0.5, casacore::Stokes::Q); // siModel.setIndex(0.5, casacore::Stokes::U); // siModel.setIndex(-1.0, casacore::Stokes::V); // const Flux<casacore::Double> LBandFlux(1.0, 1.0, 1.0, 1.0); // const casacore::MVFrequency step(casacore::Quantity(100.0, "MHz")); // casacore::MVFrequency sampleFreq = siModel.refFrequency().getValue(); // Flux<casacore::Double> sampleFlux; // cout << "Frequency\t I-Flux\t Q-Flux\t U-Flux\t V-Flux\n"; // for (casacore::uInt i = 0; i < 11; i++) { // sampleFlux = LBandFlux.copy(); // sampleFlux.convertPol(ComponentType::LINEAR); // sampleFlux.convertUnit(casacore::Unit("WU")); // siModel.sample(sampleFlux, // casacore::MFrequency(sampleFreq, siModel.refFrequency().getRef())); // cout << setprecision(3) << sampleFreq.get("GHz") // << "\t\t " << sampleFlux.value(0u).re // << "\t " << sampleFlux.value(1u).re // << "\t " << sampleFlux.value(2u).re // << "\t " << sampleFlux.value(3u).re // << " " << sampleFlux.unit().getName() << endl; // sampleFreq += step; // } //<Dec-2013> // Now for an example ///////////////////////////////////////////// // const casacore::MFrequency f1(casacore::Quantity(1.0, "GHz"), casacore::MFrequency::LSRK); // const casacore::MFrequency f2(casacore::Quantity(2.0, "GHz"), casacore::MFrequency::LSRK); // SpectralIndex siModel; // siModel.setIndex(1.0); // cout << "scale value at 1 GHz for setIndex 1.0 " << siModel.sample(f1) << endl; // casacore::Vector<casacore::Double> indices(4); // indices(0)=1.0; indices(1)=0.2; indices(2)=0.0005; indices(3)=0.1; // siModel.setStokesIndex(indices); // casacore::Vector<casacore::Double> iquv(4); // iquv(0)=10.0; iquv(1)=0.2; iquv(2)=0.4; iquv(3)=0.1; // cerr << "iquv in " << iquv << " indices " << indices << endl; // siModel.sampleStokes(f1, iquv); // cerr << "scale value of I at 1.0 GHz " << siModel.sample(f1) << " iquv out " << iquv << endl; // siModel.sampleStokes(f2, iquv); // cerr << "scale value of I at 2.0 GHz " << siModel.sample(f2) << " iquv out " << iquv << endl; //</Dec-2013> // </srcblock> // </example> // // <motivation> A Spectral Index frequency variation is the most widely used // model in radio astronomy. In particular the NFRA package 'newstar' uses it // extensively. // </motivation> // // <todo asof="1999/11/23"> // <li> Nothing I hope // </todo> // <linkfrom anchor="SpectralIndex" classes="SpectralModel ConstantSpectrum"> // <here>SpectralIndex</here> - Uses a spectral index to model the spectrum // </linkfrom> class SpectralIndex: public SpectralModel { public: // The default SpectralIndex has a reference frequency of 1 GHz in the LSR // frame and a spectral index of zero. As such it is no different from the // ConstantSpectrum class (except slower). SpectralIndex(); // Construct a SpectralIndex with specified reference frequency and // exponent. SpectralIndex(const casacore::MFrequency& refFreq, casacore::Double exponent = 0.0); // The copy constructor uses copy semantics SpectralIndex(const SpectralIndex& other); // The destructor does nothing special. virtual ~SpectralIndex(); // The assignment operator uses copy semantics. SpectralIndex& operator=(const SpectralIndex& other); // return the actual spectral type ie., ComponentType::SPECTRAL_INDEX virtual ComponentType::SpectralShape type() const; // set/get the spectral index. // <group> const casacore::Double& index() const; void setIndex(const casacore::Double& newIndex); const casacore::Vector<casacore::Double>& stokesIndex() const; void setStokesIndex(const casacore::Vector<casacore::Double>& newIndex); // </group> // Return the scaling factor that indicates what proportion of the flux is at // the specified frequency. ie. if the centreFrequency argument is the // reference frequency then this function will always return one. At other // frequencies it will return a non-negative number. virtual casacore::Double sample(const casacore::MFrequency& centerFrequency) const; virtual void sampleStokes(const casacore::MFrequency& centerFrequency, casacore::Vector<casacore::Double>& iquv) const; // Same as the previous function except that many frequencies can be sampled // at once. The reference frame must be the same for all the specified // frequencies. Uses a customised implementation for improved speed. virtual void sample(casacore::Vector<casacore::Double>& scale, const casacore::Vector<casacore::MFrequency::MVType>& frequencies, const casacore::MFrequency::Ref& refFrame) const; virtual void sampleStokes( casacore::Matrix<casacore::Double>& scale, const casacore::Vector<casacore::MFrequency::MVType>& frequencies, const casacore::MFrequency::Ref& refFrame ) const; // Return a pointer to a copy of this object upcast to a SpectralModel // object. The class that uses this function is responsible for deleting the // pointer. This is used to implement a virtual copy constructor. virtual SpectralModel* clone() const; // return the number of parameters. There is one parameter or 4 for this spectral // model, namely the spectral index for I or I,Q,U,V. So you supply a unit length vector // or one 4 element long when // using these functions. Otherwise an exception (casacore::AipsError) may be thrown. // <group> virtual casacore::uInt nParameters() const; virtual void setParameters(const casacore::Vector<casacore::Double>& newSpectralParms); virtual casacore::Vector<casacore::Double> parameters() const; virtual void setErrors(const casacore::Vector<casacore::Double>& newSpectralErrs); virtual casacore::Vector<casacore::Double> errors() const; // </group> // These functions convert between a casacore::Record and a SpectralIndex. These // functions define how a SpectralIndex object is represented in glish and // this is detailed in the synopsis above. These functions return false if // the record is malformed and append an error message to the supplied string // giving the reason. // <group> virtual casacore::Bool fromRecord(casacore::String& errorMessage, const casacore::RecordInterface& record); virtual casacore::Bool toRecord(casacore::String& errorMessage, casacore::RecordInterface& record) const; // </group> // Convert the parameters of the spectral index object to the specified // units. Only one field of the supplied record is used, namely 'index'. This // field is optional as the spectral index is a unitless quantity. If the // index field is specified it must have the empty string as its value. This // function always returns true unless the index field is specified and does // not contain an empty string. virtual casacore::Bool convertUnit(casacore::String& errorMessage, const casacore::RecordInterface& record); // casacore::Function which checks the internal data of this class for consistant // values. Returns true if everything is fine otherwise returns false. virtual casacore::Bool ok() const; private: casacore::Double itsIndex; casacore::Vector<casacore::Double> itsStokesIndex; casacore::Double itsError; }; } //# NAMESPACE CASA - END #endif