00001 //# PagedImage.h: read, store and manipulate astronomical images 00002 //# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2003 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 //# $Id$ 00027 00028 #ifndef IMAGES_PAGEDIMAGE_H 00029 #define IMAGES_PAGEDIMAGE_H 00030 00031 00032 //# Includes 00033 #include <casacore/casa/aips.h> 00034 #include <casacore/images/Images/ImageInterface.h> 00035 #include <casacore/images/Images/ImageAttrHandlerCasa.h> 00036 #include <casacore/lattices/Lattices/PagedArray.h> 00037 #include <casacore/tables/Tables/Table.h> 00038 #include <casacore/casa/Utilities/DataType.h> 00039 #include <casacore/tables/Tables/TableRecord.h> 00040 00041 //# Forward Declarations 00042 #include <casacore/casa/iosfwd.h> 00043 00044 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00045 00046 // <summary> 00047 // Read, store, and manipulate astronomical images. 00048 // </summary> 00049 00050 // <use visibility=export> 00051 00052 // <reviewed reviewer="" date="" tests="tPagedmage.cc" demos="dPagedImage.cc"> 00053 // </reviewed> 00054 00055 // <prerequisite> 00056 // <li> <linkto class=CoordinateSystem>CoordinateSystem</linkto> 00057 // <li> <linkto class=ImageInterface>ImageInterface</linkto> 00058 // <li> <linkto class=Lattice>Lattice</linkto> 00059 // <li> <linkto class=LatticeIterator>LatticeIterator</linkto> 00060 // <li> <linkto class=LatticeNavigator>LatticeNavigator</linkto> 00061 // <li> <linkto class=ImageRegion>ImageRegion</linkto> 00062 // </prerequisite> 00063 00064 // <etymology> 00065 // The PagedImage name comes from its role as the Image class with paging 00066 // from persistent memory. Users are thus invited to treat the 00067 // PagedImage instances like Casacore Lattices 00068 // </etymology> 00069 00070 // <synopsis> 00071 // All Casacore Images are Lattices. They may be treated like any other Lattice; 00072 // getSlice(...), putSlice(...), LatticeIterator for iterating, etc. 00073 // ArrayImages contain a map, a mask for that map, and coordinate 00074 // information. This provides a Lattice interface for images and their 00075 // respective coordinates. Additional functionality is defined by the 00076 // ImageInterface class. 00077 // 00078 // You can use the global function <src>imagePixelType</src> to determine 00079 // what the pixel type of an image is before you open the image if your 00080 // code can work with Images of many possible types, or for error checking. 00081 // 00082 // </synopsis> 00083 00084 // <example> 00085 // This example shows how to create a mask for an image, fill it, and 00086 // make it known to the image. 00087 // <srcblock> 00088 // // Open the image (as readonly for the moment). 00089 // PagedImage<Float> myimage ("image.name"); 00090 // // Create a mask for the image. 00091 // // The mask will be stored in a subtable of the image. 00092 // LCPagedMask mask (RegionHandler::makeMask (myimage, "mask.name")); 00093 // // Fill the mask with whatever values (e.g. all True). 00094 // mask.set (True); 00095 // // Make the mask known to the image (with name mask1). 00096 // myimage.defineRegion ("mask1", mask, RegionHandler::Masks); 00097 // // Make the mask the default mask for this image. 00098 // myimage.setDefaultMask ("mask1"); 00099 // </srcblock> 00100 // It is possible to create as many masks as one likes. They can all 00101 // be defined as masks for the image (with different names, of course). 00102 // However, only one of them can be the default mask (the mask used 00103 // by default when the image is opened). When another mask has to be 00104 // used, one can do two things: 00105 // <ul> 00106 // <li> Use setDefaultMask to make the other mask the default mask. 00107 // This is advisable when the change should be more or less permanent. 00108 // <li> Open the PagedImage without using a default mask. Thereafter 00109 // a <linkto class=SubImage>SubImage</linkto> object can be created 00110 // from the PagedImage and the mask. This is advisable when it the 00111 // mask has to be used only one time. 00112 // </ul> 00113 // </example> 00114 00115 // <motivation> 00116 // The size of astronomical data can be very large. The ability to fit an 00117 // entire image into random access memory cannot be guaranteed. Paging from 00118 // disk pieces of the image appeared to be the way to deal with this problem. 00119 // </motivation> 00120 00121 // 00122 // <note> 00123 // When you make a new PagedImage, and you are transferring 00124 // information from some other PagedImage, be aware that you 00125 // must copy, manually, things like miscInfo, imageInfo, units, 00126 // logSink (history) to the new file. 00127 // </note> 00128 // <todo asof="1996/09/04"> 00129 // <li> The CoordinateSystem::store() function returns a TableRecord. That 00130 // TableRecord should be stored in the same row as our image. This will 00131 // allow ImageStack members to have their own coordinate frames. 00132 // </todo> 00133 00134 00135 template <class T> class PagedImage: public ImageInterface<T> 00136 { 00137 public: 00138 // Construct a new Image from shape and coordinate information. 00139 // Data will be stored in the argument table. 00140 PagedImage (const TiledShape& mapShape, 00141 const CoordinateSystem& coordinateInfo, 00142 Table& table, 00143 uInt rowNumber = 0); 00144 00145 // Construct a new Image from shape and coordinate information. Table 00146 // will be stored in the named file. 00147 PagedImage (const TiledShape& mapShape, 00148 const CoordinateSystem& coordinateInfo, 00149 const String& nameOfNewFile, 00150 uInt rowNumber = 0); 00151 00152 // Construct a new Image from shape and coordinate information. Table 00153 // will be stored in the named file. 00154 // The lock options may be specified 00155 // <group> 00156 PagedImage (const TiledShape& mapShape, 00157 const CoordinateSystem& coordinateInfo, 00158 const String& nameOfNewFile, 00159 TableLock::LockOption, 00160 uInt rowNumber = 0); 00161 PagedImage (const TiledShape& mapShape, 00162 const CoordinateSystem& coordinateInfo, 00163 const String& nameOfNewFile, 00164 const TableLock& lockOptions, 00165 uInt rowNumber = 0); 00166 // </group> 00167 00168 // Reconstruct an image from a pre-existing file. 00169 // By default the default pixelmask (if available) is used. 00170 explicit PagedImage (Table& table, MaskSpecifier = MaskSpecifier(), 00171 uInt rowNumber = 0); 00172 00173 // Reconstruct an image from a pre-existing file. 00174 // By default the default pixelmask (if available) is used. 00175 explicit PagedImage (const String& filename, MaskSpecifier = MaskSpecifier(), 00176 uInt rowNumber = 0); 00177 00178 // Reconstruct an image from a pre-existing file with Locking. 00179 // By default the default pixelmask (if available) is used. 00180 // <group> 00181 PagedImage (const String& filename, TableLock::LockOption, 00182 MaskSpecifier = MaskSpecifier(), uInt rowNumber = 0); 00183 PagedImage (const String& filename, const TableLock& lockOptions, 00184 MaskSpecifier = MaskSpecifier(), uInt rowNumber = 0); 00185 // </group> 00186 00187 // Copy constructor (reference semantics). 00188 PagedImage (const PagedImage<T>& other); 00189 00190 ~PagedImage(); 00191 00192 // Assignment operator (reference semantics). 00193 PagedImage<T>& operator= (const PagedImage<T>& other); 00194 00195 // Make a copy of the object (reference semantics). 00196 virtual ImageInterface<T>* cloneII() const; 00197 00198 // Return the name of this derived class. 00199 static String className() 00200 { return "PagedImage"; } 00201 00202 // Get the image type (returns name of this derived class). 00203 virtual String imageType() const; 00204 00205 // A PagedImage is always persistent. 00206 virtual Bool isPersistent() const; 00207 00208 // A PagedImage is always paged to disk. 00209 virtual Bool isPaged() const; 00210 00211 // Is the PagedImage writable? 00212 virtual Bool isWritable() const; 00213 00214 // Does the image object use a pixelmask? 00215 virtual Bool hasPixelMask() const; 00216 00217 // Get access to the pixelmask used. 00218 // An exception is thrown if the image does not use a pixelmask. 00219 // <group> 00220 virtual const Lattice<Bool>& pixelMask() const; 00221 virtual Lattice<Bool>& pixelMask(); 00222 // </group> 00223 00224 // Get a pointer the default pixelmask object used with this image. 00225 // It returns 0 if no default pixelmask is used. 00226 virtual const LatticeRegion* getRegionPtr() const; 00227 00228 // Set the default pixelmask to the mask with the given name 00229 // (which has to exist in the "masks" group). 00230 // If the image table is writable, the setting is persistent by writing 00231 // the name as a keyword. 00232 // If the given regionName is the empty string, 00233 // the default pixelmask is unset. 00234 virtual void setDefaultMask (const String& maskName); 00235 00236 // Use the mask as specified. 00237 // If a mask was already in use, it is replaced by the new one. 00238 virtual void useMask (MaskSpecifier = MaskSpecifier()); 00239 00240 // Function to change the name of the Table file on disk. 00241 // PagedImage is given a file name at construction time. You may change 00242 // that name here. 00243 void rename (const String& newName); 00244 00245 // Return the current Table name. By default this includes the full path. 00246 // the path preceding the file name can be stripped off on request. 00247 virtual String name (Bool stripPath=False) const; 00248 00249 // Return the current TableColumn row number. 00250 uInt rowNumber() const; 00251 00252 // Return the shape of the image. 00253 virtual IPosition shape() const; 00254 00255 // Change the shape of the image (N.B. the data is thrown away). 00256 virtual void resize (const TiledShape& newShape); 00257 00258 // Function which extracts an array from the map. 00259 virtual Bool doGetSlice (Array<T>& buffer, const Slicer& theSlice); 00260 00261 // Function to replace the values in the map with soureBuffer. 00262 virtual void doPutSlice (const Array<T>& sourceBuffer, 00263 const IPosition& where, 00264 const IPosition& stride); 00265 00266 // Replace every element, x, of the lattice with the result of f(x). 00267 // you must pass in the address of the function -- so the function 00268 // must be declared and defined in the scope of your program. 00269 // Both versions of apply require a function that accepts a single 00270 // argument of type T (the Lattice template actual type) and returns 00271 // a result of the same type. The first apply expects a function with 00272 // an argument passed by value; the second expects the argument to 00273 // be passed by const reference. The first form ought to run faster 00274 // for the built-in types, which may be an issue for large Lattices 00275 // stored in memory, where disk access is not an issue. 00276 // <group> 00277 virtual void apply (T (*function)(T)); 00278 virtual void apply (T (*function)(const T& )); 00279 virtual void apply (const Functional<T,T>& function); 00280 // </group> 00281 00282 // Add a lattice to this image. 00283 PagedImage<T>& operator+= (const Lattice<T>& other); 00284 00285 // Function which sets the units associated with the image 00286 // pixels (i.e. the "brightness" unit). <src>setUnits()</src> returns 00287 // False if it cannot set the unit for some reason (e.g. the underlying 00288 // file is not writable). 00289 virtual Bool setUnits (const Unit& newUnits); 00290 00291 // Return the table holding the data. 00292 Table& table() 00293 { return map_p.table(); } 00294 00295 // Flushes the new coordinate system to disk if the table is writable. 00296 virtual Bool setCoordinateInfo (const CoordinateSystem& coords); 00297 00298 // Check for symmetry in data members. 00299 virtual Bool ok() const; 00300 00301 // These are the true implementations of the paran operator. 00302 // <note> Not for public use </note> 00303 // <group> 00304 virtual T getAt (const IPosition& where) const; 00305 virtual void putAt (const T& value, const IPosition& where); 00306 // </group> 00307 00308 // Replace the miscinfo in the PagedImage. 00309 // It can fail if, e.g., the underlying table is not writable. 00310 virtual Bool setMiscInfo (const RecordInterface& newInfo); 00311 00312 // The ImageInfo object contains some miscellaneous information about the 00313 // image, which unlike that stored in MiscInfo, has a standard list of 00314 // things, such as the restoring beam. 00315 // Note that setImageInfo REPLACES the information with the new information. 00316 // It can fail if, e.g., the underlying table is not writable. 00317 virtual Bool setImageInfo(const ImageInfo& info); 00318 00319 // Get access to the attribute handler. 00320 // If a handler keyword does not exist yet, it is created if 00321 // <src>createHandler</src> is set. 00322 // Otherwise the handler is empty and no groups can be created for it. 00323 virtual ImageAttrHandler& attrHandler (Bool createHandler=False); 00324 00325 // Remove a region/mask belonging to the image from the given group 00326 // (which can be Any). 00327 // If a mask removed is the default mask, the image gets unmasked. 00328 // <br>Optionally an exception is thrown if the region does not exist. 00329 virtual void removeRegion (const String& name, 00330 RegionHandler::GroupType = RegionHandler::Any, 00331 Bool throwIfUnknown = True); 00332 00333 // This is the implementation of the letter for the envelope Iterator 00334 // class. <note> Not for public use </note>. 00335 virtual LatticeIterInterface<T>* makeIter 00336 (const LatticeNavigator& navigator, 00337 Bool useRef) const; 00338 00339 // Returns the maximum recommended number of pixels for a cursor. This is 00340 // the number of pixels in a tile. 00341 virtual uInt advisedMaxPixels() const; 00342 00343 // Help the user pick a cursor for most efficient access. 00344 virtual IPosition doNiceCursorShape (uInt maxPixels) const; 00345 00346 // Maximum size - not necessarily all used. In pixels. 00347 virtual uInt maximumCacheSize() const; 00348 00349 // Set the maximum (allowed) cache size as indicated. 00350 virtual void setMaximumCacheSize (uInt howManyPixels); 00351 00352 // Set the cache size as to "fit" the indicated path. 00353 virtual void setCacheSizeFromPath (const IPosition& sliceShape, 00354 const IPosition& windowStart, 00355 const IPosition& windowLength, 00356 const IPosition& axisPath); 00357 00358 // Set the actual cache size for this Array to be be big enough for the 00359 // indicated number of tiles. This cache is not shared with PagedArrays 00360 // in other rows and is always clipped to be less than the maximum value 00361 // set using the setMaximumCacheSize member function. 00362 // tiles. Tiles are cached using a first in first out algorithm. 00363 virtual void setCacheSizeInTiles (uInt howManyTiles); 00364 00365 // Clears and frees up the caches, but the maximum allowed cache size is 00366 // unchanged from when setCacheSize was called 00367 virtual void clearCache(); 00368 00369 // Report on cache success. 00370 virtual void showCacheStatistics (ostream& os) const; 00371 00372 // Handle the (un)locking. 00373 // Unlocking also unlocks the logtable and a possible mask table. 00374 // Locking only locks the image itself. 00375 // <group> 00376 virtual Bool lock (FileLocker::LockType, uInt nattempts); 00377 virtual void unlock(); 00378 virtual Bool hasLock (FileLocker::LockType) const; 00379 // </group> 00380 00381 // Resynchronize the PagedImage object with the table contents. 00382 // The logtable and possible mask table are also synchronized if 00383 // they do not have a readlock. 00384 // <br>This function is only useful if no read-locking is used, ie. 00385 // if the table lock option is UserNoReadLocking or AutoNoReadLocking. 00386 // In that cases the table system does not acquire a read-lock, thus 00387 // does not synchronize itself automatically. 00388 virtual void resync(); 00389 00390 // Flush the data. 00391 virtual void flush(); 00392 00393 // Close the Image and associated files temporarily. 00394 // It'll be reopened automatically when needed or when 00395 // <src>reopen</src> is called explicitly. 00396 virtual void tempClose(); 00397 00398 // If needed, reopen a temporarily closed Image. 00399 virtual void reopen(); 00400 00401 00402 private: 00403 // Function to return the internal Table object to the RegionHandler. 00404 static Table& getTable (void* imagePtr, Bool writable); 00405 00406 // This must be called in every constructor and place where the image 00407 // is attached to a new image. 00408 void attach_logtable(); 00409 void open_logtable(); 00410 void restoreUnits (const TableRecord& rec); 00411 void restoreMiscInfo (const TableRecord& rec); 00412 void restoreImageInfo (const TableRecord& rec); 00413 void restoreAll (const TableRecord& rec); 00414 00415 void check_conformance (const Lattice<T>& other); 00416 void reopenRW(); 00417 void setTableType(); 00418 void applyMaskSpecifier (const MaskSpecifier&); 00419 void applyMask (const String& maskName); 00420 void makePagedImage (const TiledShape& mapShape, 00421 const CoordinateSystem& coordinateInfo, 00422 const String& nameOfNewFile, 00423 const TableLock& lockOptions, 00424 uInt rowNumber); 00425 void makePagedImage (const String& filename, const TableLock& lockOptions, 00426 const MaskSpecifier&, uInt rowNumber); 00427 00428 const Table& table() const 00429 { return const_cast<PagedImage<T>*>(this)->table(); } 00430 00431 00432 PagedArray<T> map_p; 00433 LatticeRegion* regionPtr_p; 00434 ImageAttrHandlerCasa itsAttrHandler; 00435 00436 //# Make members of parent class known. 00437 public: 00438 using ImageInterface<T>::logSink; 00439 using ImageInterface<T>::logger; 00440 using ImageInterface<T>::imageInfo; 00441 using ImageInterface<T>::coordinates; 00442 using ImageInterface<T>::getDefaultMask; 00443 using ImageInterface<T>::hasRegion; 00444 using ImageInterface<T>::getImageRegionPtr; 00445 protected: 00446 using ImageInterface<T>::setCoordsMember; 00447 using ImageInterface<T>::setMiscInfoMember; 00448 using ImageInterface<T>::setLogMember; 00449 using ImageInterface<T>::setUnitMember; 00450 using ImageInterface<T>::setImageInfoMember; 00451 }; 00452 00453 00454 //# A nasty - the column name is hard-coded into this function, needs to 00455 //# be centralized somewhere. 00456 // Determine the pixel type in the PagedImage contained in 00457 // <src>fileName</src>. If the file doesn't appear to be a Table or cannot 00458 // be opened, TpOther is returned. 00459 // <group name="pixeltype") 00460 DataType imagePixelType(const String& fileName); 00461 // </group> 00462 00463 00464 //# Declare extern templates for often used types. 00465 #ifdef AIPS_CXX11 00466 extern template class PagedImage<Float>; 00467 extern template class PagedImage<Complex>; 00468 #endif 00469 00470 00471 } //# NAMESPACE CASACORE - END 00472 00473 #ifndef CASACORE_NO_AUTO_TEMPLATES 00474 #include <casacore/images/Images/PagedImage.tcc> 00475 #endif //# CASACORE_NO_AUTO_TEMPLATES 00476 #endif