00001 //# ImageFITSConverter.h: Interconvert between Casacore Images and FITS files 00002 //# Copyright (C) 1996,1999,2001,2002 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 IMAGES_IMAGEFITSCONVERTER_H 00031 #define IMAGES_IMAGEFITSCONVERTER_H 00032 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/fits/FITS/fits.h> 00035 #include <casacore/casa/Arrays/IPosition.h> 00036 #include <casacore/casa/BasicSL/String.h> 00037 #include <casacore/casa/Utilities/DataType.h> 00038 #include <casacore/casa/Utilities/CountedPtr.h> 00039 00040 00041 #ifndef WCSLIB_GETWCSTAB 00042 #define WCSLIB_GETWCSTAB 00043 #endif 00044 00045 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00046 00047 template<class T> class PagedImage; 00048 template<class T> class ImageInterface; 00049 template<class T> class Vector; 00050 class FitsOutput; 00051 class File; 00052 class ImageInfo; 00053 class CoordinateSystem; 00054 class RecordInterface; 00055 class TableRecord; 00056 class LogIO; 00057 class Unit; 00058 class LoggerHolder; 00059 class ConstFitsKeywordList; 00060 class FitsInput; 00061 00062 // <summary> 00063 // Struct holding information derived from the image and its header 00064 // </summary> 00065 // <synopsis> 00066 // This is a helper struct to pass information from ImageHeaderToFITS 00067 // to ImageToFITSOut. 00068 // </synopsis> 00069 struct ImageFITSHeaderInfo { 00070 Bool applyMask; 00071 Bool needNonOptimalCursor; 00072 Bool hasBlanks; 00073 Double bzero; 00074 Double bscale; 00075 Short minshort; 00076 Short maxshort; 00077 double minPix; 00078 double maxPix; 00079 IPosition newShape; 00080 IPosition cursorOrder; 00081 FitsKeywordList kw; 00082 CountedPtr<Array<Bool> > pMask; 00083 }; 00084 00085 00086 // <summary> 00087 // Interconvert between Casacore Images and FITS files. 00088 // </summary> 00089 00090 // <use visibility=export> 00091 00092 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> 00093 // </reviewed> 00094 00095 // <prerequisite> 00096 // <li> <linkto class="PagedImage">PagedImage</linkto> 00097 // <li> <linkto class="PrimaryArray">PrimaryArray</linkto> (and FITS concepts in 00098 // general). 00099 // </prerequisite> 00100 // 00101 // <synopsis> 00102 // This class is a helper class that is used to interconvert between Casacore 00103 // images and FITS files. This adds no functionality over the general abilities 00104 // available in the underlying FITS classes, however it is a useful higher-level 00105 // packaging. 00106 // 00107 // There are two fundamental member functions in this class. 00108 // <src>FITSToImage</src> which turns a FITS file into a Casacore image, and 00109 // <src>ImageToFITS</src> which does the opposite. 00110 // 00111 // We can read images from any HDU inside the FITS file (although this isn't 00112 // well tested). Images with a quality axis (i.e. contain data and error values) 00113 // are stored in the primary HDU (data) and an extension HDU (error). Other 00114 // images are always written to the primary HDU. 00115 // 00116 // Pixels in the FITS file which are blanked are masked out (the mask 00117 // is set to False) in the output image. On conversion to FITS, 00118 // masked values are blanked. The mask which is read is the current 00119 // default mask. 00120 // </synopsis> 00121 // 00122 // <example> 00123 // A FITS to image conversion may be accomplished as follows: 00124 // <srcBlock> 00125 // PagedImage<Float> *image = 0; 00126 // String fitsName = "exists.fits"; 00127 // String imageName = "new.image"; 00128 // String error; 00129 // Bool ok = ImageFITSConverter::FITSToImage(image, error, imageName, fitsName); 00130 // if (!image) ... error ... 00131 // </srcBlock> 00132 // A couple of things to note: 00133 // <ul> 00134 // <li> If <src>ok</src> is False, the conversion failed and <src>error</src> 00135 // will be set. 00136 // <li> The pointer "image" is set if the conversion succeeds. If it is 00137 // zero the conversion failed and <src>error</src> will contain an 00138 // error message. 00139 // <li> The caller is responsible for deleting the pointer <src>image</src> 00140 // when the conversion is successful. 00141 // </ul> 00142 // Similarly, an image to FITS conversion may be accomplished as follows: 00143 // <srcBlock> 00144 // String imageName = argv[1]; 00145 // PagedImage<Float> image = ...; // An existing image from somewhere 00146 // String fitsName = "new.fits"; 00147 // String error; 00148 // Bool ok = ImageFITSConverter::ImageToFITS(error, image, fitsName); 00149 // </srcBlock> 00150 // A couple of similar remarks can be made about this example: 00151 // <ul> 00152 // <li> If <src>ok</src> is False, the conversion failed and <src>error</src> 00153 // will be set. 00154 // </ul> 00155 // </example> 00156 // 00157 // <motivation> 00158 // FITS files are the fundamental transport format for images in Astronomy. 00159 // </motivation> 00160 // 00161 // <todo asof="1999/02/15"> 00162 // <li> It might be useful to have functions that convert between FITS 00163 // and general lattices. 00164 // <li> Add support for PagedImage<Complex> 00165 // <li> Convert multiple images at once? 00166 // <li> Allow writing FITS files to an image extension in an existing 00167 // FITS file. 00168 // </todo> 00169 00170 class ImageFITSConverter 00171 { 00172 public: 00173 const static String CASAMBM; 00174 00175 // Convert a FITS file to a Casacore image. 00176 // <ul> 00177 // <li> <src>newImage</src> will be zero if the conversion fail. If the 00178 // conversion succeeds, the caller is responsible for deleting this 00179 // pointer. 00180 // <li> <src>error</src> will be set if the conversion fails. 00181 // <li> If <src>imageName</src> is empty, a TempImage will be created, 00182 // otherwise a PagedImage on disk. 00183 // <li> <src>fitsName</src> must already exist (and have an image at the 00184 // indicated HDU). 00185 // <li> <src>whichRep</src> Zero-relative coordinate representation 00186 // (Starting with wcs FITS multiple coordinate representations 00187 // can be stored in a FITS file) 00188 // <li> <src>whichHDU</src> Zero-relative hdu. The default is correct for 00189 // a primary array, set it for an image extension. A value of -1 00190 // makes the code look for the first readable HDU. 00191 // <li> <src>memoryInMB</src>. Setting this to zero will result in 00192 // row-by-row copying, otherwise it will attempt to with as large 00193 // a chunk-size as possible, while fitting in the desired memory. 00194 // <li> <src>allowOverwrite</src> If True, allow imageName to be 00195 // overwritten if it already exists. 00196 // <li> <src>zeroBlanks</src> If True, allow any blanked pixels are set 00197 // to zero rather than NaN 00198 // </ul> 00199 static Bool FITSToImage(ImageInterface<Float>*& newImage, 00200 String &error, 00201 const String &imageName, 00202 const String &fitsName, 00203 uInt whichRep = 0, 00204 Int whichHDU = 0, 00205 uInt memoryInMB = 64, 00206 Bool allowOverwrite=False, 00207 Bool zeroBlanks=False); 00208 00209 // Convert a Casacore image to a FITS file. 00210 // <ul> 00211 // <li> <src>return</src> True if the conversion succeeds, False 00212 // otherwise. 00213 // <li> <src>error</src> will be set if the conversion fails. 00214 // <li> <src>image</src> The image to convert. 00215 // <li> <src>fitsName</src> If the name is "-" (the minus character), 00216 // then write to stdout Always writes to the primary array. 00217 // <li> <src>memoryInMB</src>. Setting this to zero will result in 00218 // row-by-row copying, otherwise it will attempt to with as large 00219 // a chunk-size as possible, while fitting in the desired memory. 00220 // <li> <src>preferVelocity</src>Write a velocity primary spectral axis 00221 // if possible. 00222 // <li> <src>opticalVelocity</src>If writing a velocity, use the optical 00223 // definition (otherwise use radio). 00224 // <li> <src>BITPIX, minPix, maxPix</src> 00225 // BITPIX can presently be set to -32 or 16 only. When BITPIX is 00226 // 16 it will write BSCALE and BZERO into the FITS file. If minPix 00227 // is greater than maxPix the minimum and maximum pixel values 00228 // will be determined from the array, otherwise the supplied 00229 // values will be used and pixels outside that range will be 00230 // truncated to the minimum and maximum pixel values (note that 00231 // this truncation does not occur for BITPIX=-32). 00232 // <li> <src>allowOverwrite</src> If True, allow fitsName to be 00233 // overwritten if it already exists. 00234 // <li> <src>degenerateLast</src> If True, axes of length 1 will be written 00235 // last to the header. 00236 // <li> <src>preferWavelength</src> If True, write a wavelength primary axis. 00237 // <li> <src>airWavelength</src> If True and <src>preferWavelength</src> is True write 00238 // an air wavelength primary axis. 00239 // <li> <src>origin</src> gives the origin, i.e., the name of the package. 00240 // If empty, it defaults to "casacore-"getVersion(). 00241 // </ul> 00242 // <group> 00243 static Bool ImageToFITS(String &error, 00244 ImageInterface<Float> &image, 00245 const String &fitsName, 00246 uInt memoryInMB = 64, 00247 Bool preferVelocity = True, 00248 Bool opticalVelocity = True, 00249 Int BITPIX=-32, 00250 Float minPix = 1.0, Float maxPix = -1.0, 00251 Bool allowOverwrite=False, 00252 Bool degenerateLast=False, 00253 Bool verbose=True, 00254 Bool stokesLast=False, 00255 Bool preferWavelength=False, 00256 Bool airWavelength=False, 00257 const String& origin = String(), 00258 Bool history=True); 00259 static Bool ImageHeaderToFITS(String &error, 00260 ImageFITSHeaderInfo& fhi, 00261 const ImageInterface<Float> &image, 00262 Bool preferVelocity = True, 00263 Bool opticalVelocity = True, 00264 Int BITPIX=-32, 00265 Float minPix = 1.0, Float maxPix = -1.0, 00266 Bool degenerateLast=False, 00267 Bool verbose=True, 00268 Bool stokesLast=False, 00269 Bool preferWavelength=False, 00270 Bool airWavelength=False, 00271 Bool primHead = True, 00272 Bool allowAppend = True, 00273 const String& origin = String(), 00274 Bool history=True); 00275 // </group> 00276 00277 // Helper function - used to calculate a cursor appropriate for the 00278 // desired memory use. It's not intended that application programmers 00279 // call this, but you may if it's useful to you. 00280 static IPosition copyCursorShape(String &report, 00281 const IPosition &shape, 00282 uInt imagePixelSize, 00283 uInt fitsPixelSize, 00284 uInt memoryInMB); 00285 00286 // Recover CoordinateSystem from header. 00287 // Used keywords are removed from header and the unused ones returned 00288 // in a Record for ease of use. 00289 // Degenerate axes may be added to shape if needed. 00290 static CoordinateSystem getCoordinateSystem (Int& imageType, 00291 RecordInterface& headerRec, 00292 const Vector<String>& header, 00293 LogIO& os, uInt whichRep, 00294 IPosition& shape, 00295 Bool dropStokes); 00296 00297 // Recover ImageInfo from header. Used keywords are removed from header 00298 static ImageInfo getImageInfo (RecordInterface& header); 00299 00300 // Recover brightness unit from header. 00301 // Used keywords are removed from header. 00302 static Unit getBrightnessUnit (RecordInterface& header, LogIO& os); 00303 00304 // Recover history from FITS file keyword list into logger. 00305 static void restoreHistory (LoggerHolder& logger, 00306 ConstFitsKeywordList& kw); 00307 00308 // Parse header record and set MiscInfo 00309 static Bool extractMiscInfo (RecordInterface& miscInfo, 00310 const RecordInterface& header); 00311 00312 // Read the BEAMS table if present and add the restoring beams to 00313 // <src>info</src>. 00314 static void readBeamsTable (ImageInfo& info, const String& filename, 00315 const DataType type); 00316 00317 private: 00318 00319 // Put a CASA image to an opened FITS image 00320 // Parameters as in "ImageToFITS". In addition: 00321 // <ul> 00322 // <li> <src>output</src> The FITS output to write to. 00323 // <li> <src>primHead</src> Write to a primary HDU. 00324 // <li> <src>allowAppend</src> Allow to append extension HDU's. 00325 // </ul> 00326 static Bool ImageToFITSOut (String &error, LogIO &os, 00327 const ImageInterface<Float> &image, 00328 FitsOutput *output, uInt memoryInMB = 64, 00329 Bool preferVelocity = True, 00330 Bool opticalVelocity = True, 00331 Int BITPIX=-32, 00332 Float minPix = 1.0, Float maxPix = -1.0, 00333 Bool degenerateLast=False, 00334 Bool verbose=True, 00335 Bool stokesLast=False, 00336 Bool preferWavelength=False, 00337 Bool airWavelength=False, 00338 Bool primHead=True, 00339 Bool allowAppend=False, 00340 const String& origin = String(), 00341 Bool history=True); 00342 00343 // Put a CASA image with quality coordinate 00344 // to an opened FITS file 00345 // Parameters as in "ImageToFITS". In addition: 00346 // <ul> 00347 // <li> <src>output</src> The FITS output to write to. 00348 // </ul> 00349 static Bool QualImgToFITSOut (String &error, 00350 LogIO &os, 00351 ImageInterface<Float> &image, 00352 FitsOutput *outfile, 00353 uInt memoryInMB, 00354 Bool preferVelocity, 00355 Bool opticalVelocity, 00356 Int BITPIX, Float minPix, Float maxPix, 00357 Bool degenerateLast, 00358 Bool verbose, Bool stokesLast, 00359 Bool preferWavelength, 00360 Bool airWavelength, 00361 const String& origin, 00362 Bool history); 00363 00364 // If existing, remove the file, symlink, or directory given by 00365 // <src>outFile</src>. It is only removed if allowOverwrite=True. 00366 // An exception (using argument outName) is thrown if the file could 00367 // not be removed. 00368 static Bool removeFile (String& error, const File& outFile, 00369 const String& outName, Bool allowOverwrite); 00370 00371 // Create an open FITS file with the name given 00372 static Bool openFitsOutput (String &error, FitsOutput *(&openFitsOutput), 00373 const String &fitsName, 00374 const Bool &allowOverwrite); 00375 00376 00377 static void _writeBeamsTable (FitsOutput *const &outfile, 00378 const ImageInfo& info); 00379 00380 }; 00381 00382 00383 // <summary> 00384 // This class is an internal class for ImageFITSConverter. 00385 // </summary> 00386 00387 // <use visibility=local> 00388 00389 // <synopsis> 00390 // This class is an internal class used to implement 00391 // ImageFitsConverter::FITSToImage - in particular, it has the code which 00392 // is dependent on the various types (BITPIX values). 00393 // </synopsis> 00394 template<class HDUType> class ImageFITSConverterImpl 00395 { 00396 public: 00397 static void FITSToImage(ImageInterface<Float> *&newImage, 00398 String &error, 00399 const String &newImageName, 00400 const uInt whichRep, 00401 HDUType &fitsImage, 00402 const String& fitsFilename, 00403 const DataType dataType, 00404 const uInt memoryInMB = 64, 00405 const Bool zeroBlanks=False); 00406 }; 00407 00408 00409 } //# NAMESPACE CASACORE - END 00410 00411 #ifndef CASACORE_NO_AUTO_TEMPLATES 00412 #include <casacore/images/Images/ImageFITSConverter.tcc> 00413 #endif //# CASACORE_NO_AUTO_TEMPLATES 00414 00415 #endif