casa
$Rev:20696$
|
00001 //# CoordinateSystem.h: Interconvert pixel and image coordinates. 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: CoordinateSystem.h 20491 2009-01-16 08:33:56Z gervandiepen $ 00028 00029 00030 #ifndef COORDINATES_COORDINATESYSTEM_H 00031 #define COORDINATES_COORDINATESYSTEM_H 00032 00033 #include <casa/aips.h> 00034 #include <coordinates/Coordinates/Coordinate.h> 00035 #include <measures/Measures/MDirection.h> 00036 #include <measures/Measures/MFrequency.h> 00037 #include <coordinates/Coordinates/ObsInfo.h> 00038 #include <casa/Containers/Block.h> 00039 #include <measures/Measures/MDoppler.h> 00040 00041 namespace casa { //# NAMESPACE CASA - BEGIN 00042 00043 template<class T> class Matrix; 00044 class DirectionCoordinate; 00045 class LinearCoordinate; 00046 class SpectralCoordinate; 00047 class StokesCoordinate; 00048 class QualityCoordinate; 00049 class TabularCoordinate; 00050 class IPosition; 00051 class LogIO; 00052 00053 00054 // <summary> 00055 // Interconvert pixel and world coordinates. 00056 // </summary> 00057 00058 // <use visibility=export> 00059 00060 // <reviewed reviewer="Peter Barnes" date="1999/12/24" tests="tCoordinateSystem"> 00061 // </reviewed> 00062 // 00063 // <prerequisite> 00064 // <li> <linkto class=Coordinate>Coordinate</linkto> 00065 // </prerequisite> 00066 00067 // <synopsis> 00068 // CoordinateSystem is the normal interface to coordinate systems, 00069 // typically attached to an 00070 // <linkto class=ImageInterface>ImageInterface</linkto>, however the 00071 // coordinate system can be manipulated on its own. CoordinateSystem 00072 // is in turn composed from various classes derived from the base class 00073 // <linkto class=Coordinate>Coordinate</linkto>. 00074 // <p> 00075 // The fundamental operations available to the user of a 00076 // CoordinateSystem are: 00077 // <ol> 00078 // <li> Transform a world (physical) coordinate to a pixel coordinate 00079 // or vice versa via the methods toWorld and toPixel. 00080 // <li> Compose a CoordinateSystem from one or more independent groups, 00081 // typically the sky-plane transformation will be one group, and the 00082 // spectral axis will be another group. Each group consists of a linear 00083 // transformation (in FITS terms, apply <src>CRPIX, PC, CDELT</src>) 00084 // to turn the pixel coordinates into relative world coordinates, 00085 // followed by a (possibly) nonlinear projection to world coordinates 00086 // (i.e. apply <src>CTYPE and CRVAL</src>), typically a sky projection 00087 // or a frequency to velocity conversion. Note that an arbitrary rotation 00088 // or linear transformation can be applied by changing the 00089 // matrix. 00090 // <li> Transpose the world and/or pixel axes. 00091 // <li> One or more pixel or world axes may be removed. You are encouraged to 00092 // leave all the world axes if you remove a pixel axis. 00093 // Removing a world axis also removes the corresponding pixel axis. 00094 // <li> Calculate the CoordinateSystem that results from a subimage 00095 // operation. 00096 // </ol> 00097 // 00098 // Note that all the knowledge to do with removing and transposing axes is 00099 // maintained by the CoordinateSystem. The individual Coordinates, of which it 00100 // is made, know nothing about this. 00101 // <p> 00102 // Although the CoordinateSystem exists in the absence of an image, the usual 00103 // place you will find one is attached to an object derived from ImageInterface 00104 // such as PagedImage. When you do so, the physical (or pixel) axes in the image 00105 // map one to one with the pixel axes contained in the CoordinateSystem. 00106 // It cannot be any other way as when you create a PagedImage, it is checked 00107 // that there are equal numbers of image and CoordinateSystem pixel axes. 00108 // It is up to the creator of the PagedImage to make sure that they are 00109 // in the correct order. 00110 // <p> 00111 // However, the CoordinateSystem may have more world axes than pixel axes 00112 // because it is possible to remove a pixel axis but not its associated 00113 // world axis (for example for a moment image). Now, if you use 00114 // the CoordinateSystem functions 00115 // referencePixel and referenceValue, you will find the vector of reference 00116 // values will have more values than the vector of reference pixels, 00117 // if a pixel axis has been removed but not the world axis. You 00118 // must use the ancilliary functions provided 00119 // to find out what is where. 00120 // <p> 00121 // Let's consider an example where a CoordinateSystem consisted of 00122 // a DirectionCoordinate and a SpectralCoordinate. Let us say that 00123 // the first two pixel axes of the image associate (roughly of course 00124 // because lines of constant RA and DEC are not parallel with 00125 // the pixel coordinates) with the DirectionCoordinate (RA and DEC say) 00126 // and the third pixel axis is the SpectralCoordinate. 00127 // Now imagine we collapse the image along the second pixel axis (roughly, 00128 // the DEC axis). For the output image, we remove the second pixel axis 00129 // from the CoordinateSystem, but leave the world axis intact. This enables 00130 // us to still be able to make coordinate conversions for the first (roughly RA) 00131 // pixel axis. Thus, CoordinateSystem::referenceValue would return a Vector of 00132 // length 3 (for RA, DEC and spectral), but CoordinateSystem::referencePixel 00133 // would return a vector length 2 (for RA and spectral). 00134 // <p> 00135 // Now this CoordinateSystem has two Coordinates, a DirectionCoordinate and 00136 // a SpectralCoordinate, and let us state that that is the order in which 00137 // they exist in the CoordinateSystem (you can change them about if you wish); 00138 // they are coordinates number 0 and 1. The DirectionCoordinate has two axes 00139 // (RA and DEC) and the SpectralCoordinate has one axis. Only the 00140 // CoordinateSystem knows about removed axes, the DirectionCoordinate 00141 // itself is ignorant that it has been bisected. If you want to find 00142 // out what axis in the Coordinate system is where, you can use 00143 // the functions findPixelAxis or findWorldAxis. 00144 // 00145 // If we asked the former to find pixel axis 0, it would tell us that the 00146 // Coordinate number was 0 (the DirectionCoordinate) and that the axis in 00147 // that coordinate was 0 (the first axis in a DirectionCoordinate 00148 // is always longitude, the second always latitude). If we asked it to find 00149 // pixel axis 1, it would tell us that the coordinate number was 1 00150 // (the SpectralCoordinate) and that the axis in that coordinate was 0 00151 // (there is only one axis in a SpectralCoordinate). If we asked for 00152 // pixelAxis 2 that would generate an error because our squashed image 00153 // only has 2 pixel axes. 00154 // 00155 // Now, if we asked findWorldAxis similar questions, 00156 // it would tell us that worldAxis 0 in the CoordinateSystem can be found in 00157 // coordinate 0 (the DirectionCoordinate) in axis 0 of that DirectionCoordinate. 00158 // Similarly, worldAxis 1 in the CoordinateSystem (which has not been removed) 00159 // is in coordinate 0 (the DirectionCoordinate) in axis 1 of that 00160 // Finally, worldAxis 2 in the CoordinateSystem is in coordinate 1 00161 // (the SpectralCoordinate) in axis 0 of that SpectralCoordinate. 00162 // <p> 00163 // Other handy functions are pixelAxes and worldAxes. 00164 // These list the pixel and world axes in 00165 // the CoordinateSystem for the specified coordinate. Thus, if we asked 00166 // pixelAxes to find the pixel axes for coordinate 0 (the DirectionCoordinate) 00167 // in the CoordinateSystem it would return a vector [0, -1] indicating 00168 // the second axis of the DirectionCoordinate has been removed. However, 00169 // the worldAxes function would return [0,1] as no world axis has been removed. 00170 // Similarly, if operated on coordinate 1 (the SpectralCoordinate), pixelAxes 00171 // would return [1] and worldAxes would return [2]. 00172 // 00173 // Because you can transpose the CoordinateSystem about, you should NEVER ASSUME 00174 // ANYTHING except that the pixel axes of the CoordinateSystem map to the pixel 00175 // axes of the image when you first construct the image. 00176 // 00177 // <p> 00178 // SpectralCoordinate and DirectionCoordinate both have a (non-virtual) function 00179 // called <src>setReferenceConversion</src>. This enables an extra conversion 00180 // layer so that conversion between pixel and world can go to a reference frame 00181 // other than the construction reference. When you use the function 00182 // <src>convert</src>, these layers are active, but ONLY if the 00183 // requested conversion is purely between pixel and world. For 00184 // a SpectralCoordinate this must always be true (only has one axis) 00185 // but for the DirectionCoordinate you might request a mixed 00186 // pixel/world conversion. In this case, the extra conversion layer 00187 // is ill-defined and not active (for the DirectionCoordinate part of it). 00188 // </synopsis> 00189 00190 // <note role=caution> 00191 // All pixels coordinates are zero relative. 00192 // </note> 00193 00194 // <example> 00195 // See the example in <linkto module=Coordinates>Coordinates.h</linkto> 00196 // and tCoordinateSystem.cc 00197 // </example> 00198 00199 // <motivation> 00200 // Coordinate systems for images. 00201 // </motivation> 00202 // 00203 // <thrown> 00204 // <li> AipsError 00205 // </thrown> 00206 // 00207 // <todo asof="1997/01/13"> 00208 // <li> Undelete individual removed axes. 00209 // <li> Non-integral pixel shifts/decimations in subimage operations? 00210 // <li> Copy-on-write for efficiency? 00211 // <li> Check if the classes are thread safe in general 00212 // </todo> 00213 // 00214 00215 00216 class CoordinateSystem : public Coordinate 00217 { 00218 public: 00219 // Default constructor. This is an empty CoordinateSystem. 00220 CoordinateSystem(); 00221 00222 // Copying constructor (copy semantics) 00223 CoordinateSystem(const CoordinateSystem &other); 00224 00225 // Assignment (copy semantics). 00226 CoordinateSystem &operator=(const CoordinateSystem &other); 00227 00228 // Destructor 00229 virtual ~CoordinateSystem(); 00230 00231 // Add another Coordinate to this CoordinateSystem. This addition is done 00232 // by copying, so that if coord changes the change is NOT 00233 // reflected in the CoordinateSystem. 00234 void addCoordinate(const Coordinate &coord); 00235 00236 // Transpose the CoordinateSystem so that world axis 0 is 00237 // newWorldOrder(0) and so on for all the other axes. 00238 // newPixelOrder works similarly. Normally you will give the 00239 // same transformation vector for both the world and pixel transformations, 00240 // however this is not required. 00241 void transpose(const Vector<Int> &newWorldOrder, 00242 const Vector<Int> &newPixelOrder); 00243 00244 // Find the world and pixel axis mappings to the supplied CoordinateSystem 00245 // from the current coordinate system. <src>False</src> is 00246 // returned if either the supplied or current coordinate system, 00247 // has no world axes (and a message recoverable with function 00248 // errorMessage indicating why). Otherwise <src>True</src> is returned. 00249 // worldAxisMap(i) is the location of world axis <src>i</src> (from the 00250 // supplied CoordinateSystem, cSys, in the current CoordinateSystem. 00251 // worldAxisTranspose(i) is the location of world axis 00252 // <src>i</src> (from the current CoordinateSystem) in the supplied 00253 // CoordinateSystem, cSys. The output vectors 00254 // are resized appropriately by this function. A value of -1 00255 // in either vector means that the axis could not be found in the other 00256 // CoordinateSystem. The vector <src>refChange</src> says 00257 // if the types are the same, is there a reference type change 00258 // (e.g. TOPO versus LSR for the SpectralCoordinate, 00259 // or J2000 versus GALACTIC for DirectionCoordinate). Thus 00260 // if refChange(i) is True, it means world axis i in the 00261 // current CoordinateSystem was matched, but has a different 00262 // reference type to that of the supplied CoordinateSystem. 00263 // <group> 00264 Bool worldMap (Vector<Int>& worldAxisMap, 00265 Vector<Int>& worldAxisTranspose, 00266 Vector<Bool>& refChange, 00267 const CoordinateSystem& cSys) const; 00268 Bool pixelMap (Vector<Int>& pixelAxisMap, 00269 Vector<Int>& pixelAxisTranspose, 00270 const CoordinateSystem& cSys) const; 00271 // </group> 00272 00273 // Remove a world or pixel axis. When its value is required for forward or 00274 // backwards transformations, use <src>replacement</src> 00275 // <br> 00276 // When a world axis is removed, the corresponding pixel axis is removed 00277 // too, because it makes no sense having a pixel axis without world 00278 // coordinates. 00279 // <br> 00280 // Removing a pixel axis without removing the corresponding world axis 00281 // is, however, possible and meaningful. It can be used when e.g. a 00282 // frequency plane is taken from a cube. The plane has 2 pixel axes, but 00283 // the 3rd world axis can still describe the frequency coordinate. 00284 // See also the functions in <linkto class=CoordinateUtil>CoordinateUtil</linkto> 00285 // for removing lists of pixel/world axes (tricky because they shift down) 00286 // 00287 // False is returned (an error in <src>errorMessage()</src> will be set) 00288 // if the axis is illegal, else returns True. 00289 // <group> 00290 Bool removeWorldAxis(uInt axis, Double replacement); 00291 Bool removePixelAxis(uInt axis, Double replacement); 00292 // </group> 00293 00294 // Return a CoordinateSystem appropriate for a shift of origin 00295 // (the shift is subtracted from the reference pixel) 00296 // and change of increment (the increments are multipled 00297 // by the factor). Both vectors should be of length nPixelAxes(). 00298 // 00299 // The newShape vector is only needed for the StokesCoordinate, 00300 // if any. If this vector is of length zero, the new StokesCoordinate 00301 // is formed from all of the available input Stokes after application 00302 // of the shift and increment factor. Otherwise, 00303 // the new Stokes axis length is equal to that specified after 00304 // appliction of the shift and increment and excess values 00305 // discarded. In addition, for any StokesCoordinate, the 00306 // shift and factor must be integer. So <src>Int(value+0.5)</src> 00307 // is taken before they are used. 00308 // <group> 00309 CoordinateSystem subImage(const Vector<Float> &originShift, 00310 const Vector<Float> &incrFac, 00311 const Vector<Int>& newShape) const; 00312 void subImageInSitu (const Vector<Float> &originShift, 00313 const Vector<Float> &incrFac, 00314 const Vector<Int>& newShape); 00315 // </group> 00316 00317 // Untranspose and undelete all axes. Does not undo the effects of 00318 // subimaging. 00319 void restoreOriginal(); 00320 00321 // Returns the number of Coordinates that this CoordinateSystem contains. 00322 // The order might be unrelated to the axis order through the results of 00323 // transposing and removing axes. 00324 uInt nCoordinates() const; 00325 00326 // For a given Coordinate say where its world and pixel axes are in 00327 // this CoordinateSystem. The position in the returned Vector is its 00328 // axis number in the Coordinate, and its value is the axis 00329 // number in the CoordinateSystem. If the value is less than zero the axis 00330 // has been removed from this CoordinateSystem. 00331 // <group> 00332 Vector<Int> worldAxes(uInt whichCoord) const; 00333 Vector<Int> pixelAxes(uInt whichCoord) const; 00334 // </group> 00335 00336 // Return the type of the given Coordinate. 00337 Coordinate::Type type(uInt whichCoordinate) const; 00338 00339 // Returns the type of the given Coordinate as a string. 00340 String showType(uInt whichCoordinate) const; 00341 00342 // Return the given Coordinate as a reference to the base 00343 // class object. 00344 const Coordinate& coordinate(uInt which) const; 00345 00346 // Return the given Coordinate. 00347 // Throws an exception if retrieved as the wrong type. 00348 // The versions which take no parameters will return the 00349 // first (or in most cases only) coordinate of the requested type. 00350 // If no such coordinate exists, an exception is thrown. 00351 // <group> 00352 const LinearCoordinate &linearCoordinate(uInt which) const; 00353 const DirectionCoordinate &directionCoordinate() const; 00354 const DirectionCoordinate &directionCoordinate(uInt which) const; 00355 00356 const SpectralCoordinate &spectralCoordinate(uInt which) const; 00357 const SpectralCoordinate &spectralCoordinate() const; 00358 const StokesCoordinate &stokesCoordinate() const; 00359 00360 const StokesCoordinate &stokesCoordinate(uInt which) const; 00361 const QualityCoordinate &qualityCoordinate(uInt which) const; 00362 const TabularCoordinate &tabularCoordinate(uInt which) const; 00363 // </group> 00364 00365 // Replace one Coordinate with another. The mapping of the coordinate axes 00366 // to the CoordinateSystem axes is unchanged, therefore the number of world 00367 // and pixel axes must not be changed. You can, somewhat dangerously, 00368 // change the type of the coordinate however. For example, replace a 00369 // SpectralCoordinate with a 1-D Linearcoordinate. It is dangerous because 00370 // the world replacement values (see removeWorldAxis) have to be scaled. 00371 // The algorithm tries to find a scale factor between the old and new 00372 // units and applies it to the replacement values. If it can't find 00373 // a scale factor (non-conformant units) then the reference value is 00374 // used for any world replacement values. If the latter occurs, 00375 // it returns False, else True is returned. 00376 Bool replaceCoordinate(const Coordinate &newCoordinate, uInt whichCoordinate); 00377 00378 // Find the Coordinate number that corresponds to the given type. 00379 // Since there might be more than one Coordinate of a given type you 00380 // can call this multiple times setting <src>afterCoord</src> to 00381 // the last value found. Returns -1 if a Coordinate of the desired 00382 // type is not found. 00383 Int findCoordinate(Coordinate::Type type, Int afterCoord = -1) const; 00384 00385 // Given an axis number (pixel or world) in the CoordinateSystem, 00386 // find the corresponding coordinate number and axis in that Coordinate. 00387 // The returned values are set to -1 if the axis does not exist. 00388 // <group> 00389 void findWorldAxis(Int &coordinate, Int &axisInCoordinate, 00390 uInt axisInCoordinateSystem) const; 00391 void findPixelAxis(Int &coordinate, Int &axisInCoordinate, 00392 uInt axisInCoordinateSystem) const; 00393 // </group> 00394 00395 // Find the world axis for the given pixel axis in a CoordinateSystem. 00396 // Returns -1 if the world axis is unavailable (e.g. if it has been 00397 // removed). 00398 Int pixelAxisToWorldAxis(uInt pixelAxis) const; 00399 00400 // Find the pixel axis for the given world axis in a CoordinateSystem. 00401 // Returns -1 if the pixel axis is unavailable (e.g. if it has been 00402 // removed). 00403 Int worldAxisToPixelAxis(uInt worldAxis) const; 00404 00405 // Returns <src>Coordinate::COORDSYS</src> 00406 virtual Coordinate::Type type() const; 00407 00408 // Always returns "System" 00409 virtual String showType() const; 00410 00411 // Sums the number of axes in the Coordinates that the CoordinateSystem 00412 // contains, allowing for removed axes. 00413 // <group> 00414 virtual uInt nPixelAxes() const; 00415 virtual uInt nWorldAxes() const; 00416 // </group> 00417 00418 00419 // Convert a pixel position to a world position or vice versa. Returns True 00420 // if the conversion succeeds, otherwise it returns <src>False</src> and 00421 // <src>errorMessage()</src> contains an error message. 00422 // The input vector must be of length <src>nPixelAxes</src> or 00423 // <src>nWorldAxes</src>. The output vector is resized appropriately. 00424 // <group> 00425 virtual Bool toWorld(Vector<Double> &world, 00426 const Vector<Double> &pixel) const; 00427 // This one throws an exception rather than returning False. After all, that's 00428 // what exceptions are for. 00429 virtual Vector<Double> toWorld(const Vector<Double> &pixel) const; 00430 virtual Vector<Double> toWorld(const IPosition& pixel) const; 00431 virtual Bool toPixel(Vector<Double> &pixel, 00432 const Vector<Double> &world) const; 00433 // This one throws an exception rather than returning False. 00434 virtual Vector<Double> toPixel(const Vector<Double> &world) const; 00435 // </group> 00436 00437 // convert a pixel "length" to a world "length" 00438 virtual Quantity toWorldLength( 00439 const Double nPixels, 00440 const uInt pixelAxis 00441 ) const; 00442 00443 // This is provided as a convenience since it is a very commonly desired 00444 // operation through CoordinateSystem. The output vector is resized. 00445 Bool toWorld(Vector<Double> &world, const IPosition &pixel) const; 00446 00447 // Batch up a lot of transformations. The first (most rapidly varying) axis 00448 // of the matrices contain the coordinates. Returns False if any conversion 00449 // failed and <src>errorMessage()</src> will hold a message. 00450 // The <src>failures</src> array (True for fail, False for success) 00451 // is the length of the number of conversions and 00452 // holds an error status for each conversion. 00453 // <group> 00454 virtual Bool toWorldMany(Matrix<Double>& world, 00455 const Matrix<Double>& pixel, 00456 Vector<Bool>& failures) const; 00457 virtual Bool toPixelMany(Matrix<Double>& pixel, 00458 const Matrix<Double>& world, 00459 Vector<Bool>& failures) const; 00460 // </group> 00461 00462 00463 // Mixed pixel/world coordinate conversion. 00464 // <src>worldIn</src> and <src>worldAxes</src> are of length n<src>worldAxes</src>. 00465 // <src>pixelIn</src> and <src>pixelAxes</src> are of length nPixelAxes. 00466 // <src>worldAxes(i)=True</src> specifies you have given a world 00467 // value in <src>worldIn(i)</src> to convert to pixel. 00468 // <src>pixelAxes(i)=True</src> specifies you have given a pixel 00469 // value in <src>pixelIn(i)</src> to convert to world. 00470 // You cannot specify the same axis via <src>worldAxes</src> 00471 // and pixelAxes. 00472 // Values in <src>pixelIn</src> are converted to world and 00473 // put into <src>worldOut</src> in the appropriate world axis 00474 // location. Values in <src>worldIn</src> are copied to 00475 // <src>worldOut</src>. 00476 // Values in <src>worldIn</src> are converted to pixel and 00477 // put into <src>pixelOut</src> in the appropriate pixel axis 00478 // location. Values in <src>pixelIn</src> are copied to 00479 // <src>pixelOut</src>. Vectors 00480 // <src>worldMin</src> and <src>worldMax</src> specify the range of the world 00481 // coordinate (in the world axis units of that world axis 00482 // in the coordinate system) being solved for in a mixed calculation 00483 // for each world axis. They are only actually used for DirectionCoordinates 00484 // and for all other coordinates the relevant elements are ignored. 00485 // Functions <src>setWorldMixRanges, worldMixMin, worldMixMax</src> can be 00486 // used to compute and recover the world ranges. If you don't know 00487 // the values, use functions <src>setDefaultWorldMixRanges, worldMixMin, worldMixMax</src>. 00488 // Removed axes are handled (for example, a removed pixel 00489 // axis with remaining corresponding world axis will 00490 // correctly be converted to world using the replacement 00491 // value). 00492 // Returns True if the conversion succeeds, otherwise it returns <src>False</src> and 00493 // <src>errorMessage()</src> contains an error message. The output vectors 00494 // are resized. 00495 virtual Bool toMix(Vector<Double>& worldOut, 00496 Vector<Double>& pixelOut, 00497 const Vector<Double>& worldIn, 00498 const Vector<Double>& pixelIn, 00499 const Vector<Bool>& worldAxes, 00500 const Vector<Bool>& pixelAxes, 00501 const Vector<Double>& worldMin, 00502 const Vector<Double>& worldMax) const; 00503 00504 // Compute and recover the world min and max ranges, for use in function <src>toMix</src>, 00505 // for a lattice of the given shape (must be of length <src>nPixelAxes()</src>). 00506 // Removed pixel axes (with remaining world axes are handled). With 00507 // the retrieval functions, the output vectors are resized. They return 00508 // False if they fail (and then <src>setDefaultWorldMixRanges</src> generates the ranges) 00509 // with a reason in <src>errorMessage()</src>. 00510 // The <src>setDefaultWorldMixRanges</src> function 00511 // gives you a useful default range if you don't know the shape. 00512 // The only Coordinate type for which these ranges are actually 00513 // used in <src>toMix</src> is DirectionCoordinate (because its coupled). For 00514 // the rest the functionality is provided but never used 00515 // by toMix. 00516 //<group> 00517 virtual Bool setWorldMixRanges (const IPosition& shape); 00518 virtual void setDefaultWorldMixRanges (); 00519 virtual Vector<Double> worldMixMin () const; 00520 virtual Vector<Double> worldMixMax () const; 00521 //</group> 00522 00523 // Make absolute coordinates relative and vice-versa (relative 00524 // to the reference pixel/value). The vectors must be of length 00525 // <src>nPixelAxes()</src> or <src>nWorldAxes()</src> 00526 //<group> 00527 virtual void makePixelRelative (Vector<Double>& pixel) const; 00528 virtual void makePixelAbsolute (Vector<Double>& pixel) const; 00529 virtual void makeWorldRelative (Vector<Double>& world) const; 00530 virtual void makeWorldAbsolute (Vector<Double>& world) const; 00531 //</group> 00532 00533 // Make absolute coordinates relative and vice versa with respect 00534 // to the given reference value. Add the other functions in this grouping 00535 // as needed. The vectors must be of length 00536 // <src>nPixelAxes()</src> or <src>nWorldAxes()</src> 00537 //<group> 00538 virtual void makeWorldAbsoluteRef (Vector<Double>& world, 00539 const Vector<Double>& refVal) const; 00540 //</group> 00541 00542 // Batch up a lot of absolute/relative transformations. 00543 // Parameters as above for 00544 // <src>toWorldMany</src> and <src>toPixelMany</src> 00545 // <group> 00546 virtual void makePixelRelativeMany (Matrix<Double>& pixel) const; 00547 virtual void makePixelAbsoluteMany (Matrix<Double>& pixel) const; 00548 virtual void makeWorldRelativeMany (Matrix<Double>& world) const; 00549 virtual void makeWorldAbsoluteMany (Matrix<Double>& world) const; 00550 // </group> 00551 00552 00553 // General coordinate conversion. Only works if no axes 00554 // have been removed and no axis reordering has occurred. 00555 // That is pixel axes and world axes are the same. 00556 // 00557 // Specify the input coordinate values, input units, 00558 // whether value is absolute (or relative). For output 00559 // specify units and abs/rel. Units may be 'pix' and velocity consistent 00560 // units (e.g. m/s). Specify doppler types if velocities 00561 // involved. The pixel offsets allow for the input 00562 // and output pixel coordinates to be something other than 0-rel. 00563 // If your pixel coordinates are 1-rel input and output, set the 00564 // offsets to -1 and 1 00565 // 00566 // The Matrix interface lets you do many conversions efficiently. 00567 // Use <src>Matrix(nAxes, nConversions) </src> and 00568 // <src>Matrix.column()=coordinate</src> or 00569 // <src>Matrix(axis, iConversion)</src> to get the order right. 00570 // 00571 // These functions invoke <src>toMix</src> 00572 // so make sure you call <src>setWorldMixRanges</src> 00573 // first to set up the world ranges. 00574 // <group> 00575 Bool convert (Vector<Double>& coordOut, 00576 const Vector<Double>& coordin, 00577 const Vector<Bool>& absIn, 00578 const Vector<String>& unitsIn, 00579 MDoppler::Types dopplerIn, 00580 const Vector<Bool>& absOut, 00581 const Vector<String>& unitsOut, 00582 MDoppler::Types dopplerOut, 00583 Double pixInOffset = 0.0, 00584 Double pixOutOffset = 0.0); 00585 Bool convert (Matrix<Double>& coordOut, 00586 const Matrix<Double>& coordIn, 00587 const Vector<Bool>& absIn, 00588 const Vector<String>& unitsIn, 00589 MDoppler::Types dopplerIn, 00590 const Vector<Bool>& absOut, 00591 const Vector<String>& unitsOut, 00592 MDoppler::Types dopplerOut, 00593 Double pixInOffset = 0.0, 00594 Double pixOutOffset = 0.0); 00595 // </group> 00596 00597 // Return the requested attribute. 00598 // <group> 00599 virtual Vector<String> worldAxisNames() const; 00600 virtual Vector<Double> referencePixel() const; 00601 virtual Matrix<Double> linearTransform() const; 00602 virtual Vector<Double> increment() const; 00603 virtual Vector<Double> referenceValue() const; 00604 // </group> 00605 00606 // Set the requested attribute. Note that these just 00607 // change the internal values, they do not cause any recomputation. 00608 // <group> 00609 virtual Bool setWorldAxisNames(const Vector<String> &names); 00610 virtual Bool setReferencePixel(const Vector<Double> &refPix); 00611 virtual Bool setLinearTransform(const Matrix<Double> &xform); 00612 virtual Bool setIncrement(const Vector<Double> &inc); 00613 virtual Bool setReferenceValue(const Vector<Double> &refval); 00614 // </group> 00615 00616 // Set/get the units. Adjust the increment and 00617 // reference value by the ratio of the old and new units. This implies that 00618 // the units must be known <linkto class=Unit>Unit</linkto> strings, and 00619 // that they must be compatible, e.g. they can't change from time to 00620 // length. 00621 // <group> 00622 virtual Bool setWorldAxisUnits(const Vector<String> &units); 00623 virtual Vector<String> worldAxisUnits() const; 00624 // </group> 00625 00626 // Comparison function. Any private Double data members are compared 00627 // with the specified fractional tolerance. Don't compare on the specified 00628 // pixel axes in the CoordinateSystem. If the comparison returns 00629 // <src>False</src>, errorMessage() contains a message about why. 00630 // <group> 00631 virtual Bool near(const Coordinate& other, Double tol=1e-6) const; 00632 virtual Bool near(const Coordinate& other, 00633 const Vector<Int>& excludePixelAxes, 00634 Double tol=1e-6) const; 00635 // </group> 00636 00637 // This function compares this and the other coordinate system, 00638 // but ONLY for the non-removed pixel axes. It is less strict 00639 // than near, which, for example, insists the number of coordinates 00640 // is the same in each CS 00641 Bool nearPixel (const CoordinateSystem& other, Double tol=1e-6) const; 00642 00643 00644 // Format a world value nicely through the 00645 // common format interface. See <linkto class=Coordinate>Coordinate</linkto> 00646 // for basics. 00647 // 00648 // You specify a world value and its corresponding world axis in 00649 // the CoordinateSystem. 00650 // 00651 // For the specified worldAxis, the coordinate 00652 // number in the CoordinateSystem is found and the actual derived Coordinate 00653 // class object for that number is created. The arguments to the formatting 00654 // function are then passed on to the formatter for that Coordinate. So 00655 // refer to the other derived Coordinate classes for specifics on the 00656 // formatting. 00657 virtual String format( 00658 String& units, 00659 Coordinate::formatType format, 00660 Double worldValue, 00661 uInt worldAxis, 00662 Bool isAbsolute=True, 00663 Bool showAsAbsolute=True, 00664 Int precision=-1, Bool usePrecForMixed=False 00665 ) const; 00666 00667 // Miscellaneous information related to an observation, for example the 00668 // observation date. 00669 // <group> 00670 ObsInfo obsInfo() const; 00671 void setObsInfo(const ObsInfo &obsinfo); 00672 // </group> 00673 00674 // Find the CoordinateSystem (you can safely caste the pointer to a CoordinateSystem) 00675 // for when we Fourier Transform ourselves. This pointer 00676 // must be deleted by the caller. Axes specifies which pixel axes of the Coordinate 00677 // System you wish to transform. Shape specifies the shape of the image 00678 // associated with all the axes of the CoordinateSystem. Currently you have 00679 // no control over the reference pixel, it is always shape/2. 00680 virtual Coordinate* makeFourierCoordinate (const Vector<Bool>& axes, 00681 const Vector<Int>& shape) const; 00682 00683 00684 // Save the CoordinateSystem into the supplied record using the supplied field name. 00685 // The field must not exist, otherwise <src>False</src> is returned. 00686 // If the CoordinateSystem is empty <src>False</src> is also returned. 00687 // If <src>False</src> is returned, errorMessage() contains a message about why. 00688 virtual Bool save(RecordInterface &container, 00689 const String &fieldName) const; 00690 00691 // Restore the CoordinateSystem from a record. The <src>fieldName</src> 00692 // can be empty, in which case the CoordinateSystem is restored 00693 // directly from the Record, rather than a subrecord of it. 00694 // A null pointer means that the restoration did not succeed - probably 00695 // because fieldName doesn't exist or doesn't contain a CoordinateSystem. 00696 static CoordinateSystem *restore(const RecordInterface &container, 00697 const String &fieldName); 00698 00699 // Make a copy of the CoordinateSystem using new. The caller is responsible for calling 00700 // delete. 00701 virtual Coordinate* clone() const; 00702 00703 // Convert a CoordinateSystem to FITS, i.e. fill in ctype etc. In the record 00704 // the keywords are vectors, it is expected that the actual FITS code will 00705 // split them into scalars and upcase the names. Returns False if one of the 00706 // keywords is already taken. 00707 // 00708 // If writeWCS is True, attempt to write the WCS convention (Greisen and 00709 // Calabretta "Representation of celestial coordinates in FITS"). 00710 // Use <src>oneRelative=True</src> to convert zero-relative pixel coordinates to 00711 // one-relative FITS coordinates. 00712 // 00713 // prefix gives the prefix for the FITS keywords. E.g., 00714 // if prefix="c" then crval, cdelt etc. 00715 // if prefix="d" then drval, ddelt etc. 00716 //# Much of the work in to/from fits should be moved to the individual 00717 //# classes. 00718 Bool toFITSHeader(RecordInterface &header, 00719 IPosition &shape, 00720 Bool oneRelative, 00721 Char prefix = 'c', Bool writeWCS=True, 00722 Bool preferVelocity=True, 00723 Bool opticalVelocity=True, 00724 Bool preferWavelength=False, 00725 Bool airWavelength=False) const; 00726 00727 // Probably even if we return False we should set up the best linear 00728 // coordinate that we can. 00729 // Use oneRelative=True to convert one-relative FITS pixel coordinates to 00730 // zero-relative aips++ coordinates. On output, <src>stokesFITSValue</src> 00731 // holds the FITS value of any unofficial Stokes (beam, optical depth, 00732 // spectral index) for the last unofficial value accessed (-1 if none). 00733 // The idea is that if the Stokes axis is of length one and holds an unofficial value, 00734 // you should drop the STokes axis and convert that value to <src>ImageInfo::ImageTypes</src> 00735 // with <src>ImageInfo::imageTypeFromFITSValue</src>. If on input, <src>stokesFITSValue</src> 00736 // is positive, then a warning is issued if any unofficial values are encountered. 00737 // Otherwise no warning is issued. 00738 //# cf comment in toFITS. 00739 static Bool fromFITSHeader(Int& stokesFITSValue, 00740 CoordinateSystem &coordsys, 00741 RecordInterface& recHeader, 00742 const Vector<String>& header, 00743 const IPosition& shape, 00744 uInt which=0); 00745 00746 // List all header information. By default, the reference 00747 // values and pixel increments are converted to a "nice" unit before 00748 // formatting (e.g. RA is shown as HH:MM:SS.S). 00749 // For spectral axes, both frequency and velocity information is listed. You 00750 // can specify what velocity definition you want with <src>velocityType</src> 00751 // If you wish, you can specify two shapes; a lattice and tile shape 00752 // (perhaps an image from which the CoordinateSystem came) 00753 // If you give (both of) these, they are included in the listing. If you pass 00754 // in zero length <src>IPositions</src> then they are not included in 00755 // the listing. If <src>postlocally=True</src> the formatted summary lines 00756 // are written locally only to the sink, and then returned by the return value 00757 // vector. 00758 Vector<String> list(LogIO& os, MDoppler::Types doppler, 00759 const IPosition& latticeShape, 00760 const IPosition& tileShape, Bool postLocally=False) const; 00761 00762 // Does this coordinate system have a spectral axis? 00763 Bool hasSpectralAxis() const; 00764 00765 // what number is the spectral axis? Returns -1 if no spectral axis exists. 00766 Int spectralAxisNumber() const; 00767 00768 // what number is the spectral coordinate? Returns -1 if no spectral coordinate exists. 00769 Int spectralCoordinateNumber() const; 00770 00771 00772 // does this coordinate system have a polarizaion/stokes coordinate? 00773 Bool hasPolarizationCoordinate() const; 00774 00775 // Given a stokes or polarization parameter, find the pixel location. 00776 // Note the client is responsible for any boundedness checks 00777 // (eg finite number of stokes in an image). 00778 Int stokesPixelNumber(const String& stokesString) const; 00779 00780 // what is the number of the polarization/stokes coordinate? 00781 // Returns -1 if no stokes coordinate exists. 00782 Int polarizationCoordinateNumber() const; 00783 00784 // what is the number of the polarization/stokes axis? 00785 // Returns -1 if no stokes axis exists. 00786 Int polarizationAxisNumber() const; 00787 00788 // Does this coordinate system have a quality axis? 00789 Bool hasQualityAxis() const; 00790 00791 // what number is the quality axis? Returns -1 if no quality axis exists. 00792 Int qualityAxisNumber() const; 00793 00794 // what is the number of the quality coordinate? 00795 // Returns -1 if no quality coordinate exists. 00796 Int qualityCoordinateNumber() const; 00797 00798 // Given a quality parameter, find the pixel location. 00799 // Note the client is responsible for any boundedness checks 00800 // (eg finite number of quality in an image). 00801 Int qualityPixelNumber(const String& qualityString) const; 00802 00803 String qualityAtPixel(const uInt pixel) const; 00804 00805 Int directionCoordinateNumber() const; 00806 00807 Bool hasDirectionCoordinate() const; 00808 00809 Vector<Int> directionAxesNumbers() const; 00810 00811 String stokesAtPixel(const uInt pixel) const; 00812 00813 Int linearCoordinateNumber() const; 00814 00815 Bool hasLinearCoordinate() const; 00816 00817 Vector<Int> linearAxesNumbers() const; 00818 00819 // Get the 0 based order of the minimal match strings specified in <src>order</src>. 00820 // If <src>requireAll</src> is True, checks are done to ensure that all axes in 00821 // the coordinate system are uniquely specified in <src>order</src>. 00822 // If <src>allowFriendlyNames</src> is True, the following (fully specified) strings will 00823 // match the specified axes: 00824 // "spectral" matches both "frequency" and "velocity". 00825 // "ra" matches "right ascension" 00826 Vector<Int> getWorldAxesOrder( 00827 Vector<String>& myNames, Bool requireAll, 00828 Bool allowFriendlyNames=False 00829 ) const; 00830 00831 00832 private: 00833 // Where we store copies of the coordinates we are created with. 00834 PtrBlock<Coordinate *> coordinates_p; 00835 00836 // For coordinate[i] axis[j], 00837 // world_maps_p[i][j], if >=0 gives the location in the 00838 // input vector that maps to this coord/axis, 00839 // <0 means that the axis has been removed 00840 // world_tmp_p[i] a temporary vector length coord[i]->nworldAxes() 00841 // replacement_values_p[i][j] value to use for this axis if removed 00842 PtrBlock<Block<Int> *> world_maps_p; 00843 PtrBlock<Vector<Double> *> world_tmps_p; 00844 PtrBlock<Vector<Double> *> world_replacement_values_p; 00845 00846 // Same meanings as for the world*'s above. 00847 PtrBlock<Block<Int> *> pixel_maps_p; 00848 PtrBlock<Vector<Double> *> pixel_tmps_p; 00849 PtrBlock<Vector<Double> *> pixel_replacement_values_p; 00850 00851 // These temporaries all needed for the toMix function 00852 PtrBlock<Vector<Bool> *> worldAxes_tmps_p; 00853 PtrBlock<Vector<Bool> *> pixelAxes_tmps_p; 00854 PtrBlock<Vector<Double> *> worldOut_tmps_p; 00855 PtrBlock<Vector<Double> *> pixelOut_tmps_p; 00856 PtrBlock<Vector<Double> *> worldMin_tmps_p; 00857 PtrBlock<Vector<Double> *> worldMax_tmps_p; 00858 00859 // Miscellaneous information about the observation associated with this 00860 // Coordinate System. 00861 ObsInfo obsinfo_p; 00862 00863 const static String _class; 00864 static map<String, String> _friendlyAxisMap; 00865 00866 static void _initFriendlyAxisMap(); 00867 00868 // Helper functions to group common code. 00869 Bool mapOne(Vector<Int>& worldAxisMap, 00870 Vector<Int>& worldAxisTranspose, 00871 Vector<Bool>& refChange, 00872 const CoordinateSystem& cSys, 00873 const CoordinateSystem& cSys2, 00874 const uInt coord, const uInt coord2) const; 00875 00876 void copy(const CoordinateSystem &other); 00877 void clear(); 00878 Bool checkAxesInThisCoordinate(const Vector<Bool>& axes, uInt which) const; 00879 00880 // Delete some pointer blocks 00881 void cleanUpSpecCoord (PtrBlock<SpectralCoordinate*>& in, 00882 PtrBlock<SpectralCoordinate*>& out); 00883 00884 // Delete temporary maps 00885 void deleteTemps (const uInt which); 00886 00887 // Many abs/rel conversions 00888 // <group> 00889 void makeWorldAbsRelMany (Matrix<Double>& value, Bool toAbs) const; 00890 void makePixelAbsRelMany (Matrix<Double>& value, Bool toAbs) const; 00891 // </group> 00892 00893 // Do subImage for Stokes 00894 StokesCoordinate stokesSubImage(const StokesCoordinate& sc, Int originShift, Int pixincFac, 00895 Int newShape) const; 00896 00897 // Do subImage for Quality 00898 QualityCoordinate qualitySubImage(const QualityCoordinate& qc, Int originShift, Int pixincFac, 00899 Int newShape) const; 00900 00901 // Strip out coordinates with all world and pixel axes removed 00902 CoordinateSystem stripRemovedAxes (const CoordinateSystem& cSys) const; 00903 00904 // All these functions are in support of the <src>list</src> function 00905 // <group> 00906 void listDirectionSystem(LogIO& os) const; 00907 void listFrequencySystem(LogIO& os, MDoppler::Types velocityType) const; 00908 void listPointingCenter (LogIO& os) const; 00909 void getFieldWidths (LogIO& os, uInt& widthAxis, uInt& widthCoordType, 00910 uInt& widthCoordNumber, uInt& widthName, 00911 uInt& widthProj, uInt& widthShape, 00912 uInt& widthTile, uInt& widthRefValue, 00913 uInt& widthRefPixel, uInt& widthInc, 00914 uInt& widthUnits, Int& precRefValSci, 00915 Int& precRefValFloat, Int& precRefValRADEC, 00916 Int& precRefPixFloat, Int& precIncSci, String& nameAxis, 00917 String& nameCoordType, String& nameCoordNumber, String& nameName, String& nameProj, 00918 String& nameShape, String& nameTile, 00919 String& nameRefValue, String& nameRefPixel, 00920 String& nameInc, String& nameUnits, 00921 MDoppler::Types velocityType, 00922 const IPosition& latticeShape, const IPosition& tileShape) const; 00923 00924 void listHeader (LogIO& os, Coordinate* pc, uInt& widthAxis, uInt& widthCoordType, uInt& widthCoordNumber, 00925 uInt& widthName, uInt& widthProj, 00926 uInt& widthShape, uInt& widthTile, uInt& widthRefValue, 00927 uInt& widthRefPixel, uInt& widthInc, uInt& widthUnits, 00928 Bool findWidths, Int coordinate, Int axisInCoordinate, Int pixelAxis, 00929 Int precRefValSci, Int precRefValFloat, Int precRefValRADEC, Int precRefPixFloat, 00930 Int precIncSci, const IPosition& latticeShape, const IPosition& tileShape) const; 00931 void listVelocity (LogIO& os, Coordinate* pc, uInt widthAxis, 00932 uInt widthCoordType, uInt widthCoordNumber, 00933 uInt& widthName, uInt widthProj, 00934 uInt widthShape, uInt widthTile, uInt& widthRefValue, 00935 uInt widthRefPixel, uInt& widthInc, uInt& widthUnits, 00936 Bool findWidths, Int axisInCoordinate, Int pixelAxis, 00937 MDoppler::Types velocityType, Int precRefValSci, Int precRefValFloat, 00938 Int precRefValRADEC, Int precRefPixFloat, Int precIncSci) const; 00939 void clearFlags (LogIO& os) const; 00940 Bool velocityIncrement(Double& velocityInc, SpectralCoordinate& sc, 00941 MDoppler::Types velocityType, const String& velUnits) const; 00942 // </group> 00943 00944 void _downcase(Vector<String>& vec) const; 00945 00946 }; 00947 00948 } //# NAMESPACE CASA - END 00949 00950 #endif 00951