Line data Source code
1 : //# GridFT.cc: Implementation of GridFT class
2 : //# Copyright (C) 1997-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 addressed as follows:
20 : //# Internet email: casa-feedback@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 : //# $Id$
27 :
28 : #include <msvis/MSVis/VisibilityIterator2.h>
29 : #include <casacore/casa/Quanta/UnitMap.h>
30 : #include <casacore/casa/Quanta/UnitVal.h>
31 : #include <casacore/measures/Measures/Stokes.h>
32 : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
33 : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
34 : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
35 : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
36 : #include <casacore/coordinates/Coordinates/Projection.h>
37 : #include <casacore/ms/MeasurementSets/MSColumns.h>
38 : #include <casacore/casa/BasicSL/Constants.h>
39 : #include <casacore/scimath/Mathematics/FFTServer.h>
40 : #include <casacore/scimath/Mathematics/RigidVector.h>
41 : #include <msvis/MSVis/StokesVector.h>
42 : #include <synthesis/TransformMachines/StokesImageUtil.h>
43 : #include <synthesis/TransformMachines2/GridFT.h>
44 : #include <synthesis/Utilities/FFT2D.h>
45 : #include <msvis/MSVis/VisBuffer2.h>
46 : #include <casacore/images/Images/ImageInterface.h>
47 : #include <casacore/images/Images/PagedImage.h>
48 : #include <casacore/casa/Containers/Block.h>
49 : #include <casacore/casa/Containers/Record.h>
50 : #include <casacore/casa/Arrays/ArrayLogical.h>
51 : #include <casacore/casa/Arrays/ArrayMath.h>
52 : #include <casacore/casa/Arrays/Array.h>
53 : #include <casacore/casa/Arrays/MaskedArray.h>
54 : #include <casacore/casa/Arrays/Vector.h>
55 : #include <casacore/casa/Arrays/Matrix.h>
56 : #include <casacore/casa/Arrays/Cube.h>
57 : #include <casacore/casa/Arrays/MatrixIter.h>
58 : #include <casacore/casa/BasicSL/String.h>
59 : #include <casacore/casa/Utilities/Assert.h>
60 : #include <casacore/casa/Exceptions/Error.h>
61 : #include <casacore/lattices/Lattices/ArrayLattice.h>
62 : #include <casacore/measures/Measures/UVWMachine.h>
63 : #include <casacore/lattices/Lattices/SubLattice.h>
64 : #include <casacore/lattices/LRegions/LCBox.h>
65 : #include <casacore/lattices/Lattices/LatticeCache.h>
66 : #include <casacore/lattices/LatticeMath/LatticeFFT.h>
67 : #include <casacore/lattices/Lattices/LatticeIterator.h>
68 : #include <casacore/lattices/Lattices/LatticeStepper.h>
69 : #include <casacore/scimath/Mathematics/ConvolveGridder.h>
70 : #include <casacore/casa/Utilities/CompositeNumber.h>
71 : #include <casacore/casa/OS/Timer.h>
72 : #include <sstream>
73 : #ifdef _OPENMP
74 : #include <omp.h>
75 : #endif
76 :
77 : using namespace casacore;
78 : namespace casa { //# NAMESPACE CASA - BEGIN
79 : namespace refim {//# namespace for imaging refactor
80 : using namespace casacore;
81 : using namespace casa;
82 : using namespace casacore;
83 : using namespace casa::refim;
84 :
85 0 : GridFT::GridFT() : FTMachine(), padding_p(1.0), imageCache(0), cachesize(1000000), tilesize(1000), gridder(0), isTiled(false), convType("SF"),
86 0 : maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
87 0 : usezero_p(false), noPadding_p(false), usePut2_p(false),
88 0 : machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0){
89 :
90 0 : }
91 0 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType, Float padding,
92 0 : Bool usezero, Bool useDoublePrec)
93 0 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize),
94 0 : gridder(0), isTiled(false), convType(iconvType),
95 0 : maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
96 0 : usezero_p(usezero), noPadding_p(false), usePut2_p(false),
97 0 : machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
98 : {
99 0 : useDoubleGrid_p=useDoublePrec;
100 : // peek=NULL;
101 0 : }
102 :
103 26 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
104 26 : MPosition mLocation, Float padding, Bool usezero, Bool useDoublePrec)
105 26 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
106 26 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
107 26 : offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false),
108 52 : usePut2_p(false), machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
109 : {
110 26 : mLocation_p=mLocation;
111 26 : tangentSpecified_p=false;
112 26 : useDoubleGrid_p=useDoublePrec;
113 : // peek=NULL;
114 26 : }
115 :
116 0 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
117 0 : MDirection mTangent, Float padding, Bool usezero, Bool useDoublePrec)
118 0 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
119 0 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
120 0 : offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false),
121 0 : usePut2_p(false), machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
122 : {
123 0 : mTangent_p=mTangent;
124 0 : tangentSpecified_p=true;
125 0 : useDoubleGrid_p=useDoublePrec;
126 : // peek=NULL;
127 0 : }
128 :
129 0 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
130 : MPosition mLocation, MDirection mTangent, Float padding,
131 0 : Bool usezero, Bool useDoublePrec)
132 0 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
133 0 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
134 0 : offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false),
135 0 : usePut2_p(false),machineName_p("GridFT"), timemass_p(0.0), timegrid_p(0.0), timedegrid_p(0.0), convFunc_p(0), convSampling_p(1), convSupport_p(0)
136 : {
137 0 : mLocation_p=mLocation;
138 0 : mTangent_p=mTangent;
139 0 : tangentSpecified_p=true;
140 0 : useDoubleGrid_p=useDoublePrec;
141 : // peek=NULL;
142 0 : }
143 :
144 0 : GridFT::GridFT(const RecordInterface& stateRec)
145 0 : : FTMachine()
146 : {
147 : // Construct from the input state record
148 0 : String error;
149 0 : if (!fromRecord(error, stateRec)) {
150 0 : throw (AipsError("Failed to create gridder: " + error));
151 : };
152 0 : timemass_p=0.0;
153 0 : timegrid_p=0.0;
154 0 : timedegrid_p=0.0;
155 : // peek=NULL;
156 0 : }
157 :
158 : //----------------------------------------------------------------------
159 3 : GridFT& GridFT::operator=(const GridFT& other)
160 : {
161 3 : if(this!=&other) {
162 : //Do the base parameters
163 3 : FTMachine::operator=(other);
164 :
165 : //private params
166 3 : imageCache=other.imageCache;
167 3 : cachesize=other.cachesize;
168 3 : tilesize=other.tilesize;
169 3 : convType=other.convType;
170 3 : convType.upcase();
171 3 : uvScale.resize();
172 3 : uvOffset.resize();
173 3 : uvScale.assign(other.uvScale);
174 3 : uvOffset.assign(other.uvOffset);
175 3 : if(other.gridder==0)
176 3 : gridder=0;
177 : else{
178 0 : gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
179 0 : uvScale, uvOffset,
180 0 : convType);
181 : }
182 3 : convFunc_p.resize();
183 3 : convSupport_p=other.convSupport_p;
184 3 : convSampling_p=other.convSampling_p;
185 3 : convFunc_p=other.convFunc_p;
186 3 : isTiled=other.isTiled;
187 : //lattice=other.lattice;
188 3 : lattice.reset( );
189 3 : tilesize=other.tilesize;
190 3 : arrayLattice.reset( );
191 3 : maxAbsData=other.maxAbsData;
192 3 : centerLoc=other.centerLoc;
193 3 : offsetLoc=other.offsetLoc;
194 3 : padding_p=other.padding_p;
195 3 : usezero_p=other.usezero_p;
196 3 : noPadding_p=other.noPadding_p;
197 3 : machineName_p="GridFT";
198 3 : timemass_p=0.0;
199 3 : timegrid_p=0.0;
200 : // peek = other.peek;
201 : };
202 3 : return *this;
203 : };
204 :
205 : //----------------------------------------------------------------------
206 3 : GridFT::GridFT(const GridFT& other) : FTMachine(), machineName_p("GridFT")
207 : {
208 3 : operator=(other);
209 3 : }
210 :
211 : //-----------------------------------------------------------------------
212 3 : FTMachine* GridFT::cloneFTM(){
213 3 : return new GridFT(*this);
214 : }
215 :
216 : //===============================
217 6 : Long GridFT::estimateRAM(const CountedPtr<SIImageStore>& imstor){
218 6 : Long mem=FTMachine::estimateRAM(imstor);
219 6 : mem=mem*padding_p*padding_p;
220 6 : return mem;
221 : }
222 :
223 :
224 : //----------------------------------------------------------------------
225 17 : void GridFT::init() {
226 :
227 17 : logIO() << LogOrigin("GridFT", "init") << LogIO::NORMAL;
228 :
229 17 : ok();
230 : // if (peek == NULL)
231 : // {
232 : // // peek = new SynthesisAsyncPeek();
233 : // // peek->reset();
234 : // // peek->startThread();
235 : // }
236 :
237 : /* hardwiring isTiled is false
238 : // Padding is possible only for non-tiled processing
239 : if((padding_p*padding_p*image->shape().product())>cachesize) {
240 : isTiled=true;
241 : nx = image->shape()(0);
242 : ny = image->shape()(1);
243 : npol = image->shape()(2);
244 : nchan = image->shape()(3);
245 : }
246 : else {
247 : */
248 : // We are padding.
249 17 : isTiled=false;
250 17 : if(!noPadding_p && padding_p > 1.01){
251 17 : CompositeNumber cn(uInt(image->shape()(0)*2));
252 17 : nx = cn.nextLargerEven(Int(padding_p*Float(image->shape()(0))-0.5));
253 17 : ny = cn.nextLargerEven(Int(padding_p*Float(image->shape()(1))-0.5));
254 17 : }
255 : else{
256 0 : nx = image->shape()(0);
257 0 : ny = image->shape()(1);
258 : }
259 17 : npol = image->shape()(2);
260 17 : nchan = image->shape()(3);
261 : // }
262 :
263 17 : sumWeight.resize(npol, nchan);
264 :
265 17 : uvScale.resize(2);
266 17 : uvScale(0)=(Float(nx)*image->coordinates().increment()(0));
267 17 : uvScale(1)=(Float(ny)*image->coordinates().increment()(1));
268 17 : uvOffset.resize(2);
269 17 : uvOffset(0)=nx/2;
270 17 : uvOffset(1)=ny/2;
271 :
272 : // Now set up the gridder. The possibilities are BOX and SF
273 17 : if(gridder) delete gridder; gridder=0;
274 17 : convType.upcase();
275 34 : gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
276 17 : uvScale, uvOffset,
277 17 : convType);
278 :
279 17 : convFunc_p.resize();
280 17 : convSupport_p=gridder->cSupport()(0);
281 17 : convSampling_p=gridder->cSampling();
282 17 : convFunc_p=gridder->cFunction();
283 : // Set up image cache needed for gridding. For BOX-car convolution
284 : // we can use non-overlapped tiles. Otherwise we need to use
285 : // overlapped tiles and additive gridding so that only increments
286 : // to a tile are written.
287 17 : if(imageCache) delete imageCache; imageCache=0;
288 :
289 17 : if(isTiled) {
290 0 : Float tileOverlap=0.5;
291 0 : if(convType=="BOX") {
292 0 : tileOverlap=0.0;
293 : }
294 : else {
295 0 : tileOverlap=0.5;
296 0 : tilesize=max(12,tilesize);
297 : }
298 0 : IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
299 0 : Vector<Float> tileOverlapVec(4);
300 0 : tileOverlapVec=0.0;
301 0 : tileOverlapVec(0)=tileOverlap;
302 0 : tileOverlapVec(1)=tileOverlap;
303 0 : Int tmpCacheVal=static_cast<Int>(cachesize);
304 0 : imageCache=new LatticeCache <Complex> (*image, tmpCacheVal, tileShape,
305 : tileOverlapVec,
306 0 : (tileOverlap>0.0));
307 :
308 0 : }
309 17 : }
310 :
311 : // This is nasty, we should use CountedPointers here.
312 58 : GridFT::~GridFT() {
313 29 : if(imageCache) delete imageCache; imageCache=0;
314 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
315 29 : if(gridder) delete gridder; gridder=0;
316 58 : }
317 :
318 : // Initialize for a transform from the Sky domain. This means that
319 : // we grid-correct, and FFT the image
320 :
321 3 : void GridFT::initializeToVis(ImageInterface<Complex>& iimage,
322 : const vi::VisBuffer2& vb)
323 : {
324 3 : image=&iimage;
325 3 : toVis_p=true;
326 :
327 3 : ok();
328 :
329 3 : init();
330 : // peek->reset();
331 : // Initialize the maps for polarization and channel. These maps
332 : // translate visibility indices into image indices
333 3 : initMaps(vb);
334 : // Need to reset nx, ny for padding
335 : // Padding is possible only for non-tiled processing
336 :
337 :
338 : //cerr << "initialize to vis nx" << nx << " " << ny << " " << npol << " " << nchan << endl;
339 :
340 : //cerr << "image shape " << image->shape() << endl;
341 :
342 : // If we are memory-based then read the image in and create an
343 : // ArrayLattice otherwise just use the PagedImage
344 : /*if(isTiled) {
345 : lattice=std::shared_ptr<Lattice<Complex> >(image, false);
346 : }
347 : else {
348 :
349 : }*/
350 3 : prepGridForDegrid();
351 :
352 : //AlwaysAssert(lattice, AipsError);
353 :
354 :
355 :
356 3 : }
357 :
358 3 : void GridFT::prepGridForDegrid(){
359 3 : IPosition gridShape(4, nx, ny, npol, nchan);
360 3 : griddedData.resize(gridShape);
361 : //griddedData can be a reference of image data...if not using model col
362 : //hence using an undocumented feature of resize that if
363 : //the size is the same as old data it is not changed.
364 : //if(!usePut2_p) griddedData.set(0);
365 3 : griddedData.set(Complex(0.0));
366 :
367 3 : IPosition stride(4, 1);
368 6 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
369 6 : IPosition trc(blc+image->shape()-stride);
370 :
371 3 : IPosition start(4, 0);
372 3 : griddedData(blc, trc) = image->getSlice(start, image->shape());
373 :
374 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
375 3 : arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
376 3 : lattice=arrayLattice;
377 : //logIO() << LogIO::DEBUGGING
378 : // << "Starting grid correction and FFT of image" << LogIO::POST;
379 :
380 : // Do the Grid-correction.
381 : {
382 3 : Vector<Complex> correction(nx);
383 3 : correction=Complex(1.0, 0.0);
384 : // Do the Grid-correction
385 3 : IPosition cursorShape(4, nx, 1, 1, 1);
386 3 : IPosition axisPath(4, 0, 1, 2, 3);
387 3 : LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
388 3 : LatticeIterator<Complex> lix(*lattice, lsx);
389 8643 : for(lix.reset();!lix.atEnd();lix++) {
390 8640 : gridder->correctX1D(correction, lix.position()(1));
391 8640 : lix.rwVectorCursor()/=correction;
392 : }
393 3 : }
394 3 : image->clearCache();
395 : // Now do the FFT2D in place
396 : //LatticeFFT::cfft2d(*lattice);
397 3 : ft_p.c2cFFT(*lattice);
398 : //logIO() << LogIO::DEBUGGING
399 : // << "Finished grid correction and FFT of image" << LogIO::POST;
400 :
401 3 : }
402 :
403 :
404 3 : void GridFT::finalizeToVis()
405 : {
406 :
407 3 : logIO() << LogOrigin("GridFT", "finalizeToVis") << LogIO::NORMAL;
408 3 : logIO() <<LogIO::NORMAL2<< "Time to degrid " << timedegrid_p <<LogIO::POST;
409 3 : timedegrid_p=0.0;
410 :
411 3 : if(arrayLattice) arrayLattice=nullptr;
412 3 : if(lattice) lattice=nullptr;
413 3 : griddedData.resize();
414 3 : if(isTiled) {
415 :
416 :
417 :
418 0 : AlwaysAssert(imageCache, AipsError);
419 0 : AlwaysAssert(image, AipsError);
420 0 : ostringstream o;
421 0 : imageCache->flush();
422 0 : imageCache->showCacheStatistics(o);
423 0 : logIO() << o.str() << LogIO::POST;
424 0 : }
425 3 : }
426 :
427 :
428 : // Initialize the FFT to the Sky. Here we have to setup and initialize the
429 : // grid.
430 14 : void GridFT::initializeToSky(ImageInterface<Complex>& iimage,
431 : Matrix<Float>& weight, const vi::VisBuffer2& vb)
432 : {
433 : // image always points to the image
434 14 : image=&iimage;
435 14 : toVis_p=false;
436 :
437 14 : init();
438 :
439 : // Initialize the maps for polarization and channel. These maps
440 : // translate visibility indices into image indices
441 14 : initMaps(vb);
442 :
443 :
444 :
445 14 : sumWeight=0.0;
446 14 : weight.resize(sumWeight.shape());
447 14 : weight=0.0;
448 :
449 :
450 14 : IPosition gridShape(4, nx, ny, npol, nchan);
451 14 : if( !useDoubleGrid_p )
452 : {
453 0 : griddedData.resize(gridShape);
454 0 : griddedData=Complex(0.0);
455 : }
456 : else{
457 :
458 14 : griddedData2.resize(gridShape);
459 14 : griddedData2=DComplex(0.0);
460 : }
461 14 : image->clearCache();
462 : //iimage.get(griddedData, false);
463 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
464 :
465 :
466 : //AlwaysAssert(lattice, AipsError);
467 14 : }
468 :
469 :
470 :
471 14 : void GridFT::finalizeToSky()
472 : {
473 : //AlwaysAssert(lattice, AipsError);
474 : // Now we flush the cache and report statistics
475 : // For memory based, we don't write anything out yet.
476 14 : logIO() << LogOrigin("GridFT", "finalizeToSky") << LogIO::NORMAL;
477 14 : logIO()<<LogIO::NORMAL2 <<"Time to massage data " << timemass_p << LogIO::POST;
478 14 : logIO()<< LogIO::NORMAL2 <<"Time to grid data " << timegrid_p << LogIO::POST;
479 14 : timemass_p=0.0;
480 14 : timegrid_p=0.0;
481 14 : if(isTiled) {
482 :
483 :
484 0 : AlwaysAssert(image, AipsError);
485 0 : AlwaysAssert(imageCache, AipsError);
486 0 : imageCache->flush();
487 0 : ostringstream o;
488 0 : imageCache->showCacheStatistics(o);
489 0 : logIO() << o.str() << LogIO::POST;
490 0 : }
491 : // peek->terminate();
492 : // peek->reset();
493 14 : }
494 :
495 :
496 :
497 0 : Array<Complex>* GridFT::getDataPointer(const IPosition& centerLoc2D,
498 : Bool readonly) {
499 : Array<Complex>* result;
500 : // Is tiled: get tiles and set up offsets
501 0 : centerLoc(0)=centerLoc2D(0);
502 0 : centerLoc(1)=centerLoc2D(1);
503 0 : result=&imageCache->tile(offsetLoc,centerLoc, readonly);
504 0 : gridder->setOffset(IPosition(2, offsetLoc(0), offsetLoc(1)));
505 0 : return result;
506 : }
507 :
508 : #define NEED_UNDERSCORES
509 : #if defined(NEED_UNDERSCORES)
510 : #define ggrid ggrid_
511 : #define dgrid dgrid_
512 : #define ggrids ggrids_
513 : #define sectggridd sectggridd_
514 : #define sectggrids sectggrids_
515 : #define sectdgrid sectdgrid_
516 : #define locuvw locuvw_
517 : #endif
518 :
519 : extern "C" {
520 : void locuvw(const Double*, const Double*, const Double*, const Int*, const Double*, const Double*, const Int*,
521 : Int*, Int*, Complex*, const Int*, const Int*, const Double*);
522 : void ggrid(Double*,
523 : Double*,
524 : const Complex*,
525 : Int*,
526 : Int*,
527 : Int*,
528 : const Int*,
529 : const Int*,
530 : const Float*,
531 : Int*,
532 : Int*,
533 : Double*,
534 : Double*,
535 : DComplex*,
536 : Int*,
537 : Int*,
538 : Int *,
539 : Int *,
540 : const Double*,
541 : const Double*,
542 : Int*,
543 : Int*,
544 : Double*,
545 : Int*,
546 : Int*,
547 : Double*);
548 : void sectggridd(const Complex*,
549 : const Int*,
550 : const Int*,
551 : const Int*,
552 : const Int*,
553 : const Int*,
554 : const Float*,
555 : const Int*,
556 : DComplex*,
557 : const Int*,
558 : const Int*,
559 : const Int *,
560 : const Int *,
561 : //support
562 : const Int*,
563 : const Int*,
564 : const Double*,
565 : const Int*,
566 : const Int*,
567 : Double*,
568 : const Int*,
569 : const Int*,
570 : const Int*,
571 : const Int*,
572 : const Int*,
573 : const Int*,
574 : //loc, off, phasor
575 : const Int*,
576 : const Int*,
577 : const Complex*);
578 : //single precision gridder
579 : void sectggrids(const Complex*,
580 : const Int*,
581 : const Int*,
582 : const Int*,
583 : const Int*,
584 : const Int*,
585 : const Float*,
586 : const Int*,
587 : Complex*,
588 : const Int*,
589 : const Int*,
590 : const Int *,
591 : const Int *,
592 : const Int*,
593 : const Int*,
594 : const Double*,
595 : const Int*,
596 : const Int*,
597 : Double*,
598 : const Int*,
599 : const Int*,
600 : const Int*,
601 : const Int*,
602 : const Int*,
603 : const Int*,
604 : //loc, off, phasor
605 : const Int*,
606 : const Int*,
607 : const Complex*);
608 : void ggrids(Double*,
609 : Double*,
610 : const Complex*,
611 : Int*,
612 : Int*,
613 : Int*,
614 : const Int*,
615 : const Int*,
616 : const Float*,
617 : Int*,
618 : Int*,
619 : Double*,
620 : Double*,
621 : Complex*,
622 : Int*,
623 : Int*,
624 : Int *,
625 : Int *,
626 : const Double*,
627 : const Double*,
628 : Int*,
629 : Int*,
630 : Double*,
631 : Int*,
632 : Int*,
633 : Double*);
634 :
635 : void dgrid(Double*,
636 : Double*,
637 : Complex*,
638 : Int*,
639 : Int*,
640 : const Int*,
641 : const Int*,
642 : Int*,
643 : Int*,
644 : Double*,
645 : Double*,
646 : const Complex*,
647 : Int*,
648 : Int*,
649 : Int *,
650 : Int *,
651 : const Double*,
652 : const Double*,
653 : Int*,
654 : Int*,
655 : Double*,
656 : Int*,
657 : Int*);
658 :
659 : void sectdgrid(Complex*,
660 : const Int*,
661 : const Int*,
662 : const Int*,
663 : const Int*,
664 : const Int*,
665 : const Complex*,
666 : const Int*,
667 : const Int*,
668 : const Int *,
669 : const Int *,
670 : //support
671 : const Int*,
672 : const Int*,
673 : const Double*,
674 : const Int*,
675 : const Int*,
676 : //rbeg, rend, loc, off, phasor
677 : const Int*,
678 : const Int*,
679 : const Int*,
680 : const Int*,
681 : const Complex*);
682 : }
683 252 : void GridFT::put(const vi::VisBuffer2& vb, Int row, Bool dopsf,
684 : FTMachine::Type type)
685 : {
686 :
687 252 : gridOk(convSupport_p);
688 : // peek->setVBPtr(&vb);
689 :
690 : //Check if ms has changed then cache new spw and chan selection
691 : //if(vb.isNewMs())
692 : // matchAllSpwChans(vb);
693 :
694 : //Here we redo the match or use previous match
695 :
696 : //Channel matching for the actual spectral window of buffer
697 : //if(doConversion_p[vb.spectralWindows()[0]]){
698 252 : matchChannel(vb);
699 : //}
700 : //else{
701 : // chanMap.resize();
702 : // chanMap=multiChanMap_p[vb.spectralWindows()[0]];
703 : //}
704 :
705 : //No point in reading data if its not matching in frequency
706 252 : if(max(chanMap)==-1)
707 : {
708 : // peek->reset();
709 0 : return;
710 : }
711 :
712 252 : Timer tim;
713 252 : tim.mark();
714 :
715 : //const Matrix<Float> *imagingweight;
716 : //imagingweight=&(vb.imagingWeight());
717 252 : Matrix<Float> imagingweight;
718 252 : getImagingWeight(imagingweight, vb);
719 :
720 252 : if(dopsf) {type=FTMachine::PSF;}
721 :
722 252 : Cube<Complex> data;
723 : //Fortran gridder need the flag as ints
724 252 : Cube<Int> flags;
725 252 : Matrix<Float> elWeight;
726 252 : interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
727 :
728 :
729 : Bool iswgtCopy;
730 : const Float *wgtStorage;
731 252 : wgtStorage=elWeight.getStorage(iswgtCopy);
732 :
733 : Bool isCopy;
734 : const Complex *datStorage;
735 252 : if(!dopsf)
736 144 : datStorage=data.getStorage(isCopy);
737 : else
738 108 : datStorage=0;
739 : // If row is -1 then we pass through all rows
740 : Int startRow, endRow, nRow;
741 252 : if (row==-1) {
742 252 : nRow=vb.nRows();
743 252 : startRow=0;
744 252 : endRow=nRow-1;
745 : } else {
746 0 : nRow=1;
747 0 : startRow=row;
748 0 : endRow=row;
749 : }
750 :
751 : //cerr << "nRow " << nRow << endl;
752 :
753 :
754 : // Get the uvws in a form that Fortran can use and do that
755 : // necessary phase rotation. On a Pentium Pro 200 MHz
756 : // when null, this step takes about 50us per uvw point. This
757 : // is just barely noticeable for Stokes I continuum and
758 : // irrelevant for other cases.
759 :
760 : Bool del;
761 : // IPosition s(flags.shape());
762 252 : const IPosition &fs=flags.shape();
763 252 : std::vector<Int> s(fs.begin(),fs.end());
764 252 : Int nvispol=s[0];
765 252 : Int nvischan=s[1];
766 252 : Int nvisrow=s[2];
767 252 : Matrix<Double> uvw(negateUV(vb));
768 :
769 252 : Vector<Double> dphase(vb.nRows());
770 252 : Cube<Int> loc(2, nvischan, nRow);
771 252 : Cube<Int> off(2, nvischan, nRow);
772 252 : Matrix<Complex> phasor(nvischan, nRow);
773 252 : Int csamp=convSampling_p;
774 252 : dphase=0.0;
775 :
776 252 : timemass_p +=tim.real();
777 252 : tim.mark();
778 252 : rotateUVW(uvw, dphase, vb);
779 252 : refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
780 : Bool delphase;
781 252 : Complex * phasorstor=phasor.getStorage(delphase);
782 252 : const Double * visfreqstor=interpVisFreq_p.getStorage(del);
783 252 : const Double * scalestor=uvScale.getStorage(del);
784 252 : const Double * offsetstor=uvOffset.getStorage(del);
785 252 : const Double* uvstor= uvw.getStorage(del);
786 252 : Int * locstor=loc.getStorage(del);
787 252 : Int * offstor=off.getStorage(del);
788 252 : const Double *dpstor=dphase.getStorage(del);
789 : //Vector<Double> f1=interpVisFreq_p.copy();
790 252 : Int nvchan=nvischan;
791 : Int irow;
792 252 : Double cinv=Double(1.0)/C::c;
793 252 : Int dow=0;
794 252 : Int nth=1;
795 : #ifdef _OPENMP
796 252 : if(numthreads_p >0){
797 0 : nth=min(numthreads_p, omp_get_max_threads());
798 : }
799 : else{
800 252 : nth= omp_get_max_threads();
801 : }
802 : //nth=min(4,nth);
803 : #endif
804 :
805 :
806 252 : #pragma omp parallel default(none) private(irow) firstprivate(visfreqstor, nvchan, scalestor, offsetstor, csamp, phasorstor, uvstor, locstor, offstor, dpstor, cinv, dow) shared(startRow, endRow) num_threads(nth)
807 : {
808 : #pragma omp for schedule(dynamic)
809 : for (irow=startRow; irow<=endRow; ++irow){
810 : //locateuvw(uvstor,dpstor, visfreqstor, nvchan, scalestor, offsetstor, csamp,
811 : // locstor,
812 : // offstor, phasorstor, irow);
813 : locuvw(uvstor, dpstor, visfreqstor, &nvchan, scalestor, offsetstor, &csamp, locstor, offstor, phasorstor, &irow, &dow, &cinv);
814 : }
815 :
816 : }//end pragma parallel
817 : // Take care of translation of Bools to Integer
818 252 : Int idopsf=0;
819 252 : if(dopsf) idopsf=1;
820 :
821 : //////TESTOO
822 : //ofstream myfile;
823 : //myfile.open ("putLoc.txt", ios::out | ios::app | ios::ate );
824 : //myfile << vb.rowIds()(0) << " uv " << uvw.column(0) << " loc " << loc(0,0,0) << ", " << loc(1,0,0) << "\n" << endl;
825 : //myfile.close();
826 : ///////////////
827 :
828 :
829 :
830 252 : Vector<Int> rowFlags(vb.nRows());
831 252 : rowFlags=0;
832 252 : rowFlags(vb.flagRow())=true;
833 252 : if(!usezero_p) {
834 88704 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
835 88452 : if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
836 : }
837 : }
838 :
839 : /////////////Some extra stuff for openmp
840 :
841 : Int ixsub, iysub, icounter;
842 252 : Int csupp=convSupport_p;
843 :
844 252 : const Double * convfuncstor=(convFunc_p).getStorage(del);
845 :
846 : // cerr <<"Poffset " << min(off) << " " << max(off) << " length " << gridder->cFunction().shape() << endl;
847 :
848 :
849 :
850 252 : ixsub=1;
851 252 : iysub=1;
852 252 : if (nth >4){
853 252 : ixsub=8;
854 252 : iysub=8;
855 : }
856 0 : else if(nth >1) {
857 0 : ixsub=2;
858 0 : iysub=2;
859 : }
860 :
861 :
862 252 : Int rbeg=startRow+1;
863 252 : Int rend=endRow+1;
864 252 : Block<Matrix<Double> > sumwgt(ixsub*iysub);
865 16380 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
866 16128 : sumwgt[icounter].resize(sumWeight.shape());
867 16128 : sumwgt[icounter].set(0.0);
868 : }
869 252 : if(doneThreadPartition_p < 0){
870 12 : xsect_p.resize(ixsub*iysub);
871 12 : ysect_p.resize(ixsub*iysub);
872 12 : nxsect_p.resize(ixsub*iysub);
873 12 : nysect_p.resize(ixsub*iysub);
874 780 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
875 768 : findGridSector(nx, ny, ixsub, iysub, 0, 0, icounter, xsect_p(icounter), ysect_p(icounter), nxsect_p(icounter), nysect_p(icounter), true);
876 : }
877 : }
878 252 : Vector<Int> xsect, ysect, nxsect, nysect;
879 252 : xsect=xsect_p; ysect=ysect_p; nxsect=nxsect_p; nysect=nysect_p;
880 252 : const Int* pmapstor=polMap.getStorage(del);
881 252 : const Int *cmapstor=chanMap.getStorage(del);
882 252 : Int nc=nchan;
883 252 : Int np=npol;
884 252 : Int nxp=nx;
885 252 : Int nyp=ny;
886 252 : const Int * flagstor=flags.getStorage(del);
887 252 : const Int * rowflagstor=rowFlags.getStorage(del);
888 : ////////////////////////
889 :
890 : Bool gridcopy;
891 252 : if(useDoubleGrid_p){
892 252 : DComplex *gridstor=griddedData2.getStorage(gridcopy);
893 252 : #pragma omp parallel default(none) private(icounter, del) firstprivate(idopsf, datStorage, wgtStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc,ixsub, iysub, rend, rbeg, csamp, csupp, nvispol, nvischan, nvisrow, phasorstor, locstor, offstor, xsect, ysect, nxsect, nysect) shared(sumwgt) num_threads(nth)
894 :
895 : {
896 : //cerr << "numthreads " << omp_get_num_threads() << endl;
897 : #pragma omp for schedule(dynamic)
898 : for(icounter=0; icounter < ixsub*iysub; ++icounter){
899 : //cerr << "thread id " << omp_get_thread_num() << endl;
900 : Int x0=xsect(icounter);
901 : Int y0=ysect(icounter);
902 : Int nxsub=nxsect(icounter);
903 : Int nysub=nysect(icounter);
904 :
905 : sectggridd(datStorage,
906 : &nvispol,
907 : &nvischan,
908 : &idopsf,
909 : flagstor,
910 : rowflagstor,
911 : wgtStorage,
912 : &nvisrow,
913 : gridstor,
914 : &nxp,
915 : &nyp,
916 : &np,
917 : &nc,
918 : &csupp,
919 : &csamp,
920 : convfuncstor,
921 : cmapstor,
922 : pmapstor,
923 : (sumwgt[icounter]).getStorage(del),
924 : &x0, &y0, &nxsub, &nysub, &rbeg, &rend, locstor, offstor,
925 : phasorstor);
926 : }//end for
927 : }// end pragma parallel
928 16380 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
929 16128 : sumWeight=sumWeight+sumwgt[icounter];
930 : }
931 : //phasor.putStorage(phasorstor, delphase);
932 252 : griddedData2.putStorage(gridstor, gridcopy);
933 252 : if(dopsf && (nth >4))
934 108 : tweakGridSector(nx, ny, ixsub, iysub);
935 : }
936 : else{
937 0 : Complex *gridstor=griddedData.getStorage(gridcopy);
938 0 : #pragma omp parallel default(none) private(icounter, del) firstprivate(idopsf, datStorage, wgtStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc,ixsub, iysub, rend, rbeg, csamp, csupp, nvispol, nvischan, nvisrow, phasorstor, locstor, offstor, xsect, ysect, nxsect, nysect) shared(sumwgt) num_threads(ixsub*iysub)
939 : {
940 : //cerr << "numthreads " << omp_get_num_threads() << endl;
941 : #pragma omp for schedule(dynamic)
942 :
943 : for(icounter=0; icounter < ixsub*iysub; ++icounter){
944 : //cerr << "thread id " << omp_get_thread_num() << endl;
945 : Int x0=xsect(icounter);
946 : Int y0=ysect(icounter);
947 : Int nxsub=nxsect(icounter);
948 : Int nysub=nysect(icounter);
949 :
950 :
951 :
952 : //cerr << "x0 " << x0 << " y0 " << y0 << " nxsub " << nxsub << " nysub " << nysub << endl;
953 : sectggrids(datStorage,
954 : &nvispol,
955 : &nvischan,
956 : &idopsf,
957 : flagstor,
958 : rowflagstor,
959 : wgtStorage,
960 : &nvisrow,
961 : gridstor,
962 : &nxp,
963 : &nyp,
964 : &np,
965 : &nc,
966 : &csupp,
967 : &csamp,
968 : convfuncstor,
969 : cmapstor,
970 : pmapstor,
971 : (sumwgt[icounter]).getStorage(del),
972 : &x0, &y0, &nxsub, &nysub, &rbeg, &rend, locstor, offstor,
973 : phasorstor);
974 : }//end for
975 : }// end pragma parallel
976 0 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
977 0 : sumWeight=sumWeight+sumwgt[icounter];
978 : }
979 :
980 0 : griddedData.putStorage(gridstor, gridcopy);
981 0 : if(dopsf && (nth > 4))
982 0 : tweakGridSector(nx, ny, ixsub, iysub);
983 : }
984 : // cerr << "sunweight " << sumWeight << endl;
985 :
986 252 : timegrid_p+=tim.real();
987 :
988 252 : if(!dopsf)
989 144 : data.freeStorage(datStorage, isCopy);
990 252 : elWeight.freeStorage(wgtStorage,iswgtCopy);
991 :
992 : // peek->reset();
993 252 : }
994 :
995 0 : void GridFT::modifyConvFunc(const Vector<Double>& convFunc, Int convSupport, Int convSampling){
996 0 : convFunc_p.resize();
997 0 : convFunc_p=convFunc;
998 0 : convSupport_p=convSupport;
999 0 : convSampling_p=convSampling;
1000 :
1001 0 : }
1002 :
1003 54 : void GridFT::get(vi::VisBuffer2& vb, Int row)
1004 : {
1005 :
1006 54 : gridOk(convSupport_p);
1007 : // If row is -1 then we pass through all rows
1008 : Int startRow, endRow, nRow;
1009 54 : if (row < 0) {
1010 54 : nRow=vb.nRows();
1011 54 : startRow=0;
1012 54 : endRow=nRow-1;
1013 : //unnecessary zeroing
1014 : //vb.modelVisCube()=Complex(0.0,0.0);
1015 : } else {
1016 0 : nRow=1;
1017 0 : startRow=row;
1018 0 : endRow=row;
1019 : //unnecessary zeroing
1020 : //vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
1021 : }
1022 :
1023 :
1024 : ///Channel matching for the actual spectral window of buffer
1025 54 : matchChannel(vb);
1026 :
1027 :
1028 : //cerr << "GETchanMap " << chanMap << endl;
1029 : //No point in reading data if its not matching in frequency
1030 54 : if(max(chanMap)==-1)
1031 0 : return;
1032 :
1033 :
1034 :
1035 : // Get the uvws in a form that Fortran can use
1036 54 : Matrix<Double> uvw(negateUV(vb));
1037 54 : Vector<Double> dphase(vb.nRows());
1038 54 : dphase=0.0;
1039 54 : rotateUVW(uvw, dphase, vb);
1040 54 : refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
1041 :
1042 :
1043 :
1044 : //Check if ms has changed then cache new spw and chan selection
1045 : //if(vb.isNewMs())
1046 : // matchAllSpwChans(vb);
1047 :
1048 :
1049 : //Here we redo the match or use previous match
1050 :
1051 :
1052 54 : Cube<Complex> data;
1053 54 : Cube<Int> flags;
1054 54 : getInterpolateArrays(vb, data, flags);
1055 :
1056 : //cerr << "max min data " << max(griddedData) << " " << min(griddedData) << " flags " << max(flags) << " " << min(flags) << endl;
1057 :
1058 : // IPosition s(data.shape());
1059 54 : Int nvp=data.shape()(0);
1060 54 : Int nvc=data.shape()(1);
1061 54 : Int nvisrow=data.shape()(2);
1062 :
1063 :
1064 : //cerr << "get flags " << min(flags) << " " << max(flags) << endl;
1065 : Complex *datStorage;
1066 : Bool isCopy;
1067 54 : datStorage=data.getStorage(isCopy);
1068 :
1069 : ///
1070 54 : Cube<Int> loc(2, nvc, nvisrow);
1071 54 : Cube<Int> off(2, nvc, nRow);
1072 54 : Matrix<Complex> phasor(nvc, nRow);
1073 54 : Int csamp=convSampling_p;
1074 : Bool delphase;
1075 : Bool del;
1076 54 : Complex * phasorstor=phasor.getStorage(delphase);
1077 54 : const Double * visfreqstor=interpVisFreq_p.getStorage(del);
1078 54 : const Double * scalestor=uvScale.getStorage(del);
1079 54 : const Double * offsetstor=uvOffset.getStorage(del);
1080 54 : const Double* uvstor= uvw.getStorage(del);
1081 54 : Int * locstor=loc.getStorage(del);
1082 54 : Int * offstor=off.getStorage(del);
1083 54 : const Double *dpstor=dphase.getStorage(del);
1084 : //Vector<Double> f1=interpVisFreq_p.copy();
1085 54 : Int nvchan=nvc;
1086 : Int irow;
1087 54 : Double cinv=Double(1.0)/C::c;
1088 54 : Int dow=0;
1089 54 : Int nth=1;
1090 : #ifdef _OPENMP
1091 54 : if(numthreads_p >0){
1092 0 : nth=min(numthreads_p, omp_get_max_threads());
1093 : }
1094 : else{
1095 54 : nth= omp_get_max_threads();
1096 : }
1097 : //nth=min(4,nth);
1098 : #endif
1099 :
1100 :
1101 54 : #pragma omp parallel default(none) private(irow) firstprivate(visfreqstor, nvchan, scalestor, offsetstor, csamp, phasorstor, uvstor, locstor, offstor, dpstor, cinv, dow) shared(startRow, endRow) num_threads(nth)
1102 :
1103 : {
1104 : #pragma omp for schedule(dynamic)
1105 : for (irow=startRow; irow<=endRow; ++irow){
1106 : //locateuvw(uvstor,dpstor, visfreqstor, nvchan, scalestor, offsetstor, csamp,
1107 : // locstor,
1108 : // offstor, phasorstor, irow);
1109 :
1110 : locuvw(uvstor, dpstor, visfreqstor, &nvchan, scalestor, offsetstor, &csamp, locstor, offstor, phasorstor, &irow, &dow, &cinv);
1111 : }
1112 :
1113 : }//end pragma parallel
1114 :
1115 54 : Int rbeg=startRow+1;
1116 54 : Int rend=endRow+1;
1117 :
1118 :
1119 54 : Vector<Int> rowFlags(vb.nRows());
1120 54 : rowFlags=0;
1121 54 : rowFlags(vb.flagRow())=true;
1122 : //cerr << "rowFlags " << rowFlags << endl;
1123 54 : if(!usezero_p) {
1124 19008 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
1125 18954 : if(vb.antenna1()(rownr)==vb.antenna2()(rownr)) rowFlags(rownr)=1;
1126 : }
1127 : }
1128 :
1129 :
1130 : //cerr <<"offset " << min(off) << " " <<max(off) << " length " << gridder->cFunction().shape() << endl;
1131 :
1132 : {
1133 : Bool delgrid;
1134 54 : const Complex* gridstor=griddedData.getStorage(delgrid);
1135 54 : const Double * convfuncstor=(convFunc_p).getStorage(del);
1136 :
1137 54 : const Int* pmapstor=polMap.getStorage(del);
1138 54 : const Int *cmapstor=chanMap.getStorage(del);
1139 54 : Int nc=nchan;
1140 54 : Int np=npol;
1141 54 : Int nxp=nx;
1142 54 : Int nyp=ny;
1143 54 : Int csupp=convSupport_p;
1144 54 : const Int * flagstor=flags.getStorage(del);
1145 54 : const Int * rowflagstor=rowFlags.getStorage(del);
1146 :
1147 :
1148 54 : Int npart=nth;
1149 :
1150 :
1151 54 : Int ix=0;
1152 54 : #pragma omp parallel default(none) private(ix, rbeg, rend) firstprivate(datStorage, flagstor, rowflagstor, convfuncstor, pmapstor, cmapstor, gridstor, nxp, nyp, np, nc, csamp, csupp, nvp, nvc, nvisrow, phasorstor, locstor, offstor) shared(npart) num_threads(npart)
1153 : {
1154 : #pragma omp for schedule(dynamic)
1155 : for (ix=0; ix< npart; ++ix){
1156 : rbeg=ix*(nvisrow/npart)+1;
1157 : rend=(ix != (npart-1)) ? (rbeg+(nvisrow/npart)-1) : (rbeg+(nvisrow/npart)+nvisrow%npart-1) ;
1158 : //cerr << "rbeg " << rbeg << " rend " << rend << " " << nvisrow << endl;
1159 :
1160 : sectdgrid(datStorage,
1161 : &nvp,
1162 : &nvc,
1163 : flagstor,
1164 : rowflagstor,
1165 : &nvisrow,
1166 : gridstor,
1167 : &nxp,
1168 : &nyp,
1169 : &np,
1170 : &nc,
1171 : &csupp,
1172 : &csamp,
1173 : convfuncstor,
1174 : cmapstor,
1175 : pmapstor,
1176 : &rbeg, &rend, locstor, offstor, phasorstor);
1177 : }//end pragma parallel
1178 : }
1179 54 : data.putStorage(datStorage, isCopy);
1180 54 : griddedData.freeStorage(gridstor, delgrid);
1181 : //cerr << "Get min max " << min(data) << " " << max(data) << endl;
1182 : }
1183 54 : interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
1184 :
1185 54 : }
1186 :
1187 :
1188 :
1189 : // Finalize the FFT to the Sky. Here we actually do the FFT and
1190 : // return the resulting image
1191 14 : ImageInterface<Complex>& GridFT::getImage(Matrix<Float>& weights, Bool normalize)
1192 : {
1193 : //AlwaysAssert(lattice, AipsError);
1194 14 : AlwaysAssert(gridder, AipsError);
1195 14 : AlwaysAssert(image, AipsError);
1196 14 : logIO() << LogOrigin("GridFT", "getImage") << LogIO::NORMAL;
1197 :
1198 14 : if((griddedData.nelements() ==0) && (griddedData2.nelements()==0)){
1199 0 : throw(AipsError("Programmer error ...request for image without right order of calls"));
1200 : }
1201 14 : weights.resize(sumWeight.shape());
1202 :
1203 14 : convertArray(weights, sumWeight);
1204 : // If the weights are all zero then we cannot normalize
1205 : // otherwise we don't care.
1206 14 : if(normalize&&max(weights)==0.0) {
1207 : logIO() << LogIO::SEVERE << "No useful data in GridFT: weights all zero"
1208 0 : << LogIO::POST;
1209 : }
1210 : else {
1211 :
1212 : //const IPosition latticeShape = lattice->shape();
1213 :
1214 : //logIO() << LogIO::DEBUGGING
1215 : // << "Starting FFT and scaling of image" << LogIO::POST;
1216 :
1217 :
1218 :
1219 : // if(useDoubleGrid_p){
1220 : // convertArray(griddedData, griddedData2);
1221 : // //Don't need the double-prec grid anymore...
1222 : // griddedData2.resize();
1223 : // }
1224 :
1225 : // x and y transforms
1226 : // LatticeFFT::cfft2d(*lattice,false);
1227 : //
1228 : // Retain the double precision grid for FFT as well. Convert it
1229 : // to single precision just after (since images are still single
1230 : // precision).
1231 : //
1232 14 : if(useDoubleGrid_p)
1233 : {
1234 14 : ArrayLattice<DComplex> darrayLattice(griddedData2);
1235 : //LatticeFFT::cfft2d(darrayLattice,false);
1236 14 : ft_p.c2cFFT(darrayLattice, False);
1237 14 : griddedData.resize(griddedData2.shape());
1238 14 : convertArray(griddedData, griddedData2);
1239 :
1240 14 : SynthesisUtilMethods::getResource("mem peak in getImage");
1241 :
1242 : //Don't need the double-prec grid anymore...
1243 14 : griddedData2.resize();
1244 14 : arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
1245 14 : lattice=arrayLattice;
1246 14 : }
1247 : else{
1248 0 : arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
1249 0 : lattice=arrayLattice;
1250 :
1251 : //LatticeFFT::cfft2d(*lattice,false);
1252 0 : ft_p.c2cFFT(*lattice, False);
1253 : }
1254 :
1255 :
1256 :
1257 : {
1258 14 : Int inx = lattice->shape()(0);
1259 14 : Int iny = lattice->shape()(1);
1260 14 : Vector<Complex> correction(inx);
1261 14 : correction=Complex(1.0, 0.0);
1262 : // Do the Grid-correction
1263 14 : IPosition cursorShape(4, inx, 1, 1, 1);
1264 14 : IPosition axisPath(4, 0, 1, 2, 3);
1265 14 : LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
1266 14 : LatticeIterator<Complex> lix(*lattice, lsx);
1267 30734 : for(lix.reset();!lix.atEnd();lix++) {
1268 30720 : Int pol=lix.position()(2);
1269 30720 : Int chan=lix.position()(3);
1270 30720 : if(weights(pol, chan)!=0.0) {
1271 22080 : gridder->correctX1D(correction, lix.position()(1));
1272 22080 : lix.rwVectorCursor()/=correction;
1273 22080 : if(normalize) {
1274 0 : Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan));
1275 0 : lix.rwCursor()*=rnorm;
1276 : }
1277 : else {
1278 22080 : Complex rnorm(Float(inx)*Float(iny));
1279 22080 : lix.rwCursor()*=rnorm;
1280 : }
1281 : }
1282 : else {
1283 8640 : lix.woCursor()=0.0;
1284 : }
1285 : }
1286 14 : }
1287 14 : LatticeLocker lock1 (*(image), FileLocker::Write);
1288 14 : if(!isTiled) {
1289 : // Check the section from the image BEFORE converting to a lattice
1290 28 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
1291 14 : IPosition stride(4, 1);
1292 28 : IPosition trc(blc+image->shape()-stride);
1293 : // Do the copy
1294 14 : IPosition start(4, 0);
1295 :
1296 14 : image->put(griddedData(blc, trc));
1297 14 : }
1298 14 : }
1299 14 : image->flush();
1300 14 : image->clearCache();
1301 :
1302 14 : if(arrayLattice) arrayLattice=nullptr;
1303 14 : if(lattice) lattice=nullptr;
1304 14 : griddedData.resize();
1305 14 : return *image;
1306 : }
1307 :
1308 : // Get weight image
1309 0 : void GridFT::getWeightImage(ImageInterface<Float>& weightImage, Matrix<Float>& weights)
1310 : {
1311 :
1312 0 : logIO() << LogOrigin("GridFT", "getWeightImage") << LogIO::NORMAL;
1313 :
1314 0 : weights.resize(sumWeight.shape());
1315 0 : convertArray(weights,sumWeight);
1316 :
1317 0 : const IPosition latticeShape = weightImage.shape();
1318 :
1319 0 : Int nx=latticeShape(0);
1320 0 : Int ny=latticeShape(1);
1321 :
1322 0 : IPosition loc(2, 0);
1323 0 : IPosition cursorShape(4, nx, ny, 1, 1);
1324 0 : IPosition axisPath(4, 0, 1, 2, 3);
1325 0 : LatticeStepper lsx(latticeShape, cursorShape, axisPath);
1326 0 : LatticeIterator<Float> lix(weightImage, lsx);
1327 0 : for(lix.reset();!lix.atEnd();lix++) {
1328 0 : Int pol=lix.position()(2);
1329 0 : Int chan=lix.position()(3);
1330 0 : lix.rwCursor()=weights(pol,chan);
1331 : }
1332 0 : }
1333 :
1334 0 : Bool GridFT::toRecord(String& error,
1335 : RecordInterface& outRec, Bool withImage, const String diskimage)
1336 : {
1337 :
1338 :
1339 :
1340 : // Save the current GridFT object to an output state record
1341 0 : Bool retval = true;
1342 0 : Float elpadd=padding_p;
1343 0 : if(toVis_p && withImage)
1344 0 : elpadd=1.0;
1345 : //save the base class variables
1346 0 : if(!FTMachine::toRecord(error, outRec, withImage, diskimage))
1347 0 : return false;
1348 :
1349 : //a call to init will redo imagecache and gridder
1350 : // so no need to save these
1351 :
1352 0 : outRec.define("cachesize", Int64(cachesize));
1353 0 : outRec.define("tilesize", tilesize);
1354 0 : outRec.define("convtype", convType);
1355 0 : outRec.define("uvscale", uvScale);
1356 0 : outRec.define("uvoffset", uvOffset);
1357 0 : outRec.define("istiled", isTiled);
1358 0 : outRec.define("maxabsdata", maxAbsData);
1359 0 : Vector<Int> center_loc(4), offset_loc(4);
1360 0 : for (Int k=0; k<4 ; k++){
1361 0 : center_loc(k)=centerLoc(k);
1362 0 : offset_loc(k)=offsetLoc(k);
1363 : }
1364 0 : outRec.define("centerloc", center_loc);
1365 0 : outRec.define("offsetloc", offset_loc);
1366 0 : outRec.define("padding", elpadd);
1367 0 : outRec.define("usezero", usezero_p);
1368 0 : outRec.define("nopadding", noPadding_p);
1369 0 : return retval;
1370 0 : }
1371 :
1372 0 : Bool GridFT::fromRecord(String& error,
1373 : const RecordInterface& inRec)
1374 : {
1375 0 : Bool retval = true;
1376 0 : if(!FTMachine::fromRecord(error, inRec))
1377 0 : return false;
1378 0 : gridder=0; imageCache=0; lattice.reset( ); arrayLattice.reset( );
1379 : //For some reason int64 seems to be getting lost...
1380 : //this is not an important parameter...so filing a jira
1381 0 : if(inRec.isDefined("cachesize"))
1382 0 : cachesize=inRec.asInt64("cachesize");
1383 : else
1384 0 : cachesize=1000000;
1385 0 : inRec.get("tilesize", tilesize);
1386 0 : inRec.get("convtype", convType);
1387 0 : inRec.get("uvscale", uvScale);
1388 0 : inRec.get("uvoffset", uvOffset);
1389 0 : inRec.get("istiled", isTiled);
1390 0 : inRec.get("maxabsdata", maxAbsData);
1391 0 : Vector<Int> center_loc(4), offset_loc(4);
1392 0 : inRec.get("centerloc", center_loc);
1393 0 : inRec.get("offsetloc", offset_loc);
1394 0 : uInt ndim4 = 4;
1395 0 : centerLoc=IPosition(ndim4, center_loc(0), center_loc(1), center_loc(2),
1396 0 : center_loc(3));
1397 0 : offsetLoc=IPosition(ndim4, offset_loc(0), offset_loc(1), offset_loc(2),
1398 0 : offset_loc(3));
1399 0 : inRec.get("padding", padding_p);
1400 0 : inRec.get("usezero", usezero_p);
1401 0 : inRec.get("nopadding", noPadding_p);
1402 :
1403 0 : machineName_p="GridFT";
1404 : ///setup some of the parameters if there is an image
1405 0 : if(inRec.isDefined("image") || inRec.isDefined("diskimage"))
1406 0 : init();
1407 : /*if(!cmplxImage_p.null()){
1408 : //FTMachine::fromRecord would have recovered the image
1409 : // Might be changing the shape of sumWeight
1410 :
1411 : if(isTiled) {
1412 : lattice=std::shared_ptr<Lattice<Complex> >(image, false);
1413 : }
1414 : else {
1415 : // Make the grid the correct shape and turn it into an array lattice
1416 : // Check the section from the image BEFORE converting to a lattice
1417 : if(!toVis_p){
1418 : IPosition gridShape(4, nx, ny, npol, nchan);
1419 : griddedData.resize(gridShape);
1420 : griddedData=Complex(0.0);
1421 : }
1422 : else{
1423 : prepGridForDegrid();
1424 : }
1425 : }
1426 : };*/
1427 0 : return retval;
1428 0 : }
1429 :
1430 632 : void GridFT::ok() {
1431 632 : AlwaysAssert(image, AipsError);
1432 632 : }
1433 :
1434 : // Make a plain straightforward honest-to-God image. This returns
1435 : // a complex image, without conversion to Stokes. The representation
1436 : // is that required for the visibilities.
1437 : //----------------------------------------------------------------------
1438 0 : void GridFT::makeImage(FTMachine::Type type,
1439 : vi::VisibilityIterator2& vi,
1440 : ImageInterface<Complex>& theImage,
1441 : Matrix<Float>& weight) {
1442 :
1443 :
1444 0 : logIO() << LogOrigin("GridFT", "makeImage") << LogIO::NORMAL;
1445 :
1446 0 : if(type==FTMachine::COVERAGE) {
1447 0 : logIO() << "Type COVERAGE not defined for Fourier transforms" << LogIO::EXCEPTION;
1448 : }
1449 :
1450 :
1451 :
1452 :
1453 : // Loop over all visibilities and pixels
1454 0 : vi::VisBuffer2* vb=vi.getVisBuffer();
1455 :
1456 : // Initialize put (i.e. transform to Sky) for this model
1457 0 : vi.origin();
1458 :
1459 0 : if(vb->polarizationFrame()==MSIter::Linear) {
1460 0 : StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::LINEAR);
1461 : }
1462 : else {
1463 0 : StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::CIRCULAR);
1464 : }
1465 :
1466 0 : initializeToSky(theImage,weight,*vb);
1467 :
1468 : // Loop over the visibilities, putting VisBuffers
1469 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
1470 0 : for (vi.origin(); vi.more(); vi.next()) {
1471 :
1472 0 : switch(type) {
1473 0 : case FTMachine::RESIDUAL:
1474 0 : vb->setVisCube(vb->visCubeCorrected()-vb->visCubeModel());
1475 0 : put(*vb, -1, false);
1476 0 : break;
1477 0 : case FTMachine::MODEL:
1478 0 : vb->setVisCube(vb->visCubeModel());
1479 0 : put(*vb, -1, false);
1480 0 : break;
1481 0 : case FTMachine::CORRECTED:
1482 0 : vb->setVisCube(vb->visCubeCorrected());
1483 0 : put(*vb, -1, false);
1484 0 : break;
1485 0 : case FTMachine::PSF:
1486 0 : vb->setVisCube(Complex(1.0,0.0));
1487 0 : put(*vb, -1, true);
1488 0 : break;
1489 0 : case FTMachine::OBSERVED:
1490 : default:
1491 0 : put(*vb, -1, false);
1492 0 : break;
1493 : }
1494 : }
1495 : }
1496 0 : finalizeToSky();
1497 : // Normalize by dividing out weights, etc.
1498 0 : getImage(weight, true);
1499 0 : }
1500 :
1501 39 : String GridFT::name() const {
1502 :
1503 39 : return machineName_p;
1504 :
1505 :
1506 : }
1507 :
1508 : }//End of namespace refim
1509 : } //# NAMESPACE CASA - END
1510 :
|