Line data Source code
1 : //# Copyright (C) 1998,1999,2000,2001,2003
2 : //# Associated Universities, Inc. Washington DC, USA.
3 : //#
4 : //# This library is free software; you can redistribute it and/or modify it
5 : //# under the terms of the GNU Library General Public License as published by
6 : //# the Free Software Foundation; either version 2 of the License, or (at your
7 : //# option) any later version.
8 : //#
9 : //# This library 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 Library General Public
12 : //# License for more details.
13 : //#
14 : //# You should have received a copy of the GNU Library General Public License
15 : //# along with this library; if not, write to the Free Software Foundation,
16 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
17 : //#
18 : //# Correspondence concerning AIPS++ should be addressed as follows:
19 : //# Internet email: casa-feedback@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 :
26 : #include <imageanalysis/ImageAnalysis/SubImageFactory.h>
27 :
28 : #include <casacore/casa/BasicSL/String.h>
29 : #include <casacore/tables/LogTables/NewFile.h>
30 : #include <casacore/images/Images/ExtendImage.h>
31 : #include <casacore/images/Images/ImageExpr.h>
32 : #include <casacore/images/Images/ImageUtilities.h>
33 : #include <casacore/images/Images/SubImage.h>
34 : #include <casacore/images/Images/PagedImage.h>
35 : #include <casacore/images/Regions/WCLELMask.h>
36 : #include <casacore/lattices/LRegions/LCMask.h>
37 : #include <casacore/lattices/Lattices/LatticeUtilities.h>
38 :
39 : #include <imageanalysis/ImageAnalysis/ImageMask.h>
40 : #include <imageanalysis/ImageAnalysis/ImageMaskAttacher.h>
41 : #include <imageanalysis/ImageAnalysis/ImageMaskHandler.h>
42 :
43 : // debug
44 : #include <components/ComponentModels/C11Timer.h>
45 :
46 : namespace casa {
47 :
48 0 : template<class T> std::shared_ptr<casacore::SubImage<T> > SubImageFactory<T>::createSubImageRW(
49 : casacore::CountedPtr<casacore::ImageRegion>& outRegion, casacore::CountedPtr<casacore::ImageRegion>& outMask,
50 : casacore::ImageInterface<T>& inImage, const casacore::Record& region,
51 : const casacore::String& mask, casacore::LogIO *const &os,
52 : const casacore::AxesSpecifier& axesSpecifier,
53 : casacore::Bool extendMask, casacore::Bool preserveAxesOrder
54 : ) {
55 0 : if (! mask.empty()) {
56 0 : _getMask(outMask, mask, extendMask, inImage.shape(), inImage.coordinates());
57 : }
58 0 : std::shared_ptr<casacore::SubImage<T> > subImage;
59 : // We can get away with no region processing if the region record
60 : // is empty and the user is not dropping degenerate axes
61 0 : if (region.nfields() == 0 && axesSpecifier.keep()) {
62 0 : subImage.reset(
63 0 : ! outMask
64 0 : ? new casacore::SubImage<T>(inImage, true, axesSpecifier, preserveAxesOrder)
65 0 : : new casacore::SubImage<T>(
66 0 : inImage, *outMask,
67 : true, axesSpecifier, preserveAxesOrder
68 : )
69 : );
70 : }
71 : else {
72 0 : outRegion = casacore::ImageRegion::fromRecord(
73 : os, inImage.coordinates(),
74 0 : inImage.shape(), region
75 : );
76 0 : if (! outMask) {
77 0 : subImage.reset(
78 0 : new casacore::SubImage<T>(
79 0 : inImage, *outRegion,
80 : true, axesSpecifier,
81 : preserveAxesOrder
82 : )
83 : );
84 : }
85 : else {
86 : // on the first pass, we need to keep all axes, the second
87 : // casacore::SubImage construction after this one will properly account
88 : // for the axes specifier
89 0 : casacore::SubImage<T> subImage0(
90 0 : inImage, *outMask, true,
91 0 : casacore::AxesSpecifier(), preserveAxesOrder
92 : );
93 0 : subImage.reset(
94 0 : new casacore::SubImage<T>(
95 0 : subImage0, *outRegion,
96 : true, axesSpecifier,
97 : preserveAxesOrder
98 : )
99 : );
100 0 : }
101 : }
102 0 : return subImage;
103 0 : }
104 :
105 0 : template<class T> std::shared_ptr<casacore::SubImage<T> > SubImageFactory<T>::createSubImageRW(
106 : casacore::ImageInterface<T>& inImage, const casacore::Record& region,
107 : const casacore::String& mask, casacore::LogIO *const &os,
108 : const casacore::AxesSpecifier& axesSpecifier,
109 : casacore::Bool extendMask, casacore::Bool preserveAxesOrder
110 : ) {
111 0 : casacore::CountedPtr<casacore::ImageRegion> pRegion;
112 0 : casacore::CountedPtr<casacore::ImageRegion> pMask;
113 : return createSubImageRW(
114 : pRegion, pMask, inImage, region,
115 : mask, os, axesSpecifier,
116 : extendMask, preserveAxesOrder
117 0 : );
118 0 : }
119 :
120 0 : template<class T> std::shared_ptr<const casacore::SubImage<T> > SubImageFactory<T>::createSubImageRO(
121 : casacore::CountedPtr<casacore::ImageRegion>& outRegion, casacore::CountedPtr<casacore::ImageRegion>& outMask,
122 : const casacore::ImageInterface<T>& inImage, const casacore::Record& region,
123 : const casacore::String& mask, casacore::LogIO *const &os,
124 : const casacore::AxesSpecifier& axesSpecifier,
125 : casacore::Bool extendMask, casacore::Bool preserveAxesOrder
126 : ) {
127 0 : if (! mask.empty()) {
128 0 : _getMask(outMask, mask, extendMask, inImage.shape(), inImage.coordinates());
129 : }
130 0 : std::shared_ptr<casacore::SubImage<T> > subImage;
131 : // We can get away with no region processing if the region record
132 : // is empty and the user is not dropping degenerate axes
133 0 : if (region.nfields() == 0 && axesSpecifier.keep()) {
134 0 : subImage.reset(
135 0 : ! outMask
136 0 : ? new casacore::SubImage<T>(inImage, axesSpecifier, preserveAxesOrder)
137 0 : : new casacore::SubImage<T>(
138 0 : inImage, *outMask,
139 : axesSpecifier, preserveAxesOrder
140 : )
141 : );
142 : }
143 : else {
144 0 : outRegion = casacore::ImageRegion::fromRecord(
145 : os, inImage.coordinates(),
146 0 : inImage.shape(), region
147 : );
148 0 : if (! outMask) {
149 0 : subImage.reset(
150 0 : new casacore::SubImage<T>(
151 0 : inImage, *outRegion,
152 : axesSpecifier,
153 : preserveAxesOrder
154 : )
155 : );
156 : }
157 : else {
158 : // on the first pass, we need to keep all axes, the second
159 : // casacore::SubImage construction after this one will properly account
160 : // for the axes specifier
161 0 : casacore::SubImage<T> subImage0(
162 0 : inImage, *outMask,
163 0 : casacore::AxesSpecifier(),
164 : preserveAxesOrder
165 : );
166 0 : subImage.reset(
167 0 : new casacore::SubImage<T>(
168 0 : subImage0, *outRegion,
169 : axesSpecifier,
170 : preserveAxesOrder
171 : )
172 : );
173 0 : }
174 : }
175 0 : return subImage;
176 0 : }
177 :
178 0 : template<class T> std::shared_ptr<const casacore::SubImage<T> > SubImageFactory<T>::createSubImageRO(
179 : const casacore::ImageInterface<T>& inImage, const casacore::Record& region,
180 : const casacore::String& mask, casacore::LogIO *const &os,
181 : const casacore::AxesSpecifier& axesSpecifier,
182 : casacore::Bool extendMask, casacore::Bool preserveAxesOrder
183 : ) {
184 0 : casacore::CountedPtr<casacore::ImageRegion> pRegion;
185 0 : casacore::CountedPtr<casacore::ImageRegion> pMask;
186 : return createSubImageRO(
187 : pRegion, pMask, inImage, region,
188 : mask, os, axesSpecifier,
189 : extendMask, preserveAxesOrder
190 0 : );
191 0 : }
192 :
193 0 : template<class T> SPIIT SubImageFactory<T>::createImage(
194 : const casacore::ImageInterface<T>& image,
195 : const casacore::String& outfile, const casacore::Record& region,
196 : const casacore::String& mask, casacore::Bool dropDegenerateAxes,
197 : casacore::Bool overwrite, casacore::Bool list, casacore::Bool extendMask, casacore::Bool attachMask,
198 : const casacore::Lattice<T> *const data
199 : ) {
200 : return createImage(
201 0 : image, outfile, region, mask, casacore::AxesSpecifier(! dropDegenerateAxes),
202 : overwrite, list, extendMask, attachMask, data
203 0 : );
204 : }
205 :
206 0 : template<class T> SPIIT SubImageFactory<T>::createImage(
207 : const casacore::ImageInterface<T>& image,
208 : const casacore::String& outfile, const casacore::Record& region,
209 : const casacore::String& mask, const casacore::AxesSpecifier& axesSpec,
210 : casacore::Bool overwrite, casacore::Bool list, casacore::Bool extendMask, casacore::Bool attachMask,
211 : const casacore::Lattice<T> *const data
212 : ) {
213 0 : casacore::LogIO log;
214 0 : log << casacore::LogOrigin("SubImageFactory", __func__);
215 : // Copy a portion of the image
216 : // Verify output file
217 0 : if (! overwrite && ! outfile.empty()) {
218 0 : casacore::NewFile validfile;
219 0 : casacore::String errmsg;
220 0 : if(! validfile.valueOK(outfile, errmsg)) {
221 : // CAS-8715 users want a nicer error message in this case
222 0 : if (casacore::File(outfile).exists()) {
223 0 : errmsg = outfile + " already exists";
224 : }
225 0 : ThrowCc(errmsg);
226 : }
227 0 : }
228 0 : std::shared_ptr<const casacore::SubImage<T> > x = createSubImageRO(
229 0 : image, region, mask, list ? &log : 0,
230 : axesSpec, extendMask, true
231 : );
232 0 : SPIIT outImage;
233 0 : if (outfile.empty()) {
234 0 : outImage.reset(
235 0 : new casacore::TempImage<T>(x->shape(), x->coordinates())
236 : );
237 : }
238 : else {
239 0 : outImage.reset(
240 0 : new casacore::PagedImage<T>(
241 0 : x->shape(), x->coordinates(), outfile
242 : )
243 : );
244 0 : if (list) {
245 : log << casacore::LogIO::NORMAL << "Creating image '" << outfile
246 0 : << "' of shape " << outImage->shape() << casacore::LogIO::POST;
247 : }
248 : }
249 0 : casacore::ImageUtilities::copyMiscellaneous(*outImage, *x);
250 0 : if (attachMask || ! ImageMask::isAllMaskTrue(*x)) {
251 : // if we don't already have a mask, but the user has specified that one needs to
252 : // be present, attach it. This needs to be done prior to the copyDataAndMask() call
253 : // because in that implementation, the image to which the mask is to be copied must
254 : // have already have a mask; that call does not create one if it does not exist.
255 0 : casacore::String maskName = "";
256 0 : ImageMaskAttacher::makeMask(*outImage, maskName, false, true, log, list);
257 0 : if (data) {
258 0 : ImageMaskHandler<T> imh(outImage);
259 0 : imh.copy(*x);
260 0 : }
261 0 : }
262 0 : if (data) {
263 0 : outImage->copyData(*data);
264 : }
265 : else {
266 0 : casacore::LatticeUtilities::copyDataAndMask(log, *outImage, *x);
267 : }
268 0 : outImage->flush();
269 0 : return outImage;
270 0 : }
271 :
272 0 : template<class T> void SubImageFactory<T>::_getMask(
273 : casacore::CountedPtr<casacore::ImageRegion>& outMask, const casacore::String& mask,
274 : casacore::Bool extendMask, const casacore::IPosition& imageShape,
275 : const casacore::CoordinateSystem& csys
276 : ) {
277 0 : casacore::String mymask = mask;
278 0 : for (casacore::uInt i=0; i<2; i++) {
279 : try {
280 0 : outMask = casacore::ImageRegion::fromLatticeExpression(mymask);
281 0 : break;
282 : }
283 0 : catch (const casacore::AipsError& x) {
284 0 : if (i == 0) {
285 : // not an LEL expression, perhaps it's a clean mask image name
286 0 : mymask += ">=0.5";
287 0 : continue;
288 : }
289 0 : ThrowCc("Input mask specification is incorrect: " + x.getMesg());
290 : }
291 : }
292 0 : if (outMask && outMask->asWCRegion().type() == "WCLELMask") {
293 0 : const casacore::ImageExpr<casacore::Bool> *myExpression = dynamic_cast<const casacore::WCLELMask*>(
294 0 : outMask->asWCRegionPtr()
295 0 : )->getImageExpr();
296 0 : if (
297 : myExpression
298 0 : && ! myExpression->shape().isEqual(imageShape)
299 : ) {
300 0 : if (! extendMask) {
301 0 : ostringstream os;
302 0 : os << "The input image shape (" << imageShape << ") and mask shape ("
303 0 : << myExpression->shape() << ") are different, and it was specified "
304 : "that the mask should not be extended, so the mask cannot be applied to the "
305 : "(sub)image. Specifying that the mask should be extended may resolve the issue";
306 0 : ThrowCc(os.str());
307 0 : }
308 : try {
309 0 : casacore::ExtendImage<casacore::Bool> exIm(*myExpression, imageShape, csys);
310 0 : outMask = new casacore::ImageRegion(casacore::LCMask(exIm));
311 0 : }
312 0 : catch ( const std::exception &x ) {
313 0 : ThrowCc( String("Unable to extend mask: ") + x.what() );
314 : }
315 : }
316 : }
317 0 : }
318 :
319 : }
|