Line data Source code
1 : //# ChannelAverageTVI.h: This file contains the implementation of the ChannelAverageTVI class.
2 : //#
3 : //# CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
4 : //# Copyright (C) Associated Universities, Inc. Washington DC, USA 2011, All rights reserved.
5 : //# Copyright (C) European Southern Observatory, 2011, All rights reserved.
6 : //#
7 : //# This library is free software; you can redistribute it and/or
8 : //# modify it under the terms of the GNU Lesser General Public
9 : //# License as published by the Free software Foundation; either
10 : //# version 2.1 of the License, or (at your option) any later version.
11 : //#
12 : //# This library is distributed in the hope that it will be useful,
13 : //# but WITHOUT ANY WARRANTY, without even the implied warranty of
14 : //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : //# Lesser General Public License for more details.
16 : //#
17 : //# You should have received a copy of the GNU Lesser General Public
18 : //# License along with this library; if not, write to the Free Software
19 : //# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 : //# MA 02111-1307 USA
21 : //# $Id: $
22 :
23 : #include <mstransform/TVI/ChannelAverageTVI.h>
24 : #include <casacore/casa/Arrays/VectorIter.h>
25 :
26 : #ifdef _OPENMP
27 : #include <omp.h>
28 : #endif
29 :
30 :
31 : using namespace casacore;
32 : namespace casa { //# NAMESPACE CASA - BEGIN
33 :
34 : namespace vi { //# NAMESPACE VI - BEGIN
35 :
36 : //////////////////////////////////////////////////////////////////////////
37 : // ChannelAverageTVI class
38 : //////////////////////////////////////////////////////////////////////////
39 :
40 : // -----------------------------------------------------------------------
41 : //
42 : // -----------------------------------------------------------------------
43 21 : ChannelAverageTVI::ChannelAverageTVI( ViImplementation2 * inputVii,
44 21 : const Record &configuration):
45 21 : FreqAxisTVI (inputVii)
46 : {
47 : // Parse and check configuration parameters
48 : // Note: if a constructor finishes by throwing an exception, the memory
49 : // associated with the object itself is cleaned up — there is no memory leak.
50 21 : if (not parseConfiguration(configuration))
51 0 : throw AipsError("Error parsing ChannelAverageTVI configuration");
52 :
53 21 : if (inputVii == nullptr)
54 0 : throw AipsError("Input Vi is empty");
55 :
56 21 : initialize();
57 :
58 21 : return;
59 0 : }
60 :
61 : // -----------------------------------------------------------------------
62 : //
63 : // -----------------------------------------------------------------------
64 21 : Bool ChannelAverageTVI::parseConfiguration(const Record &configuration)
65 : {
66 21 : int exists = -1;
67 21 : Bool ret = true;
68 :
69 : // Parse chanbin parameter (mandatory)
70 21 : exists = -1;
71 21 : exists = configuration.fieldNumber ("chanbin");
72 21 : if (exists >= 0)
73 : {
74 21 : if ( configuration.type(exists) == casacore::TpInt )
75 : {
76 : Int freqbin;
77 21 : configuration.get (exists, freqbin);
78 21 : chanbin_p = Vector<Int>(spwInpChanIdxMap_p.size(),freqbin);
79 : }
80 0 : else if ( configuration.type(exists) == casacore::TpArrayInt)
81 : {
82 0 : configuration.get (exists, chanbin_p);
83 : }
84 : else
85 : {
86 0 : ret = false;
87 0 : logger_p << LogIO::SEVERE << LogOrigin("ChannelAverageTVI", __FUNCTION__)
88 : << "Wrong format for chanbin parameter (only Int and arrayInt are supported) "
89 0 : << LogIO::POST;
90 : }
91 :
92 42 : logger_p << LogIO::NORMAL << LogOrigin("ChannelAverageTVI", __FUNCTION__)
93 42 : << "Channel bin is " << chanbin_p << LogIO::POST;
94 21 : if (anyEQ(chanbin_p,0)) {
95 0 : logger_p << LogIO::NORMAL << LogOrigin("ChannelAverageTVI", __FUNCTION__)
96 0 : << " NB: Channel bin '0' means no channel averaging for the corresponding spw." << LogIO::POST;
97 : }
98 : }
99 : else
100 : {
101 0 : ret = false;
102 0 : logger_p << LogIO::SEVERE << LogOrigin("ChannelAverageTVI", __FUNCTION__)
103 : << "chanbin parameter not found in configuration "
104 0 : << LogIO::POST;
105 : }
106 :
107 21 : exists = configuration.fieldNumber ("flagdataFlagPropagation");
108 21 : flagdataFlagPropagation_p = exists >= 0;
109 :
110 : // Check consistency between chanbin vector and selected SPW/Chan map
111 21 : if (chanbin_p.size() != spwInpChanIdxMap_p.size())
112 : {
113 0 : ret = false;
114 0 : logger_p << LogIO::SEVERE << LogOrigin("ChannelAverageTVI", __FUNCTION__)
115 : << "Number of elements in chanbin vector does not match number of selected SPWs"
116 0 : << LogIO::POST;
117 : }
118 :
119 21 : return ret;
120 : }
121 :
122 : // -----------------------------------------------------------------------
123 : //
124 : // -----------------------------------------------------------------------
125 21 : void ChannelAverageTVI::initialize()
126 : {
127 : // Populate nchan input-output maps
128 : Int spw;
129 21 : uInt spw_idx = 0;
130 21 : map<Int,vector<Int> >::iterator iter;
131 :
132 89 : for(iter=spwInpChanIdxMap_p.begin();iter!=spwInpChanIdxMap_p.end();iter++)
133 : {
134 68 : spw = iter->first;
135 :
136 : // No averaging when user specifies 0
137 68 : if (chanbin_p(spw_idx)==0) {
138 0 : logger_p << LogIO::DEBUG1 << LogOrigin("ChannelAverageTVI", __FUNCTION__)
139 : << "Specified chanbin for spw " << spw
140 : << " of 0 means no averaging."
141 0 : << LogIO::POST;
142 :
143 0 : spwChanbinMap_p[spw] = 1;
144 : }
145 : // Make sure that chanbin is greater than 1
146 68 : else if ((uInt)chanbin_p(spw_idx) <= 1)
147 : {
148 46 : logger_p << LogIO::DEBUG1 << LogOrigin("ChannelAverageTVI", __FUNCTION__)
149 : << "Specified chanbin for spw " << spw
150 : << " less than 1 falls back to the default number of"
151 23 : << " existing/selected channels: " << iter->second.size()
152 46 : << LogIO::POST;
153 :
154 23 : spwChanbinMap_p[spw] = iter->second.size();
155 : }
156 : // Make sure that chanbin does not exceed number of selected channels
157 45 : else if ((uInt)chanbin_p(spw_idx) > iter->second.size())
158 : {
159 0 : logger_p << LogIO::DEBUG1 << LogOrigin("ChannelAverageTVI", __FUNCTION__)
160 0 : << "Number of selected channels " << iter->second.size()
161 : << " for SPW " << spw
162 0 : << " is smaller than specified chanbin " << (uInt)chanbin_p(spw_idx) << endl
163 0 : << "Setting chanbin to " << iter->second.size()
164 : << " for SPW " << spw
165 0 : << LogIO::POST;
166 0 : spwChanbinMap_p[spw] = iter->second.size();
167 : }
168 : else
169 : {
170 45 : spwChanbinMap_p[spw] = chanbin_p(spw_idx);
171 : }
172 :
173 : // Calculate number of output channels per spw
174 68 : spwOutChanNumMap_p[spw] = spwInpChanIdxMap_p[spw].size() / spwChanbinMap_p[spw];
175 68 : if (spwInpChanIdxMap_p[spw].size() % spwChanbinMap_p[spw] > 0) spwOutChanNumMap_p[spw] += 1;
176 :
177 68 : spw_idx++;
178 : }
179 :
180 42 : return;
181 : }
182 :
183 : #define DOJUSTO false
184 : // -----------------------------------------------------------------------
185 : //
186 : // -----------------------------------------------------------------------
187 192 : void ChannelAverageTVI::flag(Cube<Bool>& flagCube) const
188 : {
189 :
190 : // Pass-thru for single-channel case
191 192 : if (getVii()->visibilityShape()[1]==1) {
192 2 : getVii()->flag(flagCube);
193 2 : return;
194 : }
195 :
196 : // Get input VisBuffer and SPW
197 190 : VisBuffer2 *vb = getVii()->getVisBuffer();
198 190 : Int inputSPW = vb->spectralWindows()(0);
199 :
200 : // Pass-thru for chanbin=1 case:
201 190 : if (spwChanbinMap_p[inputSPW]==1) {
202 0 : getVii()->flag(flagCube);
203 0 : return;
204 : }
205 :
206 : #ifdef _OPENMP
207 : // Pre-load relevant input info and start clock
208 190 : vb->flagCube();
209 190 : Double time0=omp_get_wtime();
210 : #endif
211 :
212 :
213 : // Reshape output data before passing it to the DataCubeHolder
214 190 : flagCube.resize(getVisBuffer()->getShape(),false);
215 :
216 : // Gather input data
217 190 : DataCubeMap inputData;
218 190 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
219 190 : inputData.add(MS::FLAG,inputFlagCubeHolder);
220 :
221 : // Gather output data
222 190 : DataCubeMap outputData;
223 190 : DataCubeHolder<Bool> outputFlagCubeHolder(flagCube);
224 190 : outputData.add(MS::FLAG,outputFlagCubeHolder);
225 :
226 : // Configure Transformation Engine
227 190 : LogicalANDKernel<Bool> kernel;
228 190 : uInt width = spwChanbinMap_p[inputSPW];
229 190 : ChannelAverageTransformEngine<Bool> transformer(&kernel,&inputData,&outputData,width);
230 :
231 : // Transform data
232 : if (DOJUSTO) {
233 : transformFreqAxis2(vb->getShape(),transformer);
234 : } else {
235 190 : transformer.transformAll();
236 : }
237 :
238 : #ifdef _OPENMP
239 : // Accumulate elapsed time
240 190 : Tfl_+=omp_get_wtime()-time0;
241 : #endif
242 :
243 190 : return;
244 190 : }
245 :
246 : // -----------------------------------------------------------------------
247 : //
248 : // -----------------------------------------------------------------------
249 0 : void ChannelAverageTVI::floatData (Cube<Float> & vis) const
250 : {
251 :
252 : // Pass-thru for single-channel case
253 0 : if (getVii()->visibilityShape()[1]==1) {
254 0 : getVii()->floatData(vis);
255 0 : return;
256 : }
257 :
258 : // Get input VisBuffer and SPW
259 0 : VisBuffer2 *vb = getVii()->getVisBuffer();
260 0 : Int inputSPW = vb->spectralWindows()(0);
261 :
262 : // Pass-thru for chanbin=1 case:
263 0 : if (spwChanbinMap_p[inputSPW]==1) {
264 0 : getVii()->floatData(vis);
265 0 : return;
266 : }
267 :
268 : // Reshape output data before passing it to the DataCubeHolder
269 0 : vis.resize(getVisBuffer()->getShape(),false);
270 :
271 : // Gather input data
272 0 : DataCubeMap inputData;
273 0 : DataCubeHolder<Float> inputVisCubeHolder(vb->visCubeFloat());
274 0 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
275 0 : DataCubeHolder<Float> weightCubeHolder(vb->weightSpectrum());
276 0 : inputData.add(MS::DATA,inputVisCubeHolder);
277 0 : inputData.add(MS::FLAG,inputFlagCubeHolder);
278 0 : inputData.add(MS::WEIGHT_SPECTRUM,weightCubeHolder);
279 :
280 : // Gather output data
281 0 : DataCubeMap outputData;
282 0 : DataCubeHolder<Float> outputVisCubeHolder(vis);
283 0 : outputData.add(MS::DATA,outputVisCubeHolder);
284 :
285 : // Configure Transformation Engine
286 0 : uInt width = spwChanbinMap_p[inputSPW];
287 0 : WeightedChannelAverageKernel<Float> kernel;
288 0 : ChannelAverageTransformEngine<Float> transformer(&kernel,&inputData,&outputData,width);
289 :
290 : // Transform data
291 : if (DOJUSTO) {
292 : transformFreqAxis2(vb->getShape(),transformer);
293 : } else {
294 0 : transformer.transformAll();
295 : }
296 :
297 0 : return;
298 0 : }
299 :
300 : // -----------------------------------------------------------------------
301 : //
302 : // -----------------------------------------------------------------------
303 180 : void ChannelAverageTVI::visibilityObserved (Cube<Complex> & vis) const
304 : {
305 :
306 : // Pass-thru for single-channel case
307 180 : if (getVii()->visibilityShape()[1]==1) {
308 2 : getVii()->visibilityObserved(vis);
309 2 : return;
310 : }
311 :
312 : // Get input VisBuffer and SPW
313 178 : VisBuffer2 *vb = getVii()->getVisBuffer();
314 178 : Int inputSPW = vb->spectralWindows()(0);
315 :
316 : // Reshape output data before passing it to the DataCubeHolder
317 178 : vis.resize(getVisBuffer()->getShape(),false);
318 :
319 : // Get weightSpectrum from sigmaSpectrum
320 178 : Cube<Float> weightSpFromSigmaSp;
321 178 : weightSpFromSigmaSp.resize(vb->sigmaSpectrum().shape(),false);
322 178 : weightSpFromSigmaSp = vb->sigmaSpectrum(); // = Operator makes a copy
323 178 : arrayTransformInPlace (weightSpFromSigmaSp,sigmaToWeight);
324 :
325 : // Gather input data
326 178 : DataCubeMap inputData;
327 178 : DataCubeHolder<Complex> inputVisCubeHolder(vb->visCube());
328 178 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
329 178 : DataCubeHolder<Float> weightCubeHolder(weightSpFromSigmaSp);
330 178 : inputData.add(MS::DATA,inputVisCubeHolder);
331 178 : inputData.add(MS::FLAG,inputFlagCubeHolder);
332 178 : inputData.add(MS::WEIGHT_SPECTRUM,weightCubeHolder);
333 :
334 : // Gather output data
335 178 : DataCubeMap outputData;
336 178 : DataCubeHolder<Complex> outputVisCubeHolder(vis);
337 178 : outputData.add(MS::DATA,outputVisCubeHolder);
338 :
339 : // Configure Transformation Engine
340 178 : uInt width = spwChanbinMap_p[inputSPW];
341 178 : WeightedChannelAverageKernel<Complex> kernel;
342 178 : ChannelAverageTransformEngine<Complex> transformer(&kernel,&inputData,&outputData,width);
343 :
344 : // Transform data
345 : if (DOJUSTO) {
346 : transformFreqAxis2(vb->getShape(),transformer);
347 : }
348 : else {
349 178 : transformer.transformAll();
350 : }
351 :
352 178 : return;
353 178 : }
354 :
355 : // -----------------------------------------------------------------------
356 : //
357 : // -----------------------------------------------------------------------
358 6 : void ChannelAverageTVI::visibilityCorrected (Cube<Complex> & vis) const
359 : {
360 :
361 : // Pass-thru for single-channel case
362 6 : if (getVii()->visibilityShape()[1]==1) {
363 0 : getVii()->visibilityCorrected(vis);
364 0 : return;
365 : }
366 :
367 : // Get input VisBuffer and SPW
368 6 : VisBuffer2 *vb = getVii()->getVisBuffer();
369 6 : Int inputSPW = vb->spectralWindows()(0);
370 :
371 : // Pass-thru for chanbin=1 case:
372 6 : if (spwChanbinMap_p[inputSPW]==1) {
373 0 : getVii()->visibilityCorrected(vis);
374 0 : return;
375 : }
376 :
377 :
378 : #ifdef _OPENMP
379 : // Pre-load relevant input info and start clock
380 6 : vb->visCubeCorrected();
381 6 : vb->flagCube();
382 6 : vb->weightSpectrum();
383 6 : Double time0=omp_get_wtime();
384 : #endif
385 :
386 :
387 : // Reshape output data before passing it to the DataCubeHolder
388 6 : vis.resize(getVisBuffer()->getShape(),false);
389 :
390 : // Gather input data
391 6 : DataCubeMap inputData;
392 6 : DataCubeHolder<Complex> inputVisCubeHolder(vb->visCubeCorrected());
393 6 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
394 6 : DataCubeHolder<Float> weightCubeHolder(vb->weightSpectrum());
395 6 : inputData.add(MS::DATA,inputVisCubeHolder);
396 6 : inputData.add(MS::FLAG,inputFlagCubeHolder);
397 6 : inputData.add(MS::WEIGHT_SPECTRUM,weightCubeHolder);
398 :
399 : // Gather output data
400 6 : DataCubeMap outputData;
401 6 : DataCubeHolder<Complex> outputVisCubeHolder(vis);
402 6 : outputData.add(MS::DATA,outputVisCubeHolder);
403 :
404 : // Configure Transformation Engine
405 6 : uInt width = spwChanbinMap_p[inputSPW];
406 6 : WeightedChannelAverageKernel<Complex> kernel;
407 6 : ChannelAverageTransformEngine<Complex> transformer(&kernel,&inputData,&outputData,width);
408 :
409 : // Transform data
410 : if (DOJUSTO) {
411 : transformFreqAxis2(vb->getShape(),transformer);
412 : } else {
413 6 : transformer.transformAll();
414 :
415 : /*
416 : // Demo version upon which upgrades to DataCubeHolder/Map (in UtilsTVI.h)
417 : // and ChannelAverageTransformEngine::transformAll() are based
418 : // As written here, it averages _all_ channels (no
419 : // partial binning is supported).
420 : // NB: This is a bit faster than transformAll
421 : // (due mainly to fewer function calls? E.g. kernel.kernel()? )
422 : vis.set(0.0f); // initialize the output cube
423 : Cube<Complex> ivis(vb->visCubeCorrected());
424 : Cube<Float> iwtsp(vb->weightSpectrum());
425 : Cube<Bool> ifl(vb->flagCube());
426 : VectorIterator<Complex> vi(ivis,1);
427 : VectorIterator<Float> wi(iwtsp,1);
428 : VectorIterator<Bool> fi(ifl,1);
429 : VectorIterator<Complex> vo(vis,1);
430 :
431 : Vector<Complex>& viv = vi.vector();
432 : Vector<Float>& wiv = wi.vector();
433 : Vector<Bool>& fiv = fi.vector();
434 : Vector<Complex>& vov = vo.vector();
435 :
436 : Int nchan=viv.nelements();
437 :
438 : while (!vi.pastEnd()) {
439 :
440 : Float swt(0.0f);
441 : for (Int ich=0;ich<nchan;++ich) {
442 : if (!fiv(ich)) {
443 : vov(0)+=(viv(ich)*wiv(ich));
444 : swt+=wiv(ich);
445 : }
446 : }
447 : if (swt>0.0f)
448 : vov(0)/=swt;
449 : else
450 : vov(0)=0.0;
451 :
452 : vi.next();
453 : wi.next();
454 : fi.next();
455 : vo.next();
456 : }
457 : */
458 : }
459 :
460 : #ifdef _OPENMP
461 : // Accumulate elapsed time
462 6 : Tcd_+=omp_get_wtime()-time0;
463 : #endif
464 :
465 6 : return;
466 6 : }
467 :
468 : // -----------------------------------------------------------------------
469 : //
470 : // -----------------------------------------------------------------------
471 6 : void ChannelAverageTVI::visibilityModel (Cube<Complex> & vis) const
472 : {
473 :
474 : // Pass-thru for single-channel case
475 6 : if (getVii()->visibilityShape()[1]==1) {
476 0 : getVii()->visibilityModel(vis);
477 0 : return;
478 : }
479 :
480 : // Get input VisBuffer and SPW
481 6 : VisBuffer2 *vb = getVii()->getVisBuffer();
482 6 : Int inputSPW = vb->spectralWindows()(0);
483 :
484 : // Pass-thru for chanbin=1 case:
485 6 : if (spwChanbinMap_p[inputSPW]==1) {
486 0 : getVii()->visibilityModel(vis);
487 0 : return;
488 : }
489 :
490 : #ifdef _OPENMP
491 : // Pre-load relevant input info and start clock
492 6 : vb->visCubeModel();
493 6 : vb->flagCube();
494 6 : vb->weightSpectrum();
495 6 : Double time0=omp_get_wtime();
496 : #endif
497 :
498 :
499 : // Reshape output data before passing it to the DataCubeHolder
500 6 : vis.resize(getVisBuffer()->getShape(),false);
501 :
502 : // Gather input data
503 6 : DataCubeMap inputData;
504 6 : DataCubeHolder<Complex> inputVisCubeHolder(vb->visCubeModel());
505 6 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
506 6 : inputData.add(MS::DATA,inputVisCubeHolder);
507 6 : inputData.add(MS::FLAG,inputFlagCubeHolder);
508 :
509 : // Gather output data
510 6 : DataCubeMap outputData;
511 6 : DataCubeHolder<Complex> outputVisCubeHolder(vis);
512 6 : outputData.add(MS::DATA,outputVisCubeHolder);
513 :
514 : // Configure Transformation Engine
515 6 : uInt width = spwChanbinMap_p[inputSPW];
516 6 : FlaggedChannelAverageKernel<Complex> kernel;
517 6 : ChannelAverageTransformEngine<Complex> transformer(&kernel,&inputData,&outputData,width);
518 :
519 : // Transform data
520 : if (DOJUSTO) {
521 : transformFreqAxis2(vb->getShape(),transformer);
522 : } else {
523 6 : transformer.transformAll();
524 : }
525 :
526 : #ifdef _OPENMP
527 : // Accumulate elapsed time
528 6 : Tmd_+=omp_get_wtime()-time0;
529 : #endif
530 :
531 6 : return;
532 6 : }
533 :
534 : // -----------------------------------------------------------------------
535 : //
536 : // -----------------------------------------------------------------------
537 6 : void ChannelAverageTVI::weightSpectrum(Cube<Float> &weightSp) const
538 : {
539 :
540 : // Pass-thru for single-channel case
541 6 : if (getVii()->visibilityShape()[1]==1) {
542 0 : getVii()->weightSpectrum(weightSp);
543 0 : return;
544 : }
545 :
546 : // Get input VisBuffer and SPW
547 6 : VisBuffer2 *vb = getVii()->getVisBuffer();
548 6 : Int inputSPW = vb->spectralWindows()(0);
549 :
550 : // Pass-thru for chanbin=1 case:
551 6 : if (spwChanbinMap_p[inputSPW]==1) {
552 0 : getVii()->weightSpectrum(weightSp);;
553 0 : return;
554 : }
555 :
556 : #ifdef _OPENMP
557 : // Pre-load relevant input info and start clock
558 6 : vb->weightSpectrum();
559 6 : vb->flagCube();
560 6 : Double time0=omp_get_wtime();
561 : #endif
562 :
563 :
564 : // Reshape output data before passing it to the DataCubeHolder
565 6 : weightSp.resize(getVisBuffer()->getShape(),false);
566 :
567 : // Gather input data
568 6 : DataCubeMap inputData;
569 6 : DataCubeHolder<Float> inputWeightCubeHolder(vb->weightSpectrum());
570 6 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
571 6 : inputData.add(MS::DATA,inputWeightCubeHolder);
572 6 : inputData.add(MS::FLAG,inputFlagCubeHolder);
573 :
574 : // Gather output data
575 6 : DataCubeMap outputData;
576 6 : DataCubeHolder<Float> outputWeightCubeHolder(weightSp);
577 6 : outputData.add(MS::DATA,outputWeightCubeHolder);
578 :
579 : // Configure Transformation Engine
580 6 : uInt width = spwChanbinMap_p[inputSPW];
581 6 : ChannelAccumulationKernel<Float> kernel;
582 6 : ChannelAverageTransformEngine<Float> transformer(&kernel,&inputData,&outputData,width);
583 :
584 : // Transform data
585 : if (DOJUSTO) {
586 : transformFreqAxis2(vb->getShape(),transformer);
587 : } else {
588 6 : transformer.transformAll();
589 : }
590 :
591 : #ifdef _OPENMP
592 : // Accumulate elapsed time
593 6 : Tws_+=omp_get_wtime()-time0;
594 : #endif
595 :
596 6 : return;
597 6 : }
598 :
599 : // -----------------------------------------------------------------------
600 : //
601 : // -----------------------------------------------------------------------
602 0 : void ChannelAverageTVI::sigmaSpectrum(Cube<Float> &sigmaSp) const
603 : {
604 : // Pass-thru for single-channel case
605 0 : if (getVii()->visibilityShape()[1]==1) {
606 0 : getVii()->sigmaSpectrum(sigmaSp);
607 0 : return;
608 : }
609 :
610 : // Get input VisBuffer and SPW
611 0 : VisBuffer2 *vb = getVii()->getVisBuffer();
612 0 : Int inputSPW = vb->spectralWindows()(0);
613 :
614 : // Pass-thru for chanbin=1 case:
615 0 : if (spwChanbinMap_p[inputSPW]==1) {
616 0 : getVii()->sigmaSpectrum(sigmaSp);;
617 0 : return;
618 : }
619 :
620 : #ifdef _OPENMP
621 : // Pre-load relevant input info and start clock
622 0 : vb->sigmaSpectrum();
623 0 : vb->flagCube();
624 0 : Double time0=omp_get_wtime();
625 : #endif
626 :
627 : // Reshape output data before passing it to the DataCubeHolder
628 0 : sigmaSp.resize(getVisBuffer()->getShape(),false);
629 :
630 : // Get weightSpectrum from sigmaSpectrum
631 0 : Cube<Float> weightSpFromSigmaSp;
632 0 : weightSpFromSigmaSp.resize(vb->sigmaSpectrum().shape(),false);
633 0 : weightSpFromSigmaSp = vb->sigmaSpectrum(); // = Operator makes a copy
634 0 : arrayTransformInPlace (weightSpFromSigmaSp,sigmaToWeight);
635 :
636 : // Gather input data
637 0 : DataCubeMap inputData;
638 0 : DataCubeHolder<Float> inputWeightCubeHolder(weightSpFromSigmaSp);
639 0 : DataCubeHolder<Bool> inputFlagCubeHolder(vb->flagCube());
640 0 : inputData.add(MS::DATA,inputWeightCubeHolder);
641 0 : inputData.add(MS::FLAG,inputFlagCubeHolder);
642 :
643 : // Gather output data
644 0 : DataCubeMap outputData;
645 0 : DataCubeHolder<Float> outputWeightCubeHolder(sigmaSp);
646 0 : outputData.add(MS::DATA,outputWeightCubeHolder);
647 :
648 : // Configure Transformation Engine
649 0 : uInt width = spwChanbinMap_p[inputSPW];
650 0 : ChannelAccumulationKernel<Float> kernel;
651 0 : ChannelAverageTransformEngine<Float> transformer(&kernel,&inputData,&outputData,width);
652 :
653 : // Transform data
654 : if (DOJUSTO) {
655 : transformFreqAxis2(vb->getShape(),transformer);
656 : } else {
657 0 : transformer.transformAll();
658 : }
659 :
660 : // Transform back from weight format to sigma format
661 0 : arrayTransformInPlace (sigmaSp,weightToSigma);
662 :
663 : #ifdef _OPENMP
664 : // Accumulate elapsed time
665 0 : Tss_+=omp_get_wtime()-time0;
666 : #endif
667 :
668 0 : return;
669 0 : }
670 :
671 : // -----------------------------------------------------------------------
672 : //
673 : // -----------------------------------------------------------------------
674 39 : Vector<Double> ChannelAverageTVI::getFrequencies ( Double time,
675 : Int frameOfReference,
676 : Int spectralWindowId,
677 : Int msId) const
678 : {
679 :
680 : // Pass-thru for chanbin=1 case
681 39 : if (spwChanbinMap_p[spectralWindowId]==1) {
682 0 : return getVii()->getFrequencies(time,frameOfReference,spectralWindowId,msId);
683 : }
684 :
685 : // Get frequencies from input VI, which we will process
686 39 : Vector<Double> inputFrequencies = getVii()->getFrequencies(time,frameOfReference,
687 39 : spectralWindowId,msId);
688 :
689 : // Pass-thru for single-channel case
690 : // NB: This does NOT depend on current iteration having same spw as specified spectralWindowId
691 : // NB: Nor does it rely on sensing the apparent shape of the visibility data object (so that need not be pre-filled)
692 39 : if (inputFrequencies.nelements()==1)
693 0 : return inputFrequencies;
694 :
695 : // Produce output (transformed) frequencies
696 39 : Vector<Double> outputFrecuencies(spwOutChanNumMap_p[spectralWindowId],0);
697 :
698 : // Gather input data
699 39 : DataCubeMap inputData;
700 39 : DataCubeHolder<Double> inputFrecuenciesHolder(inputFrequencies);
701 39 : inputData.add(MS::DATA,inputFrecuenciesHolder);
702 :
703 : // Gather output data
704 39 : DataCubeMap outputData;
705 39 : DataCubeHolder<Double> outputFrecuenciesHolder(outputFrecuencies);
706 39 : outputData.add(MS::DATA,outputFrecuenciesHolder);
707 :
708 : // Configure Transformation Engine
709 39 : PlainChannelAverageKernel<Double> kernel;
710 39 : uInt width = spwChanbinMap_p[spectralWindowId];
711 39 : ChannelAverageTransformEngine<Double> transformer(&kernel,&inputData,&outputData,width);
712 :
713 : // Transform data
714 39 : transformer.transform();
715 :
716 39 : return outputFrecuencies;
717 39 : }
718 :
719 0 : Vector<Double> ChannelAverageTVI::getChanWidths ( Double time,
720 : Int frameOfReference,
721 : Int spectralWindowId,
722 : Int msId) const
723 : {
724 :
725 : // Pass-thru for chanbin=1 case
726 0 : if (spwChanbinMap_p[spectralWindowId]==1) {
727 0 : return getVii()->getChanWidths(time,frameOfReference,spectralWindowId,msId);
728 : }
729 :
730 : // Get widths from input VI
731 0 : Vector<Double> inputWidths = getVii()->getChanWidths(time,frameOfReference,
732 0 : spectralWindowId,msId);
733 : // Pass-thru for single-channel case
734 : // NB: This does NOT depend on current iteration having same spw as specified spectralWindowId
735 : // NB: Nor does it rely on sensing the apparent shape of the visibility data object (so that need not be pre-filled)
736 0 : if (inputWidths.nelements()==1)
737 0 : return inputWidths;
738 :
739 : // Produce output (summed) widths
740 0 : Vector<Double> outputWidths(spwOutChanNumMap_p[spectralWindowId],0);
741 :
742 : // Gather input data
743 0 : DataCubeMap inputData;
744 0 : DataCubeHolder<Double> inputWidthsHolder(inputWidths);
745 0 : inputData.add(MS::DATA,inputWidthsHolder);
746 : // We need flag vector (all false==unflagged) for ChannelAccumulationKernal (which just adds within bins)
747 0 : Vector<Bool> nonflagged(inputWidths.nelements(),false);
748 0 : DataCubeHolder<Bool> inputFlagHolder(nonflagged);
749 0 : inputData.add(MS::FLAG,inputFlagHolder);
750 :
751 : // Gather output data
752 0 : DataCubeMap outputData;
753 0 : DataCubeHolder<Double> outputWidthsHolder(outputWidths);
754 0 : outputData.add(MS::DATA,outputWidthsHolder);
755 :
756 : // Configure Transformation Engine
757 : //PlainChannelAverageKernel<Double> kernel;
758 0 : ChannelAccumulationKernel<Double> kernel;
759 0 : uInt width = spwChanbinMap_p[spectralWindowId];
760 0 : ChannelAverageTransformEngine<Double> transformer(&kernel,&inputData,&outputData,width);
761 :
762 : // Transform data
763 0 : transformer.transform();
764 :
765 0 : return outputWidths;
766 0 : }
767 :
768 : // -----------------------------------------------------------------------
769 : //
770 : // -----------------------------------------------------------------------
771 180 : void ChannelAverageTVI::writeFlag (const Cube<Bool> & flag)
772 : {
773 : // Create a flag cube with the input VI shape
774 180 : Cube<Bool> propagatedFlagCube;
775 180 : propagatedFlagCube = getVii()->getVisBuffer()->flagCube();
776 :
777 : // Propagate flags from the input cube to the propagated flag cube
778 180 : propagateChanAvgFlags(flag,propagatedFlagCube);
779 :
780 : // Pass propagated flag cube downstream for further propagation and/or writting
781 180 : getVii()->writeFlag(propagatedFlagCube);
782 :
783 360 : return;
784 180 : }
785 :
786 : /**
787 : * Strategy to support different ways of propagating flags from the 'transformed' cube to
788 : * the original ('propagated') cube. Iterates through rows, channels, correlations.
789 : *
790 : * This is meant to be used from propagateChanAvgFlags with at least two alternative
791 : * functors. One to propagate flags as required by flagdata (preserve pre-existing flags
792 : * in the original data cube), and a second one to propagate flags as required by plotms.
793 : * CAS-12737, CAS-9985, CAS-12205.
794 : *
795 : * @param transformedFlagCube Cube of flags after averaging
796 : * @param propagatedFlagClube Original cube of flags
797 : * @param inputOutputChan input->output channel mapping
798 : * @param propagate functor to implement the (back)propagation of flags (flagdata/plotms).
799 : */
800 : template <typename Functor>
801 180 : void cubePropagateFlags(const Cube<Bool> &transformedFlagCube,
802 : Cube<Bool> &propagatedFlagCube,
803 : const Vector<uInt> &inputOutputChan, Functor propagate)
804 : {
805 : // Get propagated (input) shape
806 180 : const auto inputShape = propagatedFlagCube.shape();
807 180 : const uInt nCorr = inputShape(0);
808 180 : const uInt nChan = inputShape(1);
809 180 : const uInt nRows = inputShape(2);
810 :
811 : // Get transformed (output) shape
812 180 : const auto transformedShape = transformedFlagCube.shape();
813 180 : const auto nTransChan = transformedShape(1);
814 :
815 : uInt outChan;
816 53098 : for (size_t row_i =0;row_i<nRows;row_i++)
817 : {
818 2216109 : for (size_t chan_i =0;chan_i<nChan;chan_i++)
819 : {
820 2163191 : outChan = inputOutputChan(chan_i);
821 2163191 : if (outChan < nTransChan) // outChan >= nChan may happen when channels are dropped
822 : {
823 7462982 : for (size_t corr_i =0;corr_i<nCorr;corr_i++)
824 5299791 : propagate(row_i, chan_i, corr_i, outChan);
825 : }
826 : }
827 : }
828 180 : }
829 :
830 : // -----------------------------------------------------------------------
831 : //
832 : // -----------------------------------------------------------------------
833 180 : void ChannelAverageTVI::propagateChanAvgFlags (const Cube<Bool> &transformedFlagCube,
834 : Cube<Bool> &propagatedFlagCube)
835 : {
836 : // Get current SPW and chanbin
837 180 : const VisBuffer2 *inputVB = getVii()->getVisBuffer();
838 180 : const Int inputSPW = inputVB->spectralWindows()(0);
839 180 : const uInt width = spwChanbinMap_p[inputSPW];
840 :
841 : // Map input-output channel
842 180 : const uInt nChan = propagatedFlagCube.shape()(1);
843 180 : uInt binCounts = 0;
844 180 : uInt transformedIndex = 0;
845 180 : Vector<uInt> inputOutputChan(nChan);
846 8161 : for (size_t chan_i =0;chan_i<nChan;chan_i++)
847 : {
848 7981 : binCounts += 1;
849 :
850 7981 : if (binCounts > width)
851 : {
852 763 : binCounts = 1;
853 763 : transformedIndex += 1;
854 : }
855 :
856 7981 : inputOutputChan(chan_i) = transformedIndex;
857 : }
858 :
859 : // Propagate chan-avg flags
860 : // Keeping two separate alternatives for 'flagdataFlagPropagation_p' (CAS-12737,
861 : // CAS-9985) until this issue is better settled.
862 180 : if (flagdataFlagPropagation_p)
863 : {
864 180 : cubePropagateFlags(transformedFlagCube, propagatedFlagCube, inputOutputChan,
865 5299791 : [&transformedFlagCube, &propagatedFlagCube]
866 7177470 : (size_t row_i, size_t chan_i, size_t corr_i, uInt outChan) {
867 5299791 : if (transformedFlagCube(corr_i, outChan, row_i))
868 1877679 : propagatedFlagCube(corr_i, chan_i, row_i) = true;
869 5299791 : });
870 : }
871 : else
872 : {
873 0 : cubePropagateFlags(transformedFlagCube, propagatedFlagCube, inputOutputChan,
874 0 : [&transformedFlagCube, &propagatedFlagCube]
875 0 : (size_t row_i, size_t chan_i, size_t corr_i, uInt outChan) {
876 0 : propagatedFlagCube(corr_i, chan_i, row_i) =
877 0 : transformedFlagCube(corr_i, outChan, row_i);
878 0 : });
879 : }
880 180 : }
881 :
882 : //////////////////////////////////////////////////////////////////////////
883 : // ChannelAverageTVIFactory class
884 : //////////////////////////////////////////////////////////////////////////
885 :
886 : // -----------------------------------------------------------------------
887 : //
888 : // -----------------------------------------------------------------------
889 0 : ChannelAverageTVIFactory::ChannelAverageTVIFactory (Record &configuration,
890 0 : ViImplementation2 *inputVii)
891 : {
892 0 : inputVii_p = inputVii;
893 0 : configuration_p = configuration;
894 0 : }
895 :
896 : // -----------------------------------------------------------------------
897 : //
898 : // -----------------------------------------------------------------------
899 0 : vi::ViImplementation2 * ChannelAverageTVIFactory::createVi() const
900 : {
901 0 : return new ChannelAverageTVI(inputVii_p,configuration_p);
902 : }
903 :
904 : //////////////////////////////////////////////////////////////////////////
905 : // ChannelAverageTVILayerFactory class
906 : //////////////////////////////////////////////////////////////////////////
907 :
908 21 : ChannelAverageTVILayerFactory::ChannelAverageTVILayerFactory(Record &configuration) :
909 : ViiLayerFactory(),
910 21 : configuration_p(configuration)
911 21 : {}
912 :
913 : ViImplementation2*
914 21 : ChannelAverageTVILayerFactory::createInstance(ViImplementation2* vii0) const
915 : {
916 : // Make the ChannelAverageTVi2, using supplied ViImplementation2, and return it
917 21 : ViImplementation2 *vii = new ChannelAverageTVI(vii0,configuration_p);
918 21 : return vii;
919 : }
920 :
921 :
922 : //////////////////////////////////////////////////////////////////////////
923 : // ChannelAverageTransformEngine class
924 : //////////////////////////////////////////////////////////////////////////
925 :
926 : // -----------------------------------------------------------------------
927 : //
928 : // -----------------------------------------------------------------------
929 425 : template<class T> ChannelAverageTransformEngine<T>::ChannelAverageTransformEngine( ChannelAverageKernel<T> *kernel,
930 : DataCubeMap *inputData,
931 : DataCubeMap *outputData,
932 : uInt width):
933 : FreqAxisTransformEngine2<T>(inputData,
934 425 : outputData)
935 : {
936 425 : width_p = width;
937 425 : chanAvgKernel_p = kernel;
938 425 : }
939 :
940 : // -----------------------------------------------------------------------
941 : //
942 : // -----------------------------------------------------------------------
943 386 : template<class T> void ChannelAverageTransformEngine<T>::transformAll()
944 : {
945 : // NB: Does NOT implement "parallelCorrAxis" option
946 : // (see, e.g., FreqAxisTVI::transformFreqAxis2(...))
947 :
948 : // Set up the VectorIterators inside the DataCubeMap/Holders
949 386 : inputData_p->setupVecIter();
950 386 : outputData_p->setupVecIter();
951 :
952 : // Iterate implicitly over row and correlation
953 289782 : while (!inputData_p->pastEnd()) {
954 289396 : this->transform(); // processes the current channel axis
955 289396 : inputData_p->next();
956 289396 : outputData_p->next();
957 : }
958 386 : }
959 :
960 :
961 : // -----------------------------------------------------------------------
962 : //
963 : // -----------------------------------------------------------------------
964 289435 : template<class T> void ChannelAverageTransformEngine<T>::transform()
965 : {
966 289435 : uInt startChan = 0;
967 289435 : uInt outChanIndex = 0;
968 289435 : uInt inputSize = inputData_p->getVectorShape()(0);
969 289435 : uInt outputSize = outputData_p->getVectorShape()(0);
970 289435 : uInt tail = inputSize % width_p;
971 289435 : uInt limit = inputSize - tail;
972 1109313 : while (startChan < limit)
973 : {
974 819878 : chanAvgKernel_p->kernel(inputData_p,outputData_p,
975 : startChan,outChanIndex,width_p);
976 819878 : startChan += width_p;
977 819878 : outChanIndex += 1;
978 : }
979 :
980 289435 : if (tail and (outChanIndex <= outputSize - 1) )
981 : {
982 65 : chanAvgKernel_p->kernel(inputData_p,outputData_p,
983 : startChan,outChanIndex,tail);
984 : }
985 :
986 289435 : return;
987 : }
988 :
989 : //////////////////////////////////////////////////////////////////////////
990 : // PlainChannelAverageKernel class
991 : // (numerical averaging, ignoring flags)
992 : //////////////////////////////////////////////////////////////////////////
993 :
994 : // -----------------------------------------------------------------------
995 : //
996 : // -----------------------------------------------------------------------
997 347 : template<class T> void PlainChannelAverageKernel<T>::kernel( DataCubeMap *inputData,
998 : DataCubeMap *outputData,
999 : uInt startInputPos,
1000 : uInt outputPos,
1001 : uInt width)
1002 : {
1003 347 : Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
1004 347 : Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
1005 :
1006 347 : uInt pos = startInputPos + 1;
1007 347 : uInt counts = 1;
1008 347 : T avg = inputVector(startInputPos);
1009 2496 : while (counts < width)
1010 : {
1011 2149 : avg += inputVector(pos);
1012 2149 : counts += 1;
1013 2149 : pos += 1;
1014 : }
1015 :
1016 347 : if (counts > 0)
1017 : {
1018 347 : avg /= counts;
1019 : }
1020 :
1021 347 : outputVector(outputPos) = avg;
1022 :
1023 347 : return;
1024 : }
1025 :
1026 : //////////////////////////////////////////////////////////////////////////
1027 : // FlaggedChannelAverageKernel class
1028 : // (numerical averaging, respecting flags)
1029 : //////////////////////////////////////////////////////////////////////////
1030 :
1031 : // -----------------------------------------------------------------------
1032 : //
1033 : // -----------------------------------------------------------------------
1034 25776 : template<class T> void FlaggedChannelAverageKernel<T>::kernel(DataCubeMap *inputData,
1035 : DataCubeMap *outputData,
1036 : uInt startInputPos,
1037 : uInt outputPos,
1038 : uInt width)
1039 : {
1040 25776 : T avg = 0;
1041 25776 : T normalization = 0;
1042 25776 : uInt inputPos = 0;
1043 25776 : Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
1044 25776 : Vector<Bool> &inputFlagVector = inputData->getVector<Bool>(MS::FLAG);
1045 25776 : Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
1046 25776 : Bool accumulatorFlag = inputFlagVector(startInputPos);
1047 :
1048 850608 : for (uInt sample_i=0;sample_i<width;sample_i++)
1049 : {
1050 : // Get input index
1051 824832 : inputPos = startInputPos + sample_i;
1052 :
1053 : // true/true or false/false
1054 824832 : if (accumulatorFlag == inputFlagVector(inputPos))
1055 : {
1056 824832 : normalization += 1.0f;
1057 824832 : avg += inputVector(inputPos);
1058 : }
1059 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
1060 0 : else if ( (accumulatorFlag == true) and (inputFlagVector(inputPos) == false) )
1061 : {
1062 0 : accumulatorFlag = false;
1063 0 : normalization = 1.0f;
1064 0 : avg = inputVector(inputPos);
1065 : }
1066 :
1067 : }
1068 :
1069 :
1070 : // Apply normalization factor
1071 25776 : if (normalization > 0)
1072 : {
1073 25776 : avg /= normalization;
1074 25776 : outputVector(outputPos) = avg;
1075 : }
1076 : // If all weights are zero set accumulatorFlag to true
1077 : else
1078 : {
1079 0 : accumulatorFlag = true;
1080 0 : outputVector(outputPos) = 0; // If all weights are zero then the avg is 0 too
1081 : }
1082 :
1083 51552 : return;
1084 : }
1085 :
1086 : //////////////////////////////////////////////////////////////////////////
1087 : // WeightedChannelAverageKernel class
1088 : // (weighted averaging, respecting flags)
1089 : //////////////////////////////////////////////////////////////////////////
1090 :
1091 : // -----------------------------------------------------------------------
1092 : //
1093 : // -----------------------------------------------------------------------
1094 396900 : template<class T> void WeightedChannelAverageKernel<T>::kernel( DataCubeMap *inputData,
1095 : DataCubeMap *outputData,
1096 : uInt startInputPos,
1097 : uInt outputPos,
1098 : uInt width)
1099 : {
1100 396900 : T avg = 0;
1101 396900 : T normalization = 0;
1102 396900 : uInt inputPos = 0;
1103 396900 : Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
1104 396900 : Vector<Bool> &inputFlagVector = inputData->getVector<Bool>(MS::FLAG);
1105 396900 : Vector<Float> &inputWeightVector = inputData->getVector<Float>(MS::WEIGHT_SPECTRUM);
1106 396900 : Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
1107 396900 : Bool accumulatorFlag = inputFlagVector(startInputPos);
1108 :
1109 6797992 : for (uInt sample_i=0;sample_i<width;sample_i++)
1110 : {
1111 : // Get input index
1112 6401092 : inputPos = startInputPos + sample_i;
1113 :
1114 6401092 : Float& wt=inputWeightVector(inputPos);
1115 :
1116 : // true/true or false/false
1117 6401092 : if (accumulatorFlag == inputFlagVector(inputPos))
1118 : {
1119 6399764 : normalization += wt;
1120 6399764 : avg += inputVector(inputPos)*wt;
1121 : }
1122 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
1123 1328 : else if ( (accumulatorFlag == true) and (inputFlagVector(inputPos) == false) )
1124 : {
1125 1328 : accumulatorFlag = false;
1126 1328 : normalization = inputWeightVector(inputPos);
1127 1328 : avg = inputVector(inputPos)*inputWeightVector(inputPos);
1128 : }
1129 : }
1130 :
1131 :
1132 : // Apply normalization factor
1133 396900 : if (normalization > 0)
1134 : {
1135 396900 : avg /= normalization;
1136 396900 : outputVector(outputPos) = avg;
1137 : }
1138 : // If all weights are zero set accumulatorFlag to true
1139 : else
1140 : {
1141 0 : accumulatorFlag = true;
1142 0 : outputVector(outputPos) = 0; // If all weights are zero then the avg is 0 too
1143 : }
1144 :
1145 793800 : return;
1146 : }
1147 :
1148 : //////////////////////////////////////////////////////////////////////////
1149 : // LogicalANDKernel class
1150 : //////////////////////////////////////////////////////////////////////////
1151 :
1152 : // -----------------------------------------------------------------------
1153 : //
1154 : // -----------------------------------------------------------------------
1155 396910 : template<class T> void LogicalANDKernel<T>::kernel( DataCubeMap *inputData,
1156 : DataCubeMap *outputData,
1157 : uInt startInputPos,
1158 : uInt outputPos,
1159 : uInt width)
1160 : {
1161 396910 : Vector<Bool> &inputVector = inputData->getVector<Bool>(MS::FLAG);
1162 396910 : Vector<Bool> &outputVector = outputData->getVector<Bool>(MS::FLAG);
1163 :
1164 396910 : Bool outputFlag = true;
1165 398254 : for (uInt sample_i=0;sample_i<width;sample_i++)
1166 : {
1167 398238 : if (not inputVector(startInputPos+sample_i))
1168 : {
1169 396894 : outputFlag = false;
1170 396894 : break;
1171 : }
1172 : }
1173 396910 : outputVector(outputPos) = outputFlag;
1174 :
1175 396910 : return;
1176 : }
1177 :
1178 : //////////////////////////////////////////////////////////////////////////
1179 : // ChannelAccumulationKernel class
1180 : // (numerical accumulation, respecting flags)
1181 : //////////////////////////////////////////////////////////////////////////
1182 :
1183 : // -----------------------------------------------------------------------
1184 : //
1185 : // -----------------------------------------------------------------------
1186 10 : template<class T> void ChannelAccumulationKernel<T>::kernel( DataCubeMap *inputData,
1187 : DataCubeMap *outputData,
1188 : uInt startInputPos,
1189 : uInt outputPos,
1190 : uInt width)
1191 : {
1192 10 : T acc = 0;
1193 10 : uInt inputPos = 0;
1194 10 : Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
1195 10 : Vector<Bool> &inputFlagVector = inputData->getVector<Bool>(MS::FLAG);
1196 10 : Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
1197 10 : Bool accumulatorFlag = inputFlagVector(startInputPos);
1198 :
1199 304 : for (uInt sample_i=0;sample_i<width;sample_i++)
1200 : {
1201 : // Get input index
1202 294 : inputPos = startInputPos + sample_i;
1203 :
1204 : // true/true or false/false
1205 294 : if (accumulatorFlag == inputFlagVector(inputPos))
1206 : {
1207 294 : acc += inputVector(inputPos);
1208 : }
1209 : // true/false: Reset accumulation when accumulator switches from flagged to unflag
1210 0 : else if ( (accumulatorFlag == true) and (inputFlagVector(inputPos) == false) )
1211 : {
1212 0 : accumulatorFlag = false;
1213 0 : acc = inputVector(inputPos);
1214 : }
1215 : }
1216 :
1217 :
1218 10 : outputVector(outputPos) = acc;
1219 :
1220 10 : return;
1221 : }
1222 :
1223 : } //# NAMESPACE VI - END
1224 :
1225 : } //# NAMESPACE CASA - END
1226 :
1227 :
|