Line data Source code
1 : //# SDGrid.cc: Implementation of SDGrid class
2 : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
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 Library 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 Library 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 <casacore/casa/Arrays/Array.h>
29 : #include <casacore/casa/Arrays/ArrayLogical.h>
30 : #include <casacore/casa/Arrays/ArrayMath.h>
31 : #include <casacore/casa/Arrays/Cube.h>
32 : #include <casacore/casa/Arrays/MaskedArray.h>
33 : #include <casacore/casa/Arrays/Matrix.h>
34 : #include <casacore/casa/Arrays/MatrixIter.h>
35 : #include <casacore/casa/Arrays/Slice.h>
36 : #include <casacore/casa/Arrays/Vector.h>
37 : #include <casacore/casa/BasicSL/Constants.h>
38 : #include <casacore/casa/BasicSL/String.h>
39 : #include <casacore/casa/Containers/Block.h>
40 : #include <casacore/casa/Exceptions/Error.h>
41 : #include <casacore/casa/OS/Timer.h>
42 : #include <casacore/casa/Quanta/MVAngle.h>
43 : #include <casacore/casa/Quanta/MVTime.h>
44 : #include <casacore/casa/Quanta/UnitMap.h>
45 : #include <casacore/casa/Quanta/UnitVal.h>
46 : #include <sstream>
47 : #include <casacore/casa/Utilities/Assert.h>
48 :
49 : #include <components/ComponentModels/ConstantSpectrum.h>
50 : #include <components/ComponentModels/Flux.h>
51 : #include <components/ComponentModels/PointShape.h>
52 :
53 : #include <casacore/coordinates/Coordinates/CoordinateSystem.h>
54 : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
55 : #include <casacore/coordinates/Coordinates/Projection.h>
56 : #include <casacore/coordinates/Coordinates/SpectralCoordinate.h>
57 : #include <casacore/coordinates/Coordinates/StokesCoordinate.h>
58 :
59 : #include <casacore/images/Images/ImageInterface.h>
60 : #include <casacore/images/Images/PagedImage.h>
61 : #include <casacore/images/Images/TempImage.h>
62 :
63 : #include <casacore/lattices/Lattices/ArrayLattice.h>
64 : #include <casacore/lattices/Lattices/LatticeCache.h>
65 : #include <casacore/lattices/Lattices/LatticeIterator.h>
66 : #include <casacore/lattices/Lattices/LatticeStepper.h>
67 : #include <casacore/lattices/Lattices/SubLattice.h>
68 : #include <casacore/lattices/LEL/LatticeExpr.h>
69 : #include <casacore/lattices/LRegions/LCBox.h>
70 :
71 : #include <casacore/measures/Measures/Stokes.h>
72 : #include <casacore/ms/MeasurementSets/MSColumns.h>
73 : #include <msvis/MSVis/StokesVector.h>
74 : #include <msvis/MSVis/VisBuffer2.h>
75 : #include <msvis/MSVis/VisibilityIterator2.h>
76 : #include <casacore/scimath/Mathematics/RigidVector.h>
77 : #include <synthesis/TransformMachines2/SDGrid.h>
78 : #include <synthesis/TransformMachines2/SkyJones.h>
79 : #include <synthesis/TransformMachines/StokesImageUtil.h>
80 :
81 : using namespace casacore;
82 : namespace casa {
83 : namespace refim {//# namespace for imaging refactor
84 :
85 0 : SDGrid::SDGrid(SkyJones& sj, Int icachesize, Int itilesize,
86 0 : String iconvType, Int userSupport, Bool useImagingWeight)
87 : : FTMachine(), sj_p(&sj), imageCache(0), wImageCache(0),
88 : cachesize(icachesize), tilesize(itilesize),
89 : isTiled(false), wImage(0), arrayLattice(0), wArrayLattice(0), lattice(0), wLattice(0), convType(iconvType),
90 : pointingToImage(0), userSetSupport_p(userSupport),
91 : truncate_p(-1.0), gwidth_p(0.0), jwidth_p(0.0),
92 : minWeight_p(0.), lastIndexPerAnt_p(), useImagingWeight_p(useImagingWeight), lastAntID_p(-1), msId_p(-1),
93 0 : isSplineInterpolationReady(false), interpolator(0), clipminmax_(false)
94 : {
95 0 : lastIndex_p=0;
96 0 : }
97 :
98 0 : SDGrid::SDGrid(MPosition& mLocation, SkyJones& sj, Int icachesize, Int itilesize,
99 0 : String iconvType, Int userSupport, Float minweight, Bool clipminmax, Bool useImagingWeight)
100 : : FTMachine(), sj_p(&sj), imageCache(0), wImageCache(0),
101 : cachesize(icachesize), tilesize(itilesize),
102 : isTiled(false), wImage(0), arrayLattice(0), wArrayLattice(0), lattice(0), wLattice(0), convType(iconvType),
103 : pointingToImage(0), userSetSupport_p(userSupport),
104 : truncate_p(-1.0), gwidth_p(0.0), jwidth_p(0.0),
105 : minWeight_p(minweight), lastIndexPerAnt_p(), useImagingWeight_p(useImagingWeight), lastAntID_p(-1), msId_p(-1),
106 0 : isSplineInterpolationReady(false), interpolator(0), clipminmax_(clipminmax)
107 : {
108 0 : mLocation_p=mLocation;
109 0 : lastIndex_p=0;
110 0 : }
111 :
112 0 : SDGrid::SDGrid(Int icachesize, Int itilesize,
113 0 : String iconvType, Int userSupport, Bool useImagingWeight)
114 : : FTMachine(), sj_p(0), imageCache(0), wImageCache(0),
115 : cachesize(icachesize), tilesize(itilesize),
116 : isTiled(false), wImage(0), arrayLattice(0), wArrayLattice(0), lattice(0), wLattice(0), convType(iconvType),
117 : pointingToImage(0), userSetSupport_p(userSupport),
118 : truncate_p(-1.0), gwidth_p(0.0), jwidth_p(0.0),
119 : minWeight_p(0.), lastIndexPerAnt_p(), useImagingWeight_p(useImagingWeight), lastAntID_p(-1), msId_p(-1),
120 0 : isSplineInterpolationReady(false), interpolator(0), clipminmax_(false)
121 : {
122 0 : lastIndex_p=0;
123 0 : }
124 :
125 0 : SDGrid::SDGrid(MPosition &mLocation, Int icachesize, Int itilesize,
126 0 : String iconvType, Int userSupport, Float minweight, Bool clipminmax, Bool useImagingWeight)
127 : : FTMachine(), sj_p(0), imageCache(0), wImageCache(0),
128 : cachesize(icachesize), tilesize(itilesize),
129 : isTiled(false), wImage(0), arrayLattice(0), wArrayLattice(0), lattice(0), wLattice(0), convType(iconvType),
130 : pointingToImage(0), userSetSupport_p(userSupport),
131 : truncate_p(-1.0), gwidth_p(0.0), jwidth_p(0.0),
132 : minWeight_p(minweight), lastIndexPerAnt_p(), useImagingWeight_p(useImagingWeight), lastAntID_p(-1),
133 : msId_p(-1),
134 0 : isSplineInterpolationReady(false), interpolator(0), clipminmax_(clipminmax)
135 : {
136 0 : mLocation_p=mLocation;
137 0 : lastIndex_p=0;
138 0 : }
139 :
140 0 : SDGrid::SDGrid(MPosition &mLocation, Int icachesize, Int itilesize,
141 : String iconvType, Float truncate, Float gwidth, Float jwidth,
142 0 : Float minweight, Bool clipminmax, Bool useImagingWeight)
143 : : FTMachine(), sj_p(0), imageCache(0), wImageCache(0),
144 : cachesize(icachesize), tilesize(itilesize),
145 : isTiled(false), wImage(0), arrayLattice(0), wArrayLattice(0), lattice(0), wLattice(0), convType(iconvType),
146 : pointingToImage(0), userSetSupport_p(-1),
147 : truncate_p(truncate), gwidth_p(gwidth), jwidth_p(jwidth),
148 : minWeight_p(minweight), lastIndexPerAnt_p(), useImagingWeight_p(useImagingWeight), lastAntID_p(-1), msId_p(-1),
149 0 : isSplineInterpolationReady(false), interpolator(0), clipminmax_(clipminmax)
150 : {
151 0 : mLocation_p=mLocation;
152 0 : lastIndex_p=0;
153 0 : }
154 :
155 :
156 : //----------------------------------------------------------------------
157 0 : SDGrid& SDGrid::operator=(const SDGrid& other)
158 : {
159 0 : if(this!=&other) {
160 : //Do the base parameters
161 0 : FTMachine::operator=(other);
162 0 : sj_p=other.sj_p;
163 0 : imageCache=other.imageCache;
164 0 : wImage=other.wImage;
165 0 : wImageCache=other.wImageCache;
166 0 : cachesize=other.cachesize;
167 0 : tilesize=other.tilesize;
168 0 : isTiled=other.isTiled;
169 0 : lattice=other.lattice;
170 0 : arrayLattice=other.arrayLattice;
171 0 : wLattice=other.wLattice;
172 0 : wArrayLattice=other.wArrayLattice;
173 0 : convType=other.convType;
174 0 : if(other.wImage !=0)
175 0 : wImage=(TempImage<Float> *)other.wImage->cloneII();
176 : else
177 0 : wImage=0;
178 0 : pointingDirCol_p=other.pointingDirCol_p;
179 0 : pointingToImage=0;
180 0 : xyPos.resize();
181 0 : xyPos=other.xyPos;
182 0 : xyPosMovingOrig_p=other.xyPosMovingOrig_p;
183 0 : convFunc.resize();
184 0 : convFunc=other.convFunc;
185 0 : convSampling=other.convSampling;
186 0 : convSize=other.convSize;
187 0 : convSupport=other.convSupport;
188 0 : userSetSupport_p=other.userSetSupport_p;
189 0 : lastIndex_p=0;
190 0 : lastIndexPerAnt_p=0;
191 0 : lastAntID_p=-1;
192 0 : msId_p=-1;
193 0 : useImagingWeight_p=other.useImagingWeight_p;
194 0 : clipminmax_=other.clipminmax_;
195 : };
196 0 : return *this;
197 : };
198 :
199 0 : String SDGrid::name() const{
200 0 : return String("SDGrid");
201 : }
202 :
203 : //----------------------------------------------------------------------
204 : // Odds are that it changed.....
205 0 : Bool SDGrid::changed(const vi::VisBuffer2& /*vb*/) {
206 0 : return false;
207 : }
208 :
209 : //----------------------------------------------------------------------
210 0 : SDGrid::SDGrid(const SDGrid& other):FTMachine()
211 : {
212 0 : operator=(other);
213 0 : }
214 :
215 : #define NEED_UNDERSCORES
216 : #if defined(NEED_UNDERSCORES)
217 : #define grdsf grdsf_
218 : #define grdgauss grdgauss_
219 : #define grdjinc1 grdjinc1_
220 : #endif
221 :
222 : extern "C" {
223 : void grdsf(Double*, Double*);
224 : void grdgauss(Double*, Double*, Double*);
225 : void grdjinc1(Double*, Double*, Int*, Double*);
226 : }
227 :
228 : //----------------------------------------------------------------------
229 0 : void SDGrid::init() {
230 :
231 0 : logIO() << LogOrigin("SDGrid", "init") << LogIO::NORMAL;
232 :
233 : //pfile = fopen("ptdata.txt","w");
234 :
235 0 : ok();
236 :
237 : /*if((image->shape().product())>cachesize) {
238 : isTiled=true;
239 : }
240 : else {
241 : isTiled=false;
242 : }*/
243 0 : isTiled=false;
244 0 : nx = image->shape()(0);
245 0 : ny = image->shape()(1);
246 0 : npol = image->shape()(2);
247 0 : nchan = image->shape()(3);
248 :
249 0 : sumWeight.resize(npol, nchan);
250 :
251 : // Set up image cache needed for gridding. For BOX-car convolution
252 : // we can use non-overlapped tiles. Otherwise we need to use
253 : // overlapped tiles and additive gridding so that only increments
254 : // to a tile are written.
255 0 : if(imageCache) delete imageCache; imageCache=0;
256 :
257 0 : convType=downcase(convType);
258 0 : logIO() << "Convolution function : " << convType << LogIO::DEBUG1 << LogIO::POST;
259 0 : if(convType=="pb") {
260 : //cerr << "CNVFunc " << convFunc << endl;
261 :
262 : }
263 0 : else if(convType=="box") {
264 0 : convSupport=(userSetSupport_p >= 0) ? userSetSupport_p : 0;
265 0 : logIO() << "Support : " << convSupport << " pixels" << LogIO::POST;
266 0 : convSampling=100;
267 0 : convSize=convSampling*(2*convSupport+2);
268 0 : convFunc.resize(convSize);
269 0 : convFunc=0.0;
270 0 : for (Int i=0;i<convSize/2;i++) {
271 0 : convFunc(i)=1.0;
272 : }
273 : }
274 0 : else if(convType=="sf") {
275 : // SF
276 0 : convSupport=(userSetSupport_p >= 0) ? userSetSupport_p : 3;
277 0 : logIO() << "Support : " << convSupport << " pixels" << LogIO::POST;
278 0 : convSampling=100;
279 0 : convSize=convSampling*(2*convSupport+2);
280 0 : convFunc.resize(convSize);
281 0 : convFunc=0.0;
282 0 : for (Int i=0;i<convSampling*convSupport;i++) {
283 0 : Double nu=Double(i)/Double(convSupport*convSampling);
284 : Double val;
285 0 : grdsf(&nu, &val);
286 0 : convFunc(i)=(1.0-nu*nu)*val;
287 : }
288 : }
289 0 : else if(convType=="gauss") {
290 : // default is b=1.0 (Mangum et al. 2007)
291 0 : Double hwhm=(gwidth_p > 0.0) ? Double(gwidth_p) : sqrt(log(2.0));
292 0 : Float truncate=(truncate_p >= 0.0) ? truncate_p : 3.0*hwhm;
293 0 : convSampling=100;
294 0 : Int itruncate=(Int)(truncate*Double(convSampling)+0.5);
295 0 : logIO() << LogIO::DEBUG1 << "hwhm=" << hwhm << LogIO::POST;
296 0 : logIO() << LogIO::DEBUG1 << "itruncate=" << itruncate << LogIO::POST;
297 : //convSupport=(Int)(truncate+0.5);
298 0 : convSupport = (Int)(truncate);
299 0 : convSupport += (((truncate-(Float)convSupport) > 0.0) ? 1 : 0);
300 0 : convSize=convSampling*(2*convSupport+2);
301 0 : convFunc.resize(convSize);
302 0 : convFunc=0.0;
303 : Double val, x;
304 0 : for (Int i = 0 ; i <= itruncate ; i++) {
305 0 : x = Double(i)/Double(convSampling);
306 0 : grdgauss(&hwhm, &x, &val);
307 0 : convFunc(i)=val;
308 : }
309 :
310 : // String outfile = convType + ".dat";
311 : // ofstream ofs(outfile.c_str());
312 : // for (Int i = 0 ; i < convSize ; i++) {
313 : // ofs << i << " " << convFunc[i] << endl;
314 : // }
315 : // ofs.close();
316 : }
317 0 : else if (convType=="gjinc") {
318 : // default is b=2.52, c=1.55 (Mangum et al. 2007)
319 0 : Double hwhm = (gwidth_p > 0.0) ? Double(gwidth_p) : sqrt(log(2.0))*2.52;
320 0 : Double c = (jwidth_p > 0.0) ? Double(jwidth_p) : 1.55;
321 : //Float truncate = truncate_p;
322 0 : convSampling = 100;
323 0 : Int itruncate=(Int)(truncate_p*Double(convSampling)+0.5);
324 0 : logIO() << LogIO::DEBUG1 << "hwhm=" << hwhm << LogIO::POST;
325 0 : logIO() << LogIO::DEBUG1 << "c=" << c << LogIO::POST;
326 0 : logIO() << LogIO::DEBUG1 << "itruncate=" << itruncate << LogIO::POST;
327 : //convSupport=(truncate_p >= 0.0) ? (Int)(truncate_p+0.5) : (Int)(2*c+0.5);
328 0 : Float convSupportF = (truncate_p >= 0.0) ? truncate_p : (2*c);
329 0 : convSupport = (Int)convSupportF;
330 0 : convSupport += (((convSupportF-(Float)convSupport) > 0.0) ? 1 : 0);
331 0 : convSize=convSampling*(2*convSupport+2);
332 0 : convFunc.resize(convSize);
333 0 : convFunc=0.0;
334 : //UNUSED: Double r;
335 : Double x, val1, val2;
336 0 : Int normalize = 1;
337 0 : if (itruncate >= 0) {
338 0 : for (Int i = 0 ; i < itruncate ; i++) {
339 0 : x = Double(i) / Double(convSampling);
340 : //r = Double(i) / (Double(hwhm)*Double(convSampling));
341 0 : grdgauss(&hwhm, &x, &val1);
342 0 : grdjinc1(&c, &x, &normalize, &val2);
343 0 : convFunc(i) = val1 * val2;
344 : }
345 : }
346 : else {
347 : // default is to truncate at first null
348 0 : for (Int i=0;i<convSize;i++) {
349 0 : x = Double(i) / Double(convSampling);
350 : //r = Double(i) / (Double(hwhm)*Double(convSampling));
351 0 : grdjinc1(&c, &x, &normalize, &val2);
352 0 : if (val2 <= 0.0) {
353 0 : logIO() << LogIO::DEBUG1 << "convFunc is automatically truncated at radius " << x << LogIO::POST;
354 0 : break;
355 : }
356 0 : grdgauss(&hwhm, &x, &val1);
357 0 : convFunc(i) = val1 * val2;
358 : }
359 : }
360 :
361 : // String outfile = convType + ".dat";
362 : // ofstream ofs(outfile.c_str());
363 : // for (Int i = 0 ; i < convSize ; i++) {
364 : // ofs << i << " " << convFunc[i] << endl;
365 : // }
366 : // ofs.close();
367 : }
368 : else {
369 0 : logIO_p << "Unknown convolution function " << convType << LogIO::EXCEPTION;
370 : }
371 :
372 0 : if(wImage) delete wImage; wImage=0;
373 0 : wImage = new TempImage<Float>(image->shape(), image->coordinates());
374 :
375 : /*if(isTiled) {
376 : Float tileOverlap=0.5;
377 : if(convType=="box") {
378 : tileOverlap=0.0;
379 : }
380 : else {
381 : tileOverlap=0.5;
382 : tilesize=max(12,tilesize);
383 : }
384 : IPosition tileShape=IPosition(4,tilesize,tilesize,npol,nchan);
385 : Vector<Float> tileOverlapVec(4);
386 : tileOverlapVec=0.0;
387 : tileOverlapVec(0)=tileOverlap;
388 : tileOverlapVec(1)=tileOverlap;
389 : imageCache=new LatticeCache <Complex> (*image, cachesize, tileShape,
390 : tileOverlapVec,
391 : (tileOverlap>0.0));
392 :
393 : wImageCache=new LatticeCache <Float> (*wImage, cachesize, tileShape,
394 : tileOverlapVec,
395 : (tileOverlap>0.0));
396 :
397 : }
398 : */
399 0 : }
400 :
401 : // This is nasty, we should use CountedPointers here.
402 0 : SDGrid::~SDGrid() {
403 : //fclose(pfile);
404 0 : if (imageCache) delete imageCache; imageCache = 0;
405 0 : if (arrayLattice) delete arrayLattice; arrayLattice = 0;
406 0 : if (wImage) delete wImage; wImage = 0;
407 0 : if (wImageCache) delete wImageCache; wImageCache = 0;
408 0 : if (wArrayLattice) delete wArrayLattice; wArrayLattice = 0;
409 0 : if (interpolator) delete interpolator; interpolator = 0;
410 0 : }
411 :
412 0 : void SDGrid::findPBAsConvFunction(const ImageInterface<Complex>& image,
413 : const vi::VisBuffer2& vb) {
414 :
415 : // Get the coordinate system and increase the sampling by
416 : // a factor of ~ 100.
417 0 : CoordinateSystem coords(image.coordinates());
418 :
419 : // Set up the convolution function: make the buffer plenty
420 : // big so that we can trim it back
421 0 : convSupport=max(128, sj_p->support(vb, coords));
422 :
423 0 : convSampling=100;
424 0 : convSize=convSampling*convSupport;
425 :
426 : // Make a one dimensional image to calculate the
427 : // primary beam. We oversample this by a factor of
428 : // convSampling.
429 0 : Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
430 0 : AlwaysAssert(directionIndex>=0, AipsError);
431 0 : DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
432 0 : Vector<Double> sampling;
433 0 : sampling = dc.increment();
434 0 : sampling*=1.0/Double(convSampling);
435 0 : dc.setIncrement(sampling);
436 :
437 : // Set the reference value to the first pointing in the coordinate
438 : // system used in the POINTING table.
439 : {
440 0 : uInt row = 0;
441 :
442 : // reset lastAntID_p to use correct antenna position
443 0 : lastAntID_p = -1;
444 :
445 0 : const MSPointingColumns& act_mspc = vb.subtableColumns().pointing();
446 0 : Bool nullPointingTable = (act_mspc.nrow() < 1);
447 0 : Int pointIndex = -1;
448 0 : if (!nullPointingTable){
449 : //if(vb.newMS()) This thing is buggy...using msId change
450 0 : if (vb.msId() != msId_p) {
451 0 : lastIndex_p=0;
452 0 : if (lastIndexPerAnt_p.nelements() < (size_t)vb.nAntennas()) {
453 0 : lastIndexPerAnt_p.resize(vb.nAntennas());
454 : }
455 0 : lastIndexPerAnt_p = 0;
456 0 : msId_p = vb.msId();
457 : }
458 0 : pointIndex = getIndex(act_mspc, vb.time()(row), -1.0, vb.antenna1()(row));
459 0 : if (pointIndex < 0)
460 0 : pointIndex = getIndex(act_mspc, vb.time()(row), vb.timeInterval()(row), vb.antenna1()(row));
461 : }
462 0 : if (!nullPointingTable && ((pointIndex < 0) || (pointIndex >= Int(act_mspc.time().nrow())))) {
463 0 : ostringstream o;
464 0 : o << "Failed to find pointing information for time " <<
465 0 : MVTime(vb.time()(row)/86400.0);
466 0 : logIO_p << String(o) << LogIO::EXCEPTION;
467 : }
468 :
469 0 : MEpoch epoch(Quantity(vb.time()(row), "s"));
470 0 : if (!pointingToImage) {
471 0 : lastAntID_p = vb.antenna1()(row);
472 0 : MPosition pos = vb.subtableColumns().antenna().positionMeas()(lastAntID_p);
473 : //mFrame_p = MeasFrame(epoch, pos);
474 0 : (!mFrame_p.epoch()) ? mFrame_p.set(epoch) : mFrame_p.resetEpoch(epoch);
475 0 : (!mFrame_p.position()) ? mFrame_p.set(pos) : mFrame_p.resetPosition(pos);
476 0 : if (!nullPointingTable) {
477 0 : worldPosMeas = directionMeas(act_mspc, pointIndex);
478 : } else {
479 0 : worldPosMeas = vb.direction1()(row);
480 : }
481 :
482 : // Make a machine to convert from the worldPosMeas to the output
483 : // Direction Measure type for the relevant frame
484 0 : MDirection::Ref outRef(dc.directionType(), mFrame_p);
485 0 : pointingToImage = new MDirection::Convert(worldPosMeas, outRef);
486 0 : if (!pointingToImage) {
487 0 : logIO_p << "Cannot make direction conversion machine" << LogIO::EXCEPTION;
488 : }
489 :
490 : } else {
491 0 : mFrame_p.resetEpoch(epoch);
492 0 : if (lastAntID_p != vb.antenna1()(row)) {
493 0 : logIO_p << LogIO::DEBUGGING
494 : << "updating antenna position. MS ID " << msId_p
495 : << ", last antenna ID " << lastAntID_p
496 0 : << " new antenna ID " << vb.antenna1()(row) << LogIO::POST;
497 0 : lastAntID_p = vb.antenna1()(row);
498 0 : MPosition pos = vb.subtableColumns().antenna().positionMeas()(lastAntID_p);
499 0 : mFrame_p.resetPosition(pos);
500 : }
501 : }
502 :
503 0 : if (!nullPointingTable) {
504 0 : worldPosMeas = (*pointingToImage)(directionMeas(act_mspc, pointIndex));
505 : } else {
506 0 : worldPosMeas = (*pointingToImage)(vb.direction1()(row));
507 : }
508 0 : delete pointingToImage;
509 0 : pointingToImage = 0;
510 : }
511 :
512 0 : directionCoord = coords.directionCoordinate(directionIndex);
513 : //make sure we use the same units
514 0 : worldPosMeas.set(dc.worldAxisUnits()(0));
515 :
516 : // Reference pixel may be modified in dc.setReferenceValue when
517 : // projection type is SFL. To take into account this effect,
518 : // keep original reference pixel here and subtract it from
519 : // the reference pixel after dc.setReferenceValue instead
520 : // of setting reference pixel to (0,0).
521 0 : Vector<Double> const originalReferencePixel = dc.referencePixel();
522 0 : dc.setReferenceValue(worldPosMeas.getAngle().getValue());
523 : //Vector<Double> unitVec(2);
524 : //unitVec=0.0;
525 : //dc.setReferencePixel(unitVec);
526 0 : Vector<Double> updatedReferencePixel = dc.referencePixel() - originalReferencePixel;
527 0 : dc.setReferencePixel(updatedReferencePixel);
528 :
529 0 : coords.replaceCoordinate(dc, directionIndex);
530 :
531 0 : IPosition pbShape(4, convSize, 2, 1, 1);
532 0 : IPosition start(4, 0, 0, 0, 0);
533 :
534 0 : TempImage<Complex> onedPB(pbShape, coords);
535 :
536 0 : onedPB.set(Complex(1.0, 0.0));
537 :
538 0 : AlwaysAssert(sj_p, AipsError);
539 0 : sj_p->apply(onedPB, onedPB, vb, 0);
540 :
541 0 : IPosition pbSlice(4, convSize, 1, 1, 1);
542 0 : Vector<Float> tempConvFunc=real(onedPB.getSlice(start, pbSlice, true));
543 : // Find number of significant points
544 0 : uInt cfLen=0;
545 0 : for(uInt i=0;i<tempConvFunc.nelements();++i) {
546 0 : if(tempConvFunc(i)<1e-3) break;
547 0 : ++cfLen;
548 : }
549 0 : if(cfLen<1) {
550 : logIO() << LogIO::SEVERE
551 : << "Possible problem in primary beam calculation: no points in gridding function"
552 0 : << " - no points to be gridded on this image?" << LogIO::POST;
553 0 : cfLen=1;
554 : }
555 0 : Vector<Float> trimConvFunc=tempConvFunc(Slice(0,cfLen-1,1));
556 :
557 : // Now fill in the convolution function vector
558 0 : convSupport=cfLen/convSampling;
559 0 : convSize=convSampling*(2*convSupport+2);
560 0 : convFunc.resize(convSize);
561 0 : convFunc=0.0;
562 0 : convFunc(Slice(0,cfLen-1,1))=trimConvFunc(Slice(0,cfLen-1,1));
563 :
564 :
565 0 : }
566 :
567 : // Initialize for a transform from the Sky domain. This means that
568 : // we grid-correct, and FFT the image
569 0 : void SDGrid::initializeToVis(ImageInterface<Complex>& iimage,
570 : const vi::VisBuffer2& vb)
571 : {
572 0 : image=&iimage;
573 :
574 0 : ok();
575 :
576 0 : init();
577 :
578 0 : if(convType=="pb") {
579 0 : findPBAsConvFunction(*image, vb);
580 : }
581 :
582 : // reset msId_p and lastAntID_p to -1
583 : // this is to ensure correct antenna position in getXYPos
584 0 : msId_p = -1;
585 0 : lastAntID_p = -1;
586 :
587 : // Initialize the maps for polarization and channel. These maps
588 : // translate visibility indices into image indices
589 0 : initMaps(vb);
590 :
591 : // First get the CoordinateSystem for the image and then find
592 : // the DirectionCoordinate
593 0 : CoordinateSystem coords=image->coordinates();
594 0 : Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
595 0 : AlwaysAssert(directionIndex>=0, AipsError);
596 0 : directionCoord=coords.directionCoordinate(directionIndex);
597 : /*if((image->shape().product())>cachesize) {
598 : isTiled=true;
599 : }
600 : else {
601 : isTiled=false;
602 : }*/
603 0 : isTiled=false;
604 0 : nx = image->shape()(0);
605 0 : ny = image->shape()(1);
606 0 : npol = image->shape()(2);
607 0 : nchan = image->shape()(3);
608 :
609 : // If we are memory-based then read the image in and create an
610 : // ArrayLattice otherwise just use the PagedImage
611 : /*if(isTiled) {
612 : lattice=image;
613 : wLattice=wImage;
614 : }
615 : else*/
616 : {
617 : // Make the grid the correct shape and turn it into an array lattice
618 0 : IPosition gridShape(4, nx, ny, npol, nchan);
619 0 : griddedData.resize(gridShape);
620 0 : griddedData = Complex(0.0);
621 :
622 0 : wGriddedData.resize(gridShape);
623 0 : wGriddedData = 0.0;
624 :
625 0 : if(arrayLattice) delete arrayLattice; arrayLattice=0;
626 0 : arrayLattice = new ArrayLattice<Complex>(griddedData);
627 :
628 0 : if(wArrayLattice) delete wArrayLattice; wArrayLattice=0;
629 0 : wArrayLattice = new ArrayLattice<Float>(wGriddedData);
630 0 : wArrayLattice->set(0.0);
631 0 : wLattice=wArrayLattice;
632 :
633 : // Now find the SubLattice corresponding to the image
634 0 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2, (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
635 0 : IPosition stride(4, 1);
636 0 : IPosition trc(blc+image->shape()-stride);
637 0 : LCBox gridBox(blc, trc, gridShape);
638 0 : SubLattice<Complex> gridSub(*arrayLattice, gridBox, true);
639 :
640 : // Do the copy
641 0 : gridSub.copyData(*image);
642 :
643 0 : lattice=arrayLattice;
644 : }
645 0 : AlwaysAssert(lattice, AipsError);
646 0 : AlwaysAssert(wLattice, AipsError);
647 0 : }
648 :
649 0 : void SDGrid::finalizeToVis()
650 : {
651 : /*if(isTiled) {
652 :
653 : logIO() << LogOrigin("SDGrid", "finalizeToVis") << LogIO::NORMAL;
654 :
655 : AlwaysAssert(imageCache, AipsError);
656 : AlwaysAssert(image, AipsError);
657 : ostringstream o;
658 : imageCache->flush();
659 : imageCache->showCacheStatistics(o);
660 : logIO() << o.str() << LogIO::POST;
661 : }*/
662 0 : if(pointingToImage) delete pointingToImage; pointingToImage=0;
663 0 : }
664 :
665 :
666 : // Initialize the FFT to the Sky. Here we have to setup and initialize the
667 : // grid.
668 0 : void SDGrid::initializeToSky(ImageInterface<Complex>& iimage,
669 : Matrix<Float>& weight, const vi::VisBuffer2& vb)
670 : {
671 : // image always points to the image
672 0 : image=&iimage;
673 :
674 0 : ok();
675 :
676 0 : init();
677 :
678 0 : if(convType=="pb") {
679 0 : findPBAsConvFunction(*image, vb);
680 : }
681 :
682 : // reset msId_p and lastAntID_p to -1
683 : // this is to ensure correct antenna position in getXYPos
684 0 : msId_p = -1;
685 0 : lastAntID_p = -1;
686 :
687 : // Initialize the maps for polarization and channel. These maps
688 : // translate visibility indices into image indices
689 0 : initMaps(vb);
690 : //cerr << "ToSky cachesize " << cachesize << " im shape " << (image->shape().product()) << endl;
691 : /*if((image->shape().product())>cachesize) {
692 : isTiled=true;
693 : }
694 : else {
695 : isTiled=false;
696 : }
697 : */
698 : //////////////No longer using isTiled
699 0 : isTiled=false;
700 0 : nx = image->shape()(0);
701 0 : ny = image->shape()(1);
702 0 : npol = image->shape()(2);
703 0 : nchan = image->shape()(3);
704 :
705 0 : sumWeight=0.0;
706 0 : weight.resize(sumWeight.shape());
707 0 : weight=0.0;
708 :
709 : // First get the CoordinateSystem for the image and then find
710 : // the DirectionCoordinate
711 0 : CoordinateSystem coords=image->coordinates();
712 0 : Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
713 0 : AlwaysAssert(directionIndex>=0, AipsError);
714 0 : directionCoord=coords.directionCoordinate(directionIndex);
715 :
716 : // Initialize for in memory or to disk gridding. lattice will
717 : // point to the appropriate Lattice, either the ArrayLattice for
718 : // in memory gridding or to the image for to disk gridding.
719 : /*if(isTiled) {
720 : imageCache->flush();
721 : image->set(Complex(0.0));
722 : lattice=image;
723 : wLattice=wImage;
724 : }
725 : else*/
726 : {
727 0 : IPosition gridShape(4, nx, ny, npol, nchan);
728 0 : logIO() << LogOrigin("SDGrid", "initializeToSky", WHERE) << LogIO::DEBUGGING
729 0 : << "gridShape = " << gridShape << LogIO::POST;
730 0 : griddedData.resize(gridShape);
731 0 : griddedData=Complex(0.0);
732 0 : if(arrayLattice) delete arrayLattice; arrayLattice=0;
733 0 : arrayLattice = new ArrayLattice<Complex>(griddedData);
734 0 : lattice=arrayLattice;
735 0 : wGriddedData.resize(gridShape);
736 0 : wGriddedData=0.0;
737 0 : if(wArrayLattice) delete wArrayLattice; wArrayLattice=0;
738 0 : wArrayLattice = new ArrayLattice<Float>(wGriddedData);
739 0 : wLattice=wArrayLattice;
740 :
741 : // clipping related stuff
742 0 : if (clipminmax_) {
743 0 : gmin_.resize(gridShape);
744 0 : gmin_ = Complex(FLT_MAX);
745 0 : gmax_.resize(gridShape);
746 0 : gmax_ = Complex(-FLT_MAX);
747 0 : wmin_.resize(gridShape);
748 0 : wmin_ = 0.0f;
749 0 : wmax_.resize(gridShape);
750 0 : wmax_ = 0.0f;
751 0 : npoints_.resize(gridShape);
752 0 : npoints_ = 0;
753 : }
754 : }
755 0 : AlwaysAssert(lattice, AipsError);
756 0 : AlwaysAssert(wLattice, AipsError);
757 0 : }
758 :
759 0 : void SDGrid::finalizeToSky()
760 : {
761 :
762 : // Now we flush the cache and report statistics
763 : // For memory based, we don't write anything out yet.
764 : /*if(isTiled) {
765 : logIO() << LogOrigin("SDGrid", "finalizeToSky") << LogIO::NORMAL;
766 :
767 : AlwaysAssert(image, AipsError);
768 : AlwaysAssert(imageCache, AipsError);
769 : imageCache->flush();
770 : ostringstream o;
771 : imageCache->showCacheStatistics(o);
772 : logIO() << o.str() << LogIO::POST;
773 : }
774 : */
775 :
776 0 : if(pointingToImage) delete pointingToImage; pointingToImage=0;
777 0 : }
778 :
779 0 : Array<Complex>* SDGrid::getDataPointer(const IPosition& centerLoc2D,
780 : Bool readonly) {
781 : Array<Complex>* result;
782 : // Is tiled: get tiles and set up offsets
783 0 : centerLoc(0)=centerLoc2D(0);
784 0 : centerLoc(1)=centerLoc2D(1);
785 0 : result=&imageCache->tile(offsetLoc, centerLoc, readonly);
786 0 : return result;
787 : }
788 0 : Array<Float>* SDGrid::getWDataPointer(const IPosition& centerLoc2D,
789 : Bool readonly) {
790 : Array<Float>* result;
791 : // Is tiled: get tiles and set up offsets
792 0 : centerLoc(0)=centerLoc2D(0);
793 0 : centerLoc(1)=centerLoc2D(1);
794 0 : result=&wImageCache->tile(offsetLoc, centerLoc, readonly);
795 0 : return result;
796 : }
797 :
798 : #define NEED_UNDERSCORES
799 : #if defined(NEED_UNDERSCORES)
800 : #define ggridsd ggridsd_
801 : #define dgridsd dgridsd_
802 : #define ggridsdclip ggridsdclip_
803 : #endif
804 :
805 : extern "C" {
806 : void ggridsd(Double*,
807 : const Complex*,
808 : Int*,
809 : Int*,
810 : Int*,
811 : const Int*,
812 : const Int*,
813 : const Float*,
814 : Int*,
815 : Int*,
816 : Complex*,
817 : Float*,
818 : Int*,
819 : Int*,
820 : Int *,
821 : Int *,
822 : Int*,
823 : Int*,
824 : Float*,
825 : Int*,
826 : Int*,
827 : Double*);
828 : void ggridsdclip(Double*,
829 : const Complex*,
830 : Int*,
831 : Int*,
832 : Int*,
833 : const Int*,
834 : const Int*,
835 : const Float*,
836 : Int*,
837 : Int*,
838 : Complex*,
839 : Float*,
840 : Int*,
841 : Complex*,
842 : Float*,
843 : Complex*,
844 : Float*,
845 : Int*,
846 : Int*,
847 : Int *,
848 : Int *,
849 : Int*,
850 : Int*,
851 : Float*,
852 : Int*,
853 : Int*,
854 : Double*);
855 : void dgridsd(Double*,
856 : Complex*,
857 : Int*,
858 : Int*,
859 : const Int*,
860 : const Int*,
861 : Int*,
862 : Int*,
863 : const Complex*,
864 : Int*,
865 : Int*,
866 : Int *,
867 : Int *,
868 : Int*,
869 : Int*,
870 : Float*,
871 : Int*,
872 : Int*);
873 : }
874 :
875 0 : void SDGrid::put(const vi::VisBuffer2& vb, Int row, Bool dopsf,
876 : FTMachine::Type type)
877 : {
878 0 : LogIO os(LogOrigin("SDGrid", "put"));
879 :
880 0 : gridOk(convSupport);
881 :
882 : // There is no channel mapping cache in VI/VB2 version of FTMachine
883 : // Perform matchChannel everytime
884 0 : matchChannel(vb);
885 :
886 : //No point in reading data if its not matching in frequency
887 0 : if(max(chanMap)==-1)
888 0 : return;
889 :
890 0 : Matrix<Float> imagingweight;
891 : //imagingweight=&(vb.imagingWeight());
892 0 : pickWeights(vb, imagingweight);
893 :
894 0 : if(type==FTMachine::PSF || type==FTMachine::COVERAGE)
895 0 : dopsf=true;
896 0 : if(dopsf) type=FTMachine::PSF;
897 0 : Cube<Complex> data;
898 : //Fortran gridder need the flag as ints
899 0 : Cube<Int> flags;
900 0 : Matrix<Float> elWeight;
901 0 : interpolateFrequencyTogrid(vb, imagingweight,data, flags, elWeight, type);
902 : //cerr << "number of rows " << vb.nRow() << " data shape " << data.shape() << endl;
903 : Bool iswgtCopy;
904 : const Float *wgtStorage;
905 0 : wgtStorage=elWeight.getStorage(iswgtCopy);
906 : Bool isCopy;
907 0 : const Complex *datStorage=0;
908 0 : if(!dopsf)
909 0 : datStorage=data.getStorage(isCopy);
910 :
911 : // If row is -1 then we pass through all rows
912 : Int startRow, endRow, nRow;
913 0 : if (row==-1) {
914 0 : nRow=vb.nRows();
915 0 : startRow=0;
916 0 : endRow=nRow-1;
917 : } else {
918 0 : nRow=1;
919 0 : startRow=row;
920 0 : endRow=row;
921 : }
922 :
923 :
924 0 : Vector<Int> rowFlags(vb.flagRow().nelements());
925 0 : rowFlags=0;
926 0 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
927 0 : if(vb.flagRow()(rownr)) rowFlags(rownr)=1;
928 : }
929 :
930 : // Take care of translation of Bools to Integer
931 0 : Int idopsf=0;
932 0 : if(dopsf) idopsf=1;
933 :
934 : /*if(isTiled) {
935 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
936 :
937 : if(getXYPos(vb, rownr)) {
938 :
939 : IPosition centerLoc2D(2, Int(xyPos(0)), Int(xyPos(1)));
940 : Array<Complex>* dataPtr=getDataPointer(centerLoc2D, false);
941 : Array<Float>* wDataPtr=getWDataPointer(centerLoc2D, false);
942 : Int aNx=dataPtr->shape()(0);
943 : Int aNy=dataPtr->shape()(1);
944 : Vector<Double> actualPos(2);
945 : for (Int i=0;i<2;i++) {
946 : actualPos(i)=xyPos(i)-Double(offsetLoc(i));
947 : }
948 : // Now use FORTRAN to do the gridding. Remember to
949 : // ensure that the shape and offsets of the tile are
950 : // accounted for.
951 : {
952 : Bool del;
953 : // IPosition s(data.shape());
954 : const IPosition& fs=flags.shape();
955 : std::vector<Int> s(fs.begin(), fs.end());
956 :
957 : ggridsd(actualPos.getStorage(del),
958 : datStorage,
959 : &s[0],
960 : &s[1],
961 : &idopsf,
962 : flags.getStorage(del),
963 : rowFlags.getStorage(del),
964 : wgtStorage,
965 : &s[2],
966 : &rownr,
967 : dataPtr->getStorage(del),
968 : wDataPtr->getStorage(del),
969 : &aNx,
970 : &aNy,
971 : &npol,
972 : &nchan,
973 : &convSupport,
974 : &convSampling,
975 : convFunc.getStorage(del),
976 : chanMap.getStorage(del),
977 : polMap.getStorage(del),
978 : sumWeight.getStorage(del));
979 : }
980 : }
981 : }
982 : }
983 : else*/
984 : {
985 0 : Matrix<Double> xyPositions(2, endRow-startRow+1);
986 0 : xyPositions=-1e9; // make sure failed getXYPos does not fall on grid
987 0 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
988 0 : if(getXYPos(vb, rownr)) {
989 0 : xyPositions(0, rownr)=xyPos(0);
990 0 : xyPositions(1, rownr)=xyPos(1);
991 : }
992 : }
993 : {
994 : Bool del;
995 : // IPosition s(data.shape());
996 0 : const IPosition& fs=flags.shape();
997 0 : std::vector<Int> s(fs.begin(), fs.end());
998 : Bool datCopy, wgtCopy;
999 0 : Complex * datStor=griddedData.getStorage(datCopy);
1000 0 : Float * wgtStor=wGriddedData.getStorage(wgtCopy);
1001 :
1002 : //Bool call_ggridsd = !clipminmax_ || dopsf;
1003 0 : Bool call_ggridsd = !clipminmax_;
1004 :
1005 0 : if (call_ggridsd) {
1006 :
1007 0 : ggridsd(xyPositions.getStorage(del),
1008 : datStorage,
1009 0 : &s[0],
1010 0 : &s[1],
1011 : &idopsf,
1012 0 : flags.getStorage(del),
1013 0 : rowFlags.getStorage(del),
1014 : wgtStorage,
1015 0 : &s[2],
1016 : &row,
1017 : datStor,
1018 : wgtStor,
1019 : &nx,
1020 : &ny,
1021 : &npol,
1022 : &nchan,
1023 : &convSupport,
1024 : &convSampling,
1025 : convFunc.getStorage(del),
1026 : chanMap.getStorage(del),
1027 : polMap.getStorage(del),
1028 : sumWeight.getStorage(del));
1029 :
1030 : } else {
1031 : Bool gminCopy;
1032 0 : Complex *gminStor = gmin_.getStorage(gminCopy);
1033 : Bool gmaxCopy;
1034 0 : Complex *gmaxStor = gmax_.getStorage(gmaxCopy);
1035 : Bool wminCopy;
1036 0 : Float *wminStor = wmin_.getStorage(wminCopy);
1037 : Bool wmaxCopy;
1038 0 : Float *wmaxStor = wmax_.getStorage(wmaxCopy);
1039 : Bool npCopy;
1040 0 : Int *npStor = npoints_.getStorage(npCopy);
1041 :
1042 0 : ggridsdclip(xyPositions.getStorage(del),
1043 : datStorage,
1044 0 : &s[0],
1045 0 : &s[1],
1046 : &idopsf,
1047 0 : flags.getStorage(del),
1048 0 : rowFlags.getStorage(del),
1049 : wgtStorage,
1050 0 : &s[2],
1051 : &row,
1052 : datStor,
1053 : wgtStor,
1054 : npStor,
1055 : gminStor,
1056 : wminStor,
1057 : gmaxStor,
1058 : wmaxStor,
1059 : &nx,
1060 : &ny,
1061 : &npol,
1062 : &nchan,
1063 : &convSupport,
1064 : &convSampling,
1065 : convFunc.getStorage(del),
1066 : chanMap.getStorage(del),
1067 : polMap.getStorage(del),
1068 : sumWeight.getStorage(del));
1069 :
1070 0 : gmin_.putStorage(gminStor, gminCopy);
1071 0 : gmax_.putStorage(gmaxStor, gmaxCopy);
1072 0 : wmin_.putStorage(wminStor, wminCopy);
1073 0 : wmax_.putStorage(wmaxStor, wmaxCopy);
1074 0 : npoints_.putStorage(npStor, npCopy);
1075 : }
1076 0 : griddedData.putStorage(datStor, datCopy);
1077 0 : wGriddedData.putStorage(wgtStor, wgtCopy);
1078 : }
1079 : }
1080 0 : if(!dopsf)
1081 0 : data.freeStorage(datStorage, isCopy);
1082 0 : elWeight.freeStorage(wgtStorage,iswgtCopy);
1083 :
1084 : }
1085 :
1086 0 : void SDGrid::get(vi::VisBuffer2& vb, Int row)
1087 : {
1088 0 : LogIO os(LogOrigin("SDGrid", "get"));
1089 :
1090 0 : gridOk(convSupport);
1091 :
1092 : // If row is -1 then we pass through all rows
1093 : Int startRow, endRow, nRow;
1094 0 : if (row==-1) {
1095 0 : nRow=vb.nRows();
1096 0 : startRow=0;
1097 0 : endRow=nRow-1;
1098 : // TODO: ask imager guru if commenting out the following line
1099 : // is safe for SDGrid
1100 : //unnecessary zeroing
1101 : //vb.modelVisCube()=Complex(0.0,0.0);
1102 : } else {
1103 0 : nRow=1;
1104 0 : startRow=row;
1105 0 : endRow=row;
1106 : // TODO: ask imager guru if commenting out the following line
1107 : // is safe for SDGrid
1108 : //unnecessary zeroing
1109 : //vb.modelVisCube().xyPlane(row)=Complex(0.0,0.0);
1110 : }
1111 :
1112 : // There is no channel mapping cache in VI/VB2 version of FTMachine
1113 : // Perform matchChannel everytime
1114 0 : matchChannel(vb);
1115 :
1116 : //No point in reading data if its not matching in frequency
1117 0 : if(max(chanMap)==-1)
1118 0 : return;
1119 0 : Cube<Complex> data;
1120 0 : Cube<Int> flags;
1121 0 : getInterpolateArrays(vb, data, flags);
1122 :
1123 : Complex *datStorage;
1124 : Bool isCopy;
1125 0 : datStorage=data.getStorage(isCopy);
1126 : // NOTE: with MS V2.0 the pointing could change per antenna and timeslot
1127 : //
1128 0 : Vector<Int> rowFlags(vb.flagRow().nelements());
1129 0 : rowFlags=0;
1130 0 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
1131 0 : if(vb.flagRow()(rownr)) rowFlags(rownr)=1;
1132 : //single dish yes ?
1133 0 : if(max(vb.uvw().column(rownr)) > 0.0) rowFlags(rownr)=1;
1134 : }
1135 :
1136 :
1137 : /*if(isTiled) {
1138 :
1139 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
1140 :
1141 : if(getXYPos(vb, rownr)) {
1142 :
1143 : // Get the tile
1144 : IPosition centerLoc2D(2, Int(xyPos(0)), Int(xyPos(1)));
1145 : Array<Complex>* dataPtr=getDataPointer(centerLoc2D, true);
1146 : Int aNx=dataPtr->shape()(0);
1147 : Int aNy=dataPtr->shape()(1);
1148 :
1149 : // Now use FORTRAN to do the gridding. Remember to
1150 : // ensure that the shape and offsets of the tile are
1151 : // accounted for.
1152 : Bool del;
1153 : Vector<Double> actualPos(2);
1154 : for (Int i=0;i<2;i++) {
1155 : actualPos(i)=xyPos(i)-Double(offsetLoc(i));
1156 : }
1157 : // IPosition s(data.shape());
1158 : const IPosition& fs=data.shape();
1159 : std::vector<Int> s(fs.begin(), fs.end());
1160 :
1161 : dgridsd(actualPos.getStorage(del),
1162 : datStorage,
1163 : &s[0],
1164 : &s[1],
1165 : flags.getStorage(del),
1166 : rowFlags.getStorage(del),
1167 : &s[2],
1168 : &rownr,
1169 : dataPtr->getStorage(del),
1170 : &aNx,
1171 : &aNy,
1172 : &npol,
1173 : &nchan,
1174 : &convSupport,
1175 : &convSampling,
1176 : convFunc.getStorage(del),
1177 : chanMap.getStorage(del),
1178 : polMap.getStorage(del));
1179 : }
1180 : }
1181 : }
1182 : else*/
1183 : {
1184 0 : Matrix<Double> xyPositions(2, endRow-startRow+1);
1185 0 : xyPositions=-1e9;
1186 0 : for (Int rownr=startRow; rownr<=endRow; rownr++) {
1187 0 : if(getXYPos(vb, rownr)) {
1188 0 : xyPositions(0, rownr)=xyPos(0);
1189 0 : xyPositions(1, rownr)=xyPos(1);
1190 : }
1191 : }
1192 :
1193 : Bool del;
1194 : // IPosition s(data.shape());
1195 0 : const IPosition& fs=data.shape();
1196 0 : std::vector<Int> s(fs.begin(), fs.end());
1197 0 : dgridsd(xyPositions.getStorage(del),
1198 : datStorage,
1199 0 : &s[0],
1200 0 : &s[1],
1201 0 : flags.getStorage(del),
1202 0 : rowFlags.getStorage(del),
1203 0 : &s[2],
1204 : &row,
1205 0 : griddedData.getStorage(del),
1206 : &nx,
1207 : &ny,
1208 : &npol,
1209 : &nchan,
1210 : &convSupport,
1211 : &convSampling,
1212 : convFunc.getStorage(del),
1213 : chanMap.getStorage(del),
1214 : polMap.getStorage(del));
1215 :
1216 0 : data.putStorage(datStorage, isCopy);
1217 : }
1218 0 : interpolateFrequencyFromgrid(vb, data, FTMachine::MODEL);
1219 : }
1220 :
1221 :
1222 :
1223 : // Make a plain straightforward honest-to-FSM image. This returns
1224 : // a complex image, without conversion to Stokes. The representation
1225 : // is that required for the visibilities.
1226 : //----------------------------------------------------------------------
1227 0 : void SDGrid::makeImage(FTMachine::Type type,
1228 : vi::VisibilityIterator2& vi,
1229 : ImageInterface<Complex>& theImage,
1230 : Matrix<Float>& weight) {
1231 :
1232 :
1233 0 : logIO() << LogOrigin("FTMachine", "makeImage0") << LogIO::NORMAL;
1234 :
1235 : // Loop over all visibilities and pixels
1236 0 : vi::VisBuffer2 *vb = vi.getVisBuffer();
1237 :
1238 : // Initialize put (i.e. transform to Sky) for this model
1239 0 : vi.origin();
1240 :
1241 0 : if(vb->polarizationFrame()==MSIter::Linear) {
1242 0 : StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::LINEAR);
1243 : }
1244 : else {
1245 0 : StokesImageUtil::changeCStokesRep(theImage, StokesImageUtil::CIRCULAR);
1246 : }
1247 0 : Bool useCorrected= !(MSMainColumns(vi.ms()).correctedData().isNull());
1248 0 : if((type==FTMachine::CORRECTED) && (!useCorrected))
1249 0 : type=FTMachine::OBSERVED;
1250 0 : Bool normalize=true;
1251 0 : if(type==FTMachine::COVERAGE)
1252 0 : normalize=false;
1253 :
1254 0 : Int Nx=theImage.shape()(0);
1255 0 : Int Ny=theImage.shape()(1);
1256 0 : Int Npol=theImage.shape()(2);
1257 0 : Int Nchan=theImage.shape()(3);
1258 0 : Double memtot=Double(HostInfo::memoryTotal(true))*1024.0; // return in kB
1259 0 : Int nchanInMem=Int(memtot/2.0/8.0/Double(Nx*Ny*Npol));
1260 0 : Int nloop=nchanInMem >= Nchan ? 1 : Nchan/nchanInMem+1;
1261 0 : ImageInterface<Complex> *imCopy=NULL;
1262 0 : IPosition blc(theImage.shape());
1263 0 : IPosition trc(theImage.shape());
1264 0 : blc-=blc; //set all values to 0
1265 0 : trc=theImage.shape();
1266 0 : trc-=1; // set trc to image size -1
1267 0 : if(nloop==1) {
1268 0 : imCopy=& theImage;
1269 0 : nchanInMem=Nchan;
1270 : }
1271 : else
1272 : logIO() << "Not enough memory to image in one go \n will process the image in "
1273 : << nloop
1274 : << " sections "
1275 0 : << LogIO::POST;
1276 :
1277 0 : weight.resize(Npol, Nchan);
1278 0 : Matrix<Float> wgtcopy(Npol, Nchan);
1279 :
1280 0 : Bool isWgtZero=true;
1281 0 : for (Int k=0; k < nloop; ++k){
1282 0 : Int bchan=k*nchanInMem;
1283 0 : Int echan=(k+1)*nchanInMem < Nchan ? (k+1)*nchanInMem-1 : Nchan-1;
1284 :
1285 0 : if(nloop > 1) {
1286 0 : blc[3]=bchan;
1287 0 : trc[3]=echan;
1288 0 : Slicer sl(blc, trc, Slicer::endIsLast);
1289 0 : imCopy=new SubImage<Complex>(theImage, sl, true);
1290 0 : wgtcopy.resize(npol, echan-bchan+1);
1291 : }
1292 0 : vi.originChunks();
1293 0 : vi.origin();
1294 0 : initializeToSky(*imCopy,wgtcopy,*vb);
1295 :
1296 :
1297 : // for minmax clipping
1298 0 : logIO() << LogOrigin("SDGrid", "makeImage", WHERE) << LogIO::DEBUGGING
1299 0 : << "doclip_ = " << (clipminmax_ ? "TRUE" : "FALSE") << " (" << clipminmax_ << ")" << LogIO::POST;
1300 0 : if (clipminmax_) {
1301 0 : logIO() << LogOrigin("SDGRID", "makeImage", WHERE)
1302 0 : << LogIO::DEBUGGING << "use ggridsd2 for imaging" << LogIO::POST;
1303 : }
1304 :
1305 : // Loop over the visibilities, putting VisBuffers
1306 0 : for (vi.originChunks();vi.moreChunks();vi.nextChunk()) {
1307 0 : for (vi.origin(); vi.more(); vi.next()) {
1308 :
1309 0 : switch(type) {
1310 0 : case FTMachine::RESIDUAL:
1311 0 : vb->setVisCube(vb->visCubeCorrected() - vb->visCubeModel());
1312 0 : put(*vb, -1, false);
1313 0 : break;
1314 0 : case FTMachine::MODEL:
1315 0 : put(*vb, -1, false, FTMachine::MODEL);
1316 0 : break;
1317 0 : case FTMachine::CORRECTED:
1318 0 : put(*vb, -1, false, FTMachine::CORRECTED);
1319 0 : break;
1320 0 : case FTMachine::PSF:
1321 0 : vb->setVisCube(Complex(1.0,0.0));
1322 0 : put(*vb, -1, true, FTMachine::PSF);
1323 0 : break;
1324 0 : case FTMachine::COVERAGE:
1325 0 : vb->setVisCube(Complex(1.0));
1326 0 : put(*vb, -1, true, FTMachine::COVERAGE);
1327 0 : break;
1328 0 : case FTMachine::OBSERVED:
1329 : default:
1330 0 : put(*vb, -1, false, FTMachine::OBSERVED);
1331 0 : break;
1332 : }
1333 : }
1334 : }
1335 0 : finalizeToSky();
1336 : // Normalize by dividing out weights, etc.
1337 0 : getImage(wgtcopy, normalize);
1338 0 : if(max(wgtcopy)==0.0){
1339 0 : if(nloop > 1)
1340 : logIO() << LogIO::WARN
1341 : << "No useful data in SDGrid: weights all zero for image slice " << k
1342 0 : << LogIO::POST;
1343 : }
1344 : else
1345 0 : isWgtZero=false;
1346 :
1347 0 : weight(Slice(0, Npol), Slice(bchan, echan-bchan+1))=wgtcopy;
1348 0 : if(nloop >1) delete imCopy;
1349 : }//loop k
1350 0 : if(isWgtZero)
1351 : logIO() << LogIO::SEVERE
1352 : << "No useful data in SDGrid: weights all zero"
1353 0 : << LogIO::POST;
1354 0 : }
1355 :
1356 :
1357 :
1358 : // Finalize : optionally normalize by weight image
1359 0 : ImageInterface<Complex>& SDGrid::getImage(Matrix<Float>& weights,
1360 : Bool normalize)
1361 : {
1362 0 : AlwaysAssert(lattice, AipsError);
1363 0 : AlwaysAssert(image, AipsError);
1364 :
1365 0 : logIO() << LogOrigin("SDGrid", "getImage") << LogIO::NORMAL;
1366 :
1367 : // execute minmax clipping
1368 0 : clipMinMax();
1369 :
1370 0 : weights.resize(sumWeight.shape());
1371 :
1372 0 : convertArray(weights,sumWeight);
1373 :
1374 : // If the weights are all zero then we cannot normalize
1375 : // otherwise we don't care.
1376 : ///////////////////////
1377 : /*{
1378 : PagedImage<Float> thisScreen(lattice->shape(), image->coordinates(), "TheData");
1379 : LatticeExpr<Float> le(abs(*lattice));
1380 : thisScreen.copyData(le);
1381 : PagedImage<Float> thisScreen2(lattice->shape(), image->coordinates(), "TheWeight");
1382 : LatticeExpr<Float> le2(abs(*wLattice));
1383 : thisScreen2.copyData(le2);
1384 : }*/
1385 : /////////////////////
1386 :
1387 0 : if(normalize) {
1388 0 : if(max(weights)==0.0) {
1389 : //logIO() << LogIO::WARN << "No useful data in SDGrid: weights all zero"
1390 : // << LogIO::POST;
1391 : //image->set(Complex(0.0));
1392 0 : return *image;
1393 : }
1394 : //Timer tim;
1395 : //tim.mark();
1396 : //lattice->copyData((LatticeExpr<Complex>)(iif((*wLattice<=minWeight_p), 0.0,
1397 : // (*lattice)/(*wLattice))));
1398 : //As we are not using disk based lattices anymore the above uses too much memory for
1399 : // ArrayLattice...it does not do a real inplace math but rather mutiple copies
1400 : // seem to be involved thus the less elegant but faster and less memory hog loop
1401 : // below.
1402 :
1403 0 : IPosition pos(4);
1404 0 : for (Int chan=0; chan < nchan; ++chan){
1405 0 : pos[3]=chan;
1406 0 : for( Int pol=0; pol < npol; ++ pol){
1407 0 : pos[2]=pol;
1408 0 : for (Int y=0; y < ny ; ++y){
1409 0 : pos[1]=y;
1410 0 : for (Int x=0; x < nx; ++x){
1411 0 : pos[0]=x;
1412 0 : Float wgt=wGriddedData(pos);
1413 0 : if(wgt > minWeight_p)
1414 0 : griddedData(pos)=griddedData(pos)/wgt;
1415 : else
1416 0 : griddedData(pos)=0.0;
1417 : }
1418 : }
1419 : }
1420 : }
1421 : //tim.show("After normalizing");
1422 : }
1423 :
1424 : //if(!isTiled)
1425 : {
1426 : // Now find the SubLattice corresponding to the image
1427 0 : IPosition gridShape(4, nx, ny, npol, nchan);
1428 0 : IPosition blc(4, (nx-image->shape()(0)+(nx%2==0))/2,
1429 0 : (ny-image->shape()(1)+(ny%2==0))/2, 0, 0);
1430 0 : IPosition stride(4, 1);
1431 0 : IPosition trc(blc+image->shape()-stride);
1432 0 : LCBox gridBox(blc, trc, gridShape);
1433 0 : SubLattice<Complex> gridSub(*arrayLattice, gridBox);
1434 :
1435 : // Do the copy
1436 0 : image->copyData(gridSub);
1437 : }
1438 :
1439 : // IMAGER MIGRATION
1440 : // set sumWeight to 1.0
1441 0 : weights = 1.0;
1442 :
1443 0 : return *image;
1444 : }
1445 :
1446 : // Return weights image
1447 0 : void SDGrid::getWeightImage(ImageInterface<Float>& weightImage, Matrix<Float>& weights)
1448 : {
1449 0 : AlwaysAssert(lattice, AipsError);
1450 0 : AlwaysAssert(image, AipsError);
1451 :
1452 0 : logIO() << LogOrigin("SDGrid", "getWeightImage") << LogIO::NORMAL;
1453 :
1454 0 : weights.resize(sumWeight.shape());
1455 : // IMAGER MIGRATION
1456 : // set sumWeight to 1.0
1457 0 : weights = 1.0;
1458 : // convertArray(weights,sumWeight);
1459 :
1460 0 : weightImage.copyData(*wArrayLattice);
1461 0 : }
1462 :
1463 0 : void SDGrid::ok() {
1464 0 : AlwaysAssert(image, AipsError);
1465 0 : }
1466 :
1467 : // Get the index into the pointing table for this time. Note that the
1468 : // in the pointing table, TIME specifies the beginning of the spanned
1469 : // time range, whereas for the main table, TIME is the centroid.
1470 : // Note that the behavior for multiple matches is not specified! i.e.
1471 : // if there are multiple matches, the index returned depends on the
1472 : // history of previous matches. It is deterministic but not obvious.
1473 : // One could cure this by searching but it would be considerably
1474 : // costlier.
1475 0 : Int SDGrid::getIndex(const MSPointingColumns& mspc, const Double& time,
1476 : const Double& interval, const Int& antid) {
1477 : //Int start=lastIndex_p;
1478 0 : Int start=lastIndexPerAnt_p[antid];
1479 0 : Double tol=interval < 0.0 ? time*C::dbl_epsilon : interval/2.0;
1480 : // Search forwards
1481 0 : Int nrows=mspc.time().nrow();
1482 0 : for (Int i=start;i<nrows;i++) {
1483 : // Check for ANTENNA_ID. When antid<0 (default) ANTENNA_ID in POINTING table < 0 is ignored.
1484 : // MS v2 definition indicates ANTENNA_ID in POINING >= 0.
1485 0 : if (antid >= 0 && mspc.antennaId()(i) != antid) {
1486 0 : continue;
1487 : }
1488 :
1489 0 : Double midpoint = mspc.time()(i); // time in POINTING table is midpoint
1490 : // If the interval in the pointing table is negative, use the last
1491 : // entry. Note that this may be invalid (-1) but in that case
1492 : // the calling routine will generate an error
1493 0 : Double mspc_interval = mspc.interval()(i);
1494 :
1495 0 : if(mspc_interval<0.0) {
1496 : //return lastIndex_p;
1497 0 : return lastIndexPerAnt_p[antid];
1498 : }
1499 : // Pointing table interval is specified so we have to do a match
1500 : else {
1501 : // Is the midpoint of this pointing table entry within the specified
1502 : // tolerance of the main table entry?
1503 0 : if(abs(midpoint-time) <= (mspc_interval/2.0+tol)) {
1504 : //lastIndex_p=i;
1505 0 : lastIndexPerAnt_p[antid]=i;
1506 0 : return i;
1507 : }
1508 : }
1509 : }
1510 : // Search backwards
1511 0 : for (Int i=start;i>=0;i--) {
1512 0 : if (antid >= 0 && mspc.antennaId()(i) != antid) {
1513 0 : continue;
1514 : }
1515 0 : Double midpoint = mspc.time()(i); // time in POINTING table is midpoint
1516 0 : Double mspc_interval = mspc.interval()(i);
1517 0 : if(mspc_interval<0.0) {
1518 : //return lastIndex_p;
1519 0 : return lastIndexPerAnt_p[antid];
1520 : }
1521 : // Pointing table interval is specified so we have to do a match
1522 : else {
1523 : // Is the midpoint of this pointing table entry within the specified
1524 : // tolerance of the main table entry?
1525 0 : if (abs(midpoint-time) <= (mspc_interval/2.0+tol)) {
1526 : //lastIndex_p=i;
1527 0 : lastIndexPerAnt_p[antid]=i;
1528 0 : return i;
1529 : }
1530 : }
1531 : }
1532 : // No match!
1533 0 : return -1;
1534 : }
1535 :
1536 0 : Bool SDGrid::getXYPos(const vi::VisBuffer2& vb, Int row) {
1537 :
1538 : Bool dointerp;
1539 0 : const MSPointingColumns& act_mspc = vb.subtableColumns().pointing();
1540 0 : Bool nullPointingTable = (act_mspc.nrow() < 1);
1541 0 : Int pointIndex = -1;
1542 0 : if (!nullPointingTable) {
1543 : ///if(vb.newMS()) vb.newMS does not work well using msid
1544 0 : if (vb.msId() != msId_p) {
1545 0 : lastIndex_p = 0;
1546 0 : if (lastIndexPerAnt_p.nelements() < (size_t)vb.nAntennas()) {
1547 0 : lastIndexPerAnt_p.resize(vb.nAntennas());
1548 : }
1549 0 : lastIndexPerAnt_p = 0;
1550 0 : msId_p = vb.msId();
1551 0 : lastAntID_p = -1;
1552 : }
1553 0 : pointIndex = getIndex(act_mspc, vb.time()(row), -1.0, vb.antenna1()(row));
1554 : //Try again to locate a pointing within the integration
1555 0 : if (pointIndex < 0)
1556 0 : pointIndex = getIndex(act_mspc, vb.time()(row), vb.timeInterval()(row), vb.antenna1()(row));
1557 : }
1558 0 : if (!nullPointingTable && ((pointIndex < 0) || (pointIndex >= Int(act_mspc.time().nrow())))) {
1559 0 : ostringstream o;
1560 0 : o << "Failed to find pointing information for time " <<
1561 0 : MVTime(vb.time()(row)/86400.0) << ": Omitting this point";
1562 0 : logIO_p << LogIO::DEBUGGING << String(o) << LogIO::POST;
1563 : // logIO_p << String(o) << LogIO::POST;
1564 0 : return false;
1565 : }
1566 :
1567 0 : dointerp = false;
1568 0 : if (!nullPointingTable && (vb.timeInterval()(row) < act_mspc.interval()(pointIndex))) {
1569 0 : dointerp = true;
1570 0 : if (!isSplineInterpolationReady) {
1571 0 : interpolator = new SDPosInterpolator(vb, pointingDirCol_p);
1572 0 : isSplineInterpolationReady = true;
1573 : } else {
1574 0 : if (!interpolator->inTimeRange(vb.time()(row), vb.antenna1()(row))) {
1575 : // setup spline interpolator for the current dataset (CAS-11261, 2018/6/13 WK)
1576 0 : delete interpolator;
1577 0 : interpolator = 0;
1578 0 : interpolator = new SDPosInterpolator(vb, pointingDirCol_p);
1579 : }
1580 : }
1581 : }
1582 :
1583 0 : if (!pointingToImage) {
1584 : // Set the frame
1585 0 : lastAntID_p = vb.antenna1()(row);
1586 0 : MPosition pos = vb.subtableColumns().antenna().positionMeas()(lastAntID_p);
1587 0 : MEpoch dummyEpoch(Quantity(0, "s"));
1588 0 : (!mFrame_p.epoch()) ? mFrame_p.set(dummyEpoch) : mFrame_p.resetEpoch(dummyEpoch);
1589 0 : (!mFrame_p.position()) ? mFrame_p.set(pos) : mFrame_p.resetPosition(pos);
1590 0 : if (!nullPointingTable) {
1591 0 : if (dointerp) {
1592 0 : worldPosMeas = directionMeas(act_mspc, pointIndex, vb.time()(row));
1593 : } else {
1594 0 : worldPosMeas = directionMeas(act_mspc, pointIndex);
1595 : }
1596 : } else {
1597 0 : worldPosMeas = vb.direction1()(row);
1598 : }
1599 :
1600 : // Make a machine to convert from the worldPosMeas to the output
1601 : // Direction Measure type for the relevant frame
1602 0 : MDirection::Ref outRef(directionCoord.directionType(), mFrame_p);
1603 0 : pointingToImage = new MDirection::Convert(worldPosMeas, outRef);
1604 0 : if (!pointingToImage) {
1605 0 : logIO_p << "Cannot make direction conversion machine" << LogIO::EXCEPTION;
1606 : }
1607 :
1608 : // perform direction conversion to clear cache
1609 0 : MDirection _dir_tmp = (*pointingToImage)();
1610 : }
1611 :
1612 0 : MEpoch epoch(Quantity(vb.time()(row), "s"));
1613 0 : mFrame_p.resetEpoch(epoch);
1614 0 : if (lastAntID_p != vb.antenna1()(row)) {
1615 0 : if (lastAntID_p == -1) {
1616 : // antenna ID is unset
1617 0 : logIO_p << LogIO::DEBUGGING
1618 : << "update antenna position for conversion: new MS ID " << msId_p
1619 0 : << ", antenna ID " << vb.antenna1()(row) << LogIO::POST;
1620 : } else {
1621 0 : logIO_p << LogIO::DEBUGGING
1622 : << "update antenna position for conversion: MS ID " << msId_p
1623 : << ", last antenna ID " << lastAntID_p
1624 0 : << ", new antenna ID " << vb.antenna1()(row) << LogIO::POST;
1625 : }
1626 0 : MPosition pos;
1627 0 : lastAntID_p = vb.antenna1()(row);
1628 0 : pos = vb.subtableColumns().antenna().positionMeas()(lastAntID_p);
1629 0 : mFrame_p.resetPosition(pos);
1630 : }
1631 :
1632 0 : if (!nullPointingTable) {
1633 0 : if (dointerp) {
1634 0 : MDirection newdir = directionMeas(act_mspc, pointIndex, vb.time()(row));
1635 : //Vector<Double> newdirv = newdir.getAngle("rad").getValue();
1636 0 : worldPosMeas = (*pointingToImage)(newdir);
1637 : //cerr<<"dir0="<<newdirv(0)<<endl;
1638 :
1639 : //fprintf(pfile,"%.8f %.8f \n", newdirv(0), newdirv(1));
1640 : //printf("%lf %lf \n", newdirv(0), newdirv(1));
1641 : } else {
1642 0 : worldPosMeas = (*pointingToImage)(directionMeas(act_mspc, pointIndex));
1643 : }
1644 : } else {
1645 0 : worldPosMeas = (*pointingToImage)(vb.direction1()(row));
1646 : }
1647 :
1648 0 : Bool result = directionCoord.toPixel(xyPos, worldPosMeas);
1649 0 : if (!result) {
1650 0 : logIO_p << "Failed to find a pixel for pointing direction of "
1651 0 : << MVTime(worldPosMeas.getValue().getLong("rad")).string(MVTime::TIME) << ", " << MVAngle(worldPosMeas.getValue().getLat("rad")).string(MVAngle::ANGLE) << LogIO::WARN << LogIO::POST;
1652 0 : return false;
1653 : }
1654 :
1655 0 : if ((pointingDirCol_p == "SOURCE_OFFSET") || (pointingDirCol_p == "POINTING_OFFSET")) {
1656 : //there is no sense to track in offset coordinates...hopefully the
1657 : //user set the image coords right
1658 0 : fixMovingSource_p = false;
1659 : }
1660 0 : if (fixMovingSource_p) {
1661 0 : if (xyPosMovingOrig_p.nelements() < 2) {
1662 0 : directionCoord.toPixel(xyPosMovingOrig_p, firstMovingDir_p);
1663 : }
1664 : //via HADEC or AZEL for parallax of near sources
1665 0 : MDirection::Ref outref1(MDirection::AZEL, mFrame_p);
1666 0 : MDirection tmphadec;
1667 0 : if (upcase(movingDir_p.getRefString()).contains("APP")) {
1668 0 : tmphadec = MDirection::Convert((vbutil_p->getEphemDir(vb, phaseCenterTime_p)), outref1)();
1669 0 : } else if (upcase(movingDir_p.getRefString()).contains("COMET")) {
1670 0 : MeasComet mcomet(Path(ephemTableName_p).absoluteName());
1671 0 : mFrame_p.set(mcomet);
1672 0 : tmphadec = MDirection::Convert(movingDir_p, outref1)();
1673 : } else {
1674 0 : tmphadec = MDirection::Convert(movingDir_p, outref1)();
1675 : }
1676 0 : MDirection actSourceDir = (*pointingToImage)(tmphadec);
1677 0 : Vector<Double> actPix;
1678 0 : directionCoord.toPixel(actPix, actSourceDir);
1679 :
1680 : //cout << row << " scan " << vb.scan()(row) << "xyPos " << xyPos << " xyposmovorig " << xyPosMovingOrig_p << " actPix " << actPix << endl;
1681 :
1682 0 : xyPos = xyPos + xyPosMovingOrig_p - actPix;
1683 : }
1684 :
1685 0 : return result;
1686 : // Convert to pixel coordinates
1687 : }
1688 :
1689 0 : MDirection SDGrid::directionMeas(const MSPointingColumns& mspc, const Int& index){
1690 0 : if (pointingDirCol_p == "TARGET") {
1691 0 : return mspc.targetMeas(index);
1692 0 : } else if (pointingDirCol_p == "POINTING_OFFSET") {
1693 0 : if (!mspc.pointingOffsetMeasCol().isNull()) {
1694 0 : return mspc.pointingOffsetMeas(index);
1695 : }
1696 0 : cerr << "No PONTING_OFFSET column in POINTING table" << endl;
1697 0 : } else if (pointingDirCol_p == "SOURCE_OFFSET") {
1698 0 : if (!mspc.sourceOffsetMeasCol().isNull()) {
1699 0 : return mspc.sourceOffsetMeas(index);
1700 : }
1701 0 : cerr << "No SOURCE_OFFSET column in POINTING table" << endl;
1702 0 : } else if (pointingDirCol_p == "ENCODER") {
1703 0 : if (!mspc.encoderMeas().isNull()) {
1704 0 : return mspc.encoderMeas()(index);
1705 : }
1706 0 : cerr << "No ENCODER column in POINTING table" << endl;
1707 : }
1708 :
1709 : //default return this
1710 0 : return mspc.directionMeas(index);
1711 : }
1712 :
1713 : // for the cases, interpolation of the pointing direction requires
1714 : // when data sampling rate higher than the pointing data recording
1715 : // (e.g. fast OTF)
1716 0 : MDirection SDGrid::directionMeas(const MSPointingColumns& mspc, const Int& index,
1717 : const Double& time){
1718 : //spline interpolation
1719 0 : if (isSplineInterpolationReady) {
1720 0 : Int antid = mspc.antennaId()(index);
1721 0 : if (interpolator->doSplineInterpolation(antid)) {
1722 0 : return interpolator->interpolateDirectionMeasSpline(mspc, time, index, antid);
1723 : }
1724 : }
1725 :
1726 : //linear interpolation (as done before CAS-7911)
1727 : Int index1, index2;
1728 0 : if (time < mspc.time()(index)) {
1729 0 : if (index > 0) {
1730 0 : index1 = index-1;
1731 0 : index2 = index;
1732 0 : } else if (index == 0) {
1733 0 : index1 = index;
1734 0 : index2 = index+1;
1735 : }
1736 : } else {
1737 0 : if (index < Int(mspc.nrow()-1)) {
1738 0 : index1 = index;
1739 0 : index2 = index+1;
1740 0 : } else if (index == Int(mspc.nrow()-1) || (mspc.time()(index)-mspc.time()(index+1))>2*mspc.interval()(index)) {
1741 0 : index1 = index-1;
1742 0 : index2 = index;
1743 : }
1744 : }
1745 0 : return interpolateDirectionMeas(mspc, time, index, index1, index2);
1746 : }
1747 :
1748 0 : MDirection SDGrid::interpolateDirectionMeas(const MSPointingColumns& mspc,
1749 : const Double& time,
1750 : const Int& index,
1751 : const Int& indx1,
1752 : const Int& indx2){
1753 0 : Vector<Double> dir1,dir2;
1754 0 : Vector<Double> newdir(2),scanRate(2);
1755 : Double dLon, dLat;
1756 : Double ftime,ftime2,ftime1,dtime;
1757 0 : MDirection newDirMeas;
1758 0 : MDirection::Ref rf;
1759 : Bool isfirstRefPt;
1760 :
1761 0 : if (indx1 == index) {
1762 0 : isfirstRefPt = true;
1763 : } else {
1764 0 : isfirstRefPt = false;
1765 : }
1766 :
1767 0 : if (pointingDirCol_p == "TARGET") {
1768 0 : dir1 = mspc.targetMeas(indx1).getAngle("rad").getValue();
1769 0 : dir2 = mspc.targetMeas(indx2).getAngle("rad").getValue();
1770 0 : } else if (pointingDirCol_p == "POINTING_OFFSET") {
1771 0 : if (!mspc.pointingOffsetMeasCol().isNull()) {
1772 0 : dir1 = mspc.pointingOffsetMeas(indx1).getAngle("rad").getValue();
1773 0 : dir2 = mspc.pointingOffsetMeas(indx2).getAngle("rad").getValue();
1774 : } else {
1775 0 : cerr << "No PONTING_OFFSET column in POINTING table" << endl;
1776 : }
1777 0 : } else if (pointingDirCol_p == "SOURCE_OFFSET") {
1778 0 : if (!mspc.sourceOffsetMeasCol().isNull()) {
1779 0 : dir1 = mspc.sourceOffsetMeas(indx1).getAngle("rad").getValue();
1780 0 : dir2 = mspc.sourceOffsetMeas(indx2).getAngle("rad").getValue();
1781 : } else {
1782 0 : cerr << "No SOURCE_OFFSET column in POINTING table" << endl;
1783 : }
1784 0 : } else if (pointingDirCol_p == "ENCODER") {
1785 0 : if (!mspc.encoderMeas().isNull()) {
1786 0 : dir1 = mspc.encoderMeas()(indx1).getAngle("rad").getValue();
1787 0 : dir2 = mspc.encoderMeas()(indx2).getAngle("rad").getValue();
1788 : } else {
1789 0 : cerr << "No ENCODER column in POINTING table" << endl;
1790 : }
1791 : } else {
1792 0 : dir1 = mspc.directionMeas(indx1).getAngle("rad").getValue();
1793 0 : dir2 = mspc.directionMeas(indx2).getAngle("rad").getValue();
1794 : }
1795 :
1796 0 : dLon = dir2(0) - dir1(0);
1797 0 : dLat = dir2(1) - dir1(1);
1798 0 : ftime = floor(mspc.time()(indx1));
1799 0 : ftime2 = mspc.time()(indx2) - ftime;
1800 0 : ftime1 = mspc.time()(indx1) - ftime;
1801 0 : dtime = ftime2 - ftime1;
1802 0 : scanRate(0) = dLon/dtime;
1803 0 : scanRate(1) = dLat/dtime;
1804 : //scanRate(0) = dir2(0)/dtime-dir1(0)/dtime;
1805 : //scanRate(1) = dir2(1)/dtime-dir1(1)/dtime;
1806 : //Double delT = mspc.time()(index)-time;
1807 : //cerr<<"index="<<index<<" dLat="<<dLat<<" dtime="<<dtime<<" delT="<< delT<<endl;
1808 : //cerr<<"deldirlat="<<scanRate(1)*fabs(delT)<<endl;
1809 0 : if (isfirstRefPt) {
1810 0 : newdir(0) = dir1(0)+scanRate(0)*fabs(mspc.time()(index)-time);
1811 0 : newdir(1) = dir1(1)+scanRate(1)*fabs(mspc.time()(index)-time);
1812 0 : rf = mspc.directionMeas(indx1).getRef();
1813 : } else {
1814 0 : newdir(0) = dir2(0)-scanRate(0)*fabs(mspc.time()(index)-time);
1815 0 : newdir(1) = dir2(1)-scanRate(1)*fabs(mspc.time()(index)-time);
1816 0 : rf = mspc.directionMeas(indx2).getRef();
1817 : }
1818 : //default return this
1819 0 : Quantity rDirLon(newdir(0), "rad");
1820 0 : Quantity rDirLat(newdir(1), "rad");
1821 0 : newDirMeas = MDirection(rDirLon, rDirLat, rf);
1822 : //cerr<<"newDirMeas rf="<<newDirMeas.getRefString()<<endl;
1823 : //return mspc.directionMeas(index);
1824 0 : return newDirMeas;
1825 : }
1826 :
1827 0 : void SDGrid::pickWeights(const vi::VisBuffer2& vb, Matrix<Float>& weight){
1828 : //break reference
1829 0 : weight.resize();
1830 :
1831 0 : if (useImagingWeight_p) {
1832 0 : weight.reference(vb.imagingWeight());
1833 : } else {
1834 0 : const Cube<Float> weightspec(vb.weightSpectrum());
1835 0 : weight.resize(vb.nChannels(), vb.nRows());
1836 :
1837 0 : if (weightspec.nelements() == 0) {
1838 0 : for (rownr_t k = 0; k < vb.nRows(); ++k) {
1839 : //cerr << "nrow " << vb.nRow() << " " << weight.shape() << " " << weight.column(k).shape() << endl;
1840 0 : weight.column(k).set(mean(vb.weight().column(k)));
1841 : }
1842 : } else {
1843 0 : Int npol = weightspec.shape()(0);
1844 0 : if (npol == 1) {
1845 0 : for (rownr_t k = 0; k < vb.nRows(); ++k) {
1846 0 : for (int chan = 0; chan < vb.nChannels(); ++chan) {
1847 0 : weight(chan, k)=weightspec(0, chan, k);
1848 : }
1849 : }
1850 : } else {
1851 0 : for (rownr_t k = 0; k < vb.nRows(); ++k) {
1852 0 : for (int chan = 0; chan < vb.nChannels(); ++chan) {
1853 0 : weight(chan, k) = (weightspec(0, chan, k) + weightspec((npol-1), chan, k))/2.0f;
1854 : }
1855 : }
1856 : }
1857 : }
1858 : }
1859 0 : }
1860 :
1861 0 : void SDGrid::clipMinMax() {
1862 0 : if (clipminmax_) {
1863 : Bool gmin_b, gmax_b, wmin_b, wmax_b, np_b;
1864 0 : const auto *gmin_p = gmin_.getStorage(gmin_b);
1865 0 : const auto *gmax_p = gmax_.getStorage(gmax_b);
1866 0 : const auto *wmin_p = wmin_.getStorage(wmin_b);
1867 0 : const auto *wmax_p = wmax_.getStorage(wmax_b);
1868 0 : const auto *np_p = npoints_.getStorage(np_b);
1869 :
1870 : Bool data_b, weight_b, sumw_b;
1871 0 : auto data_p = griddedData.getStorage(data_b);
1872 0 : auto weight_p = wGriddedData.getStorage(weight_b);
1873 0 : auto sumw_p = sumWeight.getStorage(sumw_b);
1874 :
1875 0 : auto arrayShape = griddedData.shape();
1876 0 : size_t num_xy = arrayShape.getFirst(2).product();
1877 0 : size_t num_polchan = arrayShape.getLast(2).product();
1878 0 : for (size_t i = 0; i < num_xy; ++i) {
1879 0 : for (size_t j = 0; j < num_polchan; ++j) {
1880 0 : auto k = i * num_polchan + j;
1881 0 : if (np_p[k] == 1) {
1882 0 : auto wt = wmin_p[k];
1883 0 : data_p[k] = wt * gmin_p[k];
1884 0 : weight_p[k] = wt;
1885 0 : sumw_p[j] += wt;
1886 0 : } else if (np_p[k] == 2) {
1887 0 : auto wt = wmin_p[k];
1888 0 : data_p[k] = wt * gmin_p[k];
1889 0 : weight_p[k] = wt;
1890 0 : sumw_p[j] += wt;
1891 0 : wt = wmax_p[k];
1892 0 : data_p[k] += wt * gmax_p[k];
1893 0 : weight_p[k] += wt;
1894 0 : sumw_p[j] += wt;
1895 : }
1896 : }
1897 : }
1898 :
1899 0 : wGriddedData.putStorage(weight_p, weight_b);
1900 0 : griddedData.putStorage(data_p, data_b);
1901 0 : sumWeight.putStorage(sumw_p, sumw_b);
1902 :
1903 0 : npoints_.freeStorage(np_p, np_b);
1904 0 : wmax_.freeStorage(wmax_p, wmax_b);
1905 0 : wmin_.freeStorage(wmin_p, wmin_b);
1906 0 : gmax_.freeStorage(gmax_p, gmax_b);
1907 0 : gmin_.freeStorage(gmin_p, gmin_b);
1908 : }
1909 0 : }
1910 :
1911 : } //End of namespace refim
1912 : } //#End casa namespace
|