//# tSubImage.cc: Test program for class SubImage //# Copyright (C) 1998,1999,2000,2001,2003 //# Associated Universities, Inc. Washington DC, USA. //# //# This program is free software; you can redistribute it and/or modify it //# under the terms of the GNU General Public License as published by the Free //# Software Foundation; either version 2 of the License, or (at your option) //# any later version. //# //# This program is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for //# more details. //# //# You should have received a copy of the GNU General Public License along //# with this program; if not, write to the Free Software Foundation, Inc., //# 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id: $ #include <imageanalysis/ImageAnalysis/ImageFactory.h> #include <casacore/casa/OS/Directory.h> #include <casacore/casa/OS/RegularFile.h> #include <casacore/casa/OS/SymLink.h> #include <casacore/coordinates/Coordinates/CoordinateUtil.h> #include <casacore/images/Images/PagedImage.h> #include <casacore/images/Images/TempImage.h> #include <casacore/tables/LogTables/NewFile.h> #include <casacore/tables/Tables/TableUtil.h> #include <imageanalysis/ImageAnalysis/ImageHistory.h> #include <imageanalysis/ImageAnalysis/SubImageFactory.h> namespace casa { template <class T> void ImageFactory::remove(SPIIT& image, casacore::Bool verbose) { ThrowIf( ! image, "Image cannot be null" ); ThrowIf( ! image->isPersistent(), "This image tool is not associated with a " "persistent disk file. It cannot be deleted" ); auto fileName = image->name(false); ThrowIf( fileName.empty(), "Filename is empty or does not exist." ); casacore::File f(fileName); ThrowIf( ! f.exists(), fileName + " does not exist." ); // Destroy object before deleting image. This is why a reference // needs to be passed in. image.reset(); // Now try and blow it away. If it's open, tabledelete won't delete it. casacore::String message; casacore::LogIO log; if (casacore::TableUtil::canDeleteTable(message, fileName, true)) { try { casacore::TableUtil::deleteTable(fileName, true); log << (verbose ? casacore::LogIO::NORMAL : casacore::LogIO::DEBUG1) << "deleted table " << fileName << casacore::LogIO::POST; } catch (const casacore::AipsError& x) { ThrowCc( "Failed to delete file " + fileName + " because " + x.getMesg() ); }; } else { ThrowCc( "Cannot delete file " + fileName + " because " + message ); } } template<class T> std::shared_ptr<TempImage<std::complex<T>>> ImageFactory::makeComplexImage( SPCIIT realPart, SPCIIT imagPart ) { auto shape = realPart->shape(); ThrowIf( shape != imagPart->shape(), "Real and imaginary parts have different shapes" ); std::shared_ptr<TempImage<std::complex<T>>> newImage( new TempImage<std::complex<T>>(shape, realPart->coordinates()) ); LatticeExpr<std::complex<T>> expr( casacore::formComplex(*realPart, *imagPart) ); if (ImageMask::isAllMaskTrue(expr)) { newImage->copyData(expr); } else { newImage->attachMask(casacore::ArrayLattice<Bool>(shape)); LogIO os; casacore::LatticeUtilities::copyDataAndMask(os, *newImage, expr, False); } ImageUtilities::copyMiscellaneous(*newImage, *realPart); return newImage; } template <class T> std::shared_ptr<casacore::ImageInterface<std::complex<T>>> ImageFactory::makeComplex( SPCIIT realPart, SPCIIT imagPart, const String& outfile, const Record& region, Bool overwrite ) { _checkOutfile(outfile, overwrite); const IPosition realShape = realPart->shape(); const IPosition imagShape = imagPart->shape(); ThrowIf(! realShape.isEqual(imagShape), "Image shapes are not identical"); const auto& cSysReal = realPart->coordinates(); const auto& cSysImag = imagPart->coordinates(); ThrowIf( !cSysReal.near(cSysImag), "Image Coordinate systems are not conformant" ); String mask; auto subRealImage = SubImageFactory<T>::createSubImageRO( *realPart, region, mask, nullptr ); auto subImagImage = SubImageFactory<T>::createSubImageRO( *imagPart, region, mask, nullptr ); auto complexImage = makeComplexImage( std::dynamic_pointer_cast<const casacore::ImageInterface<T>>(subRealImage), std::dynamic_pointer_cast<const casacore::ImageInterface<T>>(subImagImage) ); return SubImageFactory<std::complex<T>>::createImage( *complexImage, outfile, Record(), "", AxesSpecifier(), overwrite, false, false ); } template <class T> SPIIT ImageFactory::createImage( const casacore::String& outfile, const casacore::CoordinateSystem& cSys, const casacore::IPosition& shape, casacore::Bool log, casacore::Bool overwrite, const vector<std::pair<casacore::LogOrigin, casacore::String> > *const &msgs ) { _checkOutfile(outfile, overwrite); ThrowIf( shape.nelements() != cSys.nPixelAxes(), "Supplied CoordinateSystem and image shape are inconsistent" ); SPIIT image; if (outfile.empty()) { image.reset(new casacore::TempImage<T>(shape, cSys)); ThrowIf(! image, "Failed to create TempImage"); } else { image.reset(new casacore::PagedImage<T>(shape, cSys, outfile)); ThrowIf( ! image, "Failed to create PagedImage" ); } auto creationMsg = _imageCreationMessage(outfile, shape, whatType<T>()); ImageHistory<T> hist(image); if (msgs) { hist.addHistory(*msgs); } LogOrigin lor("ImageFactory", __func__); hist.addHistory(lor, creationMsg); image->set(0.0); if (log) { LogIO mylog; mylog << LogOrigin("ImageFactory", __func__) << LogIO::NORMAL << creationMsg << LogIO::POST; } return image; } template<class T> std::shared_ptr<casacore::TempImage<T>> ImageFactory::floatFromComplex( std::shared_ptr<const casacore::ImageInterface<std::complex<T>>> complexImage, ComplexToFloatFunction function ) { std::shared_ptr<TempImage<T>> newImage( new TempImage<T>( TiledShape(complexImage->shape()), complexImage->coordinates() ) ); { // FIXME use lattice copies auto mymask = complexImage->getMask(); if (complexImage->hasPixelMask()) { mymask = mymask && complexImage->pixelMask().get(); } if (! allTrue(mymask)) { newImage->attachMask(ArrayLattice<Bool>(mymask)); } } ImageUtilities::copyMiscellaneous(*newImage, *complexImage); switch (function) { case REAL: // FIXME use lattice copies newImage->put(real(complexImage->get())); break; case IMAG: // FIXME use lattice copies newImage->put(imag(complexImage->get())); break; default: ThrowCc("Logic Error: Unhandled function"); } return newImage; } template <class T> SPIIT ImageFactory::fromShape( const casacore::String& outfile, const casacore::Vector<casacore::Int>& shapeV, const casacore::Record& coordinates, casacore::Bool linear, casacore::Bool overwrite, casacore::Bool verbose, const vector<std::pair<casacore::LogOrigin, casacore::String> > *const &msgs ) { ThrowIf( shapeV.nelements() == 0, "The shape must have more than zero elements" ); ThrowIf(anyTrue(shapeV <= 0), "All elements of shape must be positive"); casacore::CoordinateSystem mycsys; std::unique_ptr<casacore::CoordinateSystem> csysPtr; if (coordinates.empty()) { mycsys = casacore::CoordinateUtil::makeCoordinateSystem(shapeV, linear); _centerRefPix(mycsys, shapeV); } else { csysPtr.reset(_makeCoordinateSystem(coordinates, shapeV)); mycsys = *csysPtr; } return createImage<T>(outfile, mycsys, shapeV, verbose, overwrite, msgs); } template <class T> SPIIT ImageFactory::imageFromArray( const casacore::String& outfile, const casacore::Array<T>& pixels, const casacore::Record& csys, casacore::Bool linear, casacore::Bool overwrite, casacore::Bool verbose, const vector<std::pair<casacore::LogOrigin, casacore::String> > *const &msgs ) { SPIIT myim = fromShape<T>( outfile, pixels.shape().asVector(), csys, linear, overwrite, verbose, msgs ); myim->put(pixels); return myim; } template <class T> SPIIT ImageFactory::_fromRecord( const casacore::RecordInterface& rec, const casacore::String& name ) { SPIIT image; casacore::String err; image.reset(new casacore::TempImage<T>()); ThrowIf( ! image->fromRecord(err, rec), "Error converting image from record: " + err ); if (! name.empty()) { image = SubImageFactory<T>::createImage( *image, name, casacore::Record(), "", false, true, false, false ); } return image; } template <class T> ITUPLE ImageFactory::_rename( SPIIT& image, const casacore::String& name, const casacore::Bool overwrite ) { casacore::LogIO mylog; mylog << casacore::LogOrigin(className(), __func__); ThrowIf (! image, "Image pointer cannot be null"); ThrowIf( ! image->isPersistent(), "This image tool is not associated with a " "persistent disk file. It cannot be renamed" ); ThrowIf( name.empty(), "new file name must be specified" ); casacore::String oldName = image->name(false); ThrowIf( oldName.empty(), "Current file name is empty, cannot rename" ); ThrowIf( oldName == name, "Specified output name is the same as the current image name" ); // Let's see if it exists. If it doesn't, then the user has deleted it casacore::File file(oldName); if (file.isSymLink()) { file = casacore::File(casacore::SymLink(file).followSymLink()); } ThrowIf( ! file.exists(), "The image to be renamed no longer exists" ); _checkOutfile(name, overwrite); // close image before renaming image.reset(); // Now try and move it casacore::Bool follow(true); if (file.isRegular(follow)) { casacore::RegularFile(file).move(name, overwrite); } else if (file.isDirectory(follow)) { casacore::Directory(file).move(name, overwrite); } else if (file.isSymLink()) { casacore::SymLink(file).copy(name, overwrite); } else { ThrowCc("Failed to rename file " + oldName + " to " + name); } mylog << casacore::LogIO::NORMAL << "Successfully renamed file " << oldName << " to " << name << casacore::LogIO::POST; return fromFile(name); } }