Line data Source code
1 : //# WPConvFunc.cc: implementation of WPConvFunc
2 : //# Copyright (C) 2007-2016
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be adressed as follows:
20 : //# Internet email: aips2-request@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //#
27 : //# $Id$
28 : #include <sstream>
29 : #include <iostream>
30 : #include <iomanip>
31 : #include <casacore/casa/Arrays/ArrayMath.h>
32 : #include <casacore/casa/Arrays/Array.h>
33 : #include <casacore/casa/Arrays/MaskedArray.h>
34 : #include <casacore/casa/Arrays/Vector.h>
35 : #include <casacore/casa/Arrays/Slice.h>
36 : #include <casacore/casa/Arrays/Matrix.h>
37 : #include <casacore/casa/Arrays/Cube.h>
38 : #include <casacore/casa/OS/HostInfo.h>
39 : #include <casacore/casa/Utilities/Assert.h>
40 : #include <casacore/casa/Utilities/CompositeNumber.h>
41 : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
42 : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
43 :
44 : #include <casacore/images/Images/ImageInterface.h>
45 : #include <casacore/images/Images/PagedImage.h>
46 : #include <casacore/images/Images/TempImage.h>
47 : #include <casacore/casa/Logging/LogIO.h>
48 : #include <casacore/casa/Logging/LogSink.h>
49 : #include <casacore/casa/Logging/LogMessage.h>
50 :
51 : #include <casacore/lattices/Lattices/ArrayLattice.h>
52 : #include <casacore/lattices/Lattices/SubLattice.h>
53 : #include <casacore/lattices/LRegions/LCBox.h>
54 : #include <casacore/lattices/LEL/LatticeExpr.h>
55 : #include <casacore/lattices/Lattices/LatticeCache.h>
56 : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
57 : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
58 : #include <msvis/MSVis/VisBuffer2.h>
59 : #include <msvis/MSVis/VisibilityIterator2.h>
60 : #include <casacore/scimath/Mathematics/FFTPack.h>
61 : #include <msvis/MSVis/VisBuffer.h>
62 : #include <msvis/MSVis/VisibilityIterator.h>
63 : #include <synthesis/TransformMachines/SimplePBConvFunc.h> //por SINCOS
64 :
65 : #include <synthesis/TransformMachines2/WPConvFunc.h>
66 : #ifdef _OPENMP
67 : #include <omp.h>
68 : #endif
69 :
70 :
71 :
72 :
73 : using namespace casacore;
74 : namespace casa { //# NAMESPACE CASA - BEGIN
75 : namespace refim{ //namespace for refactoring imager
76 :
77 : using namespace casacore;
78 : using namespace casa;
79 : using namespace casacore;
80 : using namespace casa::refim;
81 : typedef unsigned long long ooLong;
82 80 : WPConvFunc::WPConvFunc(const Double minW, const Double maxW, const Double rmsW):
83 80 : actualConvIndex_p(-1), convSize_p(0), convSupport_p(0), minW_p(minW), maxW_p(maxW), rmsW_p(rmsW) {
84 : //
85 80 : }
86 0 : WPConvFunc::WPConvFunc(const WPConvFunc& other):
87 0 : actualConvIndex_p(-1), convSize_p(0), convSupport_p(0){
88 :
89 0 : operator=(other);
90 0 : }
91 :
92 0 : WPConvFunc& WPConvFunc::operator=(const WPConvFunc& other){
93 0 : if(this != &other){
94 0 : uInt numConv=other.convFunctions_p.nelements();
95 0 : convFunctions_p.resize(numConv, true, false);
96 0 : convSupportBlock_p.resize(numConv, true, false);
97 0 : for (uInt k=0; k < numConv; ++k){
98 0 : convFunctions_p[k]=new Cube<Complex>();
99 0 : *(convFunctions_p[k])=*(other.convFunctions_p[k]);
100 0 : convSupportBlock_p[k]=new Vector<Int> ();
101 0 : *(convSupportBlock_p[k]) = *(other.convSupportBlock_p[k]);
102 : }
103 :
104 0 : convFunctionMap_p=other.convFunctionMap_p;
105 0 : convSizes_p.resize();
106 0 : convSizes_p=other.convSizes_p;
107 0 : actualConvIndex_p=other.actualConvIndex_p;
108 0 : convSize_p=other.convSize_p;
109 0 : convSupport_p.resize();
110 0 : convSupport_p=other.convSupport_p;
111 0 : convFunc_p.resize();
112 0 : convFunc_p=other.convFunc_p;
113 0 : wScaler_p=other.wScaler_p;
114 0 : convSampling_p=other.convSampling_p;
115 0 : nx_p=other.nx_p;
116 0 : ny_p=other.ny_p;
117 0 : minW_p=other.minW_p;
118 0 : maxW_p=other.maxW_p;
119 0 : rmsW_p=other.rmsW_p;
120 :
121 :
122 :
123 : }
124 0 : return *this;
125 : }
126 :
127 160 : WPConvFunc::~WPConvFunc(){
128 : //usage of CountedPtr keeps this simple
129 :
130 160 : }
131 :
132 0 : WPConvFunc::WPConvFunc(const RecordInterface& rec):
133 0 : actualConvIndex_p(-1), convSize_p(0), convSupport_p(0){
134 0 : String error;
135 0 : if (!fromRecord(error, rec)) {
136 0 : throw (AipsError("Failed to create WPConvFunc: " + error));
137 : }
138 :
139 0 : }
140 :
141 1544 : void WPConvFunc::findConvFunction(const ImageInterface<Complex>& image,
142 : const vi::VisBuffer2& vb,
143 : const Int& wConvSizeUser,
144 : const Vector<Double>& uvScale,
145 : const Vector<Double>& uvOffset,
146 : const Float& padding,
147 : Int& convSampling,
148 : Cube<Complex>& convFunc,
149 : Int& convSize,
150 : Vector<Int>& convSupport, Double& wScale){
151 1544 : if(checkCenterPix(image)){
152 1512 : convFunc.resize();
153 1512 : convFunc.reference(convFunc_p);
154 1512 : convSize=convSize_p;
155 1512 : convSampling=convSampling_p;
156 1512 : convSupport.resize();
157 1512 : convSupport=convSupport_p;
158 1512 : wScale=Float((convFunc.shape()(2)-1)*(convFunc.shape()(2)-1))/wScaler_p;
159 1512 : return;
160 : }
161 64 : LogIO os;
162 32 : os << LogOrigin("WPConvFunc", "findConvFunction") << LogIO::NORMAL;
163 :
164 :
165 : // Get the coordinate system
166 64 : CoordinateSystem coords(image.coordinates());
167 32 : Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
168 32 : nx_p=Int(image.shape()(directionIndex));
169 32 : ny_p=Int(image.shape()(directionIndex+1));
170 :
171 32 : Int wConvSize=wConvSizeUser;
172 : ////Automatic mode
173 : Double maxUVW;
174 32 : if(wConvSize < 1){
175 5 : maxUVW=rmsW_p < 0.5*(minW_p+maxW_p) ? 1.05*maxW_p: (rmsW_p /(0.5*((minW_p)+maxW_p))*1.05*maxW_p) ;
176 5 : wConvSize=Int(maxUVW*fabs(sin(fabs(image.coordinates().increment()(0))*max(nx_p, ny_p)/2.0)));
177 5 : convSupport.resize(wConvSize);
178 : }
179 : else{
180 27 : if(maxW_p> 0.0)
181 0 : maxUVW= 1.05*maxW_p;
182 : else
183 27 : maxUVW=0.25/abs(image.coordinates().increment()(0));
184 :
185 : }
186 32 : if(wConvSize>1) {
187 32 : os << "W projection using " << wConvSize << " planes" << LogIO::POST;
188 :
189 : os << "Using maximum possible W = " << maxUVW
190 32 : << " (wavelengths)" << LogIO::POST;
191 :
192 32 : Double invLambdaC=vb.getFrequency(0,0)/C::c;
193 : os << "Typical wavelength = " << 1.0/invLambdaC
194 32 : << " (m)" << LogIO::POST;
195 :
196 :
197 32 : wScale=Float((wConvSize-1)*(wConvSize-1))/maxUVW;
198 : //wScale=Float(wConvSize-1)/maxUVW;
199 32 : wScaler_p=maxUVW;;
200 32 : os << "Scaling in W (at maximum W) = " << 1.0/wScale
201 32 : << " wavelengths per pixel" << LogIO::POST;
202 : }
203 :
204 32 : Int planesPerChunk=100;
205 :
206 :
207 32 : if(wConvSize>1) {
208 32 : Int maxMemoryMB=min(uInt64(HostInfo::memoryTotal(true)), uInt64(HostInfo::memoryFree()))/1024;
209 : ////Common you have to have 4 GB...memoryFree sometimes is whacky
210 32 : if(maxMemoryMB < 4000)
211 0 : maxMemoryMB=4000;
212 32 : convSize=max(Int(nx_p*padding),Int(ny_p*padding));
213 : ///Do the same thing as in WProject::init
214 32 : CompositeNumber cn(convSize);
215 32 : convSize = cn.nextLargerEven(convSize);
216 : //nominal 100 wprojplanes above that you may (or not) go swapping
217 :
218 32 : planesPerChunk=Int((Double(maxMemoryMB)/8.0*1024.0*1024.0)/Double(convSize)/Double(convSize));
219 : //cerr << "planesPerChunk" << planesPerChunk << endl;
220 32 : planesPerChunk=min(planesPerChunk, 100);
221 : // CompositeNumber cn(Int(maxConvSizeConsidered/2.0)*2);
222 32 : convSampling_p=4;
223 :
224 : //convSize=min(convSize,(Int)cn.nearestEven(Int(maxConvSizeConsidered/2.0)*2));
225 :
226 : }
227 : else{
228 0 : convSampling_p=1;
229 0 : convSize=max(Int(nx_p*padding),Int(ny_p*padding));
230 : }
231 32 : convSampling=convSampling_p;
232 32 : Int maxConvSize=convSize;
233 32 : convSupport.resize(wConvSize);
234 32 : convSupport.set(-1);
235 : ////set sampling
236 32 : AlwaysAssert(directionIndex>=0, AipsError);
237 64 : DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
238 64 : Vector<Double> sampling;
239 32 : sampling = dc.increment();
240 32 : sampling*=Double(convSampling_p);
241 : //sampling*=Double(max(nx,ny))/Double(convSize);
242 32 : sampling[0]*=Double(padding*Float(nx_p))/Double(convSize);
243 32 : sampling[1]*=Double(padding*Float(ny_p))/Double(convSize);
244 : /////
245 32 : Int inner=convSize/convSampling_p;
246 : ConvolveGridder<Double, Complex>
247 96 : ggridder(IPosition(2, inner, inner), uvScale, uvOffset, "SF");
248 :
249 32 : Int nchunk=wConvSize/planesPerChunk;
250 32 : if((wConvSize%planesPerChunk) !=0)
251 32 : nchunk +=1;
252 64 : Vector<Int> chunksize(nchunk, planesPerChunk);
253 32 : if((wConvSize%planesPerChunk) !=0)
254 32 : chunksize(nchunk-1)=wConvSize%planesPerChunk;
255 :
256 32 : Int warner=0;
257 64 : Vector<Complex> maxes(wConvSize);
258 : // Bool maxdel;
259 : // Complex* maxptr=maxes.getStorage(maxdel);
260 64 : Matrix<Complex> corr(inner, inner);
261 64 : Vector<Complex> correction(inner);
262 9664 : for (Int iy=-inner/2;iy<inner/2;iy++) {
263 :
264 9632 : ggridder.correctX1D(correction, iy+inner/2);
265 9632 : corr.row(iy+inner/2)=correction;
266 : }
267 : Bool cpcor;
268 :
269 32 : Complex *cor=corr.getStorage(cpcor);
270 64 : Vector<Int>pcsupp;
271 32 : pcsupp=convSupport;
272 : Bool delsupstor;
273 32 : Int* suppstor=pcsupp.getStorage(delsupstor);
274 32 : Double s1=sampling(1);
275 32 : Double s0=sampling(0);
276 : ///////////Por FFTPack
277 64 : Vector<Float> wsave(2*convSize*convSize+15);
278 32 : Int lsav=2*convSize*convSize+15;
279 : Bool wsavesave;
280 32 : Float *wsaveptr=wsave.getStorage(wsavesave);
281 : Int ier;
282 32 : FFTPack::cfft2i(convSize, convSize, wsaveptr, lsav, ier);
283 : //////////
284 32 : Matrix<Complex> screen(convSize, convSize);
285 32 : makeGWplane(screen, 0, s0, s1, wsaveptr, lsav, inner, cor, wScale);
286 32 : Float maxconv=abs(screen(0,0));
287 73 : for (Int chunkId=nchunk-1; chunkId >= 0; --chunkId){
288 : //cerr << "chunkId " << chunkId << endl;
289 82 : Cube<Complex> convFuncSect( maxConvSize/2-1, maxConvSize/2-1, chunksize(chunkId));
290 41 : convFuncSect.set(0.0);
291 41 : Bool convFuncStor=false;
292 41 : Complex *convFuncPtr=convFuncSect.getStorage(convFuncStor);
293 : //////openmp like to share reference param ...but i don't like to share
294 41 : Int cpConvSize=maxConvSize;
295 : //cerr << "orig convsize " << convSize << endl;
296 : // Int cpWConvSize=wConvSize;
297 41 : Double cpWscale=wScale;
298 41 : Int wstart=planesPerChunk*chunkId;
299 41 : Int wend=wstart+chunksize(chunkId)-1;
300 :
301 : #ifdef _OPENMP
302 41 : omp_set_nested(0);
303 41 : Int nthreads=omp_get_max_threads();
304 41 : nthreads=min(nthreads, chunksize(chunkId));
305 41 : omp_set_num_threads(nthreads);
306 :
307 : #endif
308 41 : #pragma omp parallel for default(none) firstprivate(/*cpWConvSize,*/ cpConvSize, convFuncPtr, s0, s1, wsaveptr, lsav, cor, inner, cpWscale, wstart, wend) schedule(dynamic, 1)
309 :
310 :
311 : for (Int iw=wstart; iw < (wend+1) ; ++iw) {
312 : Matrix<Complex> screen1(cpConvSize, cpConvSize);
313 : makeGWplane(screen1, iw, s0, s1, wsaveptr, lsav, inner, cor, cpWscale);
314 : ooLong offset=ooLong(ooLong(iw-wstart)*ooLong(cpConvSize/2-1)*ooLong(cpConvSize/2-1));
315 : for (ooLong y=0; y< ooLong(cpConvSize/2)-1; ++y){
316 : for (ooLong x=0; x< ooLong(cpConvSize/2)-1; ++x){
317 : ////////convFuncPtr[offset+y*(convSize/2-1)+x] = quarter(x,y);
318 : convFuncPtr[offset+y*ooLong(cpConvSize/2-1)+x] = screen1(x,y);
319 : }
320 : }
321 :
322 : }//iw
323 :
324 41 : convFuncSect.putStorage(convFuncPtr, convFuncStor);
325 1332 : for (uInt iw=0; iw< uInt(chunksize(chunkId)); ++iw){
326 1291 : convFuncSect.xyPlane(iw)=convFuncSect.xyPlane(iw)/(maxconv);
327 : }
328 41 : convFuncPtr=convFuncSect.getStorage(convFuncStor);
329 41 : Int thischunkSize=chunksize(chunkId);
330 : //cerr << "chunkId* planesPerChunk " << chunkId* planesPerChunk << " chunksize " << thischunkSize << endl;
331 41 : #pragma omp parallel for default(none) firstprivate(suppstor, cpConvSize, /*cpWConvSize,*/ convFuncPtr, maxConvSize, thischunkSize, wstart, planesPerChunk, chunkId) reduction(+: warner)
332 : for (Int iw=0; iw<thischunkSize; iw++) {
333 : Bool found=false;
334 : Int trial=0;
335 : ooLong ploffset=(ooLong)(cpConvSize/2-1)*(ooLong)(cpConvSize/2-1)*(ooLong)iw;
336 : for (trial=cpConvSize/2-2;trial>0;trial--) {
337 : // if((abs(convFunc(trial,0,iw))>1e-3)||(abs(convFunc(0,trial,iw))>1e-3) ) {
338 : if((abs(convFuncPtr[(ooLong)(trial)+ploffset])>1e-3)||(abs(convFuncPtr[(ooLong)(trial*(cpConvSize/2-1))+ploffset])>1e-3) ) {
339 : //cout <<"iw " << iw << " x " << abs(convFunc(trial,0,iw)) << " y "
340 : // <<abs(convFunc(0,trial,iw)) << endl;
341 : found=true;
342 : break;
343 : }
344 : }
345 : Int trueIw=iw+chunkId* planesPerChunk;
346 : if(found) {
347 : suppstor[trueIw]=Int(0.5+Float(trial)/Float(convSampling_p))+1;
348 : if(suppstor[trueIw]*convSampling_p*2 >= maxConvSize){
349 : suppstor[trueIw]=cpConvSize/2/convSampling_p-1;
350 : ++warner;
351 : }
352 : }
353 : else{
354 : suppstor[trueIw]=cpConvSize/2/convSampling_p-1;
355 : ++warner;
356 : }
357 : }
358 41 : convFuncSect.putStorage(convFuncPtr, convFuncStor);
359 41 : if(chunkId==(nchunk-1)){
360 32 : Int newConvSize=2*(suppstor[wConvSize-1]+2)*convSampling;
361 32 : if(newConvSize < convSize){
362 64 : convFunc.resize((newConvSize/2-1),
363 32 : (newConvSize/2-1),
364 : wConvSize);
365 32 : convSize=newConvSize;
366 : }
367 : else{
368 0 : convFunc.resize((convSize/2-1),
369 0 : (convSize/2-1),
370 : wConvSize);
371 : }
372 : }
373 82 : IPosition blc(3, 0,0,wstart);
374 41 : IPosition trc(3, (convSize/2-2),(convSize/2-2),wend);
375 82 : convFunc(blc, trc)=convFuncSect(IPosition(3, 0,0,0), IPosition(3, (convSize/2-2),
376 82 : (convSize/2-2), thischunkSize-1));
377 :
378 :
379 : }//chunkId
380 32 : corr.putStorage(cor, cpcor);
381 32 : pcsupp.putStorage(suppstor, delsupstor);
382 32 : convSupport=pcsupp;
383 32 : Double pbSum=0.0;
384 320 : for (Int iy=-convSupport(0);iy<=convSupport(0);iy++) {
385 2880 : for (Int ix=-convSupport(0);ix<=convSupport(0);ix++) {
386 2592 : pbSum+=real(convFunc(abs(ix)*convSampling_p,abs(iy)*convSampling_p,0));
387 : }
388 : }
389 32 : if(pbSum>0.0) {
390 32 : convFunc*=Complex(1.0/pbSum,0.0);
391 : }
392 : else {
393 : os << "Convolution function integral is not positive"
394 0 : << LogIO::EXCEPTION;
395 : }
396 :
397 :
398 32 : os << "Convolution support = " << convSupport*convSampling_p
399 : << " pixels in Fourier plane"
400 32 : << LogIO::POST;
401 32 : convSupportBlock_p.resize(actualConvIndex_p+1);
402 32 : convSupportBlock_p[actualConvIndex_p]= new Vector<Int>();
403 32 : convSupportBlock_p[actualConvIndex_p]->assign(convSupport);
404 32 : convFunctions_p.resize(actualConvIndex_p+1);
405 32 : convFunctions_p[actualConvIndex_p]= new Cube<Complex>(convFunc);
406 32 : convSizes_p.resize(actualConvIndex_p+1, true);
407 32 : convSizes_p(actualConvIndex_p)=convSize;
408 32 : Int maxMemoryMB=HostInfo::memoryTotal(true)/1024;
409 : Int memoryMB;
410 96 : memoryMB = Int(Double(convSize/2-1)*Double(convSize/2-1)*
411 64 : Double(wConvSize)*8.0/1024.0/1024.0);
412 : os << "Memory used in gridding function = "
413 : << memoryMB << " MB from maximum "
414 32 : << maxMemoryMB << " MB" << LogIO::POST;
415 32 : convSampling=convSampling_p;
416 32 : wScale=Float((wConvSize-1)*(wConvSize-1))/wScaler_p;
417 :
418 : }//end func
419 :
420 1323 : void WPConvFunc::makeGWplane(Matrix<Complex>& screen, const Int iw, Double s0, Double s1, Float *& wsaveptr, Int& lsav, Int& inner, Complex*& cor, Double&cpWscale){
421 :
422 1323 : Int cpConvSize=screen.shape()(0);
423 : //cerr << "cpConvSize " << cpConvSize << " shape " << screen.shape() << endl;
424 1323 : screen.set(0.0);
425 : Bool cpscr;
426 1323 : Complex *scr=screen.getStorage(cpscr);
427 1323 : Double twoPiW=2.0*C::pi*Double(iw*iw)/cpWscale;
428 472075 : for (Int iy=-inner/2;iy<inner/2;iy++) {
429 470752 : Double m=s1*Double(iy);
430 470752 : Double msq=m*m;
431 : //////Int offset= (iy+convSize/2)*convSize;
432 : ///fftpack likes it flipped
433 470752 : ooLong offset= (iy>-1 ? ooLong(iy) : ooLong(iy+cpConvSize))*ooLong(cpConvSize);
434 233616480 : for (Int ix=-inner/2;ix<inner/2;ix++) {
435 : ////// Int ind=offset+ix+convSize/2;
436 : ///fftpack likes it flipped
437 233145728 : ooLong ind=offset+(ix > -1 ? ooLong(ix) : ooLong(ix+cpConvSize));
438 233145728 : Double l=s0*Double(ix);
439 233145728 : Double rsq=l*l+msq;
440 233145728 : if(rsq<1.0) {
441 233145728 : Double phase=twoPiW*(sqrt(1.0-rsq)-1.0);
442 : Double cval, sval;
443 233145728 : SINCOS(phase, sval, cval);
444 233145728 : Complex comval(cval, sval);
445 233145728 : scr[ind]=(cor[ix+inner/2+ (iy+inner/2)*inner])*comval;
446 : //screen(ix+convSize/2, iy+convSize/2)=comval;
447 : }
448 : }
449 : }
450 : ////Por FFTPack
451 2646 : Vector<Float>work(2*cpConvSize*cpConvSize);
452 1323 : Int lenwrk=2*cpConvSize*cpConvSize;
453 : Bool worksave;
454 1323 : Float *workptr=work.getStorage(worksave);
455 : Int ier;
456 1323 : FFTPack::cfft2f(cpConvSize, cpConvSize, cpConvSize, scr, wsaveptr, lsav, workptr, lenwrk, ier);
457 :
458 1323 : screen.putStorage(scr, cpscr);
459 :
460 1323 : }
461 :
462 :
463 1544 : Bool WPConvFunc::checkCenterPix(const ImageInterface<Complex>& image){
464 :
465 3088 : CoordinateSystem imageCoord=image.coordinates();
466 3088 : MDirection wcenter;
467 1544 : Int directionIndex=imageCoord.findCoordinate(Coordinate::DIRECTION);
468 : DirectionCoordinate
469 3088 : directionCoord=imageCoord.directionCoordinate(directionIndex);
470 3088 : Vector<Double> incr=directionCoord.increment();
471 1544 : nx_p=image.shape()(directionIndex);
472 1544 : ny_p=image.shape()(directionIndex+1);
473 :
474 :
475 : //Images with same number of pixels and increments can have the same conv functions
476 3088 : ostringstream oos;
477 1544 : oos << std::setprecision(6);
478 :
479 1544 : oos << nx_p << "_"<< fabs(incr(0)) << "_";
480 1544 : oos << ny_p << "_"<< fabs(incr(1));
481 3088 : String imageKey(oos);
482 :
483 1544 : if(convFunctionMap_p.size( ) == 0){
484 32 : convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(imageKey, 0));
485 32 : actualConvIndex_p=0;
486 32 : return false;
487 : }
488 :
489 1512 : if( convFunctionMap_p.find(imageKey) == convFunctionMap_p.end( ) ){
490 0 : actualConvIndex_p=convFunctionMap_p.size( );
491 0 : convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(imageKey,actualConvIndex_p));
492 0 : return false;
493 : }
494 : else{
495 1512 : actualConvIndex_p=convFunctionMap_p[imageKey];
496 1512 : convFunc_p.resize(); // break any reference
497 1512 : convFunc_p.reference(*convFunctions_p[actualConvIndex_p]);
498 1512 : convSupport_p.resize();
499 1512 : convSupport_p.reference(*convSupportBlock_p[actualConvIndex_p]);
500 1512 : convSize_p=convSizes_p[actualConvIndex_p];
501 :
502 : }
503 :
504 1512 : return true;
505 : }
506 :
507 0 : Bool WPConvFunc::toRecord(RecordInterface& rec){
508 :
509 0 : Int numConv=convFunctions_p.nelements();
510 : try{
511 0 : rec.define("numconv", numConv);
512 0 : auto convptr = convFunctionMap_p.begin( );
513 0 : for (Int k=0; k < numConv; ++k, ++convptr){
514 0 : rec.define("convfunctions"+String::toString(k), *(convFunctions_p[k]));
515 0 : rec.define("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
516 0 : rec.define("key"+String::toString(k), convptr->first);
517 0 : rec.define("val"+String::toString(k), convptr->second);
518 : }
519 0 : rec.define("convsizes", convSizes_p);
520 0 : rec.define("actualconvIndex",actualConvIndex_p);
521 0 : rec.define("convsize", convSize_p);
522 0 : rec.define("convsupport", convSupport_p);
523 0 : rec.define("convfunc",convFunc_p);
524 0 : rec.define("wscaler", wScaler_p);
525 0 : rec.define("convsampling", convSampling_p);
526 0 : rec.define("nx", nx_p);
527 0 : rec.define("ny", ny_p);
528 : }
529 0 : catch(AipsError x) {
530 0 : return false;
531 : }
532 0 : return true;
533 :
534 :
535 :
536 : }
537 :
538 0 : Bool WPConvFunc::fromRecord(String& err, const RecordInterface& rec){
539 :
540 0 : Int numConv=0;
541 : try{
542 0 : rec.get("numconv", numConv);
543 0 : convFunctions_p.resize(numConv, true, false);
544 0 : convSupportBlock_p.resize(numConv, true, false);
545 0 : convFunctionMap_p.clear( );
546 0 : for (Int k=0; k < numConv; ++k){
547 0 : convFunctions_p[k]=new Cube<Complex>();
548 0 : convSupportBlock_p[k]=new Vector<Int>();
549 0 : rec.get("convfunctions"+String::toString(k), *(convFunctions_p[k]));
550 0 : rec.get("convsupportblock"+String::toString(k), *(convSupportBlock_p[k]));
551 0 : String key;
552 : Int val;
553 0 : rec.get("key"+String::toString(k), key);
554 0 : rec.get("val"+String::toString(k), val);
555 0 : convFunctionMap_p.insert(std::pair<casacore::String, casacore::Int>(key,val));
556 : }
557 0 : rec.get("convsizes", convSizes_p);
558 0 : rec.get("actualconvIndex",actualConvIndex_p);
559 0 : rec.get("convsize", convSize_p);
560 0 : rec.get("convsupport", convSupport_p);
561 0 : rec.get("convfunc",convFunc_p);
562 0 : if(rec.isDefined("wscaler"))
563 0 : rec.get("wscaler", wScaler_p);
564 0 : rec.get("convsampling", convSampling_p);
565 0 : rec.get("nx", nx_p);
566 0 : rec.get("ny", ny_p);
567 : }
568 0 : catch(AipsError x) {
569 0 : err=x.getMesg();
570 0 : return false;
571 : }
572 0 : return true;
573 :
574 : }
575 :
576 :
577 :
578 :
579 : } //end of namespace refim
580 : } //# NAMESPACE CASA - END
|