Line data Source code
1 : //# VisBuffAccumulator.cc: Implementation of VisBuffAccumulator.h
2 : //# Copyright (C) 1996,1997,1998,1999,2000,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: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id: VisBuffAccumulator.cc,v 19.7 2006/01/17 08:22:27 gvandiep Exp $
27 : //----------------------------------------------------------------------------
28 :
29 : #include <msvis/MSVis/VisBuffAccumulator.h>
30 : #include <casacore/casa/Exceptions/Error.h>
31 : #include <casacore/casa/Arrays/ArrayLogical.h>
32 : #include <casacore/casa/Logging/LogIO.h>
33 : #include <casacore/casa/Quanta/MVTime.h>
34 : #include <iomanip>
35 :
36 : #define PRTLEV_VBA 0
37 :
38 : using namespace casacore;
39 : namespace casa { //# NAMESPACE CASA - BEGIN
40 :
41 : //----------------------------------------------------------------------------
42 :
43 0 : VisBuffAccumulator::VisBuffAccumulator(const Int& nAnt, const Double& interval,
44 0 : const Bool& prenorm, const Bool fillModel)
45 0 : : avBuf_p(),
46 0 : nAnt_p(nAnt),
47 0 : interval_p(interval),
48 0 : prenorm_p(prenorm),
49 0 : prtlev_(PRTLEV_VBA),
50 0 : nBuf_p(0),
51 0 : fillModel_p(fillModel),
52 0 : tvi_debug(False)
53 : {
54 : // Construct from the number of antennas and the averaging interval
55 : // Input:
56 : // nAnt const Int& No. of antennas
57 : // interval const Double& Time interval (in seconds).
58 : // prenorm const Bool& Pre-normalization flag
59 : // fillModel const Bool Whether or not to accumulate MODEL_DATA
60 : // Output to private data:
61 : // nAnt_p Int No. of antennas
62 : // interval_p Double Time interval (in seconds).
63 : // prenorm_p Bool Pre-normalization flag
64 : //
65 :
66 0 : if (prtlev()>2) cout << "VBA::VBA()" << endl;
67 :
68 : // Interval MUST be strictly greater than zero
69 0 : if (interval_p < DBL_EPSILON)
70 0 : interval_p=0.1; // TBD: is this reasonable?
71 :
72 : // Reset the averager
73 0 : reset();
74 :
75 0 : }
76 :
77 : //----------------------------------------------------------------------------
78 :
79 0 : VisBuffAccumulator::~VisBuffAccumulator()
80 : {
81 : // Null default destructor
82 : //
83 0 : if (prtlev()>2) cout << "VBA::~VBA()" << endl;
84 0 : }
85 :
86 : //----------------------------------------------------------------------------
87 :
88 0 : void VisBuffAccumulator::reset()
89 : {
90 : // Reset the averager
91 : // Output to private data:
92 : // tStart_p Double Start time of current accumulation
93 : // firstInterval_p Bool Is this the first interval ?
94 : // nChan_p Int No. of channels in the averaging buffer
95 : // avrow_p Int Starting row of current accumulation
96 : // avBuf_p VisBuffer Averaging buffer
97 : //
98 0 : tStart_p = 0.0;
99 0 : firstInterval_p = true;
100 0 : nCorr_p = 0;
101 0 : nChan_p = 0;
102 0 : avrow_p = 0;
103 0 : aveTime_p = 0.0;
104 0 : aveTimeWt_p = 0.0;
105 0 : globalTime_p = 0.0;
106 0 : globalTimeWt_p = 0.0;
107 0 : nBuf_p = 0;
108 :
109 0 : if (prtlev()>2) cout << " VBA::reset()" << endl;
110 :
111 0 : }
112 :
113 : //----------------------------------------------------------------------------
114 :
115 0 : void VisBuffAccumulator::accumulate (const VisBuffer& vb)
116 : {
117 : // Accumulate a VisBuffer
118 : // Input:
119 : // vb const VisBuffer& VisBuffer to accumulate
120 : // Output to private data:
121 : // tStart_p Double Start time of current accumulation
122 : // nChan_p Int No. of channels in the avg. buffer
123 : // avrow_p Int Start row of current accumulation
124 : // avBuf_p CalVisBuffer Averaging buffer
125 : //
126 :
127 0 : if (prtlev()>2) cout << " VBA::accumulate() " << endl;
128 :
129 : // Check if avBuf_p initialization required; if so,
130 : // assign to vb to establish a two-way connection to
131 : // the underlying VisIter.
132 0 : if (firstInterval_p) {
133 : // Initialize the averaging buffer
134 : // THIS IS OLD INEFFICIENT WAY (PRE-CALVISBUFFER)
135 : // avBuf_p = vb;
136 :
137 : // Assign main meta info only
138 : // avBuf_p.assign(vb,true);
139 0 : avBuf_p.assign(vb,false);
140 : //avBuf_p.updateCoordInfo(); // This is (simplified) CalVisBuffer version!
141 0 : avBuf_p.copyCoordInfo(vb, true); // This only goes to VisIter if vb is
142 : // missing something needed.
143 :
144 : // Zero row count
145 0 : avBuf_p.nRow();
146 0 : avBuf_p.nRow() = 0;
147 :
148 : // Immutables:
149 0 : nChan_p = vb.nChannel();
150 0 : nCorr_p = vb.corrType().nelements();
151 :
152 : // Initialize the first accumulation interval
153 : // without copy (nothing accumulated yet)
154 0 : initialize(false);
155 :
156 : }
157 :
158 : // Iterate through the current VisBuffer
159 0 : Int row = 0;
160 0 : while (row < vb.nRow()) {
161 : // Find the next unflagged time
162 0 : while (row < vb.nRow() && vb.flagRow()(row)) {
163 0 : row++;
164 : }
165 0 : if (row < vb.nRow()) {
166 0 : Double thisTime = vb.time()(row);
167 :
168 : // Check for the first accumulation interval
169 0 : if (firstInterval_p) {
170 0 : tStart_p = thisTime;
171 0 : firstInterval_p = false;
172 : }
173 :
174 : // Check for end of the current accumulation interval
175 :
176 0 : if ((vb.time()(row) - tStart_p) > (interval_p-DBL_EPSILON)) {
177 : // Normalize
178 0 : normalize();
179 : // Advance indices to the next accumulation interval
180 0 : tStart_p = thisTime;
181 0 : avrow_p += hashFunction(nAnt_p-1, nAnt_p-1) + 1;
182 : // Initialize the next accumulation interval
183 : // (copy prior preavg'd intervals)
184 0 : initialize(true);
185 : }
186 :
187 : // Add the VisBuffer row to the current accumulation
188 : //
189 : // Only accumulate VisBuffers with the same number of channels
190 0 : Int nCorr=vb.corrType().nelements();
191 0 : if (vb.nChannel() != nChan_p || nCorr != nCorr_p) {
192 0 : throw(AipsError("VisBuffAccumulator: data shape does not conform"));
193 : }
194 :
195 0 : Int ant1 = vb.antenna1()(row);
196 0 : Int ant2 = vb.antenna2()(row);
197 :
198 : // Calculate row from antenna numbers with the hash function.
199 0 : Int outrow = avrow_p + hashFunction (ant1, ant2);
200 :
201 : // Record the row in vb that corresponds to outrow in avBuf_p.
202 0 : outToInRow_p[outrow] = row;
203 :
204 0 : Vector<Float> wtM(vb.weightMat().column(row));
205 : // Row weight for timestamp ave:
206 : // (used to use vb.weight(), which read WEIGHT col
207 : // directly, which is wrong because it might be calibrated!)
208 : // The following is what vb.weight() does, but here with
209 : // the weigthMat info, which has been reset from SIGMA
210 0 : Float wt = (wtM(0)+wtM(nCorr-1))/2;
211 :
212 : // (Prenormalization removed!)
213 :
214 : // Accumulate the visCube itself
215 : // TBD: Handle weights of channel-dep accumulation
216 : // better (i.e., if some channels are sometimes
217 : // flagged, they should accumulate with different
218 : // total weights, even if we will maintain only
219 : // a channel-indep weightMat. So, either use
220 : // weightSpectrum, or at least accumulate per
221 : // channel correctly!)
222 :
223 0 : Int goodChan(0);
224 0 : for (Int chn=0; chn<vb.nChannel(); chn++) {
225 0 : if (!vb.flag()(chn,row) or tvi_debug) {// jagonzal: Always copy inputVis to outputVis
226 0 : goodChan++;
227 0 : avBuf_p.flag()(chn,outrow) = false;
228 0 : for (Int cor=0;cor<nCorr;cor++) {
229 0 : avBuf_p.visCube()(cor,chn,outrow) +=
230 0 : (wtM(cor)*vb.visCube()(cor,chn,row));
231 0 : if(fillModel_p)
232 0 : avBuf_p.modelVisCube()(cor,chn,outrow) +=
233 0 : (wtM(cor)*vb.modelVisCube()(cor,chn,row));
234 : }
235 : }
236 : }
237 :
238 : // Only if there is any good channels this row
239 0 : if (goodChan > 0) {
240 0 : avBuf_p.flagRow()(outrow) = false;
241 0 : avBuf_p.weight()(outrow) += wt;
242 0 : for (Int cor=0;cor<nCorr;cor++)
243 0 : avBuf_p.weightMat()(cor,outrow) += wtM(cor);
244 :
245 : // UVW (vector average, is this right?)
246 : // gcc-3.2 needs the multiplication on a separate line; gcc-3.4 can do
247 : // it as: avBuf_p.uvw()(outrow) += vb.uvw()(row) * Double(wt);
248 0 : RigidVector<Double,3> wtuvw = vb.uvw()(row) * Double(wt);
249 0 : avBuf_p.uvw()(outrow) += wtuvw;
250 :
251 : // Accumulate global timestamp average for this interval:
252 : // (subtract offset from time here to avoid roundoff problems)
253 0 : aveTime_p += (vb.time()(row)-tStart_p) * Double(wt);
254 0 : aveTimeWt_p += Double(wt);
255 : }
256 :
257 : // Increment the row number
258 0 : row++;
259 0 : } // if (row < vb.nRow())
260 : } // while (row < vb.nRow())
261 0 : ++nBuf_p;
262 :
263 : // jagonzal: Fill rowId and flagCube (flag only provides
264 : // an OR of the flags corresponding to all corrs per chan)
265 0 : if (nBuf_p==1 and tvi_debug)
266 : {
267 0 : for (uInt outrow_idx=0;outrow_idx<outToInRow_p.size();outrow_idx++)
268 : {
269 0 : if (outToInRow_p(outrow_idx) > -1)
270 : {
271 0 : avBuf_p.rowIds()(outrow_idx) = vb.rowIds()(outToInRow_p(outrow_idx));
272 0 : avBuf_p.flagCube().xyPlane(outrow_idx) = vb.flagCube().xyPlane(outToInRow_p(outrow_idx));
273 : }
274 : else
275 : {
276 0 : avBuf_p.rowIds()(outrow_idx) = -1;
277 0 : avBuf_p.flagCube().xyPlane(outrow_idx) = True;
278 : }
279 : }
280 : }
281 0 : }
282 :
283 : //----------------------------------------------------------------------------
284 :
285 0 : void VisBuffAccumulator::finalizeAverage ()
286 : {
287 : // Finalize the average, and return the result
288 : // Output:
289 : // avBuf VisBuffer& Averaged buffer
290 : //
291 :
292 0 : if (prtlev()>2) cout << " VBA::finalizeAverage()" << endl;
293 :
294 : // Normalize the current (final) accumulation interval
295 0 : normalize();
296 :
297 0 : }
298 :
299 : //----------------------------------------------------------------------------
300 :
301 0 : void VisBuffAccumulator::initialize(const Bool& copydata)
302 : {
303 : // Initialize the next accumulation interval
304 : // Output to private data:
305 : // avBuf_p VisBuffer Averaging buffer
306 : //
307 :
308 0 : if (prtlev()>2) cout << " VBA::initialize()" << endl;
309 :
310 :
311 :
312 :
313 : ///KG notes
314 : ////Really dangerous and unmaintainable code changing private variables of vb without
315 : ////really changing the internal connnections ...so if say some internal or vb or like here
316 : //// vb.modelVisCube decides to use its private variables ...its nrow is totally wrong ...
317 : /// after the next few lines !
318 : ////function decide to use nRow_p or nChannel_p it is bound to be wrong
319 : //// that is why i am calling the damn visCube and modelVisCube above because
320 : /// coders belive that vb.nRow should give the visbuffer number of rows when accessing /// a given array
321 :
322 0 : Int nRowAdd = hashFunction (nAnt_p-1, nAnt_p-1) + 1;
323 0 : avBuf_p.nRow() += nRowAdd;
324 0 : avBuf_p.nChannel() = nChan_p;
325 :
326 : // Resize and initialize the VisBuffer columns used here
327 0 : Int nRow = avBuf_p.nRow();
328 :
329 0 : avBuf_p.antenna1().resize(nRow, copydata);
330 0 : avBuf_p.antenna2().resize(nRow, copydata);
331 :
332 0 : avBuf_p.time().resize(nRow, copydata);
333 0 : avBuf_p.uvw().resize(nRow, copydata);
334 :
335 0 : avBuf_p.visCube().resize(nCorr_p,nChan_p, nRow,copydata);
336 0 : if(fillModel_p)
337 0 : copydata ?
338 0 : avBuf_p.modelVisCube().resize(nCorr_p,nChan_p, nRow,copydata):
339 0 : avBuf_p.setModelVisCube(Cube<Complex>(nCorr_p,nChan_p, nRow));
340 :
341 0 : avBuf_p.weight().resize(nRow, copydata);
342 0 : avBuf_p.weightMat().resize(nCorr_p,nRow, copydata);
343 :
344 0 : avBuf_p.flagRow().resize(nRow, copydata);
345 :
346 0 : avBuf_p.flag().resize(nChan_p, nRow,copydata);
347 :
348 : // jagonzal: Fill rowId and flagCube (flag only provides
349 : // an OR of the flags corresponding to all corrs per chan)
350 0 : if (tvi_debug)
351 : {
352 0 : avBuf_p.rowIds().resize(nRow, copydata);
353 0 : avBuf_p.flagCube().resize(nCorr_p,nChan_p, nRow,copydata);
354 : }
355 :
356 : // Setup the map from avBuf_p's row numbers to input row numbers.
357 0 : outToInRow_p.resize(nRow, copydata);
358 0 : if(!copydata)
359 0 : outToInRow_p = -1; // Unfilled rows point to -1.
360 :
361 : // Fill in the antenna numbers for all rows
362 0 : Int row = avrow_p;
363 0 : for (Int ant1=0; ant1 < nAnt_p; ant1++) {
364 0 : for (Int ant2 = ant1; ant2 < nAnt_p; ant2++) {
365 0 : avBuf_p.antenna1()(row) = ant1;
366 0 : avBuf_p.antenna2()(row) = ant2;
367 0 : row++;
368 : }
369 : }
370 :
371 : // Initialize everything else
372 0 : for (row = avrow_p; row < nRow; row++) {
373 0 : avBuf_p.time()(row) = 0.0;
374 0 : avBuf_p.uvw()(row) = 0.0;
375 0 : for (Int chn = 0; chn < nChan_p; chn++) {
376 0 : avBuf_p.flag()(chn,row) = true;
377 0 : for (Int cor=0; cor < nCorr_p; cor++) {
378 0 : avBuf_p.visCube()(cor,chn,row) = Complex(0.0);
379 0 : if(fillModel_p)
380 0 : avBuf_p.modelVisCube()(cor,chn,row) = Complex(0.0);
381 : }
382 : }
383 0 : avBuf_p.weight()(row) = 0.0f;
384 0 : avBuf_p.weightMat().column(row) = 0.0f;
385 0 : avBuf_p.flagRow()(row) = true;
386 : }
387 :
388 : // Init global timestamp
389 0 : aveTime_p = 0.0;
390 0 : aveTimeWt_p = 0.0;
391 :
392 0 : }
393 :
394 : //----------------------------------------------------------------------------
395 :
396 0 : void VisBuffAccumulator::normalize()
397 : {
398 : // Normalize the current accumulation interval
399 : // Output to private data:
400 : // avBuf_p VisBuffer& Averaged buffer
401 : //
402 :
403 0 : if (prtlev()>2) cout << " VBA::normalize()" << endl;
404 :
405 : // Only if there will be a valid timestamp
406 0 : if (aveTimeWt_p > 0.0 ) {
407 :
408 : // Contribute to global timestamp average
409 0 : globalTime_p-=tStart_p;
410 0 : globalTime_p*=globalTimeWt_p;
411 0 : globalTime_p+=aveTime_p;
412 0 : globalTimeWt_p+=aveTimeWt_p;
413 0 : globalTime_p/=globalTimeWt_p;
414 0 : globalTime_p+=tStart_p;
415 :
416 : // Mean timestamp for this interval
417 0 : aveTime_p/=aveTimeWt_p;
418 0 : aveTime_p+=tStart_p;
419 :
420 : // Divide by the weights
421 0 : for (Int row=avrow_p; row<avBuf_p.nRow(); row++) {
422 0 : Float wt=avBuf_p.weight()(row);
423 0 : Vector<Float> wtM(avBuf_p.weightMat().column(row));
424 0 : if (wt==0.0f) avBuf_p.flagRow()(row)=true;
425 0 : if (!avBuf_p.flagRow()(row)) {
426 0 : avBuf_p.time()(row)=aveTime_p;
427 0 : avBuf_p.uvw()(row)*=(1.0f/wt);
428 0 : for (Int chn=0; chn<avBuf_p.nChannel(); chn++) {
429 0 : if (!avBuf_p.flag()(chn,row)) {
430 0 : for (Int cor=0;cor<nCorr_p;cor++) {
431 0 : if (wtM(cor)>0.0f) {
432 0 : avBuf_p.visCube()(cor,chn,row)*=1.0f/wtM(cor);
433 0 : if(fillModel_p)
434 0 : avBuf_p.modelVisCube()(cor,chn,row)*=1.0f/wtM(cor);
435 : }
436 : else {
437 0 : avBuf_p.visCube()(cor,chn,row)=0.0;
438 0 : if(fillModel_p)
439 0 : avBuf_p.modelVisCube()(cor,chn,row)=0.0;
440 : }
441 : }
442 : }
443 : }
444 : }
445 0 : }
446 : }
447 : else {
448 : // Ensure this interval is entirely flagged
449 0 : for (Int row=avrow_p; row<avBuf_p.nRow(); row++) {
450 0 : avBuf_p.flagRow()(row)=true;
451 0 : avBuf_p.weight()(row)=0.0f;
452 0 : avBuf_p.weightMat().column(row)=0.0f;
453 : }
454 : }
455 0 : }
456 :
457 : //----------------------------------------------------------------------------
458 :
459 0 : Int VisBuffAccumulator::hashFunction (const Int& ant1, const Int& ant2)
460 : {
461 : // Compute row index in an accumulation interval for an
462 : // interferometer index (ant1, ant2).
463 : // Input:
464 : // ant1 const Int& Antenna 1
465 : // ant2 const Int& Antenna 2
466 : // Output:
467 : // hashFunction Int Row offset in current accumulation
468 : //
469 : Int index;
470 0 : index = nAnt_p * ant1 - (ant1 * (ant1 - 1)) / 2 + ant2 - ant1;
471 0 : return index;
472 : }
473 :
474 : //----------------------------------------------------------------------------
475 :
476 0 : void VisBuffAccumulator::throw_err(const String& origin, const String &msg)
477 : {
478 0 : LogOrigin("VisBuffAccumulator", origin);
479 0 : throw(AipsError(msg));
480 : }
481 :
482 0 : void VisBuffAccumulator::reportData() {
483 :
484 0 : CalVisBuffer& cvb(aveCalVisBuff());
485 0 : Slice corrs(0,2,3), sl;
486 :
487 0 : Vector<Int> a1(cvb.antenna1()), a2(cvb.antenna2());
488 0 : Cube<Complex> vCC(cvb.visCube()(corrs,sl,sl));
489 0 : Cube<Complex> vCM(cvb.modelVisCube()(corrs,sl,sl));
490 0 : Matrix<Float> wtS(cvb.weightMat()(corrs,sl));
491 0 : Matrix<Bool> flg(cvb.flag()(sl,sl));
492 :
493 0 : cout << "Time=" << MVTime(timeStamp()/C::day).string(MVTime::YMD,7) << endl;
494 0 : cout.precision(8);
495 0 : for (Int irow=0;irow<cvb.nRow();++irow) {
496 0 : for (Int ich=0;ich<cvb.nChannel();++ich) {
497 0 : if (flg(ich,irow)) continue;
498 0 : cout << std::setw(2) << a1(irow) << "-" << std::setw(2) << a2(irow) << " ";
499 0 : if (cvb.nChannel()>1) cout << "ich=" << ich << " ";
500 0 : cout << "fl=" << flg(Slice(ich),Slice(irow)).nonDegenerate() << " ";
501 0 : cout << "wt=" << wtS(Slice(),Slice(irow)).nonDegenerate() << " ";
502 0 : cout << "cM=" << vCM(Slice(),Slice(),Slice(irow)).nonDegenerate() << " ";
503 0 : cout << "cC=" << vCC(Slice(),Slice(),Slice(irow)).nonDegenerate() << " ";
504 0 : cout << endl;
505 : }
506 : }
507 :
508 :
509 :
510 0 : }
511 :
512 :
513 :
514 : } //# NAMESPACE CASA - END
515 :
|