Line data Source code
1 : // -*- C++ -*-
2 : //# EVLAConvFunc.cc: Implementation of the EVLAConvFunc class
3 : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
4 : //# Associated Universities, Inc. Washington DC, USA.
5 : //#
6 : //# This library is free software; you can redistribute it and/or modify it
7 : //# under the terms of the GNU Library General Public License as published by
8 : //# the Free Software Foundation; either version 2 of the License, or (at your
9 : //# option) any later version.
10 : //#
11 : //# This library is distributed in the hope that it will be useful, but WITHOUT
12 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14 : //# License for more details.
15 : //#
16 : //# You should have received a copy of the GNU Library General Public License
17 : //# along with this library; if not, write to the Free Software Foundation,
18 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
19 : //#
20 : //# Correspondence concerning AIPS++ should be addressed as follows:
21 : //# Internet email: casa-feedback@nrao.edu.
22 : //# Postal address: AIPS++ Project Office
23 : //# National Radio Astronomy Observatory
24 : //# 520 Edgemont Road
25 : //# Charlottesville, VA 22903-2475 USA
26 : //#
27 : //# $Id$
28 : //
29 : #include <synthesis/TransformMachines/EVLAConvFunc.h>
30 : #include <synthesis/TransformMachines/SynthesisError.h>
31 : #include <synthesis/TransformMachines/BeamCalc.h>
32 : #include <synthesis/TransformMachines/WTerm.h>
33 : //
34 : //---------------------------------------------------------------------
35 : //---------------------------------------------------------------------
36 : // TEMPS
37 : //---------------------------------------------------------------------
38 : //---------------------------------------------------------------------
39 : //
40 : #define CONVSIZE (1024*2)
41 : #define CONVWTSIZEFACTOR 1.0
42 : #define OVERSAMPLING 20
43 : #define THRESHOLD 1E-4
44 :
45 : using namespace casacore;
46 : namespace casa{
47 :
48 0 : EVLAConvFunc& EVLAConvFunc::operator=(const EVLAConvFunc& other)
49 : {
50 0 : if(this!=&other)
51 : {
52 0 : ConvolutionFunction::operator=(other);
53 0 : logIO_p = other.logIO_p;
54 : // setParams(other.polMap_p, other.feedStokes_p);
55 0 : setPolMap(other.polMap_p);
56 0 : bandID_p=other.bandID_p;
57 0 : Diameter_p=other.Diameter_p;
58 0 : Nant_p=other.Nant_p;
59 0 : HPBW=other.HPBW;
60 0 : sigma=other.sigma;
61 : }
62 0 : return *this;
63 : }
64 0 : Int EVLAConvFunc::getVLABandID(Double& freq,String&telescopeName)
65 : {
66 0 : if (telescopeName=="VLA")
67 : {
68 0 : if ((freq >=1.34E9) && (freq <=1.73E9))
69 0 : return BeamCalc_VLA_L;
70 0 : else if ((freq >=4.5E9) && (freq <=5.0E9))
71 0 : return BeamCalc_VLA_C;
72 0 : else if ((freq >=8.0E9) && (freq <=8.8E9))
73 0 : return BeamCalc_VLA_X;
74 0 : else if ((freq >=14.4E9) && (freq <=15.4E9))
75 0 : return BeamCalc_VLA_U;
76 0 : else if ((freq >=22.0E9) && (freq <=24.0E9))
77 0 : return BeamCalc_VLA_K;
78 0 : else if ((freq >=40.0E9) && (freq <=50.0E9))
79 0 : return BeamCalc_VLA_Q;
80 0 : else if ((freq >=100E6) && (freq <=300E6))
81 0 : return BeamCalc_VLA_4;
82 : }
83 : else
84 0 : if (telescopeName=="EVLA")
85 : {
86 0 : if ((freq >=0.6E9) && (freq <=2.0E9))
87 0 : return BeamCalc_EVLA_L;
88 0 : else if ((freq >=2.0E9) && (freq <=4.0E9))
89 0 : return BeamCalc_EVLA_S;
90 0 : else if ((freq >=4.0E9) && (freq <=8.0E9))
91 0 : return BeamCalc_EVLA_C;
92 0 : else if ((freq >=8.0E9) && (freq <=12.0E9))
93 0 : return BeamCalc_EVLA_X;
94 0 : else if ((freq >=12.0E9) && (freq <=18.0E9))
95 0 : return BeamCalc_EVLA_U;
96 0 : else if ((freq >=18.0E9) && (freq <=26.5E9))
97 0 : return BeamCalc_EVLA_K;
98 0 : else if ((freq >=26.5E9) && (freq <=40.8E9))
99 0 : return BeamCalc_EVLA_A;
100 0 : else if ((freq >=4.0E9) && (freq <=50.0E9))
101 0 : return BeamCalc_EVLA_Q;
102 : }
103 0 : ostringstream mesg;
104 0 : mesg << telescopeName << "/" << freq << "(Hz) combination not recognized.";
105 0 : throw(SynthesisError(mesg.str()));
106 0 : }
107 :
108 0 : void EVLAConvFunc::setPolMap(const Vector<Int>& polMap)
109 0 : {polMap_p.resize(0);polMap_p=polMap;};
110 0 : void EVLAConvFunc::setFeedStokes(const Vector<Int>& feedStokes)
111 0 : {feedStokes_p.resize(0);feedStokes_p=feedStokes;};
112 :
113 0 : int EVLAConvFunc::getVisParams(const VisBuffer& vb)
114 : {
115 : Double Freq;
116 :
117 0 : Vector<String> telescopeNames=vb.msColumns().observation().telescopeName().getColumn();
118 0 : for(uInt nt=0;nt<telescopeNames.nelements();nt++)
119 : {
120 0 : if ((telescopeNames(nt) != "VLA") && (telescopeNames(nt) != "EVLA"))
121 : {
122 0 : String mesg="We can handle only (E)VLA antennas for now.\n";
123 0 : mesg += "Erroneous telescope name = " + telescopeNames(nt) + ".";
124 0 : SynthesisError err(mesg);
125 0 : throw(err);
126 0 : }
127 0 : if (telescopeNames(nt) != telescopeNames(0))
128 : {
129 0 : String mesg="We do not (yet) handle inhomogeneous arrays for A-Projection!\n";
130 0 : mesg += "Not yet a \"priority\"!!";
131 0 : SynthesisError err(mesg);
132 0 : throw(err);
133 0 : }
134 : }
135 : // MSSpWindowColumns mssp(vb.msColumns().spectralWindow());
136 0 : Freq = vb.msColumns().spectralWindow().refFrequency()(0);
137 0 : Diameter_p=0;
138 0 : Nant_p = vb.msColumns().antenna().nrow();
139 0 : for (Int i=0; i < Nant_p; i++)
140 0 : if (!vb.msColumns().antenna().flagRow()(i))
141 : {
142 0 : Diameter_p = vb.msColumns().antenna().dishDiameter()(i);
143 0 : break;
144 : }
145 0 : if (Diameter_p == 0)
146 : {
147 0 : logIO() << LogOrigin("EVLAConvFunc", "getVisParams")
148 : << "No valid or finite sized antenna found in the antenna table. "
149 : << "Assuming diameter = 25m."
150 : << LogIO::WARN
151 0 : << LogIO::POST;
152 0 : Diameter_p=25.0;
153 : }
154 :
155 0 : Double Lambda=C::c/Freq;
156 0 : HPBW = Lambda/(Diameter_p*sqrt(log(2.0)));
157 0 : sigma = 1.0/(HPBW*HPBW);
158 : // awEij.setSigma(sigma);
159 0 : Int bandID = getVLABandID(Freq,telescopeNames(0));
160 0 : return bandID;
161 0 : }
162 :
163 0 : Int EVLAConvFunc::makePBPolnCoords(const VisBuffer&vb,
164 : const Vector<Int>& polMap,
165 : const Int& convSize,
166 : const Int& convSampling,
167 : const CoordinateSystem& skyCoord,
168 : const Int& skyNx, const Int& /*skyNy*/,
169 : CoordinateSystem& feedCoord,
170 : Vector<Int>& cfStokes)
171 : {
172 0 : feedCoord = skyCoord;
173 : //
174 : // Make a two dimensional image to calculate auto-correlation of
175 : // the ideal illumination pattern. We want this on a fine grid in
176 : // the UV plane
177 : //
178 0 : Int directionIndex=skyCoord.findCoordinate(Coordinate::DIRECTION);
179 0 : AlwaysAssert(directionIndex>=0, AipsError);
180 0 : DirectionCoordinate dc=skyCoord.directionCoordinate(directionIndex);
181 0 : Vector<Double> sampling;
182 0 : sampling = dc.increment();
183 0 : sampling*=Double(convSampling);
184 0 : sampling*=Double(skyNx)/Double(convSize);
185 0 : dc.setIncrement(sampling);
186 :
187 :
188 0 : Vector<Double> unitVec(2);
189 0 : unitVec=convSize/2;
190 0 : dc.setReferencePixel(unitVec);
191 :
192 : // Set the reference value to that of the image
193 0 : feedCoord.replaceCoordinate(dc, directionIndex);
194 :
195 : //
196 : // Make an image with circular polarization axis.
197 : //
198 0 : Int NPol=0,M,N=0;
199 0 : M=polMap.nelements();
200 0 : for(Int i=0;i<M;i++) if (polMap(i) > -1) NPol++;
201 0 : Vector<Int> poln(NPol);
202 :
203 : Int index;
204 0 : Vector<Int> inStokes;
205 0 : index = feedCoord.findCoordinate(Coordinate::STOKES);
206 0 : inStokes = feedCoord.stokesCoordinate(index).stokes();
207 0 : N = 0;
208 : try
209 : {
210 0 : for(Int i=0;i<M;i++) if (polMap(i) > -1) {poln(N) = vb.corrType()(i);N++;}
211 0 : StokesCoordinate polnCoord(poln);
212 0 : Int StokesIndex = feedCoord.findCoordinate(Coordinate::STOKES);
213 0 : feedCoord.replaceCoordinate(polnCoord,StokesIndex);
214 0 : cfStokes = poln;
215 0 : }
216 0 : catch(AipsError& x)
217 : {
218 0 : throw(SynthesisFTMachineError("Likely cause: Discrepancy between the poln. "
219 0 : "axis of the data and the image specifications."));
220 0 : }
221 :
222 0 : return NPol;
223 0 : }
224 :
225 0 : Bool EVLAConvFunc::findSupport(Array<Complex>& func, Float& threshold,Int& origin, Int& R)
226 : {
227 : Double NSteps;
228 0 : Int PixInc=1;
229 0 : Vector<Complex> vals;
230 0 : IPosition ndx(4,origin,0,0,0);
231 0 : Bool found=false;
232 0 : IPosition cfShape=func.shape();
233 0 : Int convSize = cfShape(0);
234 0 : for(R=convSize/4;R>1;R--)
235 : {
236 0 : NSteps = 90*R/PixInc; //Check every PixInc pixel along a
237 : //circle of radious R
238 0 : vals.resize((Int)(NSteps+0.5));
239 0 : vals=0;
240 0 : for(Int th=0;th<NSteps;th++)
241 : {
242 0 : ndx(0)=(int)(origin + R*sin(2.0*M_PI*th*PixInc/R));
243 0 : ndx(1)=(int)(origin + R*cos(2.0*M_PI*th*PixInc/R));
244 :
245 0 : if ((ndx(0) < cfShape(0)) && (ndx(1) < cfShape(1)))
246 0 : vals(th)=func(ndx);
247 : }
248 0 : if (max(abs(vals)) > threshold)
249 0 : {found=true;break;}
250 : }
251 0 : return found;
252 0 : }
253 :
254 0 : void EVLAConvFunc::makeConvFunction(const ImageInterface<Complex>& image,
255 : const VisBuffer& vb,
256 : const Int wConvSize,
257 : // const Vector<Int>& polMap,
258 : Float pa,
259 : Float dpa,
260 : // Vector<Int>& cfStokes,
261 : CFStore& cfs,
262 : CFStore& cfwts,Bool /*fillCF*/)
263 : {
264 0 : LogIO log_l(LogOrigin("EVLAConvFunc", "makeConvFunction"));
265 : Int convSize, convSampling, polInUse;
266 0 : Double wScale=1;
267 0 : Array<Complex> convFunc_l, convWeights_l;
268 :
269 : (void)dpa;
270 :
271 0 : Int nx=image.shape()(0);
272 0 : if (bandID_p == -1) bandID_p=getVisParams(vb);
273 :
274 : log_l << "Making a new convolution function for PA="
275 0 : << pa*(180/C::pi) << "deg"
276 0 : << LogIO::NORMAL << LogIO::POST;
277 :
278 0 : if(wConvSize>0) {
279 0 : log_l << "Using " << wConvSize << " planes for W-projection" << LogIO::POST;
280 : Double maxUVW;
281 0 : maxUVW=0.25/abs(image.coordinates().increment()(0));
282 : log_l << "Estimating maximum possible W = " << maxUVW
283 0 : << " (wavelengths)" << LogIO::POST;
284 :
285 0 : Double invLambdaC=vb.frequency()(0)/C::c;
286 0 : Double invMinL = vb.frequency()((vb.frequency().nelements())-1)/C::c;
287 : log_l << "wavelength range = " << 1.0/invLambdaC << " (m) to "
288 0 : << 1.0/invMinL << " (m)" << LogIO::POST;
289 0 : if (wConvSize > 1)
290 : {
291 0 : wScale=Float((wConvSize-1)*(wConvSize-1))/maxUVW;
292 : log_l << "Scaling in W (at maximum W) = " << 1.0/wScale
293 0 : << " wavelengths per pixel" << LogIO::POST;
294 : }
295 : }
296 : //
297 : // Get the coordinate system
298 : //
299 0 : CoordinateSystem coords(image.coordinates());
300 :
301 : //
302 : // Set up the convolution function.
303 : //
304 0 : if(wConvSize>0)
305 : {
306 0 : if(wConvSize>256)
307 : {
308 0 : convSampling=4;
309 0 : convSize=min(nx,512);
310 : }
311 : else
312 : {
313 0 : convSampling=4;
314 0 : convSize=min(nx,2048);
315 : }
316 : }
317 : else
318 : {
319 0 : convSampling=4;
320 0 : convSize=nx;
321 : }
322 0 : convSampling=OVERSAMPLING;
323 0 : convSize=CONVSIZE;
324 : //
325 : // Make a two dimensional image to calculate auto-correlation of
326 : // the ideal illumination pattern. We want this on a fine grid in
327 : // the UV plane
328 : //
329 :
330 0 : Int directionIndex=coords.findCoordinate(Coordinate::DIRECTION);
331 0 : AlwaysAssert(directionIndex>=0, AipsError);
332 0 : DirectionCoordinate dc=coords.directionCoordinate(directionIndex);
333 0 : Vector<Double> sampling;
334 0 : sampling = dc.increment();
335 : // sampling /= Double(2.0);
336 :
337 0 : sampling*=Double(convSampling);
338 0 : sampling*=Double(nx)/Double(convSize);
339 :
340 : // cerr << "Sampling on the sky = " << dc.increment() << " " << nx << "x" << ny << endl;
341 : // cerr << "Sampling on the PB = " << sampling << " " << convSize << "x" << convSize << endl;
342 0 : dc.setIncrement(sampling);
343 :
344 0 : Vector<Double> unitVec(2);
345 0 : unitVec=convSize/2;
346 0 : dc.setReferencePixel(unitVec);
347 :
348 : // Set the reference value to that of the image
349 0 : coords.replaceCoordinate(dc, directionIndex);
350 :
351 : //
352 : // Make an image with circular polarization axis. Return the
353 : // no. of vis. poln. planes that will be used in making the user
354 : // defined Stokes image.
355 : //
356 0 : polInUse=makePBPolnCoords(vb, polMap_p, convSize, convSampling,
357 : image.coordinates(),nx,nx,
358 0 : coords,feedStokes_p);
359 : //------------------------------------------------------------------
360 : //
361 : // Make the sky Stokes PB. This will be used in the gridding
362 : // correction
363 : //
364 : //------------------------------------------------------------------
365 0 : IPosition pbShape(4, convSize, convSize, polInUse, 1);
366 0 : TempImage<Complex> twoDPB(pbShape, coords);
367 :
368 0 : IPosition pbSqShp(pbShape);
369 : // pbSqShp[0] *= 2; pbSqShp[1] *= 2;
370 :
371 0 : unitVec=pbSqShp[0]/2;
372 0 : dc.setReferencePixel(unitVec);
373 : // sampling *= Double(2.0);
374 : // dc.setIncrement(sampling);
375 0 : coords.replaceCoordinate(dc, directionIndex);
376 :
377 0 : TempImage<Complex> twoDPBSq(pbSqShp,coords);
378 : // twoDPB.setMaximumCacheSize(cachesize);
379 0 : twoDPB.set(Complex(1.0,0.0));
380 : // twoDPBSq.setMaximumCacheSize(cachesize);
381 0 : twoDPBSq.set(Complex(1.0,0.0));
382 : //
383 : // Accumulate the various terms that constitute the gridding
384 : // convolution function.
385 : //
386 : //------------------------------------------------------------------
387 :
388 0 : Int inner=convSize/convSampling;
389 : // inner = convSize/2;
390 :
391 : // Vector<Double> cfUVScale(3,0),cfUVOffset(3,0);
392 :
393 : // cfUVScale(0)=Float(twoDPB.shape()(0))*sampling(0);
394 : // cfUVScale(1)=Float(twoDPB.shape()(1))*sampling(1);
395 : // cfUVOffset(0)=Float(twoDPB.shape()(0))/2;
396 : // cfUVOffset(1)=Float(twoDPB.shape()(1))/2;
397 : // // cerr << wScale << " " << cfUVScale << endl;
398 : // // cerr << uvOffset << " " << cfUVOffset << endl;
399 : // // ConvolveGridder<Double, Complex>
400 : // // // ggridder(IPosition(2, inner, inner), cfUVScale, cfUVOffset, "SF");
401 : // // ggridder(IPosition(2, inner, inner), uvScale, uvOffset, "SF");
402 :
403 : // // convFuncCache[PAIndex] = new Array<Complex>(IPosition(4,convSize/2,convSize/2,
404 : // // wConvSize,polInUse));
405 : // // convWeightsCache[PAIndex] = new Array<Complex>(IPosition(4,convSize/2,convSize/2,
406 : // // wConvSize,polInUse));
407 : // // convFuncCache[PAIndex] = new Array<Complex>(IPosition(4,convSize,convSize,
408 : // // wConvSize,polInUse));
409 : // // convWeightsCache[PAIndex] = new Array<Complex>(IPosition(4,convSize,convSize,
410 : // // wConvSize,polInUse));
411 0 : cfs.data = new Array<Complex>(IPosition(4,convSize,convSize,
412 0 : wConvSize,polInUse));
413 0 : cfwts.data = new Array<Complex>(IPosition(4,convSize,convSize,
414 0 : wConvSize,polInUse));
415 0 : convFunc_l.reference(*cfs.data);
416 0 : convWeights_l.reference(*cfwts.data);
417 0 : convFunc_l=0;
418 0 : convWeights_l=0.0;
419 0 : cfs.resize(wConvSize);
420 0 : cfwts.resize(wConvSize);
421 :
422 0 : IPosition start(4, 0, 0, 0, 0);
423 0 : IPosition pbSlice(4, convSize, convSize, 1, 1);
424 :
425 0 : Matrix<Complex> screen(convSize, convSize);
426 : // if (paChangeDetector.changed(vb,0)) paChangeDetector.update(vb,0);
427 0 : VLACalcIlluminationConvFunc vlaPB;
428 0 : WTerm wterm;
429 0 : Long cachesize=(HostInfo::memoryTotal(true)/8)*1024;
430 0 : vlaPB.setMaximumCacheSize(cachesize);
431 :
432 0 : for (Int iw=0;iw<wConvSize;iw++)
433 : {
434 0 : screen = 1.0;
435 :
436 : /*
437 : screen=0.0;
438 : // First the spheroidal function
439 : //
440 : // inner=convSize/2;
441 : // screen = 0.0;
442 : Vector<Complex> correction(inner);
443 : for (Int iy=-inner/2;iy<inner/2;iy++)
444 : {
445 : ggridder.correctX1D(correction, iy+inner/2);
446 : for (Int ix=-inner/2;ix<inner/2;ix++)
447 : screen(ix+convSize/2,iy+convSize/2)=correction(ix+inner/2);
448 : // if (iy==0)
449 : // for (Int ii=0;ii<inner;ii++)
450 : // cout << ii << " " << correction(ii) << endl;
451 : }
452 : */
453 : //
454 : // Now the w term
455 : //
456 0 : wterm.applySky(screen, iw, sampling, wScale, inner);
457 : //
458 : // Fill the complex image with the w-term...
459 : //
460 0 : IPosition PolnPlane(4,0,0,0,0);
461 0 : IPosition ndx(4,0,0,0,0);
462 :
463 0 : for(Int i=0;i<polInUse;i++)
464 : {
465 0 : PolnPlane(2)=i;
466 0 : twoDPB.putSlice(screen, PolnPlane);
467 0 : twoDPBSq.putSlice(screen, PolnPlane);
468 : }
469 : //
470 : // Apply the PB...
471 : //
472 0 : Bool doSquint=true;
473 0 : Double pa=getPA(vb);
474 0 : vlaPB.applyPB(twoDPB, pa, bandID_p, doSquint);
475 0 : doSquint = false;
476 : // vlaPB.applyPBSq(twoDPBSq, vb, bandID_p, doSquint);
477 0 : vlaPB.applyPB(twoDPBSq, pa, bandID_p, doSquint);
478 : /*
479 : // twoDPB.put(abs(twoDPB.get()));
480 : // twoDPBSq.put(abs(twoDPBSq.get()));
481 : */
482 :
483 : // {
484 : // String name("twoDPB.before.im");
485 : // storeImg(name,twoDPB);
486 : // }
487 :
488 0 : Complex cpeak=max(twoDPB.get());
489 0 : twoDPB.put(twoDPB.get()/cpeak);
490 0 : cpeak=max(twoDPBSq.get());
491 0 : twoDPBSq.put(twoDPBSq.get()/cpeak);
492 : // twoDPBSq.set(1.0);
493 : // {
494 : // String name("twoDPB.im");
495 : // storeImg(name,twoDPB);
496 : // }
497 :
498 0 : CoordinateSystem cs=twoDPB.coordinates();
499 0 : Int index= twoDPB.coordinates().findCoordinate(Coordinate::SPECTRAL);
500 0 : SpectralCoordinate SpCS = twoDPB.coordinates().spectralCoordinate(index);
501 :
502 0 : Double cfRefFreq=SpCS.referenceValue()(0);
503 0 : Vector<Double> refValue; refValue.resize(1); refValue(0)=cfRefFreq;
504 0 : SpCS.setReferenceValue(refValue);
505 0 : cs.replaceCoordinate(SpCS,index);
506 : //
507 : // Now FFT and get the result back
508 : //
509 : // {
510 : // String name("twoDPB.im");
511 : // storeImg(name,twoDPB);
512 : // }
513 0 : LatticeFFT::cfft2d(twoDPB);
514 0 : LatticeFFT::cfft2d(twoDPBSq);
515 : // {
516 : // String name("twoDPBFT.im");
517 : // storeImg(name,twoDPB);
518 : // }
519 : //
520 : // Fill the convolution function planes with the result.
521 : //
522 : {
523 0 : IPosition start(4, 0, 0, 0, 0),
524 0 : pbSlice(4, twoDPB.shape()[0]-1, twoDPB.shape()[1]-1, polInUse, 1);
525 0 : IPosition sliceStart(4,0,0,iw,0),
526 0 : sliceLength(4,convFunc_l.shape()[0]-1,convFunc_l.shape()[1]-1,1,polInUse);
527 :
528 0 : convFunc_l(Slicer(sliceStart,sliceLength)).nonDegenerate()
529 0 : =(twoDPB.getSlice(start, pbSlice, true));
530 :
531 0 : IPosition shp(twoDPBSq.shape());
532 :
533 0 : IPosition sqStart(4, 0, 0, 0, 0),
534 0 : pbSqSlice(4, shp[0]-1, shp[1]-1, polInUse, 1);
535 0 : IPosition sqSliceStart(4,0,0,iw,0),
536 0 : sqSliceLength(4,shp[0]-1,shp[1]-1,1,polInUse);
537 :
538 0 : convWeights_l(Slicer(sqSliceStart,sqSliceLength)).nonDegenerate()
539 0 : =(twoDPBSq.getSlice(sqStart, pbSqSlice, true));
540 :
541 0 : }
542 0 : }
543 :
544 : {
545 0 : Complex cpeak = max(convFunc_l);
546 0 : convFunc_l/=cpeak;
547 0 : cpeak=max(convWeights_l);
548 0 : convWeights_l/=cpeak;
549 : }
550 : //
551 : // Find the convolution function support size. No assumption
552 : // about the symmetry of the conv. func. can be made (except that
553 : // they are same for all poln. planes).
554 : //
555 :
556 0 : Int maxConvSupport=-1;
557 0 : Int ConvFuncOrigin=convFunc_l.shape()[0]/2; // Conv. Func. is half that size of convSize
558 0 : IPosition ndx(4,ConvFuncOrigin,0,0,0);
559 :
560 0 : Int maxConvWtSupport=0, supportBuffer;
561 0 : for (Int iw=0;iw<wConvSize;iw++)
562 : {
563 0 : Bool found=false;
564 : Float threshold;
565 : Int R;
566 0 : ndx(2) = iw;
567 :
568 0 : ndx(0)=ndx(1)=ConvFuncOrigin;
569 0 : ndx(2) = iw;
570 : // Complex maxVal = max(convFunc);
571 0 : threshold = abs(convFunc_l(ndx))*THRESHOLD;
572 : //
573 : // Find the support size of the conv. function in pixels
574 : //
575 : Int wtR;
576 0 : found = findSupport(convWeights_l,threshold,ConvFuncOrigin,wtR);
577 0 : found = findSupport(convFunc_l,threshold,ConvFuncOrigin,R);
578 :
579 : // R *=2.5;
580 : //
581 : // Set the support size for each W-plane and for all
582 : // Pol-planes. Assuming that support size for all Pol-planes
583 : // is same.
584 : //
585 0 : if(found)
586 : {
587 : // Int maxR=R;//max(ndx(0),ndx(1));
588 0 : cfs.sampling(0)=cfwts.sampling(0)=convSampling;
589 0 : for(Int ipol=0;ipol<polInUse;ipol++)
590 : {
591 0 : cfs.xSupport(iw)=cfs.ySupport(iw)=Int(R/cfs.sampling(0));
592 0 : cfs.xSupport(iw)=cfs.ySupport(iw)=Int(0.5+Float(R)/cfs.sampling(0))+1;
593 :
594 0 : cfwts.xSupport(iw)=cfwts.ySupport(iw)=Int(R*CONVWTSIZEFACTOR/
595 0 : cfwts.sampling(0));
596 0 : cfwts.xSupport(iw)=cfwts.ySupport(iw)=Int(0.5+Float(R)*CONVWTSIZEFACTOR/
597 0 : cfwts.sampling(0))+1;
598 :
599 0 : if (cfs.maxXSupport == -1)
600 0 : if (cfs.xSupport(iw) > maxConvSupport)
601 0 : maxConvSupport = cfs.xSupport(iw);
602 0 : maxConvWtSupport=cfwts.xSupport(iw);//HOW CAN THIS BE RIGHT!!!!
603 : }
604 : }
605 : }
606 :
607 0 : if(cfs.xSupport(0)<1)
608 : log_l << "Convolution function is misbehaved - support seems to be zero"
609 0 : << LogIO::EXCEPTION;
610 :
611 : log_l << "Re-sizing the convolution functions"
612 0 : << LogIO::POST;
613 :
614 : {
615 0 : supportBuffer = OVERSAMPLING;
616 0 : Int bot=(Int)(ConvFuncOrigin-cfs.sampling[0]*maxConvSupport-supportBuffer),//-convSampling/2,
617 0 : top=(Int)(ConvFuncOrigin+cfs.sampling[0]*maxConvSupport+supportBuffer);//+convSampling/2;
618 0 : bot = max(0,bot);
619 0 : top = min(top, convFunc_l.shape()(0)-1);
620 : {
621 0 : Array<Complex> tmp;
622 0 : IPosition blc(4,bot,bot,0,0), trc(4,top,top,wConvSize-1,polInUse-1);
623 : //
624 : // Cut out the conv. func., copy in a temp. array, resize the
625 : // CFStore.data, and copy the cutout version to CFStore.data.
626 : //
627 0 : tmp = convFunc_l(blc,trc);
628 0 : cfs.data->resize(tmp.shape());
629 0 : *cfs.data = tmp;
630 0 : convFunc_l.reference(*cfs.data);
631 0 : }
632 :
633 0 : supportBuffer = (Int)(OVERSAMPLING*CONVWTSIZEFACTOR);
634 0 : bot=(Int)(ConvFuncOrigin-cfwts.sampling[0]*maxConvWtSupport-supportBuffer);
635 0 : top=(Int)(ConvFuncOrigin+cfwts.sampling[0]*maxConvWtSupport+supportBuffer);
636 0 : bot=max(0,bot);
637 0 : top=min(top,convWeights_l.shape()(0)-1);
638 : {
639 0 : Array<Complex> tmp;
640 0 : IPosition blc(4,bot,bot,0,0), trc(4,top,top,wConvSize-1,polInUse-1);
641 :
642 0 : tmp = convWeights_l(blc,trc);
643 0 : cfwts.data->resize(tmp.shape());
644 0 : *cfwts.data = tmp;
645 0 : convWeights_l.reference(*cfwts.data);
646 0 : }
647 : }
648 :
649 : //
650 : // Normalize such that plane 0 sums to 1 (when jumping in steps of
651 : // convSampling). This is really not necessary here since we do
652 : // the normalizing by the area more accurately in the gridder
653 : // (fpbwproj.f).
654 : //
655 0 : ndx(2)=ndx(3)=0;
656 :
657 :
658 0 : Complex pbSum=0.0;
659 0 : IPosition peakPix(ndx);
660 :
661 0 : Int Nx = convFunc_l.shape()(0), Ny=convFunc_l.shape()(1);
662 :
663 0 : for(Int nw=0;nw<wConvSize;nw++)
664 0 : for(Int np=0;np<polInUse;np++)
665 : {
666 0 : ndx(2) = nw; ndx(3)=np;
667 : {
668 : //
669 : // Locate the pixel with the peak value. That's the
670 : // origin in pixel co-ordinates.
671 : //
672 0 : Float peak=0;
673 0 : peakPix = 0;
674 0 : for(ndx(1)=0;ndx(1)<convFunc_l.shape()(1);ndx(1)++)
675 0 : for(ndx(0)=0;ndx(0)<convFunc_l.shape()(0);ndx(0)++)
676 0 : if (abs(convFunc_l(ndx)) > peak) {peakPix = ndx;peak=abs(convFunc_l(ndx));}
677 : }
678 :
679 0 : ConvFuncOrigin = peakPix(0);
680 : // ConvFuncOrigin = convFunc.shape()(0)/2+1;
681 : // Int thisConvSupport=convSampling*convSupport(nw,np,lastPASlot);
682 0 : Int thisConvSupport=cfs.xSupport(nw);
683 0 : pbSum=0.0;
684 :
685 0 : for(Int iy=-thisConvSupport;iy<thisConvSupport;iy++)
686 0 : for(Int ix=-thisConvSupport;ix<thisConvSupport;ix++)
687 : {
688 0 : ndx(0)=ix*(Int)cfs.sampling[0]+ConvFuncOrigin;
689 0 : ndx(1)=iy*(Int)cfs.sampling[0]+ConvFuncOrigin;
690 0 : pbSum += real(convFunc_l(ndx));
691 : }
692 0 : if(pbSum>0.0)
693 : {
694 : //
695 : // Normalize each Poln. plane by the area under its convfunc.
696 : //
697 0 : Nx = convFunc_l.shape()(0), Ny = convFunc_l.shape()(1);
698 0 : for (ndx(1)=0;ndx(1)<Ny;ndx(1)++)
699 0 : for (ndx(0)=0;ndx(0)<Nx;ndx(0)++)
700 : {
701 0 : convFunc_l(ndx) /= pbSum;
702 : }
703 :
704 0 : Nx = convWeights_l.shape()(0); Ny = convWeights_l.shape()(1);
705 0 : for (ndx(1)=0; ndx(1)<Ny; ndx(1)++)
706 0 : for (ndx(0)=0; ndx(0)<Nx; ndx(0)++)
707 : {
708 0 : convWeights_l(ndx) /= pbSum*pbSum;
709 : }
710 : }
711 : else
712 0 : throw(SynthesisFTMachineError("Convolution function integral is not positive"));
713 :
714 0 : Vector<Float> maxVal(convWeights_l.shape()(2));
715 0 : Vector<IPosition> posMax(convWeights_l.shape()(2));
716 0 : SynthesisUtils::findLatticeMax(convWeights_l,maxVal,posMax);
717 0 : }
718 :
719 0 : Int index=coords.findCoordinate(Coordinate::SPECTRAL);
720 0 : SpectralCoordinate spCS = coords.spectralCoordinate(index);
721 0 : Vector<Double> refValue; refValue.resize(1);refValue(0)=spCS.referenceValue()(0);
722 0 : spCS.setReferenceValue(refValue);
723 0 : coords.replaceCoordinate(spCS,index);
724 :
725 0 : cfs.coordSys=coords; cfwts.coordSys=coords;
726 0 : cfs.pa=Quantity(pa,"rad"); cfwts.pa=Quantity(pa,"rad");
727 0 : }
728 : //
729 : //---------------------------------------------------------------------
730 : //---------------------------------------------------------------------
731 : // TEMPS
732 : //---------------------------------------------------------------------
733 : //---------------------------------------------------------------------
734 : //
735 : };
|