LCOV - code coverage report
Current view: top level - mstransform/TVI - PolAverageTVI.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 461 0.0 %
Date: 2024-10-29 13:38:20 Functions: 0 69 0.0 %

          Line data    Source code
       1             : //# PolAverageTVI.h: This file contains the implementation of the PolAverageTVI 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             : #include <mstransform/TVI/PolAverageTVI.h>
      23             : 
      24             : #include <casacore/casa/Arrays/Cube.h>
      25             : #include <casacore/casa/Arrays/Matrix.h>
      26             : #include <casacore/casa/Arrays/Vector.h>
      27             : #include <casacore/casa/BasicSL/String.h>
      28             : #include <casacore/casa/Logging/LogIO.h>
      29             : #include <casacore/casa/Containers/Record.h>
      30             : #include <casacore/casa/Exceptions/Error.h>
      31             : #include <casacore/casa/Arrays/ArrayIter.h>
      32             : #include <casacore/measures/Measures/Stokes.h>
      33             : #include <casacore/ms/MeasurementSets/MSDataDescColumns.h>
      34             : #include <casacore/ms/MeasurementSets/MSPolColumns.h>
      35             : 
      36             : #include <msvis/MSVis/VisBufferComponents2.h>
      37             : #include <msvis/MSVis/VisibilityIteratorImpl2.h>
      38             : 
      39             : #include <mstransform/TVI/UtilsTVI.h>
      40             : 
      41             : using namespace casacore;
      42             : 
      43             : namespace {
      44             : template<class T>
      45           0 : inline T replaceFlaggedDataWithZero(T v, Bool b) {
      46           0 :   return ((b) ? T(0) : v);
      47             : }
      48             : 
      49             : struct StokesTransformation {
      50             : public:
      51             :   template<class T>
      52           0 :   inline static void transformData(Cube<T> const &dataIn,
      53             :       Cube<Bool> const &flagIn, Int pid0, Int pid1, Cube<T> &dataOut) {
      54           0 :     if (dataIn.empty()) {
      55           0 :       dataOut.resize();
      56           0 :       return;
      57             :     }
      58           0 :     auto const cubeShape = dataIn.shape();
      59           0 :     IPosition const newShape(3, 1, cubeShape[1], cubeShape[2]);
      60             : //    size_t const npol = cubeShape[0];
      61           0 :     size_t const nchan = cubeShape[1];
      62           0 :     size_t const nrow = cubeShape[2];
      63           0 :     size_t const nelem = cubeShape[1] * cubeShape[2];
      64           0 :     Cube<T> transformedData(newShape, T(0));
      65           0 :     Cube<Float> weightSum(newShape, 0.0f);
      66             : 
      67           0 :     Int pols[] = { pid0, pid1 };
      68           0 :     for (size_t i = 0; i < 2; ++i) {
      69           0 :       Int ipol = pols[i];
      70           0 :       IPosition start(3, ipol, 0, 0);
      71           0 :       IPosition end(3, ipol, nchan - 1, nrow - 1);
      72           0 :       auto dslice = dataIn(start, end);
      73           0 :       auto fslice = flagIn(start, end);
      74           0 :       Array<Float> weight(dslice.shape());
      75           0 :       Array<T> weightedData(dslice.shape());
      76           0 :       arrayContTransform(dslice, fslice, weightedData,
      77             :           replaceFlaggedDataWithZero<T>);
      78           0 :       arrayContTransform(fslice, weight, [](Bool b) {
      79           0 :         return ((b) ? 0.0f : 1.0f);
      80             :       });
      81           0 :       transformedData += weightedData;
      82           0 :       weightSum += weight;
      83             :     }
      84             : 
      85             :     // transformedData, transformedFlag and nAccumulated should be contiguous array
      86           0 :     auto p_tdata = transformedData.data();
      87           0 :     auto p_wsum = weightSum.data();
      88             : 
      89           0 :     for (size_t i = 0; i < nelem; ++i) {
      90           0 :       if (p_wsum[i] > 0.0) {
      91           0 :         p_tdata[i] /= T(p_wsum[i]);
      92             :       }
      93             :     }
      94             : 
      95           0 :     dataOut.reference(transformedData);
      96           0 :   }
      97             : 
      98           0 :   static inline void AccumulateWeight(Float const wt, Double &wtsum) {
      99           0 :     wtsum += 1.0 / wt;
     100           0 :   }
     101             : 
     102           0 :   static inline void NormalizeWeight(Double const wtsum, Float &wt) {
     103           0 :     wt = 4.0 / wtsum;
     104           0 :   }
     105             : };
     106             : 
     107             : struct GeometricTransformation {
     108             :   template<class T>
     109           0 :   inline static void transformData(Cube<T> const &dataIn,
     110             :       Cube<Bool> const &flagIn, Cube<Float> const &weightIn, Int pid0, Int pid1,
     111             :       Cube<T> &dataOut) {
     112           0 :     if (dataIn.empty()) {
     113           0 :       dataOut.resize();
     114           0 :       return;
     115             :     }
     116           0 :     auto const cubeShape = dataIn.shape();
     117           0 :     IPosition const newShape(3, 1, cubeShape[1], cubeShape[2]);
     118           0 :     Cube<T> transformedData(newShape, T(0));
     119           0 :     Cube<Bool> transformedFlag(newShape, True);
     120           0 :     Cube<Float> weightSum(newShape, 0.0f);
     121             : //    size_t const npol = cubeShape[0];
     122           0 :     size_t const nchan = cubeShape[1];
     123           0 :     size_t const nrow = cubeShape[2];
     124           0 :     size_t const nelem = cubeShape[1] * cubeShape[2];
     125             : 
     126           0 :     Int pols[] = { pid0, pid1 };
     127           0 :     for (size_t i = 0; i < 2; ++i) {
     128           0 :       Int ipol = pols[i];
     129           0 :       IPosition start(3, ipol, 0, 0);
     130           0 :       IPosition end(3, ipol, nchan - 1, nrow - 1);
     131           0 :       auto const dslice = dataIn(start, end);
     132           0 :       auto const wslice = weightIn(start, end);
     133           0 :       auto const fslice = flagIn(start, end);
     134           0 :       Array<Float> weight(dslice.shape());
     135           0 :       Array<T> weightedData(dslice.shape());
     136           0 :       arrayContTransform(dslice * wslice, fslice, weightedData,
     137             :           replaceFlaggedDataWithZero<T>);
     138           0 :       arrayContTransform(wslice, fslice, weight,
     139             :           replaceFlaggedDataWithZero<Float>);
     140           0 :       transformedData += weightedData;
     141           0 :       weightSum += weight;
     142             :     }
     143             : 
     144             :     // transformedData, transformedFlag and nAccumulated should be contiguous array
     145           0 :     T *p_tdata = transformedData.data();
     146           0 :     Float *p_wsum = weightSum.data();
     147           0 :     for (size_t i = 0; i < nelem; ++i) {
     148           0 :       if (p_wsum[i] > 0.0) {
     149           0 :         p_tdata[i] /= T(p_wsum[i]);
     150             :       }
     151             :     }
     152             : 
     153           0 :     dataOut.reference(transformedData);
     154           0 :   }
     155             : 
     156             :   template<class T>
     157           0 :   inline static void transformData(Cube<T> const &dataIn,
     158             :       Cube<Bool> const &flagIn, Matrix<Float> const &weightIn, Int pid0,
     159             :       Int pid1, Cube<T> &dataOut) {
     160             : //    cout << "start " << __func__ << endl;
     161           0 :     if (dataIn.empty()) {
     162           0 :       dataOut.resize();
     163           0 :       return;
     164             :     }
     165           0 :     auto const cubeShape = dataIn.shape();
     166           0 :     IPosition const newShape(3, 1, cubeShape[1], cubeShape[2]);
     167           0 :     Cube<T> transformedData(newShape, T(0));
     168           0 :     Cube<Float> weightSum(newShape, 0.0f);
     169             : //    auto const npol = dataIn.shape()[0];
     170           0 :     auto const nchan = dataIn.shape()[1];
     171           0 :     auto const nrow = dataIn.shape()[2];
     172           0 :     auto const nelem = nchan * nrow;
     173             : 
     174           0 :     Int pols[] = { pid0, pid1 };
     175           0 :     for (ssize_t i = 0; i < 2; ++i) {
     176           0 :       Int ipol = pols[i];
     177           0 :       for (ssize_t j = 0; j < nrow; ++j) {
     178           0 :         IPosition start(3, ipol, 0, j);
     179           0 :         IPosition end(3, ipol, nchan - 1, j);
     180           0 :         auto dslice = dataIn(start, end);
     181           0 :         auto fslice = flagIn(start, end);
     182           0 :         auto w = weightIn(ipol, j);
     183           0 :         Array<Float> weight(dslice.shape());
     184           0 :         Array<T> weightedData(dslice.shape());
     185           0 :         arrayContTransform(dslice * w, fslice, weightedData,
     186             :             replaceFlaggedDataWithZero<T>);
     187           0 :         arrayContTransform(fslice, weight, [&w](Bool b) {
     188           0 :           return ((b) ? 0.0f: w);
     189             :         });
     190           0 :         IPosition tstart(3, 0, 0, j);
     191           0 :         IPosition tend(3, 0, nchan - 1, j);
     192           0 :         Array<T> tdSlice = transformedData(tstart, tend);
     193           0 :         Array<Float> twSlice = weightSum(tstart, tend);
     194           0 :         AlwaysAssert(tdSlice.conform(weightedData), AipsError);
     195           0 :         AlwaysAssert(twSlice.conform(weight), AipsError);
     196           0 :         tdSlice += weightedData;
     197           0 :         twSlice += weight;
     198             :       }
     199             :     }
     200             : 
     201             :     // transformedData, transformedFlag and nAccumulated should be contiguous array
     202           0 :     T *p_tdata = transformedData.data();
     203           0 :     Float *p_wsum = weightSum.data();
     204             : 
     205           0 :     for (ssize_t i = 0; i < nelem; ++i) {
     206           0 :       if (p_wsum[i] > 0.0) {
     207           0 :         p_tdata[i] /= T(p_wsum[i]);
     208             :       }
     209             :     }
     210             : 
     211           0 :     dataOut.reference(transformedData);
     212             : //    cout << "end " << __func__ << endl;
     213           0 :   }
     214             : 
     215           0 :   static inline void AccumulateWeight(Float const wt, Double &wtsum) {
     216           0 :     wtsum += wt;
     217           0 :   }
     218             : 
     219           0 :   static inline void NormalizeWeight(Double const wtsum, Float &wt) {
     220           0 :     wt = wtsum;
     221           0 :   }
     222             : };
     223             : 
     224           0 : inline Float weight2Sigma(Float x) {
     225           0 :   return 1.0 / sqrt(x);
     226             : }
     227             : 
     228             : template<class WeightHandler>
     229           0 : inline void transformWeight(Array<Float> const &weightIn, Int pid0, Int pid1,
     230             :     Array<Float> &weightOut) {
     231             : //  cout << "start " << __func__ << endl;
     232           0 :   if (weightIn.empty()) {
     233             : //    cout << "input weight is empty" << endl;
     234           0 :     weightOut.resize();
     235           0 :     return;
     236             :   }
     237           0 :   IPosition const shapeIn = weightIn.shape();
     238           0 :   IPosition shapeOut(shapeIn);
     239             :   // set length of polarization axis to 1
     240           0 :   shapeOut[0] = 1;
     241             : //  cout << "shapeIn = " << shapeIn << " shapeOut = " << shapeOut << endl;
     242             : 
     243             :   // initialization
     244           0 :   weightOut.resize(shapeOut);
     245           0 :   weightOut = 0.0f;
     246             : 
     247           0 :   ssize_t numPol = shapeIn[0];
     248           0 :   Int64 numElemPerPol = shapeOut.product();
     249             : //  cout << "numElemPerPol = " << numElemPerPol << endl;
     250             : //  cout << "numPol = " << numPol << endl;
     251             : 
     252             :   Bool b;
     253           0 :   Float const *p_wIn = weightIn.getStorage(b);
     254           0 :   Float *p_wOut = weightOut.data();
     255             : 
     256           0 :   Int pols[] = { pid0, pid1 };
     257           0 :   for (Int64 i = 0; i < numElemPerPol; ++i) {
     258           0 :     ssize_t offsetIndex = i * numPol;
     259           0 :     Double sum = 0.0;
     260           0 :     for (ssize_t j = 0; j < 2; ++j) {
     261           0 :       Int ipol = pols[j];
     262           0 :       WeightHandler::AccumulateWeight(p_wIn[offsetIndex + ipol], sum);
     263             :     }
     264           0 :     WeightHandler::NormalizeWeight(sum, p_wOut[i]);
     265             :   }
     266             : 
     267           0 :   weightIn.freeStorage(p_wIn, b);
     268           0 : }
     269             : } // anonymous namespace
     270             : 
     271             : namespace casa { //# NAMESPACE CASA - BEGIN
     272             : 
     273             : namespace vi { //# NAMESPACE VI - BEGIN
     274             : //////////
     275             : // Base Class
     276             : // PolAverageTVI
     277             : /////////
     278           0 : PolAverageTVI::PolAverageTVI(ViImplementation2 *inputVII) :
     279           0 :     TransformingVi2(inputVII) {
     280           0 :   configurePolAverage();
     281             : 
     282             :   // Initialize attached VisBuffer
     283           0 :   setVisBuffer(createAttachedVisBuffer(VbRekeyable));
     284           0 : }
     285             : 
     286           0 : PolAverageTVI::~PolAverageTVI() {
     287           0 : }
     288             : 
     289           0 : void PolAverageTVI::origin() {
     290           0 :   TransformingVi2::origin();
     291             : 
     292             :   // Configure the correlations per shape
     293           0 :   configureShapes();
     294             : 
     295             :   // Synchronize own VisBuffer
     296           0 :   configureNewSubchunk();
     297             : 
     298             :   // reconfigure if necessary
     299           0 :   reconfigurePolAverageIfNecessary();
     300             : 
     301             :   // warn if current dd is inappropriate for polarization averaging
     302           0 :   warnIfNoTransform();
     303           0 : }
     304             : 
     305           0 : void PolAverageTVI::next() {
     306           0 :   TransformingVi2::next();
     307             : 
     308             :   // Configure the correlations per shape
     309           0 :   configureShapes();
     310             : 
     311             :   // Synchronize own VisBuffer
     312           0 :   configureNewSubchunk();
     313             : 
     314             :   // reconfigure if necessary
     315           0 :   reconfigurePolAverageIfNecessary();
     316             : 
     317             :   // warn if current dd is inappropriate for polarization averaging
     318           0 :   warnIfNoTransform();
     319           0 : }
     320             : 
     321           0 : void PolAverageTVI::configureShapes() {
     322           0 :     Vector <Int> corrs = getCorrelations ();
     323           0 :     Int nCorrs = corrs.nelements();
     324             : 
     325           0 :     nCorrelationsPerShape_ = casacore::Vector<casacore::Int> (1, nCorrs);
     326           0 : }
     327             : 
     328           0 : void PolAverageTVI::warnIfNoTransform() {
     329           0 :   if (!doTransform_[dataDescriptionId()]) {
     330           0 :     auto const vb = getVii()->getVisBuffer();
     331           0 :     LogIO os(LogOrigin("PolAverageTVI", __func__, WHERE));
     332           0 :     String msg("Skip polarization average because");
     333           0 :     if (vb->nCorrelations() == 1) {
     334           0 :       msg += " number of polarizations is 1.";
     335           0 :     } else if (anyEQ(vb->correlationTypes(), (Int) Stokes::I)) {
     336           0 :       msg += " polarization type is Stokes.";
     337             :     } else {
     338           0 :       msg += " no valid polarization components are found.";
     339             :     }
     340           0 :     os << LogIO::WARN << msg << LogIO::POST;
     341           0 :   }
     342           0 : }
     343             : 
     344           0 : void PolAverageTVI::corrType(Vector<Int> & corrTypes) const {
     345           0 :   if (doTransform_[dataDescriptionId()]) {
     346             :     // Always return (Stokes::I)
     347           0 :     Vector<Int> myCorrTypes(1, (Int) Stokes::I);
     348           0 :     corrTypes.reference(myCorrTypes);
     349           0 :   } else {
     350           0 :     getVii()->corrType(corrTypes);
     351             :   }
     352           0 : }
     353             : 
     354           0 : void PolAverageTVI::flagRow(Vector<Bool> & rowflags) const {
     355           0 :   Cube<Bool> const &flags = getVisBuffer()->flagCube();
     356           0 :   accumulateFlagCube(flags, rowflags);
     357           0 : }
     358             : 
     359           0 : void PolAverageTVI::flag(Cube<Bool> & flags) const {
     360           0 :   auto const vb = getVii()->getVisBuffer();
     361           0 :   Cube<Bool> originalFlags = vb->flagCube();
     362           0 :   Int ddid = dataDescriptionId();
     363             : 
     364           0 :   if (doTransform_[ddid]) {
     365           0 :     auto const cubeShape = originalFlags.shape();
     366           0 :     IPosition const newShape(3, 1, cubeShape[1], cubeShape[2]);
     367           0 :     Cube<Bool> transformedFlags(newShape, True);
     368             :     // accumulate first polarization component
     369           0 :     IPosition start(3, polId0_[ddid], 0, 0);
     370           0 :     IPosition end(3, polId0_[ddid], cubeShape[1] - 1, cubeShape[2] - 1);
     371           0 :     transformedFlags = originalFlags(start, end);
     372             : 
     373             :     // accumulate second polarization component
     374           0 :     start[0] = polId1_[ddid];
     375           0 :     end[0] = polId1_[ddid];
     376           0 :     transformedFlags &= originalFlags(start, end);
     377           0 :     flags.reference(transformedFlags);
     378           0 :   } else {
     379           0 :     flags.reference(originalFlags);
     380             :   }
     381           0 : }
     382             : 
     383           0 : void PolAverageTVI::flag(Matrix<Bool> & flags) const {
     384           0 :   Cube<Bool> transformedFlags;
     385           0 :   flag(transformedFlags);
     386             : 
     387           0 :   flags.reference(transformedFlags.yzPlane(0));
     388           0 : }
     389             : 
     390           0 : void PolAverageTVI::jonesC(Vector<SquareMatrix<Complex, 2> > &cjones) const {
     391           0 :   if (doTransform_[dataDescriptionId()]) {
     392           0 :     throw AipsError("PolAverageTVI::jonesC should not be called.");
     393             :   } else {
     394           0 :     getVii()->jonesC(cjones);
     395             :   }
     396           0 : }
     397             : 
     398           0 : void PolAverageTVI::sigma(Matrix<Float> & sigmat) const {
     399           0 :   if (weightSpectrumExists()) {
     400           0 :     Cube<Float> const &sigmaSp = getVisBuffer()->sigmaSpectrum();
     401           0 :     Cube<Bool> const &flag = getVisBuffer()->flagCube();
     402           0 :     accumulateWeightCube(sigmaSp, flag, sigmat);
     403             :   } else {
     404           0 :     if (doTransform_[dataDescriptionId()]) {
     405           0 :       weight(sigmat);
     406           0 :       arrayTransformInPlace(sigmat, ::weight2Sigma);
     407             :     } else {
     408           0 :       getVii()->sigma(sigmat);
     409             :     }
     410             :   }
     411           0 : }
     412             : 
     413           0 : void PolAverageTVI::visibilityCorrected(Cube<Complex> & vis) const {
     414           0 :   if (getVii()->existsColumn(VisBufferComponent2::VisibilityCorrected)) {
     415           0 :     Cube<Complex> dataCube;
     416           0 :     getVii()->visibilityCorrected(dataCube);
     417           0 :     if (doTransform_[dataDescriptionId()]) {
     418           0 :       Cube<Bool> flagCube;
     419           0 :       getVii()->flag(flagCube);
     420           0 :       transformComplexData(dataCube, flagCube, vis);
     421           0 :     } else {
     422           0 :       vis.reference(dataCube);
     423             :     }
     424           0 :   } else {
     425           0 :     vis.resize();
     426             :   }
     427           0 : }
     428             : 
     429           0 : void PolAverageTVI::visibilityModel(Cube<Complex> & vis) const {
     430           0 :   if (getVii()->existsColumn(VisBufferComponent2::VisibilityModel)) {
     431           0 :     Cube<Complex> dataCube;
     432           0 :     getVii()->visibilityModel(dataCube);
     433           0 :     if (doTransform_[dataDescriptionId()]) {
     434           0 :       Cube<Bool> flagCube;
     435           0 :       getVii()->flag(flagCube);
     436           0 :       transformComplexData(dataCube, flagCube, vis);
     437           0 :     } else {
     438           0 :       vis.reference(dataCube);
     439             :     }
     440           0 :   } else {
     441           0 :     vis.resize();
     442             :   }
     443           0 : }
     444             : 
     445           0 : void PolAverageTVI::visibilityObserved(Cube<Complex> & vis) const {
     446           0 :   if (getVii()->existsColumn(VisBufferComponent2::VisibilityObserved)) {
     447           0 :     Cube<Complex> dataCube;
     448           0 :     getVii()->visibilityObserved(dataCube);
     449           0 :     if (doTransform_[dataDescriptionId()]) {
     450           0 :       Cube<Bool> flagCube;
     451           0 :       getVii()->flag(flagCube);
     452           0 :       transformComplexData(dataCube, flagCube, vis);
     453           0 :     } else {
     454           0 :       vis.reference(dataCube);
     455             :     }
     456           0 :   } else {
     457           0 :     vis.resize();
     458             :   }
     459           0 : }
     460             : 
     461           0 : void PolAverageTVI::floatData(casacore::Cube<casacore::Float> & fcube) const {
     462           0 :   if (getVii()->existsColumn(VisBufferComponent2::FloatData)) {
     463           0 :     Cube<Float> dataCube;
     464           0 :     getVii()->floatData(dataCube);
     465           0 :     if (doTransform_[dataDescriptionId()]) {
     466           0 :       Cube<Bool> flagCube;
     467           0 :       getVii()->flag(flagCube);
     468           0 :       transformFloatData(dataCube, flagCube, fcube);
     469           0 :     } else {
     470           0 :       fcube.reference(dataCube);
     471             :     }
     472           0 :   } else {
     473           0 :     fcube.resize();
     474             :   }
     475           0 : }
     476             : 
     477           0 : IPosition PolAverageTVI::visibilityShape() const {
     478           0 :   IPosition cubeShape = getVii()->visibilityShape();
     479           0 :   if (doTransform_[dataDescriptionId()]) {
     480             :     // Length of polarization (Stokes) axis is always 1 after polarizaton averaging
     481           0 :     cubeShape[0] = 1;
     482             :   }
     483           0 :   return cubeShape;
     484           0 : }
     485             : 
     486           0 : void PolAverageTVI::weight(Matrix<Float> & wtmat) const {
     487           0 :   if (weightSpectrumExists()) {
     488           0 :     Cube<Float> const &weightSp = getVisBuffer()->weightSpectrum();
     489           0 :     Cube<Bool> const &flag = getVisBuffer()->flagCube();
     490           0 :     accumulateWeightCube(weightSp, flag, wtmat);
     491             :   } else {
     492           0 :     Matrix<Float> wtmatOrg;
     493           0 :     getVii()->weight(wtmatOrg);
     494           0 :     if (doTransform_[dataDescriptionId()]) {
     495           0 :       transformWeight(wtmatOrg, wtmat);
     496             :     } else {
     497           0 :       wtmat.reference(wtmatOrg);
     498             :     }
     499           0 :   }
     500           0 : }
     501             : 
     502           0 : void PolAverageTVI::weightSpectrum(Cube<Float> & wtsp) const {
     503           0 :   if (weightSpectrumExists()) {
     504           0 :     Cube<Float> wtspOrg;
     505           0 :     getVii()->weightSpectrum(wtspOrg);
     506           0 :     if (doTransform_[dataDescriptionId()]) {
     507           0 :       transformWeight(wtspOrg, wtsp);
     508             :     } else {
     509           0 :       wtsp.reference(wtspOrg);
     510             :     }
     511           0 :   } else {
     512           0 :     wtsp.resize();
     513             :   }
     514           0 : }
     515             : 
     516           0 : void PolAverageTVI::sigmaSpectrum(Cube<Float> & wtsp) const {
     517           0 :   if (sigmaSpectrumExists()) {
     518           0 :     if (doTransform_[dataDescriptionId()]) {
     519             :       // sigma = (weight)^-1/2
     520           0 :       weightSpectrum(wtsp);
     521           0 :       arrayTransformInPlace(wtsp, ::weight2Sigma);
     522             :     } else {
     523           0 :       getVii()->sigmaSpectrum(wtsp);
     524             :     }
     525             :   } else {
     526           0 :     wtsp.resize();
     527             :   }
     528           0 : }
     529             : 
     530           0 : const VisImagingWeight & PolAverageTVI::getImagingWeightGenerator() const {
     531           0 :   if (doTransform_[dataDescriptionId()]) {
     532           0 :     throw AipsError(
     533           0 :         "PolAverageTVI::getImagingWeightGenerator should not be called.");
     534             :   }
     535             : 
     536           0 :   return getVii()->getImagingWeightGenerator();
     537             : }
     538             : 
     539           0 : Vector<Int> PolAverageTVI::getCorrelations() const {
     540           0 :   if (doTransform_[dataDescriptionId()]) {
     541             :     // Always return (Stokes::I)
     542           0 :     return Vector<Int>(1, Stokes::I);
     543             :   } else {
     544           0 :     return getVii()->getCorrelations();
     545             :   }
     546             : }
     547             : 
     548           0 : Vector<Stokes::StokesTypes> PolAverageTVI::getCorrelationTypesDefined() const {
     549           0 :   if (doTransform_[dataDescriptionId()]) {
     550             :     // Always return (Stokes::I)
     551           0 :     return Vector<Stokes::StokesTypes>(1, Stokes::I);
     552             :   } else {
     553           0 :     return getVii()->getCorrelationTypesDefined();
     554             :   }
     555             : }
     556             : 
     557           0 : Vector<Stokes::StokesTypes> PolAverageTVI::getCorrelationTypesSelected() const {
     558           0 :   if (doTransform_[dataDescriptionId()]) {
     559             :     // Always return (Stokes::I)
     560           0 :     return Vector<Stokes::StokesTypes>(1, Stokes::I);
     561             :   } else {
     562           0 :     return getVii()->getCorrelationTypesSelected();
     563             :   }
     564             : }
     565             : 
     566             : const casacore::Vector<casacore::Int>&
     567           0 : PolAverageTVI::nCorrelationsPerShape() const {
     568           0 :   return nCorrelationsPerShape_;
     569             : }
     570             : 
     571           0 : void PolAverageTVI::configurePolAverage() {
     572           0 :   MeasurementSet const &ms = getVii()->ms();
     573           0 :   auto const &msdd = ms.dataDescription();
     574           0 :   MSDataDescColumns msddcols(msdd);
     575           0 :   uInt ndd = msddcols.nrow();
     576           0 :   Vector<Int> polIds = msddcols.polarizationId().getColumn();
     577           0 :   doTransform_.resize(ndd);
     578           0 :   polId0_.resize(ndd);
     579           0 :   polId1_.resize(ndd);
     580           0 :   auto const &mspol = ms.polarization();
     581           0 :   MSPolarizationColumns mspolcols(mspol);
     582           0 :   doTransform_ = False;
     583           0 :   for (uInt idd = 0; idd < ndd; ++idd) {
     584           0 :     Vector<Int> corrType = mspolcols.corrType()(polIds[idd]);
     585           0 :     polId0_[idd] = -1;
     586           0 :     polId1_[idd] = -1;
     587           0 :     for (size_t i = 0; i < corrType.size(); ++i) {
     588           0 :       auto stokesType = Stokes::type(corrType[i]);
     589           0 :       if (stokesType == Stokes::XX || stokesType == Stokes::RR) {
     590           0 :         polId0_[idd] = i;
     591           0 :       } else if (stokesType == Stokes::YY || stokesType == Stokes::LL) {
     592           0 :         polId1_[idd] = i;
     593             :       }
     594             :     }
     595           0 :     doTransform_[idd] = (polId0_[idd] >= 0 && polId1_[idd] >= 0);
     596           0 :   }
     597           0 : }
     598             : 
     599             : //////////
     600             : // GeometricPolAverageTVI
     601             : /////////
     602           0 : GeometricPolAverageTVI::GeometricPolAverageTVI(ViImplementation2 *inputVII) :
     603           0 :     PolAverageTVI(inputVII) {
     604           0 : }
     605             : 
     606           0 : GeometricPolAverageTVI::~GeometricPolAverageTVI() {
     607           0 : }
     608             : 
     609           0 : void GeometricPolAverageTVI::transformComplexData(Cube<Complex> const &dataIn,
     610             :     Cube<Bool> const &flagIn, Cube<Complex> &dataOut) const {
     611           0 :   Int ddid = dataDescriptionId();
     612           0 :   Int pid0 = polId0_[ddid];
     613           0 :   Int pid1 = polId1_[ddid];
     614           0 :   transformData(dataIn, flagIn, pid0, pid1, dataOut);
     615           0 : }
     616             : 
     617           0 : void GeometricPolAverageTVI::transformFloatData(Cube<Float> const &dataIn,
     618             :     Cube<Bool> const &flagIn, Cube<Float> &dataOut) const {
     619           0 :   Int ddid = dataDescriptionId();
     620           0 :   Int pid0 = polId0_[ddid];
     621           0 :   Int pid1 = polId1_[ddid];
     622           0 :   transformData(dataIn, flagIn, pid0, pid1, dataOut);
     623           0 : }
     624             : 
     625           0 : void GeometricPolAverageTVI::transformWeight(Array<Float> const &weightIn,
     626             :     Array<Float> &weightOut) const {
     627           0 :   Int ddid = dataDescriptionId();
     628           0 :   Int pid0 = polId0_[ddid];
     629           0 :   Int pid1 = polId1_[ddid];
     630           0 :   ::transformWeight<GeometricTransformation>(weightIn, pid0, pid1, weightOut);
     631           0 : }
     632             : 
     633             : template<class T>
     634           0 : void GeometricPolAverageTVI::transformData(Cube<T> const &dataIn,
     635             :     Cube<Bool> const &flagIn, Int pid0, Int pid1, Cube<T> &dataOut) const {
     636           0 :   if (weightSpectrumExists()) {
     637           0 :     Cube<Float> weightSp;
     638           0 :     getVii()->weightSpectrum(weightSp);
     639           0 :     ::GeometricTransformation::transformData<T>(dataIn, flagIn, weightSp, pid0,
     640             :         pid1, dataOut);
     641           0 :   } else {
     642           0 :     Matrix<Float> weightMat;
     643           0 :     getVii()->weight(weightMat);
     644           0 :     ::GeometricTransformation::transformData<T>(dataIn, flagIn, weightMat, pid0,
     645             :         pid1, dataOut);
     646           0 :   }
     647           0 : }
     648             : 
     649             : //////////
     650             : // StokesPolAverageTVI
     651             : /////////
     652           0 : StokesPolAverageTVI::StokesPolAverageTVI(ViImplementation2 *inputVII) :
     653           0 :     PolAverageTVI(inputVII) {
     654           0 : }
     655             : 
     656           0 : StokesPolAverageTVI::~StokesPolAverageTVI() {
     657           0 : }
     658             : 
     659           0 : void StokesPolAverageTVI::transformComplexData(Cube<Complex> const &dataIn,
     660             :     Cube<Bool> const &flagIn, Cube<Complex> &dataOut) const {
     661           0 :   Int ddid = dataDescriptionId();
     662           0 :   Int pid0 = polId0_[ddid];
     663           0 :   Int pid1 = polId1_[ddid];
     664           0 :   transformData(dataIn, flagIn, pid0, pid1, dataOut);
     665           0 : }
     666             : 
     667           0 : void StokesPolAverageTVI::transformFloatData(Cube<Float> const &dataIn,
     668             :     Cube<Bool> const &flagIn, Cube<Float> &dataOut) const {
     669           0 :   Int ddid = dataDescriptionId();
     670           0 :   Int pid0 = polId0_[ddid];
     671           0 :   Int pid1 = polId1_[ddid];
     672           0 :   transformData(dataIn, flagIn, pid0, pid1, dataOut);
     673           0 : }
     674             : 
     675           0 : void StokesPolAverageTVI::transformWeight(Array<Float> const &weightIn,
     676             :     Array<Float> &weightOut) const {
     677           0 :   Int ddid = dataDescriptionId();
     678           0 :   Int pid0 = polId0_[ddid];
     679           0 :   Int pid1 = polId1_[ddid];
     680           0 :   ::transformWeight<StokesTransformation>(weightIn, pid0, pid1, weightOut);
     681           0 : }
     682             : 
     683             : template<class T>
     684           0 : void StokesPolAverageTVI::transformData(Cube<T> const &dataIn,
     685             :     Cube<Bool> const &flagIn, Int pid0, Int pid1, Cube<T> &dataOut) const {
     686           0 :   ::StokesTransformation::transformData<T>(dataIn, flagIn, pid0, pid1, dataOut);
     687           0 : }
     688             : 
     689             : //////////
     690             : // PolAverageTVIFactory
     691             : /////////
     692           0 : PolAverageVi2Factory::PolAverageVi2Factory(Record const &configuration,
     693           0 :     ViImplementation2 *inputVII) :
     694           0 :     inputVII_p(inputVII), mode_(AveragingMode::DEFAULT) {
     695           0 :   inputVII_p = inputVII;
     696             : 
     697           0 :   mode_ = PolAverageVi2Factory::GetAverageModeFromConfig(configuration);
     698           0 : }
     699             : 
     700           0 : PolAverageVi2Factory::PolAverageVi2Factory(Record const &configuration,
     701             :     MeasurementSet const *ms, SortColumns const sortColumns,
     702           0 :     Double timeInterval, Bool isWritable) :
     703           0 :     inputVII_p(nullptr), mode_(AveragingMode::DEFAULT) {
     704           0 :   inputVII_p = new VisibilityIteratorImpl2(Block<MeasurementSet const *>(1, ms),
     705           0 :       sortColumns, timeInterval, isWritable);
     706             : 
     707           0 :   mode_ = PolAverageVi2Factory::GetAverageModeFromConfig(configuration);
     708           0 : }
     709             : 
     710           0 : PolAverageVi2Factory::~PolAverageVi2Factory() {
     711           0 : }
     712             : 
     713           0 : ViImplementation2 * PolAverageVi2Factory::createVi() const {
     714           0 :   if (mode_ == AveragingMode::GEOMETRIC) {
     715           0 :     return new GeometricPolAverageTVI(inputVII_p);
     716           0 :   } else if (mode_ == AveragingMode::STOKES) {
     717           0 :     return new StokesPolAverageTVI(inputVII_p);
     718             :   }
     719             : 
     720           0 :   throw AipsError("Invalid Averaging Mode for PolAverageTVI.");
     721             : 
     722             :   return nullptr;
     723             : }
     724             : 
     725           0 : PolAverageTVILayerFactory::PolAverageTVILayerFactory(
     726           0 :     Record const &configuration) :
     727           0 :     ViiLayerFactory() {
     728           0 :   configuration_p = configuration;
     729           0 : }
     730             : 
     731             : ViImplementation2*
     732           0 : PolAverageTVILayerFactory::createInstance(ViImplementation2* vii0) const {
     733             :   // Make the PolAverageTVI, using supplied ViImplementation2, and return it
     734           0 :   PolAverageVi2Factory factory(configuration_p, vii0);
     735           0 :   ViImplementation2 *vii = nullptr;
     736             :   try {
     737           0 :     vii = factory.createVi();
     738           0 :   } catch (...) {
     739           0 :     if (vii0) {
     740           0 :       delete vii0;
     741             :     }
     742           0 :     throw;
     743           0 :   }
     744           0 :   return vii;
     745           0 : }
     746             : } // # NAMESPACE VI - END
     747             : } // #NAMESPACE CASA - END

Generated by: LCOV version 1.16