LCOV - code coverage report
Current view: top level - mstransform/TVI - PhaseShiftingTVI.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 231 282 81.9 %
Date: 2025-12-12 07:32:35 Functions: 20 26 76.9 %

          Line data    Source code
       1             : //# PhaseShiftingTVI.h: This file contains the implementation of the PhaseShiftingTVI 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-2024, 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/PhaseShiftingTVI.h>
      24             : 
      25             : using namespace casacore;
      26             : namespace casa { //# NAMESPACE CASA - BEGIN
      27             : 
      28             : namespace vi { //# NAMESPACE VI - BEGIN
      29             : 
      30             : //////////////////////////////////////////////////////////////////////////
      31             : // PhaseShiftingTVI class
      32             : //////////////////////////////////////////////////////////////////////////
      33             : 
      34             : // -----------------------------------------------------------------------
      35             : //
      36             : // -----------------------------------------------------------------------
      37          88 : PhaseShiftingTVI::PhaseShiftingTVI(     ViImplementation2 * inputVii,
      38          88 :                                                                 const Record &configuration):
      39          88 :                                                                 FreqAxisTVI (inputVii)
      40             : {
      41          88 :         dx_p = 0;
      42          88 :         dy_p = 0;
      43             : 
      44             :         // CAS-12706 Zero initialization for wide-field phase shifting algorithm
      45          88 :         wideFieldMode_p = false;
      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          88 :         parseConfiguration(configuration);
      51             : 
      52          87 :         initialize();
      53             : 
      54          87 :         return;
      55           7 : }
      56             : 
      57             : /**
      58             :  * Get max valid FIELD IDs for this iterator. MSv2 uses the FIELD
      59             :  * table row index as FIELD ID.
      60             :  */
      61           6 : rownr_t PhaseShiftingTVI::getMaxMSFieldID() const
      62             : {
      63           6 :   const auto &fieldsTable = getVii()->fieldSubtablecols();
      64           6 :   return fieldsTable.nrow() - 1;
      65             : }
      66             : 
      67             : /**
      68             :  * Parses the phase center parameter, whether given as a single string or
      69             :  * as a dictionary/record of per-field strings.
      70             :  * Populates the phaseCenterSpec_p map.
      71             :  *
      72             :  * @param config TVI configuration object
      73             :  */
      74          88 : void PhaseShiftingTVI::parsePhasecenter(const Record &config)
      75             : {
      76          88 :   auto exists = config.fieldNumber ("phasecenter");
      77          88 :   if (exists < 0) {
      78           0 :     return;
      79             :   }
      80             : 
      81             :   // phasecenter can be given as a string or as a dict (per-field centers)
      82          88 :   auto isStr = false;
      83          88 :   casacore::String phaseCenterStr;
      84             :   try {
      85          94 :     config.get(exists, phaseCenterStr);
      86          82 :     isStr = true;
      87         164 :     logger_p << LogIO::NORMAL << LogOrigin("PhaseShiftingTVI", __FUNCTION__)
      88             :              << "Interpreting phasecenter as a single string, to be applied"
      89         164 :              " to all input (selected) fields."<< LogIO::POST;
      90           6 :   } catch(const AipsError &exc) {
      91             :     // ignore "RecordRep::get_pointer - incorrect data type String used...
      92             :     //   for field phasecenter with type Record" and similar, try record type
      93          12 :     logger_p << LogIO::NORMAL << LogOrigin("PhaseShiftingTVI", __FUNCTION__)
      94             :              << "Interpreting phasecenter as a dictionary of field->center."
      95          12 :              << "Using following phase centers:" << LogIO::POST;
      96           6 :   }
      97             : 
      98          88 :   if (isStr) {
      99          82 :     const auto &phaseCenterDir = checkPhaseCenterStr(phaseCenterStr);
     100          82 :     phaseCenterSpec_p.insert({-1, phaseCenterDir});
     101          82 :   } else {
     102           6 :     parsePhasecenterDict(config);
     103             :   }
     104          88 : }
     105             : 
     106             : /**
     107             :  * Parses the phase center strings in the items of a dict/record.
     108             :  * Populates the phaseCenterSpec_p map.
     109             :  *
     110             :  * @param config TVI configuration object
     111             :  */
     112           6 : void PhaseShiftingTVI::parsePhasecenterDict(const Record &config)
     113             : {
     114           6 :   const auto &inPhasecenter = config.asRecord("phasecenter");
     115           6 :   if (inPhasecenter.empty()) {
     116           0 :     throw AipsError("The dictionary 'phasecenter' is empty.");
     117             :   }
     118             : 
     119           6 :   const auto maxMSField = getMaxMSFieldID();
     120           6 :   std::set<unsigned int> fieldsSeen;
     121             :   // Go through items in the input dict/record
     122          15 :   for (unsigned int rid=0; rid < inPhasecenter.nfields(); ++rid) {
     123          20 :     const std::string fieldStr = inPhasecenter.name(RecordFieldId(rid));
     124          10 :     const auto fid = std::stoi(fieldStr);
     125          10 :     if (fid < 0 || static_cast<unsigned int>(fid) > maxMSField) {
     126           3 :       throw AipsError("Wrong field ID given: " + std::to_string(fid) +
     127           2 :                       ". This MeasurementSet has field IDs between 0 and " +
     128           2 :                       std::to_string(maxMSField));
     129             :     }
     130           9 :     if (not fieldsSeen.insert(fid).second) {
     131           0 :       throw AipsError("Field " + std::to_string(fid) + " is given multiple times");
     132             :     }
     133             : 
     134           9 :     std::string center;
     135             :     try {
     136           9 :       center = inPhasecenter.asString(RecordFieldId(rid));
     137           0 :     } catch (const AipsError &exc) {
     138           0 :       throw AipsError("For field " + std::to_string(fid) + ", cannot interpret "
     139           0 :                       "phasecenter value as a string: " +
     140           0 :                       std::string(exc.getMesg()));
     141           0 :     }
     142           9 :     const auto strFieldID = std::to_string(fid);
     143           9 :     const auto &phaseCenterDir = checkPhaseCenterStr(center, strFieldID);
     144           9 :     phaseCenterSpec_p.insert({fid, phaseCenterDir});
     145          10 :   }
     146           6 : }
     147             : 
     148             : /**
     149             :  * Checks that a phase center string can be correctly converted to a
     150             :  * MDirection object, and checks that the ref frame is supported.
     151             :  *
     152             :  * @param phasecenter center string as given in the 'phasecenter' param
     153             :  * @param fieldInfo more info to print about the field
     154             :  *
     155             :  * @returns direction as an MDirection
     156             :  */
     157          91 : MDirection PhaseShiftingTVI::checkPhaseCenterStr(const String &phasecenter,
     158             :                                                  const string &fieldInfo)
     159             : {
     160             :   // casaMDirection requires a variant
     161          91 :   casac::variant phaseCenterVar(phasecenter);
     162          91 :   casacore::MDirection phaseCenterDir;
     163          91 :   if(!casaMDirection(phaseCenterVar, phaseCenterDir)) {
     164           0 :     throw AipsError("Cannot interpret phase center string as a direction object: "
     165           0 :                     + phasecenter);
     166             :   } else {
     167          91 :     const auto myFrame = phaseCenterDir.getRefString();
     168             :     MDirection::Types mdtype;
     169          91 :     MDirection::getType(mdtype, myFrame);
     170          91 :     ThrowIf(
     171             :             mdtype == MDirection::HADEC || mdtype == MDirection::AZEL
     172             :             || mdtype == MDirection::AZELSW || mdtype == MDirection::AZELNE
     173             :             || mdtype == MDirection::AZELGEO || mdtype == MDirection::AZELSWGEO
     174             :             || mdtype == MDirection::MECLIPTIC || mdtype == MDirection::TECLIPTIC
     175             :             || mdtype == MDirection::TOPO,
     176             :             myFrame + " is a time dependent reference frame and so is not supported"
     177             :             );
     178          91 :     ThrowIf(
     179             :             mdtype == MDirection::MERCURY || mdtype == MDirection::VENUS
     180             :             || mdtype == MDirection::MARS || mdtype == MDirection::JUPITER
     181             :             || mdtype == MDirection::SATURN || mdtype == MDirection::URANUS
     182             :             || mdtype == MDirection::NEPTUNE || mdtype == MDirection::PLUTO
     183             :             || mdtype == MDirection::SUN || mdtype == MDirection::MOON
     184             :             || mdtype == MDirection::COMET,
     185             :             myFrame + " denotes an ephemeris object and so is not supported"
     186             :             );
     187             : 
     188         182 :     auto msg = "Phase center '" + std::string(phasecenter) +
     189          91 :       "' successfully parsed";
     190          91 :     if (not fieldInfo.empty()) {
     191           9 :       msg +=  " for field " + fieldInfo;
     192             :     }
     193         182 :     logger_p << LogIO::NORMAL << LogOrigin("PhaseShiftingTVI", __FUNCTION__)
     194         182 :              << msg << LogIO::POST;
     195          91 :   }
     196             : 
     197         182 :   return phaseCenterDir;
     198          91 : }
     199             : 
     200             : // -----------------------------------------------------------------------
     201             : //
     202             : // -----------------------------------------------------------------------
     203          88 : void PhaseShiftingTVI::parseConfiguration(const Record &configuration)
     204             : {
     205          88 :   int exists = -1;
     206             : 
     207          88 :   exists = -1;
     208          88 :   exists = configuration.fieldNumber ("XpcOffset");
     209          88 :   if (exists >= 0)
     210             :   {
     211           0 :     configuration.get (exists, dx_p);
     212             :   }
     213             : 
     214          88 :   exists = -1;
     215          88 :   exists = configuration.fieldNumber ("YpcOffset");
     216          88 :   if (exists >= 0)
     217             :   {
     218           0 :     configuration.get (exists, dy_p);
     219             :   }
     220             : 
     221          88 :   if (abs(dx_p) > 0 or abs(dy_p) > 0)
     222             :   {
     223           0 :     logger_p << LogIO::NORMAL << LogOrigin("PhaseShiftingTVI", __FUNCTION__)
     224           0 :              << "Phase shift is dx="<< dx_p << " dy=" << dy_p << LogIO::POST;
     225             :   }
     226             : 
     227             :   // CAS-12706 Add support for shifting across large offset/angles
     228          88 :   parsePhasecenter(configuration);
     229          87 :   wideFieldMode_p = true;
     230          87 : }
     231             : 
     232             : /**
     233             :  * Finds the phase center (converted as MDirection object) for the current
     234             :  * field, converting the ref frame if needed to match the current Vis Buffer
     235             :  * ref frame.
     236             :  *
     237             :  * @returns whether any shift should be applied (if an output phasecenter is
     238             :  *          defined for this field + phase center to shift to, for current
     239             :  *          field
     240             :  */
     241             : std::pair<bool, MDirection>
     242        5185 : PhaseShiftingTVI::findConvertedPhaseCenter() const
     243             : {
     244        5185 :   const auto *vb = getVii()->getVisBuffer();
     245             : 
     246        5185 :   auto centerIt = phaseCenterSpec_p.find(-1);
     247        5185 :   if (centerIt == phaseCenterSpec_p.end()) {
     248        2220 :     auto fieldID = vb->fieldId()[0];
     249        2220 :     centerIt = phaseCenterSpec_p.find(fieldID);
     250        2220 :     if (centerIt == phaseCenterSpec_p.end()) {
     251        1580 :       return {false, MDirection()};
     252             :     }
     253             :   }
     254        4395 :   auto convertedPhaseCenter = centerIt->second;
     255             : 
     256        4395 :   if (convertedPhaseCenter.getRefString() != vb->phaseCenter().getRefString()) {
     257             :     MDirection::Types mdtype;
     258        1915 :     MDirection::getType(mdtype, vb->phaseCenter().getRefString());
     259        1915 :     convertedPhaseCenter = MDirection::Convert(convertedPhaseCenter, mdtype)();
     260             :   }
     261             : 
     262        4395 :   return {true, convertedPhaseCenter};
     263        4395 : }
     264             : 
     265             : // -----------------------------------------------------------------------
     266             : //
     267             : // -----------------------------------------------------------------------
     268          87 : void PhaseShiftingTVI::initialize()
     269             : {
     270             :   // Populate nchan input-output maps
     271             :  Int spw;
     272          87 :  uInt spw_idx = 0;
     273          87 :  map<Int,vector<Int> >::iterator iter;
     274         181 :  for (iter=spwInpChanIdxMap_p.begin();iter!=spwInpChanIdxMap_p.end();iter++)
     275             :  {
     276          94 :    spw = iter->first;
     277          94 :    spwOutChanNumMap_p[spw] = spwInpChanIdxMap_p[spw].size();
     278             : 
     279          94 :    spw_idx++;
     280             :  }
     281             : 
     282             :  // CAS-12706 Add support for shifting across large offset/angles
     283             :  // Access observatory position and observation start (reference) time.
     284          87 :  if (wideFieldMode_p)
     285             :  {
     286          87 :    const auto selectedInputMsCols = std::make_unique<MSColumns>(getVii()->ms());
     287          87 :    observatoryPosition_p = selectedInputMsCols->antenna().positionMeas()(0);
     288          87 :    referenceTime_p  = selectedInputMsCols->timeMeas()(0);
     289          87 :    referenceTimeUnits_p = selectedInputMsCols->timeQuant()(0).getUnit();
     290          87 :  }
     291          87 : }
     292             : 
     293             : // -----------------------------------------------------------------------
     294             : // CAS-12706 Recalculate UVW and Phases according to wide-field phase shifting
     295             : // algorithm. This method should do the same as ComponentFTMachine::rotateUVW
     296             : // -----------------------------------------------------------------------
     297        5185 : void PhaseShiftingTVI::shiftUVWPhases()
     298             : {
     299             :   // Get input VisBuffer
     300        5185 :   VisBuffer2 *vb = getVii()->getVisBuffer();
     301             : 
     302        5185 :   bool doShift = false;
     303        5185 :   MDirection convertedPhaseCenter;
     304        5185 :   std::tie(doShift, convertedPhaseCenter) = findConvertedPhaseCenter();
     305        5185 :   if (not doShift) {
     306         790 :       phaseShift_p.resize(0, false);
     307             :       // reinit to avoid shape mismatch, CAS-14633
     308         790 :       auto temp = vb->uvw();
     309         790 :       newUVW_p.resize(temp.shape(), false);
     310         790 :       newUVW_p = temp;
     311         790 :       return;
     312         790 :   }
     313             : 
     314             :   // Initialize epoch corresponding to current buffer
     315             :   // with time reference to the first row in the MS
     316        8790 :   MEpoch epoch(Quantity(vb->time()(0),referenceTimeUnits_p),referenceTime_p.getRef());
     317        4395 :   MeasFrame refFrame(epoch,observatoryPosition_p);
     318        4395 :   UVWMachine uvwMachine(convertedPhaseCenter, vb->phaseCenter(), refFrame,false,false);
     319             :   // Initialize phase array and uvw matrix
     320        4395 :   phaseShift_p.resize(vb->nRows(),false);
     321        4395 :   newUVW_p.resize(vb->uvw().shape(),false);
     322             : 
     323             :   // Obtain phase shift and new uvw coordinates
     324        4395 :   Vector<Double> dummy(3,0.0);
     325        4395 :   double phase2radPerHz = -2.0 * M_PI / C::c;
     326      770463 :   for (rownr_t row=0; row<vb->nRows(); row++)
     327             :   {
     328             :     // Copy current uvw coordinates so that they are not modified
     329             :     // Note: Columns in uvw correspond to rows in the main table/VisBuffer!
     330      766068 :     dummy = vb->uvw().column(row);
     331             : 
     332             :     // Have to change (u,v,w) to (-u,-v,w) because is the convention used by uvwMachine
     333      766068 :     dummy(0) = -1*dummy(0);
     334      766068 :     dummy(1) = -1*dummy(1);
     335             : 
     336             :     // Transform uvw coordinates and obtain corresponding phase shift
     337      766068 :     uvwMachine.convertUVW(phaseShift_p(row), dummy);
     338             : 
     339             :     // Store new uvw coordinates
     340             :     // Have to change back (-u,-v,w) to (u,v,w) because is the convention used by the MS
     341      766068 :     dummy(0) = -1*dummy(0);
     342      766068 :     dummy(1) = -1*dummy(1);
     343      766068 :     newUVW_p.column(row) = dummy;
     344             :     // Convert phase shift to radian/Hz
     345      766068 :     phaseShift_p(row) = phase2radPerHz*phaseShift_p(row);
     346             :   }
     347        5185 : }
     348             : 
     349             : // -----------------------------------------------------------------------
     350             : //
     351             : // -----------------------------------------------------------------------
     352         542 : void PhaseShiftingTVI::origin()
     353             : {
     354             :   // Drive underlying ViImplementation2
     355         542 :  getVii()->origin();
     356             : 
     357             :  // CAS-12706 Add support for shifting across large offset/angles
     358         542 :  if (wideFieldMode_p) {
     359         542 :    shiftUVWPhases();
     360             :  }
     361             : 
     362             :  // Define the shapes in the VB2, patch provided by cgarcia in CAS-12706
     363         542 :  configureShapes();
     364             : 
     365             :  // Synchronize own VisBuffer
     366         542 :  configureNewSubchunk();
     367         542 : }
     368             : 
     369             : // -----------------------------------------------------------------------
     370             : //
     371             : // -----------------------------------------------------------------------
     372        4643 : void PhaseShiftingTVI::next()
     373             : {
     374             :   // Drive underlying ViImplementation2
     375        4643 :   getVii()->next();
     376             : 
     377             :   // CAS-12706 Add support for shifting across large offset/angles
     378        4643 :   if (wideFieldMode_p) {
     379        4643 :     shiftUVWPhases();
     380             :   }
     381             : 
     382             :   // Define the shapes in the VB2, patch provided by cgarcia in CAS-12706
     383        4643 :   configureShapes();
     384             : 
     385             :   // Synchronize own VisBuffer
     386        4643 :   configureNewSubchunk();
     387        4643 : }
     388             : 
     389             : 
     390             : // -----------------------------------------------------------------------
     391             : //
     392             : // -----------------------------------------------------------------------
     393        4643 : void PhaseShiftingTVI::visibilityObserved (Cube<Complex> & vis) const
     394             : {
     395             :   // Get input VisBuffer
     396        4643 :   VisBuffer2 *vb = getVii()->getVisBuffer();
     397        4643 :   Matrix<Double> uvw = vb->uvw();
     398        4643 :   Vector<Double> frequencies = vb->getFrequencies(0);
     399             : 
     400             :   // Reshape output data before passing it to the DataCubeHolder
     401        4643 :   vis.resize(getVisBuffer()->getShape(),false);
     402             : 
     403             :   // Gather input data
     404        4643 :   DataCubeMap inputData;
     405        4643 :   DataCubeHolder<Complex> inputVisCubeHolder(vb->visCube());
     406        4643 :   inputData.add(MS::DATA,inputVisCubeHolder);
     407             : 
     408             :   // Gather output data
     409        4643 :   DataCubeMap outputData;
     410        4643 :   DataCubeHolder<Complex> outputVisCubeHolder(vis);
     411        4643 :   outputData.add(MS::DATA,outputVisCubeHolder);
     412             : 
     413        4643 :   if (wideFieldMode_p)
     414             :   {
     415             :     // Configure Transformation Engine
     416        4643 :     WideFieldPhaseShiftingTransformEngine<Complex> transformer(phaseShift_p,&uvw,&frequencies,&inputData,&outputData);
     417             : 
     418             :     // Transform data
     419        4643 :     transformFreqAxis2(vb->getShape(),transformer);
     420        4643 :   }
     421             :   else
     422             :   {
     423             :     // Configure Transformation Engine
     424           0 :     PhaseShiftingTransformEngine<Complex> transformer(dx_p,dy_p,&uvw,&frequencies,&inputData,&outputData);
     425             : 
     426             :     // Transform data
     427           0 :     transformFreqAxis2(vb->getShape(),transformer);
     428             :   }
     429        4643 : }
     430             : 
     431             : // -----------------------------------------------------------------------
     432             : //
     433             : // -----------------------------------------------------------------------
     434        1757 : void PhaseShiftingTVI::visibilityCorrected (Cube<Complex> & vis) const
     435             : {
     436             :   // Get input VisBuffer
     437        1757 :  VisBuffer2 *vb = getVii()->getVisBuffer();
     438        1757 :  Matrix<Double> uvw = vb->uvw();
     439        1757 :  Vector<Double> frequencies = vb->getFrequencies(0);
     440             : 
     441             :  // Reshape output data before passing it to the DataCubeHolder
     442        1757 :  vis.resize(getVisBuffer()->getShape(),false);
     443             : 
     444             :  // Gather input data
     445        1757 :  DataCubeMap inputData;
     446        1757 :  DataCubeHolder<Complex> inputVisCubeHolder(vb->visCubeCorrected());
     447        1757 :  inputData.add(MS::DATA,inputVisCubeHolder);
     448             : 
     449             :  // Gather output data
     450        1757 :  DataCubeMap outputData;
     451        1757 :  DataCubeHolder<Complex> outputVisCubeHolder(vis);
     452        1757 :  outputData.add(MS::DATA,outputVisCubeHolder);
     453             : 
     454        1757 :  if (wideFieldMode_p)
     455             :  {
     456             :    // Configure Transformation Engine
     457        1757 :    WideFieldPhaseShiftingTransformEngine<Complex> transformer(phaseShift_p,&uvw,&frequencies,&inputData,&outputData);
     458             : 
     459             :    // Transform data
     460        1757 :    transformFreqAxis2(vb->getShape(),transformer);
     461        1757 :  }
     462             :  else
     463             :  {
     464             :    // Configure Transformation Engine
     465           0 :    PhaseShiftingTransformEngine<Complex> transformer(dx_p,dy_p,&uvw,&frequencies,&inputData,&outputData);
     466             : 
     467             :    // Transform data
     468           0 :    transformFreqAxis2(vb->getShape(),transformer);
     469             :  }
     470        1757 : }
     471             : 
     472             : // -----------------------------------------------------------------------
     473             : //
     474             : // -----------------------------------------------------------------------
     475        1757 : void PhaseShiftingTVI::visibilityModel (Cube<Complex> & vis) const
     476             : {
     477             :   // Get input VisBuffer
     478        1757 :   VisBuffer2 *vb = getVii()->getVisBuffer();
     479        1757 :   Matrix<Double> uvw = vb->uvw();
     480        1757 :   Vector<Double> frequencies = vb->getFrequencies(0);
     481             : 
     482             :   // Reshape output data before passing it to the DataCubeHolder
     483        1757 :   vis.resize(getVisBuffer()->getShape(),false);
     484             : 
     485             :   // Gather input data
     486        1757 :   DataCubeMap inputData;
     487        1757 :   DataCubeHolder<Complex> inputVisCubeHolder(vb->visCubeModel());
     488        1757 :   inputData.add(MS::DATA,inputVisCubeHolder);
     489             : 
     490             :   // Gather output data
     491        1757 :   DataCubeMap outputData;
     492        1757 :   DataCubeHolder<Complex> outputVisCubeHolder(vis);
     493        1757 :   outputData.add(MS::DATA,outputVisCubeHolder);
     494             : 
     495        1757 :   if (wideFieldMode_p)
     496             :   {
     497             :     // Configure Transformation Engine
     498        1757 :     WideFieldPhaseShiftingTransformEngine<Complex> transformer(phaseShift_p,&uvw,&frequencies,&inputData,&outputData);
     499             : 
     500             :     // Transform data
     501        1757 :     transformFreqAxis2(vb->getShape(),transformer);
     502        1757 :   }
     503             :   else
     504             :   {
     505             :       // Configure Transformation Engine
     506           0 :       PhaseShiftingTransformEngine<Complex> transformer(dx_p,dy_p,&uvw,&frequencies,&inputData,&outputData);
     507             : 
     508             :       // Transform data
     509           0 :       transformFreqAxis2(vb->getShape(),transformer);
     510             :   }
     511        1757 : }
     512             : 
     513             : // -----------------------------------------------------------------------
     514             : //
     515             : // -----------------------------------------------------------------------
     516        4643 : void PhaseShiftingTVI::uvw (casacore::Matrix<double> & uvw) const
     517             : {
     518        4643 :   if (wideFieldMode_p) {
     519        4643 :     uvw.resize(newUVW_p.shape(),false);
     520        4643 :     uvw = newUVW_p;
     521             :   }
     522             :   else {
     523           0 :     getVii()->uvw (uvw);
     524             :   }
     525        4643 : }
     526             : 
     527             : //////////////////////////////////////////////////////////////////////////
     528             : // PhaseShiftingTVIFactory class
     529             : //////////////////////////////////////////////////////////////////////////
     530             : 
     531             : // -----------------------------------------------------------------------
     532             : //
     533             : // -----------------------------------------------------------------------
     534           0 : PhaseShiftingTVIFactory::PhaseShiftingTVIFactory (      Record &configuration,
     535           0 :                                                                                                         ViImplementation2 *inputVii)
     536             : {
     537           0 :   inputVii_p = inputVii;
     538           0 :   configuration_p = configuration;
     539           0 : }
     540             : 
     541             : // -----------------------------------------------------------------------
     542             : //
     543             : // -----------------------------------------------------------------------
     544           0 : vi::ViImplementation2 * PhaseShiftingTVIFactory::createVi(VisibilityIterator2 *) const
     545             : {
     546           0 :   return new PhaseShiftingTVI(inputVii_p,configuration_p);
     547             : }
     548             : 
     549             : // -----------------------------------------------------------------------
     550             : //
     551             : // -----------------------------------------------------------------------
     552           0 : vi::ViImplementation2 * PhaseShiftingTVIFactory::createVi() const
     553             : {
     554           0 :   return new PhaseShiftingTVI(inputVii_p,configuration_p);
     555             : }
     556             : 
     557             : //////////////////////////////////////////////////////////////////////////
     558             : // PhaseShiftingTVILayerFactory class
     559             : //////////////////////////////////////////////////////////////////////////
     560             : 
     561          88 : PhaseShiftingTVILayerFactory::PhaseShiftingTVILayerFactory(Record &configuration) :
     562             :   ViiLayerFactory(),
     563          88 :   configuration_p(configuration)
     564          88 : {}
     565             : 
     566             : ViImplementation2* 
     567          88 : PhaseShiftingTVILayerFactory::createInstance(ViImplementation2* vii0) const 
     568             : {
     569             :   // Make the PhaseShiftingTVi2, using supplied ViImplementation2, and return it
     570          88 :   ViImplementation2 *vii = new PhaseShiftingTVI(vii0,configuration_p);
     571          87 :   return vii;
     572             : }
     573             : 
     574             : //////////////////////////////////////////////////////////////////////////
     575             : // PhaseShiftingTransformEngine class
     576             : //////////////////////////////////////////////////////////////////////////
     577             : 
     578             : // -----------------------------------------------------------------------
     579             : //
     580             : // -----------------------------------------------------------------------
     581           0 : template<class T> PhaseShiftingTransformEngine<T>::PhaseShiftingTransformEngine(
     582             :                                                                                                                         Double dx, Double dy,
     583             :                                                                                                                         Matrix<Double> *uvw,
     584             :                                                                                                                         Vector<Double> *frequencies,
     585             :                                                                                                                         DataCubeMap *inputData,
     586             :                                                                                                                         DataCubeMap *outputData):
     587           0 :                                                                                                                         FreqAxisTransformEngine2<T>(inputData,outputData)
     588             : {
     589           0 :   uvw_p = uvw;
     590           0 :   frequencies_p = frequencies;
     591             : 
     592             :   // Offsets in radians (input is arcsec)
     593           0 :   dx_p = dx*(M_PI / 180.0 / 3600.0);
     594           0 :   dy_p = dy*(M_PI / 180.0 / 3600.0);
     595           0 : }
     596             : 
     597             : // -----------------------------------------------------------------------
     598             : //
     599             : // -----------------------------------------------------------------------
     600           0 : template<class T> void PhaseShiftingTransformEngine<T>::transform(  )
     601             : {
     602           0 :    transformCore(inputData_p,outputData_p);
     603           0 : }
     604             : 
     605             : // -----------------------------------------------------------------------
     606             : //
     607             : // -----------------------------------------------------------------------
     608           0 : template<class T> void PhaseShiftingTransformEngine<T>::transformCore(      DataCubeMap *inputData,
     609             :                                                                                                                                                 DataCubeMap *outputData)
     610             : {
     611             :   // Get input/output data
     612           0 :   Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
     613           0 :   Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
     614             : 
     615             :   // Extra path as fraction of U and V in m
     616           0 :   Double phase = dx_p*(*uvw_p)(0,rowIndex_p) + dy_p*(*uvw_p)(1,rowIndex_p);
     617             : 
     618             :   // In radian/Hz
     619           0 :   phase *= -2.0 * M_PI / C::c;
     620             : 
     621             :   // Main loop
     622             :   Double phase_i;
     623           0 :   Complex factor;
     624           0 :   for (uInt chan_i=0;chan_i<inputVector.size();chan_i++)
     625             :   {
     626           0 :     phase_i = phase * (*frequencies_p)(chan_i);
     627           0 :     factor = Complex(cos(phase_i), sin(phase_i));
     628           0 :     outputVector(chan_i) = factor*inputVector(chan_i);
     629             :   }
     630           0 : }
     631             : 
     632             : //////////////////////////////////////////////////////////////////////////
     633             : // WideFieldPhaseShiftingTransformEngine class
     634             : //////////////////////////////////////////////////////////////////////////
     635             : 
     636             : // -----------------------------------------------------------------------
     637             : //
     638             : // -----------------------------------------------------------------------
     639        8157 : template<class T> WideFieldPhaseShiftingTransformEngine<T>::WideFieldPhaseShiftingTransformEngine(
     640             :                                                                                                                         const Vector<Double> &phaseShift,
     641             :                                                                                                                         Matrix<Double> *uvw,
     642             :                                                                                                                         Vector<Double> *frequencies,
     643             :                                                                                                                         DataCubeMap *inputData,
     644             :                                                                                                                         DataCubeMap *outputData):
     645        8157 :                                                                                                                         FreqAxisTransformEngine2<T>(inputData,outputData)
     646             : {
     647        8157 :   uvw_p = uvw;
     648        8157 :   frequencies_p = frequencies;
     649        8157 :   phaseShift_p = phaseShift;
     650        8157 : }
     651             : 
     652             : // -----------------------------------------------------------------------
     653             : //
     654             : // -----------------------------------------------------------------------
     655     3944138 : template<class T> void WideFieldPhaseShiftingTransformEngine<T>::transform( )
     656             : {
     657     3944138 :   transformCore(inputData_p,outputData_p);
     658     3944138 : }
     659             : 
     660             : // -----------------------------------------------------------------------
     661             : //
     662             : // -----------------------------------------------------------------------
     663     3944138 : template<class T> void WideFieldPhaseShiftingTransformEngine<T>::transformCore(     DataCubeMap *inputData,
     664             :                                                                                                                                                 DataCubeMap *outputData)
     665             : {
     666             :   // Get input/output data
     667     3944138 :  Vector<T> &inputVector = inputData->getVector<T>(MS::DATA);
     668     3944138 :  Vector<T> &outputVector = outputData->getVector<T>(MS::DATA);
     669             : 
     670     3944138 :  if (phaseShift_p.shape() == 0) {
     671             :    // no shift, bypass data as 'passthrough' field
     672       38324 :    outputVector = inputVector;
     673       38324 :    return;
     674             :  }
     675             : 
     676             :  // Main loop
     677             :  Double phase_i;
     678     3905814 :  Complex factor;
     679    11948290 :  for (uInt chan_i=0;chan_i<inputVector.size();chan_i++)
     680             :  {
     681     8042476 :    phase_i = phaseShift_p(rowIndex_p) * (*frequencies_p)(chan_i);
     682     8042476 :    factor = Complex(cos(phase_i), sin(phase_i));
     683     8042476 :    outputVector(chan_i) = factor*inputVector(chan_i);
     684             :  }
     685             : }
     686             : 
     687             : 
     688             : } //# NAMESPACE VI - END
     689             : 
     690             : } //# NAMESPACE CASA - END
     691             : 
     692             : 

Generated by: LCOV version 1.16