#ifndef _ATM_SPECTRALGRID_H #define _ATM_SPECTRALGRID_H /******************************************************************************* * ALMA - Atacama Large Millimiter Array * (c) Instituto de Estructura de la Materia, 2009 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * "@(#) $Id: ATMSpectralGrid.h Exp $" * * who when what * -------- -------- ---------------------------------------------- * pardo 24/03/09 created */ #ifndef __cplusplus #error "This is a C++ include file and cannot be used from plain C" #endif #include "ATMCommon.h" #include "ATMEnumerations.h" #include "ATMFrequency.h" #include <string> #include <vector> ATM_NAMESPACE_BEGIN /*! \brief Spectral grid defined as a list of frequencies with basic complementary * informations. * * This grid is composed by a set frequency channels (or pixels) which may or may not * be at a regular interval. The grid is composed of one or more spectral windows. * A spectral window is defined as a group of channels, this group having the following * attributes: * <ul> * <li> a number of channels * <li> a reference channel * <li> the frequency for that reference channel * <li> a channel separation (it is set to 0 if there is only one channel or when the * channels are at irregular intervals. * <li> the intermediate frequency (if NetSideband is greater than -1) * To every spectral window is assigned an identifier (zero-based) which can be used * when retrieving the parameters of a given window.<br> * In case of spectral windows with regularily spaced channels this reference frequency * can be associated to a position in channel number units. * * There are several different constructors which can be used to define a spectral * window. One of these must be used to construct the first spectral window. Would * more than a single spectral be necessary, they are appended with the add methods. * When there are two sidebands, every of these corresponds to a single spectral window. * Note that these two sidebands can be constructed using a single method if the intermediate * frequency is an input parameter. * \note The Alma Science Data Model (ASDM) spectral windows derive from spectral grids, * with extra informations such as the channel width, the resolution the noise bandwidth * etc... * */ class SpectralGrid { public: SpectralGrid(const Frequency &oneFreq); /** A full constructor to be used in cases the channel separation is uniform. The * position of the reference frequency is set at the center of the specified * reference channel. This reference channel does not need to be necessarily * in the range [1,numChan]. * @pre no spectral window has yet been defined * @param numChan Number of channels for the spectral window * @param refChan Reference channel for the spectral window * @param refFreq Frequency for this reference channel * @param chanSep Frequency increment between two adjacent channels * @post the spectral window has been defined; it is taken as a spectral window * with no sideband. Its spectral window identifier spwId is 0. */ SpectralGrid(unsigned int numChan, unsigned int refChan, const Frequency &refFreq, const Frequency &chanSep); /** A full constructor to be used in cases the channel separation is not uniform. * In this case the reference frequency may not coincide with the center * of a channel. The frequency units (freqUnits) is common for the reference * frequency (refFReq) and for the numChan frequencies in the list chanFreq. * Known units are GHz, MHz, kHz and Hz. * @pre no spectral window has yet been defined * @param numChan Number of channels for the spectral window * @param refFreq The frequency of the reference channel * @param chanFreq The frequencies of the individual channels * @param freqUnits The frequency units used to define refFreq and chanFreq * @post the spectral window has been defined; it is taken as a spectral window * with no sideband. Its spectral window identifier spwId is 0. */ SpectralGrid(unsigned int numChan, double refFreq, double* chanFreq, Frequency::Units freqUnits); SpectralGrid(double refFreq, const std::vector<double> &chanFreq, Frequency::Units freqUnits); SpectralGrid(const std::vector<double> &chanFreq, Frequency::Units freqUnits); SpectralGrid(const std::vector<Frequency> &chanFreq); /** A full constructor to be used in cases of two sibands (separated or not) * The reference frequency, may not coincide with the center * of a channel, is the frequency used to track on. * The frequency units (freqUnits) is common for the reference * frequency (refFReq) and for the numChan frequencies in the list chanFreq. * Known units are GHz, MHz, kHz and Hz. * @pre no spectral window has yet been defined * @param numChan Number of channels for the spectral window * @param refFreq Frequency of the reference channel * @param chanSep Frequency interval between two adajacent channels * @param intermediateFreq Intermediate Frequency * @param SidebandSide code (see #SidebandSide for details) * @param SidebandType code (see #SidebandType for details) * @post <b>Two</b> spectral windows have been defined, one for each sideband * Their spectral window identifiers are 0 and 1. The identifier is 0 and 1 for the lower * and upper sidebands if the input netSideband is 0, 1, 3 or 5 else it is 1 and 0 respectively. */ SpectralGrid(unsigned int numChan, unsigned int refChan, const Frequency &refFreq, const Frequency &chanSep, const Frequency &intermediateFreq, const SidebandSide &sbSide, const SidebandType &sbType); /** A full constructor to be used in cases the channel separation is not uniform. * In this case the reference frequency coincides with the center of a channel, * the one at the refChan position in the numChan elements of the list of * frequencies chanFreq. Hence refChan must be in the range [1,numChan]. The * frequency units (freqUnits) is common for the reference * frequency (refFReq) and for the numChan frequencies in the list chanFreq. * Known units are GHz, MHz, kHz and Hz. * @pre no spectral window has yet been defined * @param numChan Number of channels for the spectral window * @param refChan Reference channel for the spectral window * @param chanFreq The frequencies of the individual channels * @param freqUnits The frequency units used to define refFreq and chanFreq * @post the spectral window has been defined; it is taken as a spectral window * with no sideband. Its spectral window identifier spwId is 0. */ SpectralGrid(unsigned int numChan, unsigned int refChan, double* chanFreq, Frequency::Units freqUnits); SpectralGrid(); SpectralGrid(const SpectralGrid &); ~SpectralGrid(); /** Add a new spectral window, uniformly sampled, this spectral window having no sideband. * @pre at least one spectral window has already been defined * @param numChan Number of channels for the spectral window * @param refChan Reference channel for the spectral window * @param refFreq Frequency for this reference channel * @param chanSep Frequency increment between two adjacent channels * @return the identifier for this spectral window * @post the spectral window has been defined and appended to the set of spectral windows; * this new spectral window is taken as one with no sideband. */ unsigned int add(unsigned int numChan, unsigned int refChan, const Frequency &refFreq, const Frequency &chanSep); /** Add a new spectral window, this spectral window having no sideband. * @pre at least one spectral window has already been defined * @param numChan Number of channels for the spectral window * @param refChan Reference channel for the spectral window * @param chanFreq The frequency for every channel * @param freqUnits The frequency units (GHz, MHz or kHz, else assumed in Hz) used for chanFreq * @return the identifier for this spectral window * @post the spectral window has been defined and appended to the set of spectral windows; * this new spectral window is taken as one with no sideband. */ unsigned int add(unsigned int numChan, unsigned int refChan, double* chanFreq, Frequency::Units freqUnits); /** Add a new spectral window, this spectral window having no sideband. * @pre at least one spectral window has already been defined * @param numChan Number of channels for the spectral window * @param refFreq The frequency at the reference channel for the spectral window * @param chanFreq The frequency for every channel * @param freqUnits The frequency units (GHz, MHz or kHz, else assumed in Hz) used for refFreq and chanFreq * @return the identifier for this spectral window * @post the spectral window has been defined and appended to the set of spectral windows; * this new spectral window is taken as one with no sideband. */ unsigned int add(unsigned int numChan, double refFreq, double* chanFreq, Frequency::Units freqUnits); unsigned int add(unsigned int numChan, double refFreq, const std::vector<double> &chanFreq, Frequency::Units freqUnits); unsigned int add(const std::vector<Frequency> &chanFreq) { unsigned int spwid; std::vector<double> v; for(unsigned int i = 0; i < chanFreq.size(); i++) { v.push_back(chanFreq[i].get(Frequency::UnitGigaHertz)); } spwid = add(chanFreq.size(), chanFreq[0].get(Frequency::UnitGigaHertz), v, Frequency::UnitGigaHertz); return spwid; } /** Add two new spectral windows, one spectral window per sideband. * @pre at least one spectral window has already been defined * @param numChan Number of channels for the spectral window in one sideband * @param refFreq The frequency at the reference channel for that spectral window * @param chanSep The channel separation (unsigned) * @param intermediateFreq the Intermediate Frequency * @return the netSideband for this first spectral window (the second spectral will have the corresponding * netSideband for the other sideband. * @post the spectral window has been defined and appended to the set of spectral windows; * this new spectral window is taken as one with no sideband. * \note For SSB receivers the first sideband is the signal sideband and in this case refFreq is usually * the frequency for the middle of that sideband. For DSB refFreq may be in between the two sideband. */ void add(unsigned int numChan, unsigned int refChan, const Frequency &refFreq, const Frequency &chanSep, const Frequency &intermediateFreq, const SidebandSide &sbSide, const SidebandType &sbType); //@{ /** Accessor to the number of spectral wondows * @return number of spectral windows */ unsigned int getNumSpectralWindow() const; /** Accessor to the number of frequency points for the first spectral window * @return number of frequency channels */ unsigned int getNumChan() const; /** Accessor to the number of frequency points for a given spectral window * @param spwId spectral window identifier (0-based) * @return number of frequency channels */ unsigned int getNumChan(unsigned int spwId) const; /** Accessor to the reference channel of the first spectral window * @return the reference channel * \note with the constructor SpectralGrid( int numChan, double refFreq, double* chanFreq, std::string freqUnits) * there is no way to determine the reference channel if the grid is not regularily sampled! would that be * the case, the returned value is 0. */ unsigned int getRefChan() const; /** Accessor to the reference channel for a given spectral window * @param spwId spectral window identifier (0-based) * @return the reference channel */ unsigned int getRefChan(unsigned int spwId) const; // Frequency getRefFreq(); /** Accessor to the reference frequency (Hz) for the first spectral window * @return the frequency at the reference channel position */ Frequency getRefFreq() const; /** Accessor to the reference frequency (Hz) for a given spectral window * @param spwId spectral window identifier (0-based) * @return the frequency at the reference channel position */ Frequency getRefFreq(unsigned int spwId) const; /** Accessor to the channel separation for regularily spaced grids (for the first spectral window) * @return the channel separation (Hz) */ Frequency getChanSep() const; /** Accessor to the channel separation for regularily spaced grids (for a given spectral window) * @param spwId spectral window identifier (0-based) * @return the channel separation (Hz) */ Frequency getChanSep(unsigned int spwId) const; /** Accessor to the frequency (Hz) for a given grid point (for the first spectral window) * @param chanNum the channel number (grid units) * @ return the frequency (Hz) corresponding to the center of the channel */ Frequency getChanFreq(unsigned int chanNum) const; Frequency getChanWidth(unsigned int chanNum) const; /** Accessor to the frequency (Hz) for a given grid point for the specified spectral window * @param spwId spectral window identifier (0-based) * @param chanNum the channel number (grid units) * @ return the frequency (Hz) corresponding to the center of the channel */ Frequency getChanFreq(unsigned int spwId, unsigned int chanNum) const; Frequency getChanWidth(unsigned int spwId, unsigned int chanNum) const; /** Accessor to the frequencies in the specified units for a given channel index (0-based) for the * the specified spectral window its corresponding other sideband. * @param spwId spectral window identifier (0-based) * @param chanNum the channel number (grid units) * @param freqUnits the requested units * @return the frequencies corresponding to the center of the channel in the specified units for * the input spectral window and for the corresponding channel in the other sideband */ std::vector<double> getSbChanFreq(unsigned int spwId, unsigned int chanNum, const std::string &freqUnits) const; /** Accessor to retrieve the spectral grid of a spectral window * @param spwId spectral window identifier (0-based) * @return a std::vector of numChan frequencies (Hz) */ std::vector<double> getSpectralWindow(unsigned int spwId) const; /** Method to get the grid position for a given frequency specified in Hz (the first spectral window) * @return the grid position */ double getChanNum(double freq) const; /** Method to get the grid position for a given frequency specified in Hz for the specified spectral window * @param freq the frequency (Hz) for the grid position * @param spwId spectral window identifier (0-based) * @return the grid position */ double getChanNum(unsigned int spwId, double freq) const; /** Method to get the frequency range encompassing the list of frequency grid points (for the first spectral window) * \note In case of irregular sampling the return value is the difference between the frequencies of the channels * with the highest one and the channel with the lowedt one else it the product of the number of channels * times the channel separation * @return the frequency bandwidth (Hz) */ Frequency getBandwidth() const; /** Method to get the frequency range encompassing the list of frequency grid points for the specified spectral window * \note In case of irregular sampling the return value is the difference between the frequencies of the channels * with the highest one and the channel with the lowedt one else it the product of the number of channels * times the channel separation * @param spwId spectral window identifier (0-based) * @return the frequency bandwidth (Hz) */ Frequency getBandwidth(unsigned int spwId) const; /** Method to get the frequency (Hz) for the point at the lowest frequency (for the first spectral window) * @return the frequency of the channel at the lowest frequency */ Frequency getMinFreq() const; /** Method to get the frequency in the specified units for the channel at the lowest frequency for the * specified spectral window * @param spwId spectral window identifier (0-based) * @return the frequency (Hz) of the channel at the lowest frequency */ Frequency getMinFreq(unsigned int spwId) const; /** Method to get the frequency (Hz) for the point at the largest frequency (for the first spectral window) * @return the frequency (Hz) of the channel at the highest frequency */ Frequency getMaxFreq() const; /** Method to get the frequency in the specified units for the point at the largest frequency (for the first * spectral window) * @param units the requested units * @return the frequency (Hz) of the channel at the highest frequency */ Frequency getMaxFreq(unsigned int spwId) const; /** Method to know if the spectral grid is regular or not (the first spectral window) * @return true if uniformly sampled, else false */ bool isRegular() const; /** Method to know if the spectral grid is regular or not for the specified spectral window * @param spwId spectral window identifier (0-based) * @return true if uniformly sampled, else false */ bool isRegular(unsigned int spwId) const; /** Accessor for the side of the sideband * @param spwId spectral window identifier (0-based) * @return the side of the sideband * \note Possible result is no sideband (NoSB) or lower sideband (LSB) or upper sideband (USB) */ std::string getSidebandSide(unsigned int spwId) const; /** Accessor to the nature(s) of the associated spectral window(s) * @pre the spectral window must have an associated sideband. Would that not be the * case the returned std::vector has a size of 0. * @param spwId spectral window identifier (0-based) * @return the associated nature(s) of the associated spectral windows */ std::vector<std::string> getAssocNature(unsigned int spwId) const; /** Accessor to the identifier of the associated spectral window(s) * @pre the spectral window must have an associated spectral window. Would that not be the * case the returned std::vector has a size of 0. * @param spwId spectral window identifier (0-based) * @return the identifiers of the its associated spectral windows */ std::vector<unsigned int> getAssocSpwId(unsigned int spwId) const; std::vector<unsigned int> getAssocSpwIds(const std::vector<unsigned int> &spwIds) const; /** Accessor for the type of sideband * @pre the spectral window must have an associated spectral window. Would that not be the * case the returned std::vector has a size of 0. * @param spwId spectral window identifier (0-based) * @return the type of the sideband * \note Possible result is double sideband (DSB) or single sideband (SSB) or two sidebands (2SB). * 2SB implies sideband separation which is possible only in the interferometric case */ std::string getSidebandType(unsigned int spwId) const; /** Accessor for the side of the sideband and its type * @pre the spectral window must have a sideband side and a sideband type. Would that not be the * case the returned std::string has a size of 0. * @param spwId spectral window identifier (0-based) * @return the side and the type of the sideband */ std::string getSideband(unsigned int spwId) const; double getLoFrequency() const; double getLoFrequency(unsigned int spwId) const; //@} bool operator ==(const SpectralGrid&) const; protected: Frequency::Units freqUnits_; //!< The frequency inits (always Frequency::UnitHertz) std::vector<double> v_chanFreq_; //!< Channel frequencies of ALL the channels (i.e. all spectral window appended) std::vector<unsigned int> v_numChan_; //!< number of channels for every spectral window std::vector<unsigned int> v_refChan_; //!< reference channel for every spectral window std::vector<double> v_refFreq_; //!< frequency at reference channel for every spectral window std::vector<double> v_chanSep_; //!< channel separation for every spectral window std::vector<double> v_maxFreq_; //!< frequency maximum for every spectral window std::vector<double> v_minFreq_; //!< frequency minimum for every spectral window std::vector<double> v_intermediateFrequency_; //<! intermediate frequency of the band for every spectral window std::vector<double> v_loFreq_; //<! LO frequency std::vector<SidebandSide> v_sidebandSide_; //<! NOSB=0, LSB=1, USB=2 std::vector<SidebandType> v_sidebandType_; //<! DSB=0, SSB=1, TWOSB=2 std::vector<std::vector<unsigned int> > vv_assocSpwId_; //<! associated spectral window Id(s) std::vector<std::vector<std::string> > vv_assocNature_; //<! corresponding associated nature std::vector<unsigned int> v_transfertId_; private: void appendChanFreq(unsigned int numChan, double* chanFreq); void appendChanFreq(unsigned int numChan, const std::vector<double> &chanFreq); bool wrongSpwId(unsigned int spwId) const; }; inline bool SpectralGrid::operator ==(const SpectralGrid & a) const { bool equals = false; if(freqUnits_ != a.freqUnits_) return equals; if(v_refChan_ != a.v_refChan_) return equals; if(v_chanSep_ != a.v_chanSep_) return equals; if(v_numChan_ != a.v_numChan_) return equals; if(v_maxFreq_ != a.v_maxFreq_) return equals; if(v_minFreq_ != a.v_minFreq_) return equals; if(!equals) if(v_chanFreq_ != a.v_chanFreq_) return equals; equals = true; return equals; }; // class SpectralGrid ATM_NAMESPACE_END #endif /*!_ATM_SPECTRALGRID_H*/