Line data Source code
1 : //# Copyright (C) 1998,1999,2000,2001,2003
2 : //# Associated Universities, Inc. Washington DC, USA.
3 : //#
4 : //# This program is free software; you can redistribute it and/or modify it
5 : //# under the terms of the GNU General Public License as published by the Free
6 : //# Software Foundation; either version 2 of the License, or (at your option)
7 : //# any later version.
8 : //#
9 : //# This program is distributed in the hope that it will be useful, but WITHOUT
10 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 : //# more details.
13 : //#
14 : //# You should have received a copy of the GNU General Public License along
15 : //# with this program; if not, write to the Free Software Foundation, Inc.,
16 : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
17 : //#
18 : //# Correspondence concerning AIPS++ should be addressed as follows:
19 : //# Internet email: aips2-request@nrao.edu.
20 : //# Postal address: AIPS++ Project Office
21 : //# National Radio Astronomy Observatory
22 : //# 520 Edgemont Road
23 : //# Charlottesville, VA 22903-2475 USA
24 : //#
25 : //# $Id: $
26 :
27 : #include <imageanalysis/ImageAnalysis/ImageMaskHandler.h>
28 :
29 : #include <imageanalysis/ImageAnalysis/ImageFactory.h>
30 :
31 : #include <casacore/casa/Exceptions/Error.h>
32 : #include <casacore/images/Images/ImageExprParse.h>
33 : #include <casacore/images/Images/ImageProxy.h>
34 : #include <casacore/images/Regions/RegionHandler.h>
35 :
36 : namespace casa {
37 :
38 0 : template <class T> ImageMaskHandler<T>::ImageMaskHandler(SPIIT image)
39 0 : : _image(image) {}
40 :
41 0 : template <class T> ImageMaskHandler<T>::~ImageMaskHandler() {}
42 :
43 : template <class T> void ImageMaskHandler<T>::set(const casacore::String& name) {
44 : _image->setDefaultMask(name);
45 : }
46 :
47 : template <class T> casacore::String ImageMaskHandler<T>::defaultMask() const {
48 : return _image->getDefaultMask();
49 : }
50 :
51 : template <class T> void ImageMaskHandler<T>::deleteMasks(
52 : const std::set<casacore::String>& masks
53 : ) {
54 : ThrowIf(masks.empty(), "You have not supplied any mask names");
55 : for (const auto& mask: masks) {
56 : _image->removeRegion(mask, casacore::RegionHandler::Masks, false);
57 : }
58 : }
59 :
60 : template <class T> void ImageMaskHandler<T>::rename(
61 : const casacore::String& oldName, const casacore::String& newName
62 : ) {
63 : _image->renameRegion(newName, oldName, casacore::RegionHandler::Masks, false);
64 : }
65 :
66 : template <class T> casacore::Vector<casacore::String> ImageMaskHandler<T>::get() const {
67 : return _image->regionNames(casacore::RegionHandler::Masks);
68 : }
69 :
70 : template <class T> void ImageMaskHandler<T>::copy(
71 : const casacore::String& currentName, const casacore::String& newName
72 : ) {
73 : ThrowIf(_image->hasRegion(
74 : newName, casacore::RegionHandler::Any),
75 : "Mask " + newName + " already exists"
76 : );
77 : casacore::Vector<casacore::String> mask2 = stringToVector(currentName, ':');
78 : ThrowIf(mask2.size() > 2, "Illegal mask specification " + currentName);
79 : auto external = mask2.size() == 2;
80 : _image->makeMask(newName, true, false);
81 :
82 : if (external) {
83 : casacore::ImageProxy proxy(casacore::Vector<casacore::String>(1, mask2[0]), 0);
84 : ThrowIf(
85 : ! proxy.shape().isEqual(_image->shape()),
86 : "Images have different shapes"
87 : );
88 : auto imagePtrs = ImageFactory::fromFile(mask2[0]);
89 : if (auto myImage = std::get<0>(imagePtrs)) {
90 : casacore::ImageUtilities::copyMask(
91 : *_image, *myImage,
92 : newName, mask2[1], casacore::AxesSpecifier()
93 : );
94 : }
95 : else if (auto myimage = std::get<1>(imagePtrs)) {
96 : casacore::ImageUtilities::copyMask(
97 : *_image, *myimage,
98 : newName, mask2[1], casacore::AxesSpecifier()
99 : );
100 : }
101 : else {
102 : ThrowCc("This image pixel data type not supported");
103 : }
104 : }
105 : else {
106 : casacore::ImageUtilities::copyMask(
107 : *_image, *_image,
108 : newName, mask2[0], casacore::AxesSpecifier()
109 : );
110 : }
111 : }
112 :
113 0 : template <class T> template<class U> void ImageMaskHandler<T>::copy(
114 : const casacore::MaskedLattice<U>& mask
115 : ) {
116 0 : auto shape = _image->shape();
117 0 : ThrowIf (
118 : ! shape.isEqual(mask.shape()),
119 : "Mask must be the same shape as the image"
120 : );
121 0 : auto cursorShape = _image->niceCursorShape(4096*4096);
122 0 : casacore::LatticeStepper stepper(shape, cursorShape, casacore::LatticeStepper::RESIZE);
123 0 : if (! _image->hasPixelMask()) {
124 0 : if (ImageMask::isAllMaskTrue(mask)) {
125 : // the current image has no pixel mask and the mask is all true, so
126 : // there is no point in copying anything.
127 0 : return;
128 : }
129 0 : casacore::String maskname = "";
130 0 : casacore::LogIO log;
131 0 : ImageMaskAttacher::makeMask(*_image, maskname, false, true, log, false);
132 : }
133 0 : casacore::Lattice<casacore::Bool>& pixelMask = _image->pixelMask();
134 0 : casacore::LatticeIterator<casacore::Bool> iter(pixelMask, stepper);
135 0 : casacore::RO_MaskedLatticeIterator<U> miter(mask, stepper);
136 0 : for (iter.reset(); ! iter.atEnd(); ++iter, ++miter) {
137 0 : auto mymask = miter.getMask();
138 0 : iter.rwCursor() = mymask;
139 : }
140 : }
141 :
142 : template <class T> void ImageMaskHandler<T>::calcmask(
143 : const casacore::String& mask, casacore::Record& regions,
144 : const casacore::String& maskName, const casacore::Bool makeDefault
145 : ) {
146 : ThrowIf(mask.empty(), "You must specify an expression");
147 : ThrowIf (
148 : ! _image->canDefineRegion(),
149 : "Cannot make requested mask for this image type which is " + _image->imageType()
150 : );
151 : casacore::Block<casacore::LatticeExprNode> temps;
152 : casacore::PtrBlock<const casacore::ImageRegion*> tempRegs;
153 : _makeRegionBlock(tempRegs, regions);
154 : casacore::LatticeExprNode node = casacore::ImageExprParse::command(mask, temps, tempRegs);
155 :
156 : // Delete the ImageRegions
157 : _makeRegionBlock(tempRegs, casacore::Record());
158 :
159 : // Make sure the expression is Boolean
160 : DataType type = node.dataType();
161 : ThrowIf(type != TpBool, "The expression type must be Boolean");
162 : _calcmask(node, maskName, makeDefault);
163 : }
164 :
165 : template<class T> void ImageMaskHandler<T>::_calcmask(
166 : const casacore::LatticeExprNode& node,
167 : const casacore::String& maskName, const casacore::Bool makeDefault
168 : ) {
169 : // Get the shape of the expression and check it matches that
170 : // of the output image. We don't check that the Coordinates
171 : // match as that would be an un-necessary restriction.
172 : if (
173 : ! node.isScalar()
174 : && ! _image->shape().isEqual(node.shape())
175 : ) {
176 : ostringstream os;
177 : os << "The shape of the expression does not conform "
178 : << "with the shape of the output image"
179 : << "Expression shape = " << node.shape()
180 : << "Image shape = " << _image->shape();
181 : ThrowCc(os.str());
182 : }
183 : // Make mask and get hold of its name. Currently new mask is forced to
184 : // be default because of other problems. Cannot use the usual ImageMaskAttacher<casacore::Float>::makeMask
185 : // function because I cant attach/make it default until the expression
186 : // has been evaluated
187 : // Generate mask name if not given
188 : casacore::String maskName2 = maskName.empty()
189 : ? _image->makeUniqueRegionName(
190 : casacore::String("mask"), 0
191 : ) : maskName;
192 :
193 : // Make the mask if it does not exist
194 : if (! _image->hasRegion(maskName2, casacore::RegionHandler::Masks)) {
195 : _image->makeMask(maskName2, true, false);
196 : casacore::LogIO log;
197 : log << casacore::LogOrigin("ImageMaskHandler", __func__);
198 : log << casacore::LogIO::NORMAL << "Created mask `" << maskName2 << "'"
199 : << casacore::LogIO::POST;
200 : casacore::ImageRegion iR = _image->getRegion(
201 : maskName2, casacore::RegionHandler::Masks
202 : );
203 : casacore::LCRegion& mask = iR.asMask();
204 : if (node.isScalar()) {
205 : casacore::Bool value = node.getBool();
206 : mask.set(value);
207 : }
208 : else {
209 : mask.copyData(casacore::LatticeExpr<casacore::Bool> (node));
210 : }
211 : }
212 : else {
213 : // Access pre-existing mask.
214 : casacore::ImageRegion iR = _image->getRegion(
215 : maskName2, casacore::RegionHandler::Masks
216 : );
217 : casacore::LCRegion& mask2 = iR.asMask();
218 : if (node.isScalar()) {
219 : casacore::Bool value = node.getBool();
220 : mask2.set(value);
221 : }
222 : else {
223 : mask2.copyData(casacore::LatticeExpr<casacore::Bool> (node));
224 : }
225 : }
226 : if (makeDefault) {
227 : _image->setDefaultMask(maskName2);
228 : }
229 : }
230 :
231 : template<class T> void ImageMaskHandler<T>::_makeRegionBlock(
232 : casacore::PtrBlock<const casacore::ImageRegion*>& regions,
233 : const casacore::Record& Regions
234 : ) {
235 : auto n = regions.size();
236 : for (casacore::uInt j=0; j<n; ++j) {
237 : delete regions[j];
238 : }
239 : regions.resize(0, true, true);
240 : casacore::uInt nreg = Regions.nfields();
241 : if (nreg > 0) {
242 : regions.resize(nreg);
243 : regions.set(static_cast<casacore::ImageRegion*> (0));
244 : for (casacore::uInt i=0; i<nreg; ++i) {
245 : regions[i] = casacore::ImageRegion::fromRecord(Regions.asRecord(i), "");
246 : }
247 : }
248 : }
249 :
250 : }
|