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: 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 : //# $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 : maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
87 : 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 14 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType, Float padding,
92 14 : Bool usezero, Bool useDoublePrec)
93 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize), tilesize(itilesize),
94 : gridder(0), isTiled(false), convType(iconvType),
95 : maxAbsData(0.0), centerLoc(IPosition(4,0)), offsetLoc(IPosition(4,0)),
96 : usezero_p(usezero), noPadding_p(false), usePut2_p(false),
97 14 : 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 14 : useDoubleGrid_p=useDoublePrec;
100 : // peek=NULL;
101 14 : }
102 :
103 2432 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
104 2432 : MPosition mLocation, Float padding, Bool usezero, Bool useDoublePrec)
105 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
106 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
107 : offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false),
108 2432 : 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 2432 : mLocation_p=mLocation;
111 2432 : tangentSpecified_p=false;
112 2432 : useDoubleGrid_p=useDoublePrec;
113 : // peek=NULL;
114 2432 : }
115 :
116 0 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
117 0 : MDirection mTangent, Float padding, Bool usezero, Bool useDoublePrec)
118 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
119 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
120 : 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 6 : GridFT::GridFT(Long icachesize, Int itilesize, String iconvType,
130 : MPosition mLocation, MDirection mTangent, Float padding,
131 6 : Bool usezero, Bool useDoublePrec)
132 : : FTMachine(), padding_p(padding), imageCache(0), cachesize(icachesize),
133 : tilesize(itilesize), gridder(0), isTiled(false), convType(iconvType), maxAbsData(0.0), centerLoc(IPosition(4,0)),
134 : offsetLoc(IPosition(4,0)), usezero_p(usezero), noPadding_p(false),
135 6 : 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 6 : mLocation_p=mLocation;
138 6 : mTangent_p=mTangent;
139 6 : tangentSpecified_p=true;
140 6 : useDoubleGrid_p=useDoublePrec;
141 : // peek=NULL;
142 6 : }
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 264 : GridFT& GridFT::operator=(const GridFT& other)
160 : {
161 264 : if(this!=&other) {
162 : //Do the base parameters
163 264 : FTMachine::operator=(other);
164 :
165 : //private params
166 264 : imageCache=other.imageCache;
167 264 : cachesize=other.cachesize;
168 264 : tilesize=other.tilesize;
169 264 : convType=other.convType;
170 264 : convType.upcase();
171 264 : uvScale.resize();
172 264 : uvOffset.resize();
173 264 : uvScale.assign(other.uvScale);
174 264 : uvOffset.assign(other.uvOffset);
175 264 : if(other.gridder==0)
176 264 : gridder=0;
177 : else{
178 0 : gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
179 0 : uvScale, uvOffset,
180 0 : convType);
181 : }
182 264 : convFunc_p.resize();
183 264 : convSupport_p=other.convSupport_p;
184 264 : convSampling_p=other.convSampling_p;
185 264 : convFunc_p=other.convFunc_p;
186 264 : isTiled=other.isTiled;
187 : //lattice=other.lattice;
188 264 : lattice.reset( );
189 264 : tilesize=other.tilesize;
190 264 : arrayLattice.reset( );
191 264 : maxAbsData=other.maxAbsData;
192 264 : centerLoc=other.centerLoc;
193 264 : offsetLoc=other.offsetLoc;
194 264 : padding_p=other.padding_p;
195 264 : usezero_p=other.usezero_p;
196 264 : noPadding_p=other.noPadding_p;
197 264 : machineName_p="GridFT";
198 264 : timemass_p=0.0;
199 264 : timegrid_p=0.0;
200 : // peek = other.peek;
201 : };
202 264 : return *this;
203 : };
204 :
205 : //----------------------------------------------------------------------
206 264 : GridFT::GridFT(const GridFT& other) : FTMachine(), machineName_p("GridFT")
207 : {
208 264 : operator=(other);
209 264 : }
210 :
211 : //-----------------------------------------------------------------------
212 264 : FTMachine* GridFT::cloneFTM(){
213 264 : return new GridFT(*this);
214 : }
215 :
216 : //===============================
217 2111 : Long GridFT::estimateRAM(const CountedPtr<SIImageStore>& imstor){
218 2111 : Long mem=FTMachine::estimateRAM(imstor);
219 2111 : mem=mem*padding_p*padding_p;
220 2111 : return mem;
221 : }
222 :
223 :
224 : //----------------------------------------------------------------------
225 2842 : void GridFT::init() {
226 :
227 2842 : logIO() << LogOrigin("GridFT", "init") << LogIO::NORMAL;
228 :
229 2842 : 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 2842 : isTiled=false;
250 2842 : if(!noPadding_p && padding_p > 1.01){
251 2828 : CompositeNumber cn(uInt(image->shape()(0)*2));
252 2828 : nx = cn.nextLargerEven(Int(padding_p*Float(image->shape()(0))-0.5));
253 2828 : ny = cn.nextLargerEven(Int(padding_p*Float(image->shape()(1))-0.5));
254 : }
255 : else{
256 14 : nx = image->shape()(0);
257 14 : ny = image->shape()(1);
258 : }
259 2842 : npol = image->shape()(2);
260 2842 : nchan = image->shape()(3);
261 : // }
262 :
263 2842 : sumWeight.resize(npol, nchan);
264 :
265 2842 : uvScale.resize(2);
266 2842 : uvScale(0)=(Float(nx)*image->coordinates().increment()(0));
267 2842 : uvScale(1)=(Float(ny)*image->coordinates().increment()(1));
268 2842 : uvOffset.resize(2);
269 2842 : uvOffset(0)=nx/2;
270 2842 : uvOffset(1)=ny/2;
271 :
272 : // Now set up the gridder. The possibilities are BOX and SF
273 2842 : if(gridder) delete gridder; gridder=0;
274 2842 : convType.upcase();
275 5684 : gridder = new ConvolveGridder<Double, Complex>(IPosition(2, nx, ny),
276 2842 : uvScale, uvOffset,
277 2842 : convType);
278 :
279 2842 : convFunc_p.resize();
280 2842 : convSupport_p=gridder->cSupport()(0);
281 2842 : convSampling_p=gridder->cSampling();
282 2842 : 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 2842 : if(imageCache) delete imageCache; imageCache=0;
288 :
289 2842 : 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 : }
309 2842 : }
310 :
311 : // This is nasty, we should use CountedPointers here.
312 5432 : GridFT::~GridFT() {
313 2716 : if(imageCache) delete imageCache; imageCache=0;
314 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
315 2716 : if(gridder) delete gridder; gridder=0;
316 5432 : }
317 :
318 : // Initialize for a transform from the Sky domain. This means that
319 : // we grid-correct, and FFT the image
320 :
321 764 : void GridFT::initializeToVis(ImageInterface<Complex>& iimage,
322 : const vi::VisBuffer2& vb)
323 : {
324 764 : image=&iimage;
325 764 : toVis_p=true;
326 :
327 764 : ok();
328 :
329 764 : init();
330 : // peek->reset();
331 : // Initialize the maps for polarization and channel. These maps
332 : // translate visibility indices into image indices
333 764 : 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 764 : prepGridForDegrid();
351 :
352 : //AlwaysAssert(lattice, AipsError);
353 :
354 :
355 :
356 764 : }
357 :
358 764 : void GridFT::prepGridForDegrid(){
359 1528 : IPosition gridShape(4, nx, ny, npol, nchan);
360 764 : 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 764 : griddedData.set(Complex(0.0));
366 :
367 1528 : IPosition stride(4, 1);
368 2292 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
369 2292 : IPosition trc(blc+image->shape()-stride);
370 :
371 1528 : IPosition start(4, 0);
372 764 : griddedData(blc, trc) = image->getSlice(start, image->shape());
373 :
374 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
375 764 : arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
376 764 : lattice=arrayLattice;
377 : //logIO() << LogIO::DEBUGGING
378 : // << "Starting grid correction and FFT of image" << LogIO::POST;
379 :
380 : // Do the Grid-correction.
381 : {
382 1528 : Vector<Complex> correction(nx);
383 764 : correction=Complex(1.0, 0.0);
384 : // Do the Grid-correction
385 1528 : IPosition cursorShape(4, nx, 1, 1, 1);
386 1528 : IPosition axisPath(4, 0, 1, 2, 3);
387 1528 : LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
388 1528 : LatticeIterator<Complex> lix(*lattice, lsx);
389 531028 : for(lix.reset();!lix.atEnd();lix++) {
390 530264 : gridder->correctX1D(correction, lix.position()(1));
391 530264 : lix.rwVectorCursor()/=correction;
392 : }
393 : }
394 764 : image->clearCache();
395 : // Now do the FFT2D in place
396 : //LatticeFFT::cfft2d(*lattice);
397 764 : ft_p.c2cFFT(*lattice);
398 : //logIO() << LogIO::DEBUGGING
399 : // << "Finished grid correction and FFT of image" << LogIO::POST;
400 :
401 764 : }
402 :
403 :
404 764 : void GridFT::finalizeToVis()
405 : {
406 :
407 764 : logIO() << LogOrigin("GridFT", "finalizeToVis") << LogIO::NORMAL;
408 764 : logIO() <<LogIO::NORMAL2<< "Time to degrid " << timedegrid_p <<LogIO::POST;
409 764 : timedegrid_p=0.0;
410 :
411 764 : if(arrayLattice) arrayLattice=nullptr;
412 764 : if(lattice) lattice=nullptr;
413 764 : griddedData.resize();
414 764 : 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 : }
425 764 : }
426 :
427 :
428 : // Initialize the FFT to the Sky. Here we have to setup and initialize the
429 : // grid.
430 2078 : void GridFT::initializeToSky(ImageInterface<Complex>& iimage,
431 : Matrix<Float>& weight, const vi::VisBuffer2& vb)
432 : {
433 : // image always points to the image
434 2078 : image=&iimage;
435 2078 : toVis_p=false;
436 :
437 2078 : init();
438 :
439 : // Initialize the maps for polarization and channel. These maps
440 : // translate visibility indices into image indices
441 2078 : initMaps(vb);
442 :
443 :
444 :
445 2078 : sumWeight=0.0;
446 2078 : weight.resize(sumWeight.shape());
447 2078 : weight=0.0;
448 :
449 :
450 4156 : IPosition gridShape(4, nx, ny, npol, nchan);
451 2078 : if( !useDoubleGrid_p )
452 : {
453 14 : griddedData.resize(gridShape);
454 14 : griddedData=Complex(0.0);
455 : }
456 : else{
457 :
458 2064 : griddedData2.resize(gridShape);
459 2064 : griddedData2=DComplex(0.0);
460 : }
461 2078 : image->clearCache();
462 : //iimage.get(griddedData, false);
463 : //if(arrayLattice) delete arrayLattice; arrayLattice=0;
464 :
465 :
466 : //AlwaysAssert(lattice, AipsError);
467 2078 : }
468 :
469 :
470 :
471 2077 : 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 2077 : logIO() << LogOrigin("GridFT", "finalizeToSky") << LogIO::NORMAL;
477 2077 : logIO()<<LogIO::NORMAL2 <<"Time to massage data " << timemass_p << LogIO::POST;
478 2077 : logIO()<< LogIO::NORMAL2 <<"Time to grid data " << timegrid_p << LogIO::POST;
479 2077 : timemass_p=0.0;
480 2077 : timegrid_p=0.0;
481 2077 : 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 : }
491 : // peek->terminate();
492 : // peek->reset();
493 2077 : }
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 501698 : void GridFT::put(const vi::VisBuffer2& vb, Int row, Bool dopsf,
684 : FTMachine::Type type)
685 : {
686 :
687 501698 : 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 501697 : 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 501697 : if(max(chanMap)==-1)
707 : {
708 : // peek->reset();
709 136 : return;
710 : }
711 :
712 501561 : Timer tim;
713 501561 : tim.mark();
714 :
715 : //const Matrix<Float> *imagingweight;
716 : //imagingweight=&(vb.imagingWeight());
717 1003122 : Matrix<Float> imagingweight;
718 501561 : getImagingWeight(imagingweight, vb);
719 :
720 501561 : if(dopsf) {type=FTMachine::PSF;}
721 :
722 1003122 : Cube<Complex> data;
723 : //Fortran gridder need the flag as ints
724 1003122 : Cube<Int> flags;
725 1003122 : Matrix<Float> elWeight;
726 501561 : interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
727 :
728 :
729 : Bool iswgtCopy;
730 : const Float *wgtStorage;
731 501561 : wgtStorage=elWeight.getStorage(iswgtCopy);
732 :
733 : Bool isCopy;
734 : const Complex *datStorage;
735 501561 : if(!dopsf)
736 306684 : datStorage=data.getStorage(isCopy);
737 : else
738 194877 : datStorage=0;
739 : // If row is -1 then we pass through all rows
740 : Int startRow, endRow, nRow;
741 501561 : if (row==-1) {
742 501561 : nRow=vb.nRows();
743 501561 : startRow=0;
744 501561 : 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 501561 : const IPosition &fs=flags.shape();
763 1003122 : std::vector<Int> s(fs.begin(),fs.end());
764 501561 : Int nvispol=s[0];
765 501561 : Int nvischan=s[1];
766 501561 : Int nvisrow=s[2];
767 1003122 : Matrix<Double> uvw(negateUV(vb));
768 :
769 1003122 : Vector<Double> dphase(vb.nRows());
770 1003122 : Cube<Int> loc(2, nvischan, nRow);
771 1003122 : Cube<Int> off(2, nvischan, nRow);
772 1003122 : Matrix<Complex> phasor(nvischan, nRow);
773 501561 : Int csamp=convSampling_p;
774 501561 : dphase=0.0;
775 :
776 501561 : timemass_p +=tim.real();
777 501561 : tim.mark();
778 501561 : rotateUVW(uvw, dphase, vb);
779 501561 : refocus(uvw, vb.antenna1(), vb.antenna2(), dphase, vb);
780 : Bool delphase;
781 501561 : Complex * phasorstor=phasor.getStorage(delphase);
782 501561 : const Double * visfreqstor=interpVisFreq_p.getStorage(del);
783 501561 : const Double * scalestor=uvScale.getStorage(del);
784 501561 : const Double * offsetstor=uvOffset.getStorage(del);
785 501561 : const Double* uvstor= uvw.getStorage(del);
786 501561 : Int * locstor=loc.getStorage(del);
787 501561 : Int * offstor=off.getStorage(del);
788 501561 : const Double *dpstor=dphase.getStorage(del);
789 : //Vector<Double> f1=interpVisFreq_p.copy();
790 501561 : Int nvchan=nvischan;
791 : Int irow;
792 501561 : Double cinv=Double(1.0)/C::c;
793 501561 : Int dow=0;
794 501561 : Int nth=1;
795 : #ifdef _OPENMP
796 501561 : if(numthreads_p >0){
797 0 : nth=min(numthreads_p, omp_get_max_threads());
798 : }
799 : else{
800 501561 : nth= omp_get_max_threads();
801 : }
802 : //nth=min(4,nth);
803 : #endif
804 :
805 :
806 501561 : #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 501561 : Int idopsf=0;
819 501561 : 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 1003122 : Vector<Int> rowFlags(vb.nRows());
831 501561 : rowFlags=0;
832 501561 : rowFlags(vb.flagRow())=true;
833 501561 : if(!usezero_p) {
834 168987676 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
835 168491509 : 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 501561 : Int csupp=convSupport_p;
843 :
844 501561 : const Double * convfuncstor=(convFunc_p).getStorage(del);
845 :
846 : // cerr <<"Poffset " << min(off) << " " << max(off) << " length " << gridder->cFunction().shape() << endl;
847 :
848 :
849 :
850 501561 : ixsub=1;
851 501561 : iysub=1;
852 501561 : if (nth >4){
853 0 : ixsub=8;
854 0 : iysub=8;
855 : }
856 501561 : else if(nth >1) {
857 0 : ixsub=2;
858 0 : iysub=2;
859 : }
860 :
861 :
862 501561 : Int rbeg=startRow+1;
863 501561 : Int rend=endRow+1;
864 1003122 : Block<Matrix<Double> > sumwgt(ixsub*iysub);
865 1003122 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
866 501561 : sumwgt[icounter].resize(sumWeight.shape());
867 501561 : sumwgt[icounter].set(0.0);
868 : }
869 501561 : if(doneThreadPartition_p < 0){
870 1146 : xsect_p.resize(ixsub*iysub);
871 1146 : ysect_p.resize(ixsub*iysub);
872 1146 : nxsect_p.resize(ixsub*iysub);
873 1146 : nysect_p.resize(ixsub*iysub);
874 2292 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
875 1146 : findGridSector(nx, ny, ixsub, iysub, 0, 0, icounter, xsect_p(icounter), ysect_p(icounter), nxsect_p(icounter), nysect_p(icounter), true);
876 : }
877 : }
878 1003122 : Vector<Int> xsect, ysect, nxsect, nysect;
879 501561 : xsect=xsect_p; ysect=ysect_p; nxsect=nxsect_p; nysect=nysect_p;
880 501561 : const Int* pmapstor=polMap.getStorage(del);
881 501561 : const Int *cmapstor=chanMap.getStorage(del);
882 501561 : Int nc=nchan;
883 501561 : Int np=npol;
884 501561 : Int nxp=nx;
885 501561 : Int nyp=ny;
886 501561 : const Int * flagstor=flags.getStorage(del);
887 501561 : const Int * rowflagstor=rowFlags.getStorage(del);
888 : ////////////////////////
889 :
890 : Bool gridcopy;
891 501561 : if(useDoubleGrid_p){
892 496167 : DComplex *gridstor=griddedData2.getStorage(gridcopy);
893 496167 : #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 992334 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
929 496167 : sumWeight=sumWeight+sumwgt[icounter];
930 : }
931 : //phasor.putStorage(phasorstor, delphase);
932 496167 : griddedData2.putStorage(gridstor, gridcopy);
933 496167 : if(dopsf && (nth >4))
934 0 : tweakGridSector(nx, ny, ixsub, iysub);
935 : }
936 : else{
937 5394 : Complex *gridstor=griddedData.getStorage(gridcopy);
938 5394 : #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 10788 : for (icounter=0; icounter < ixsub*iysub; ++icounter){
977 5394 : sumWeight=sumWeight+sumwgt[icounter];
978 : }
979 :
980 5394 : griddedData.putStorage(gridstor, gridcopy);
981 5394 : if(dopsf && (nth > 4))
982 0 : tweakGridSector(nx, ny, ixsub, iysub);
983 : }
984 : // cerr << "sunweight " << sumWeight << endl;
985 :
986 501561 : timegrid_p+=tim.real();
987 :
988 501561 : if(!dopsf)
989 306684 : data.freeStorage(datStorage, isCopy);
990 501561 : elWeight.freeStorage(wgtStorage,iswgtCopy);
991 :
992 : // peek->reset();
993 : }
994 :
995 14 : void GridFT::modifyConvFunc(const Vector<Double>& convFunc, Int convSupport, Int convSampling){
996 14 : convFunc_p.resize();
997 14 : convFunc_p=convFunc;
998 14 : convSupport_p=convSupport;
999 14 : convSampling_p=convSampling;
1000 :
1001 14 : }
1002 :
1003 157782 : void GridFT::get(vi::VisBuffer2& vb, Int row)
1004 : {
1005 :
1006 157782 : gridOk(convSupport_p);
1007 : // If row is -1 then we pass through all rows
1008 : Int startRow, endRow, nRow;
1009 157782 : if (row < 0) {
1010 157782 : nRow=vb.nRows();
1011 157782 : startRow=0;
1012 157782 : 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 157782 : matchChannel(vb);
1026 :
1027 :
1028 : //cerr << "GETchanMap " << chanMap << endl;
1029 : //No point in reading data if its not matching in frequency
1030 157782 : if(max(chanMap)==-1)
1031 58 : return;
1032 :
1033 :
1034 :
1035 : // Get the uvws in a form that Fortran can use
1036 315448 : Matrix<Double> uvw(negateUV(vb));
1037 315448 : Vector<Double> dphase(vb.nRows());
1038 157724 : dphase=0.0;
1039 157724 : rotateUVW(uvw, dphase, vb);
1040 157724 : 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 315448 : Cube<Complex> data;
1053 315448 : Cube<Int> flags;
1054 157724 : 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 157724 : Int nvp=data.shape()(0);
1060 157724 : Int nvc=data.shape()(1);
1061 157724 : Int nvisrow=data.shape()(2);
1062 :
1063 :
1064 : //cerr << "get flags " << min(flags) << " " << max(flags) << endl;
1065 : Complex *datStorage;
1066 : Bool isCopy;
1067 157724 : datStorage=data.getStorage(isCopy);
1068 :
1069 : ///
1070 315448 : Cube<Int> loc(2, nvc, nvisrow);
1071 315448 : Cube<Int> off(2, nvc, nRow);
1072 315448 : Matrix<Complex> phasor(nvc, nRow);
1073 157724 : Int csamp=convSampling_p;
1074 : Bool delphase;
1075 : Bool del;
1076 157724 : Complex * phasorstor=phasor.getStorage(delphase);
1077 157724 : const Double * visfreqstor=interpVisFreq_p.getStorage(del);
1078 157724 : const Double * scalestor=uvScale.getStorage(del);
1079 157724 : const Double * offsetstor=uvOffset.getStorage(del);
1080 157724 : const Double* uvstor= uvw.getStorage(del);
1081 157724 : Int * locstor=loc.getStorage(del);
1082 157724 : Int * offstor=off.getStorage(del);
1083 157724 : const Double *dpstor=dphase.getStorage(del);
1084 : //Vector<Double> f1=interpVisFreq_p.copy();
1085 157724 : Int nvchan=nvc;
1086 : Int irow;
1087 157724 : Double cinv=Double(1.0)/C::c;
1088 157724 : Int dow=0;
1089 157724 : Int nth=1;
1090 : #ifdef _OPENMP
1091 157724 : if(numthreads_p >0){
1092 0 : nth=min(numthreads_p, omp_get_max_threads());
1093 : }
1094 : else{
1095 157724 : nth= omp_get_max_threads();
1096 : }
1097 : //nth=min(4,nth);
1098 : #endif
1099 :
1100 :
1101 157724 : #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 157724 : Int rbeg=startRow+1;
1116 157724 : Int rend=endRow+1;
1117 :
1118 :
1119 315448 : Vector<Int> rowFlags(vb.nRows());
1120 157724 : rowFlags=0;
1121 157724 : rowFlags(vb.flagRow())=true;
1122 : //cerr << "rowFlags " << rowFlags << endl;
1123 157724 : if(!usezero_p) {
1124 54180610 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
1125 54022886 : 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 157724 : const Complex* gridstor=griddedData.getStorage(delgrid);
1135 157724 : const Double * convfuncstor=(convFunc_p).getStorage(del);
1136 :
1137 157724 : const Int* pmapstor=polMap.getStorage(del);
1138 157724 : const Int *cmapstor=chanMap.getStorage(del);
1139 157724 : Int nc=nchan;
1140 157724 : Int np=npol;
1141 157724 : Int nxp=nx;
1142 157724 : Int nyp=ny;
1143 157724 : Int csupp=convSupport_p;
1144 157724 : const Int * flagstor=flags.getStorage(del);
1145 157724 : const Int * rowflagstor=rowFlags.getStorage(del);
1146 :
1147 :
1148 157724 : Int npart=nth;
1149 :
1150 :
1151 157724 : Int ix=0;
1152 157724 : #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 157724 : data.putStorage(datStorage, isCopy);
1180 157724 : griddedData.freeStorage(gridstor, delgrid);
1181 : //cerr << "Get min max " << min(data) << " " << max(data) << endl;
1182 : }
1183 157724 : interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
1184 :
1185 : }
1186 :
1187 :
1188 :
1189 : // Finalize the FFT to the Sky. Here we actually do the FFT and
1190 : // return the resulting image
1191 2063 : ImageInterface<Complex>& GridFT::getImage(Matrix<Float>& weights, Bool normalize)
1192 : {
1193 : //AlwaysAssert(lattice, AipsError);
1194 2063 : AlwaysAssert(gridder, AipsError);
1195 2063 : AlwaysAssert(image, AipsError);
1196 2063 : logIO() << LogOrigin("GridFT", "getImage") << LogIO::NORMAL;
1197 :
1198 2063 : if((griddedData.nelements() ==0) && (griddedData2.nelements()==0)){
1199 0 : throw(AipsError("Programmer error ...request for image without right order of calls"));
1200 : }
1201 2063 : weights.resize(sumWeight.shape());
1202 :
1203 2063 : convertArray(weights, sumWeight);
1204 : // If the weights are all zero then we cannot normalize
1205 : // otherwise we don't care.
1206 2063 : 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 2063 : if(useDoubleGrid_p)
1233 : {
1234 4126 : ArrayLattice<DComplex> darrayLattice(griddedData2);
1235 : //LatticeFFT::cfft2d(darrayLattice,false);
1236 2063 : ft_p.c2cFFT(darrayLattice, False);
1237 2063 : griddedData.resize(griddedData2.shape());
1238 2063 : convertArray(griddedData, griddedData2);
1239 :
1240 2063 : SynthesisUtilMethods::getResource("mem peak in getImage");
1241 :
1242 : //Don't need the double-prec grid anymore...
1243 2063 : griddedData2.resize();
1244 2063 : arrayLattice.reset( new ArrayLattice<Complex>(griddedData) );
1245 2063 : lattice=arrayLattice;
1246 : }
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 2063 : Int inx = lattice->shape()(0);
1259 2063 : Int iny = lattice->shape()(1);
1260 4126 : Vector<Complex> correction(inx);
1261 2063 : correction=Complex(1.0, 0.0);
1262 : // Do the Grid-correction
1263 4126 : IPosition cursorShape(4, inx, 1, 1, 1);
1264 4126 : IPosition axisPath(4, 0, 1, 2, 3);
1265 4126 : LatticeStepper lsx(lattice->shape(), cursorShape, axisPath);
1266 4126 : LatticeIterator<Complex> lix(*lattice, lsx);
1267 1510951 : for(lix.reset();!lix.atEnd();lix++) {
1268 1508888 : Int pol=lix.position()(2);
1269 1508888 : Int chan=lix.position()(3);
1270 1508888 : if(weights(pol, chan)!=0.0) {
1271 1462880 : gridder->correctX1D(correction, lix.position()(1));
1272 1462880 : lix.rwVectorCursor()/=correction;
1273 1462880 : if(normalize) {
1274 0 : Complex rnorm(Float(inx)*Float(iny)/weights(pol,chan));
1275 0 : lix.rwCursor()*=rnorm;
1276 : }
1277 : else {
1278 1462880 : Complex rnorm(Float(inx)*Float(iny));
1279 1462880 : lix.rwCursor()*=rnorm;
1280 : }
1281 : }
1282 : else {
1283 46008 : lix.woCursor()=0.0;
1284 : }
1285 : }
1286 : }
1287 4126 : LatticeLocker lock1 (*(image), FileLocker::Write);
1288 2063 : if(!isTiled) {
1289 : // Check the section from the image BEFORE converting to a lattice
1290 6189 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
1291 4126 : IPosition stride(4, 1);
1292 6189 : IPosition trc(blc+image->shape()-stride);
1293 : // Do the copy
1294 2063 : IPosition start(4, 0);
1295 :
1296 2063 : image->put(griddedData(blc, trc));
1297 : }
1298 : }
1299 2063 : image->flush();
1300 2063 : image->clearCache();
1301 :
1302 2063 : if(arrayLattice) arrayLattice=nullptr;
1303 2063 : if(lattice) lattice=nullptr;
1304 2063 : griddedData.resize();
1305 2063 : 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 42 : 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 42 : Bool retval = true;
1342 42 : Float elpadd=padding_p;
1343 42 : if(toVis_p && withImage)
1344 19 : elpadd=1.0;
1345 : //save the base class variables
1346 42 : 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 42 : outRec.define("cachesize", Int64(cachesize));
1353 42 : outRec.define("tilesize", tilesize);
1354 42 : outRec.define("convtype", convType);
1355 42 : outRec.define("uvscale", uvScale);
1356 42 : outRec.define("uvoffset", uvOffset);
1357 42 : outRec.define("istiled", isTiled);
1358 42 : outRec.define("maxabsdata", maxAbsData);
1359 84 : Vector<Int> center_loc(4), offset_loc(4);
1360 210 : for (Int k=0; k<4 ; k++){
1361 168 : center_loc(k)=centerLoc(k);
1362 168 : offset_loc(k)=offsetLoc(k);
1363 : }
1364 42 : outRec.define("centerloc", center_loc);
1365 42 : outRec.define("offsetloc", offset_loc);
1366 42 : outRec.define("padding", elpadd);
1367 42 : outRec.define("usezero", usezero_p);
1368 42 : outRec.define("nopadding", noPadding_p);
1369 42 : return retval;
1370 : }
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 : }
1429 :
1430 1322176 : void GridFT::ok() {
1431 1322176 : AlwaysAssert(image, AipsError);
1432 1322176 : }
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 3975 : String GridFT::name() const {
1502 :
1503 3975 : return machineName_p;
1504 :
1505 :
1506 : }
1507 :
1508 : }//End of namespace refim
1509 : } //# NAMESPACE CASA - END
1510 :
|