00001 //# SpectralCoordinate.h: Interconvert between pixel and frequency. 00002 //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2004 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 //# 00027 //# $Id$ 00028 00029 00030 #ifndef COORDINATES_SPECTRALCOORDINATE_H 00031 #define COORDINATES_SPECTRALCOORDINATE_H 00032 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/casa/Arrays/Vector.h> 00035 #include <casacore/coordinates/Coordinates/Coordinate.h> 00036 #include <casacore/coordinates/Coordinates/ObsInfo.h> 00037 #include <casacore/measures/Measures/MFrequency.h> 00038 #include <casacore/measures/Measures/MDoppler.h> 00039 #include <casacore/measures/Measures/MDirection.h> 00040 #include <casacore/measures/Measures/MPosition.h> 00041 #include <casacore/measures/Measures/MEpoch.h> 00042 #include <casacore/casa/Quanta/Quantum.h> 00043 #include <casacore/casa/Utilities/PtrHolder.h> 00044 00045 #include <wcslib/wcs.h> 00046 00047 00048 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00049 00050 00051 class TabularCoordinate; 00052 class LogIO; 00053 class MVFrequency; 00054 class VelocityMachine; 00055 template<class T> class Quantum; 00056 00057 00058 // <summary> 00059 // Interconvert pixel and frequency values. 00060 // </summary> 00061 00062 // <use visibility=export> 00063 00064 // <reviewed reviewer="Peter Barnes" date="1999/12/24" tests="tSpectralCoordinate"> 00065 // </reviewed> 00066 // 00067 // <prerequisite> 00068 // <li> <linkto class=Coordinate>Coordinate</linkto> 00069 // <li> <linkto class=MFrequency>MFrequency</linkto>, 00070 // <linkto class=MDoppler>MDoppler</linkto> and 00071 // <linkto class=VelocityMachine>VelocityMachine</linkto> 00072 // classes if you want radial velocities. 00073 // </prerequisite> 00074 // 00075 // <synopsis> 00076 // This class performs the mapping from pixel to frequency. 00077 // This can be done via a Tabular lookup or via an algorithmic 00078 // implementation which may be linear or non-linear. The latter 00079 // is implemented via the WCS library. 00080 // 00081 // </synopsis> 00082 // 00083 00084 // <note role=caution> 00085 // All pixels coordinates are zero relative. 00086 // </note> 00087 // 00088 // <example> 00089 // Let us make a linear SpectralCoordinate first 00090 // <srcblock> 00091 // Double restfreq = 1.420405752E9; 00092 // Double crpix = 10.0; 00093 // Double crval = 1.4e9; 00094 // Double cdelt = 1.0e6; 00095 // SpectralCoordinate sc(MFrequency::TOPO, crval, cdelt, crpix, restfreq); 00096 // 00097 // Double world, pixel; 00098 // pixel = 12.1; 00099 // if (!sc.toWorld(world, pixel)) { 00100 // cerr << "Error : " << sc.errorMessage() << endl; 00101 // } else { 00102 // cerr << "pixel, world = " << pixel << ", " << world << endl; 00103 // } 00104 // 00105 // </srcblock> 00106 // </example> 00107 // 00108 // <example> 00109 // Now we make a non-linear SpectralCoordinate 00110 // <srcblock> 00111 // Vector<Double> freqs(5); 00112 // freqs(0) = 1.4e9; freqs(1) = 1.41e9; 00113 // freqs(2) = 1.43e9; freqs(3) = 1.44e9; 00114 // freqs(4) = 1.47e9; 00115 // SpectralCoordinate sc(MFrequency::LSRK, freqs, restfreq); 00116 // 00117 // Double world, pixel; 00118 // world = 1.42e9; 00119 // if (!sc.toPixel(pixel, world)) { 00120 // cerr << "Error : " << sc.errorMessage() << endl; 00121 // } else { 00122 // cerr << "world, pixel = " << world << ", " << pixel << endl; 00123 // } 00124 // 00125 // </srcblock> 00126 // </example> 00127 // 00128 // <motivation> 00129 // Spectral-line astronomy requires a specialized SpectralCoordinate. 00130 // </motivation> 00131 00132 // <todo asof="2000/01/01"> 00133 // <li> Allow other than linear interpolations for frequency lookup. 00134 // </todo> 00135 // 00136 00137 class SpectralCoordinate : public Coordinate 00138 { 00139 public: 00140 enum SpecType { // taken from the FITS spectral coordinate type codes 00141 FREQ, 00142 VRAD, 00143 VOPT, 00144 BETA, 00145 WAVE, 00146 AWAV 00147 }; 00148 00149 // Default constructor. It is equivalent to doing 00150 // SpectralCoordinate(MFrequency::TOPO, 0.0, 1.0, 0.0) 00151 SpectralCoordinate(); 00152 00153 // Create a linear frequency axis SpectralCoordinate 00154 // <src>f0</src> is the frequency of the reference pixel, <src>inc</src> is the pixel increment, 00155 // <src>refPix</src> is the reference pixel. You can 00156 // optionally store the rest frequency for later use in calculating radial 00157 // velocities. Use 0 for restFrequency if continuum. 00158 // 00159 // Frequencies and increments initially in Hz. 00160 SpectralCoordinate(MFrequency::Types type, Double f0, Double inc, 00161 Double refPix, Double restFrequency = 0.0); 00162 00163 // Create linear frequency axis SpectralCoordinate with Quantum-based interface. 00164 // Parameters are the same as above. 00165 // Regardless of the units of the Quanta, the initial units 00166 // of the SpectralCoordinate will be Hz. You can change it to 00167 // something else with the setWorldAxisUnits method later if you want. 00168 // Use 0 for restFrequency if continuum. 00169 SpectralCoordinate(MFrequency::Types type, const Quantum<Double>& f0, 00170 const Quantum<Double>& inc, Double refPix, 00171 const Quantum<Double>& restFrequency = Quantum<Double>(0.0,"Hz")); 00172 00173 // Construct a SpectralCoordinate with the specified frequencies (in Hz). 00174 // This axis can be nonlinear; the increments and related 00175 // functions return the <src>average</src> values 00176 // (calculated from the first and last pixel's frequencies). 00177 // 00178 // A linear interpolation/extrapolation is used for pixels which are 00179 // not supplied. The reference pixel is chosen to be 0. 00180 // The frequencies must increase or decrease monotonically (otherwise 00181 // the toPixel lookup would not be possible). 00182 // Use 0 for restFrequency if continuum. 00183 SpectralCoordinate(MFrequency::Types type, const Vector<Double> &freqs, 00184 Double restFrequency = 0.0); 00185 00186 // Construct a SpectralCoordinate with the specified frequencies 00187 // with Quantum-based interface. 00188 // Parameters are the same as above. 00189 // Regardless of the units of the Quanta, the initial units 00190 // of the SpectralCoordinate will be Hz. 00191 // Use 0 for restFrequency if continuum. 00192 SpectralCoordinate(MFrequency::Types type, const Quantum<Vector<Double> >& freqs, 00193 const Quantum<Double>& restFrequency = Quantum<Double>(0.0,"Hz")); 00194 00195 // Construct a SpectralCoordinate with the specified velocities (in km/s). 00196 // They will be converted to Hz and the SpectralCoordinate constructed. 00197 // This axis can be nonlinear; the increments and related 00198 // functions return the <src>average</src> values 00199 // (calculated from the first and last pixel's frequencies). 00200 // 00201 // A linear interpolation/extrapolation is used for pixels which are 00202 // not supplied. The reference pixel is chosen to be 0. 00203 // The velocities must increase or decrease monotonically (otherwise 00204 // the toPixel lookup would not be possible). 00205 SpectralCoordinate(MFrequency::Types freqType, MDoppler::Types velType, 00206 const Vector<Double>& velocities, const String& velUnit, 00207 Double restFrequency = 0.0); 00208 00209 // Construct a SpectralCoordinate with the specified wavelengths (in mm). 00210 // They will be converted to Hz and the SpectralCoordinate constructed. 00211 // This axis can be nonlinear; the increments and related 00212 // functions return the <src>average</src> values 00213 // (calculated from the first and last pixel's frequencies). 00214 // If inAir is True, the input wavelengths are assumed to be Air Wavelengths. 00215 // They are converted to vacuum frequency using the refractive index 00216 // which is calculated based on the mean input air wavelength. 00217 // 00218 // A linear interpolation/extrapolation is used for pixels which are 00219 // not supplied. The reference pixel is chosen to be 0. 00220 // The wavelengths must increase or decrease monotonically (otherwise 00221 // the toPixel lookup would not be possible). 00222 SpectralCoordinate(MFrequency::Types freqType, 00223 const Vector<Double>& wavelengths, const String& waveUnit, 00224 Double restFrequency = 0.0, Bool inAir = False); 00225 00226 // Construct from wcs structure. Must hold only a spectral wcs structure 00227 // Specify whether the absolute pixel coordinates in the wcs structure 00228 // are 0- or 1-relative. The coordinate is always constructed with 0-relative 00229 // pixel coordinates 00230 SpectralCoordinate(MFrequency::Types freqType, const ::wcsprm& wcs, Bool oneRel=True); 00231 00232 // Copy constructor (copy semantics). 00233 SpectralCoordinate(const SpectralCoordinate &other); 00234 00235 // Assignment (copy semantics). 00236 SpectralCoordinate &operator=(const SpectralCoordinate &other); 00237 00238 // Destructor. 00239 virtual ~SpectralCoordinate(); 00240 00241 // Always returns Coordinate::SPECTRAL. 00242 virtual Coordinate::Type type() const; 00243 00244 // Always returns the String "Spectral". 00245 virtual String showType() const; 00246 00247 // Always returns 1. 00248 // <group> 00249 virtual uInt nPixelAxes() const; 00250 virtual uInt nWorldAxes() const; 00251 // </group> 00252 00253 // Set extra conversion layer. Whenever a conversion from pixel to world is done, 00254 // the world value is then further converted to this MFrequency::Types value. 00255 // For example, your SpectralCoordinate may be defined in LSRK. 00256 // You can use this to get the world values out in say BARY. You must 00257 // specify the position on earth, the epoch and the direction for the conversions 00258 // and it is your responsibility to ensure they are viable. 00259 // Similarly, whenever you convert from world to pixel, the world 00260 // value is assumed to be that appropriate to the setReferenceConversion type. 00261 // It is first converted to the MFrequency::Types with which the 00262 // SpectralCoordinate was constructed and from there to pixel. 00263 // If you don't call this function, or you set the same type 00264 // for which the SpectralCoordinate was constructed, no extra 00265 // conversions occur. Some conversions will fail. These are the 00266 // ones that require extra frame information (radial velocity) such 00267 // as to REST. This will be added later. In this case this function 00268 // returns False (and the conversion parameters are all left as they were), 00269 // else it returns True. 00270 // <group> 00271 Bool setReferenceConversion (MFrequency::Types type, 00272 const MEpoch& epoch, const MPosition& position, 00273 const MDirection& direction); 00274 void getReferenceConversion (MFrequency::Types& type, 00275 MEpoch& epoch, MPosition& position, 00276 MDirection& direction) const 00277 {type = conversionType_p; epoch=epoch_p; 00278 position=position_p; direction=direction_p;}; 00279 // </group> 00280 00281 // Convert a pixel to a world coordinate or vice versa. Returns True 00282 // if the conversion succeeds, otherwise it returns False and 00283 // <src>errorMessage()</src> contains an error message. The input vectors 00284 // must be of length one and the output vectors are resized if they are not 00285 // already of length one. 00286 // if <src>useConversionFrame</src>, if the coordinate has a conversion 00287 // layer frame, it is used. Else, the native frame is used for the conversion. 00288 // <group> 00289 virtual Bool toWorld(Vector<Double> &world, 00290 const Vector<Double> &pixel, Bool useConversionFrame=True) const; 00291 virtual Bool toPixel(Vector<Double> &pixel, 00292 const Vector<Double> &world) const; 00293 Bool toWorld(Double& world, const Double& pixel) const; 00294 Bool toPixel(Double& pixel, const Double& world) const; 00295 // </group> 00296 00297 // Convert a pixel (channel number) into an MFrequency or MVFrequency and vice 00298 // versa. Usually you will do 00299 // this for calculating velocities or converting frequencies from one frame 00300 // to another. 00301 // <group> 00302 Bool toWorld(MFrequency &world, 00303 Double pixel) const; 00304 Bool toPixel(Double& pixel, const MFrequency &world) const; 00305 Bool toWorld(MVFrequency &world, 00306 Double pixel) const; 00307 Bool toPixel(Double& pixel, const MVFrequency &world) const; 00308 // </group> 00309 00310 // Batch up a lot of transformations. The first (most rapidly varying) axis 00311 // of the matrices contain the coordinates. Returns False if any conversion 00312 // failed and <src>errorMessage()</src> will hold a message. 00313 // The <src>failures</src> array (True for fail, False for success) 00314 // is the length of the number of conversions and 00315 // holds an error status for each conversion. 00316 // <group> 00317 virtual Bool toWorldMany(Matrix<Double>& world, 00318 const Matrix<Double>& pixel, 00319 Vector<Bool>& failures) const; 00320 virtual Bool toPixelMany(Matrix<Double>& pixel, 00321 const Matrix<Double>& world, 00322 Vector<Bool>& failures) const; 00323 // </group> 00324 00325 // Set the state that is used for conversions from pixel and frequency to velocity 00326 // or wavelength. The SpectralCoordinate is constructed with 00327 // <src>MDoppler::RADIO</src> and <src>km/s</src> as the velocity conversion state 00328 // and <src>mm</src> as the wavelength conversion state. 00329 // The functions in this class which use this state are those that convert 00330 // to or from velocity. Also, function <src>format</src> uses the Doppler 00331 // state set here. If the function returns False it means the unit was 00332 // not valid. There will be an error message in function <src>errorMessage</src> 00333 // <group> 00334 Bool setVelocity (const String& velUnit=String("km/s"), 00335 MDoppler::Types velType=MDoppler::RADIO); 00336 00337 MDoppler::Types velocityDoppler () const {return velType_p;}; 00338 String velocityUnit () const {return velUnit_p;}; 00339 // 00340 Bool setWavelengthUnit (const String& waveUnit=String("mm")); 00341 String wavelengthUnit () const {return waveUnit_p;}; 00342 // 00343 Bool setNativeType (const SpectralCoordinate::SpecType spcType); 00344 SpectralCoordinate::SpecType nativeType() const {return nativeType_p;} 00345 00346 // </group> 00347 // Functions to convert to velocity (uses the current active 00348 // rest frequency) or wavelength. There is no reference frame 00349 // change but you can specify the velocity Doppler and the output 00350 // units of the velocity with function <src>setVelocity</src> 00351 // or <src>setWavelength</src> respectively. When the input is a frequency stored 00352 // as a Double it must be in the current units of the SpectralCoordinate. 00353 // 00354 // Note that the extra conversion layer (see function <src>setReferenceConversion</src>) 00355 // is active in the <src>pixelToVelocity</src> functions (because internally 00356 // the use <src>toWorld</src>) but not in the <src>frequencyToVelocity</src> 00357 // or <src>frequencyToWavelength</src> functions. 00358 // <group> 00359 Bool pixelToVelocity (Quantum<Double>& velocity, Double pixel) const; 00360 Bool pixelToVelocity (Double& velocity, Double pixel) const; 00361 Bool pixelToVelocity (Vector<Double>& velocity, const Vector<Double>& pixel) const; 00362 // 00363 Bool frequencyToVelocity (Quantum<Double>& velocity, Double frequency) const; 00364 Bool frequencyToVelocity (Quantum<Double>& velocity, const MFrequency& frequency) const; 00365 Bool frequencyToVelocity (Quantum<Double>& velocity, const MVFrequency& frequency) const; 00366 Bool frequencyToVelocity (Double& velocity, Double frequency) const; 00367 Bool frequencyToVelocity (Vector<Double>& velocity, const Vector<Double>& frequency) const; 00368 // 00369 Bool frequencyToWavelength (Vector<Double>& wavelength, const Vector<Double>& frequency) const; 00370 Bool frequencyToAirWavelength (Vector<Double>& wavelength, const Vector<Double>& frequency) const; 00371 // The refractive index of air (argument can be wavelength or airwavelength) 00372 // according to Greisen et al., 2006, A&A, 464, 746. 00373 // If airwavelength is used there is an error of the order of 1E-9. 00374 // Argument must be in micrometers! 00375 //static Double refractiveIndex(const Double& lambda_um); 00376 // </group> 00377 00378 // Functions to convert from velocity (uses the current active 00379 // rest frequency) or wavelength. There is no reference frame 00380 // change but you can specify the velocity Doppler and the output 00381 // units of the velocity with function <src>setVelocity</src> 00382 // and those of the wavelength with <src>setWavelength</src>. 00383 // When the input is a frequency stored 00384 // as a Double it must be in the current units of the SpectralCoordinate. 00385 // 00386 // Note that the extra conversion layer (see function <src>setReferenceConversion</src>) 00387 // is active in the <src>pixelToVelocity</src> functions (because internally 00388 // the use <src>toPixel</src>) but not in the <src>frequencyToVelocity</src> functions. 00389 // <group> 00390 Bool velocityToPixel (Double& pixel, Double velocity) const; 00391 Bool velocityToPixel (Vector<Double>& pixel, const Vector<Double>& velocity) const; 00392 // 00393 Bool velocityToFrequency (Double& frequency, Double velocity) const; 00394 Bool velocityToFrequency (Vector<Double>& frequency, const Vector<Double>& velocity) const; 00395 // 00396 Bool wavelengthToFrequency (Vector<Double>& frequency, const Vector<Double>& wavelength) const; 00397 Bool airWavelengthToFrequency (Vector<Double>& frequency, const Vector<Double>& wavelength) const; 00398 // </group> 00399 00400 // The SpectralCoordinate can maintain a list of rest frequencies 00401 // (e.g. multiple lines within a band). However, only 00402 // one of them is active (e.g. for velocity conversions) at any 00403 // one time. Function <src>restFrequency</src> returns that 00404 // frequency. Function <src>restFrequencies</src> returns 00405 // all of the possible restfrequencies. 00406 // 00407 // When you construct the SpectralCoordinate, you give it one rest frequency 00408 // and it is the active one. Thereafter you can add a new restfrequency 00409 // with function <src>setRestFrequency</src> (<src>append=True</src>) and 00410 // that frequency will become the active one. With this function 00411 // and <src>append=False</src>, the current active restfrequency will 00412 // be replaced by the one you give. 00413 // 00414 // You can change the list of 00415 // restfrequencies with function <src>setRestFrequencies</src>. When 00416 // you do so, you can either replace the list of rest frequencies or append to it. 00417 // You specify which frequency of the new (appended) list 00418 // becomes active. 00419 // 00420 // You can also select the active rest frequency either by an index into 00421 // the current list (exception if out of range) given by 00422 // <src>restFrequencies()</src> or by the value in the list 00423 // nearest to the frequency you give. 00424 // 00425 // Whenever you change the active rest frequency, the class internals 00426 // are adjusted (e.g. the velocity machine is updated). 00427 // <group> 00428 Double restFrequency() const; 00429 const Vector<Double>& restFrequencies() const; 00430 Bool setRestFrequency(Double newFrequency, Bool append=False); 00431 void setRestFrequencies(const Vector<Double>& newFrequencies, uInt which=0, 00432 Bool append=False); 00433 void selectRestFrequency(uInt which); 00434 void selectRestFrequency(Double frequency); 00435 String formatRestFrequencies () const; 00436 // </group> 00437 00438 // Retrieve/set the frequency system. Note that setting the 00439 // frequency system just changes the internal value of the 00440 // frequency system. In addition, it will reset the internal 00441 // conversion frequency system to the new type and delete any 00442 // conversion machines. 00443 // <group> 00444 MFrequency::Types frequencySystem(Bool showConversion=False) const; 00445 void setFrequencySystem(MFrequency::Types type, Bool verbose=True); 00446 00447 // Transform the SpectralCoordinate to a different native reference frame 00448 // keeping the conversion layer as is 00449 Bool transformFrequencySystem(MFrequency::Types type, 00450 const MEpoch& epoch, 00451 const MPosition& position, 00452 const MDirection& direction); 00453 // </group> 00454 00455 // Report the value of the requested attribute. 00456 // <group> 00457 virtual Vector<String> worldAxisNames() const; 00458 virtual Vector<Double> referencePixel() const; 00459 virtual Matrix<Double> linearTransform() const; 00460 virtual Vector<Double> increment() const; 00461 virtual Vector<Double> referenceValue() const; 00462 // </group> 00463 00464 // Set the value of the requested attribute. Note that these just 00465 // change the internal values, they do not cause any recomputation. 00466 // <group> 00467 virtual Bool setWorldAxisNames(const Vector<String> &names); 00468 virtual Bool setReferencePixel(const Vector<Double> &refPix); 00469 virtual Bool setLinearTransform(const Matrix<Double> &xform); 00470 virtual Bool setIncrement(const Vector<Double> &inc) ; 00471 virtual Bool setReferenceValue(const Vector<Double> &refval); 00472 // </group> 00473 00474 // Get the table, i.e. the pixel and world values. The length of these 00475 // Vectors will be zero if this axis is pure linear (i.e. if the 00476 // channel and frequencies are related through an increment and offset). 00477 // <group> 00478 Vector<Double> pixelValues() const; 00479 Vector<Double> worldValues() const; 00480 // </group> 00481 00482 // Set/get the unit. Adjust the increment and 00483 // reference value by the ratio of the old and new units. 00484 // The unit must be compatible with frequency. 00485 //<group> 00486 virtual Bool setWorldAxisUnits(const Vector<String> &units); 00487 virtual Vector<String> worldAxisUnits() const; 00488 //</group> 00489 00490 // Comparison function. Any private Double data members are compared 00491 // with the specified fractional tolerance. Don't compare on the specified 00492 // axes in the Coordinate. If the comparison returns False, 00493 // <src>errorMessage()</src> contains a message about why. 00494 // <group> 00495 virtual Bool near(const Coordinate& other, 00496 Double tol=1e-6) const; 00497 virtual Bool near(const Coordinate& other, 00498 const Vector<Int>& excludeAxes, 00499 Double tol=1e-6) const; 00500 // </group> 00501 00502 00503 // Find the Coordinate for when we Fourier Transform ourselves. This pointer 00504 // must be deleted by the caller. Axes specifies which axes of the Coordinate 00505 // you wish to transform. Shape specifies the shape of the image 00506 // associated with all the axes of the Coordinate. Currently the 00507 // output reference pixel is always shape/2. Cannot transform tabular 00508 // coordinates. If the pointer returned is 0, it failed with a message 00509 // in <src>errorMessage</src> 00510 virtual Coordinate* makeFourierCoordinate (const Vector<Bool>& axes, 00511 const Vector<Int>& shape) const; 00512 00513 00514 // Format a SpectralCoordinate coordinate world value nicely through the 00515 // common format interface. See <linkto class=Coordinate>Coordinate</linkto> 00516 // for basics. 00517 // 00518 // Format types SCIENTIFIC, FIXED, MIXED and DEFAULT are supported. 00519 // DEFAULT will use MIXED. 00520 // 00521 // The world value must always be given in native frequency units. 00522 // Use argument <src>unit</src> to determine what it will be 00523 // converted to for formatting. If <src>unit</src> is given, it 00524 // must be dimensionally consistent with Hz, m, or m/s. 00525 // If you give a unit consistent with m/s then the 00526 // appropriate velocity Doppler type is taken from that set by 00527 // function <src>setVelocity</src>. There is no frame conversion. 00528 // If <src>unit</src> is empty, the unit given by <src>setFormatUnit</src> 00529 // is used. If this is turn empty, then native units are used. 00530 virtual String format(String& unit, 00531 Coordinate::formatType format, 00532 Double worldValue, 00533 uInt worldAxis, 00534 Bool isAbsolute=True, 00535 Bool showAsAbsolute=True, 00536 Int precision=-1, Bool usePrecForFixed=False) const; 00537 00538 // Set the default formatter unit (which is initialized to empty). Must 00539 // be consistent with Hz or km/s. 00540 // If the given unit is illegal, False is returned and the internal state unchanged. 00541 // This unit is used by the function <src>format</src> when the given 00542 // unit is empty. 00543 // <group> 00544 String formatUnit () const {return formatUnit_p;} 00545 Bool setFormatUnit (const String& unit); 00546 // </group> 00547 00548 // Convert to FITS header record. When writing the FITS record, 00549 // the fields "ctype, crval, crpix", and "cdelt" must already be created. Other header 00550 // words are created as needed. Use <src>oneRelative=True</src> to 00551 // convert zero-relative SpectralCoordinate pixel coordinates to 00552 // one-relative FITS coordinates, and vice-versa. If <src>preferVelocity=True</src> 00553 // the primary axis type will be velocity, if <src>preferWavelength=True</src> it will 00554 // be wavelength, else frequency. For a velocity axis, if <src>opticalVelDef=False</src>, 00555 // the radio velocity definition will be used, else optical definition. Similarly for a 00556 // wavelength axis, if <src>airWaveDef=True</src> air wavelength will be used, the 00557 // default is vacuum wavelength. 00558 //<group> 00559 void toFITS(RecordInterface &header, uInt whichAxis, 00560 LogIO &logger, Bool oneRelative=True, 00561 Bool preferVelocity=True, Bool opticalVelDef=True, 00562 Bool preferWavelength=False, Bool airWaveDef=False) const; 00563 00564 // Old interface. Handled by wcs in new interface in FITSCoordinateUtil.cc 00565 // static Bool fromFITSOld(SpectralCoordinate &out, String &error, 00566 // const RecordInterface &header, 00567 // uInt whichAxis, 00568 // LogIO &logger, Bool oneRelative=True); 00569 //</group> 00570 00571 // Save the SpectralCoordinate into the supplied record using the supplied field name. 00572 // The field must not exist, otherwise <src>False</src> is returned. 00573 virtual Bool save(RecordInterface &container, 00574 const String &fieldName) const; 00575 00576 // Recover the SpectralCoordinate from a record. 00577 // A null pointer means that the restoration did not succeed. 00578 static SpectralCoordinate* restore(const RecordInterface &container, 00579 const String &fieldName); 00580 00581 // Convert from String to spectral type and vice versa. 00582 static Bool specTypetoString(String &stypeString, const SpecType &specType); 00583 static Bool stringtoSpecType(SpecType &specType, const String &stypeString); 00584 00585 // Make a copy of the SpectralCoordinate using new. The caller is responsible for calling 00586 // delete. 00587 virtual Coordinate* clone() const; 00588 00589 ostream& print(ostream& os) const; 00590 00591 // is this a tabular coordinate? 00592 Bool isTabular() const; 00593 00594 private: 00595 00596 SPtrHolder<TabularCoordinate> _tabular; // Tabular coordinate OR 00597 mutable ::wcsprm wcs_p; // wcs structure is used 00598 Double to_hz_p; // Convert from current world units to Hz 00599 Double to_m_p; // Convert from current wavelength units to m 00600 // 00601 MFrequency::Types type_p, conversionType_p; // Frequency system and conversion system 00602 Vector<Double> restfreqs_p; // List of possible rest frequencies 00603 uInt restfreqIdx_p; // Current active rest frequency index 00604 00605 // Conversion machines; for pixel<->world conversions only. 00606 mutable MFrequency::Convert* pConversionMachineTo_p; // For type_p -> conversionType_p 00607 mutable MFrequency::Convert* pConversionMachineFrom_p; // For conversionType_p -> type_p 00608 00609 VelocityMachine* pVelocityMachine_p; // The velocity machine does all conversions between world & velocity. 00610 MDoppler::Types velType_p; // Velocity Doppler 00611 String velUnit_p; // Velocity unit 00612 // 00613 String waveUnit_p; // Wavelength unit for conversions between world & wavelength 00614 SpectralCoordinate::SpecType nativeType_p; // The native spectral type 00615 // 00616 Unit unit_p; // World axis unit 00617 String axisName_p; // The axis name 00618 String formatUnit_p; // The default unit for the format function 00619 // 00620 MDirection direction_p; // These are a part of the frame set for 00621 MPosition position_p; // the reference conversions machines 00622 MEpoch epoch_p; // They are only private so we can save their state 00623 00624 // Format checker 00625 void checkFormat(Coordinate::formatType& format, 00626 const Bool ) const; 00627 00628 // Copy private data 00629 void copy (const SpectralCoordinate& other); 00630 00631 // Convert to and from conversion reference type 00632 virtual void convertTo (Vector<Double>& world) const; 00633 virtual void convertFrom (Vector<Double>& world) const; 00634 00635 // Deletes and sets pointer to 0 00636 void deleteVelocityMachine (); 00637 00638 // Deletes and sets pointers to 0 00639 void deleteConversionMachines (); 00640 00641 // Set up pixel<->world conversion machines 00642 // Returns: 3 (machines were noOPs, machines deleted) 00643 // 2 (types the same, machines deleted), 00644 // 1 (machines created and functioning) 00645 // -1 (machines could not make trial conversion, machines deleted) 00646 Int makeConversionMachines (MFrequency::Types type, MFrequency::Types conversionType, 00647 const MEpoch& epoch, 00648 const MPosition& position, 00649 const MDirection& direction); 00650 00651 // Create velocity<->frequency machine 00652 void makeVelocityMachine (const String& velUnit, 00653 MDoppler::Types velType, 00654 const Unit& freqUnit, 00655 MFrequency::Types freqType, 00656 Double restFreq); 00657 00658 // Make spectral wcs structure (items in Hz) 00659 static void makeWCS(wcsprm& wcs, const String& ctype, Double refPix, Double refVal, 00660 Double inc, Double pc, Double restFreq); 00661 00662 // Record restoration handling 00663 // <group> 00664 static SpectralCoordinate* restoreVersion1 (const RecordInterface& container); 00665 static SpectralCoordinate* restoreVersion2 (const RecordInterface& container); 00666 static void restoreVelocity (SpectralCoordinate*& pSpectral, 00667 const RecordInterface& subrec); 00668 static void restoreRestFrequencies (SpectralCoordinate*& pSpectral, 00669 const RecordInterface& subrec, 00670 Double restFreq); 00671 static void restoreConversion (SpectralCoordinate*& pSpectral, 00672 const RecordInterface& subrec); 00673 00674 // </group> 00675 00676 // Interconvert between the current units and wcs units (Hz) 00677 // <group> 00678 void toCurrent(Vector<Double>& value) const; 00679 void fromCurrent(Vector<Double>& value) const; 00680 // </group> 00681 00682 // Return unit conversion vector for converting to current units 00683 const Vector<Double> toCurrentFactors () const; 00684 00685 // Update Velocity Machine 00686 void updateVelocityMachine (const String& velUnit, 00687 MDoppler::Types velType); 00688 // Restore wcs stuff from Record 00689 static Bool wcsRestore (Double& crval, Double& crpix, Double& cdelt, 00690 Double& pc, String& ctype, 00691 const RecordInterface& rec); 00692 00693 // Save wcs stuff into Record 00694 Bool wcsSave (RecordInterface& rec, const wcsprm& wcs, 00695 const String& fieldName) const; 00696 00697 void _setTabulatedFrequencies(const Vector<Double>& freqs); 00698 00699 }; 00700 00701 ostream &operator<<(ostream &os, const SpectralCoordinate& spcoord); 00702 00703 } //# NAMESPACE CASACORE - END 00704 00705 00706 #endif