LCOV - code coverage report
Current view: top level - synthesis/Utilities - PointingDirectionCalculator.cc (source / functions) Hit Total Coverage
Test: casa_coverage.info Lines: 464 568 81.7 %
Date: 2023-10-25 08:47:59 Functions: 42 51 82.4 %

          Line data    Source code
       1             : //# PointingDirectionCalculator.cc: Implementation of PointingDirectionCalculator.h
       2             : //# All helper functions of imager moved here for readability
       3             : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
       4             : //# Associated Universities, Inc. Washington DC, USA.
       5             : //#
       6             : //# This library is free software; you can redistribute it and/or modify it
       7             : //# under the terms of the GNU Library General Public License as published by
       8             : //# the Free Software Foundation; either version 2 of the License, or (at your
       9             : //# option) any later version.
      10             : //#
      11             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      12             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      14             : //# License for more details.
      15             : //#
      16             : //# You should have received a copy of the GNU Library General Public License
      17             : //# along with this library; if not, write to the Free Software Foundation,
      18             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      19             : //#
      20             : //# Correspondence concerning AIPS++ should be addressed as follows:
      21             : //#        Internet email: aips2-request@nrao.edu.
      22             : //#        Postal address: AIPS++ Project Office
      23             : //#                        National Radio Astronomy Observatory
      24             : //#                        520 Edgemont Road
      25             : //#                        Charlottesville, VA 22903-2475 USA
      26             : //#
      27             : //# $Id$
      28             : #include <cassert>
      29             : #include <sstream>
      30             : #include <iostream>
      31             : #include <iomanip>
      32             : 
      33             : #include <synthesis/Utilities/PointingDirectionCalculator.h>
      34             : #include <memory>  // for unique_ptr<>
      35             : #include <utility> // for std::pair
      36             : 
      37             : #include <casacore/casa/aipstype.h>
      38             : #include <casacore/casa/Exceptions/Error.h>
      39             : #include <casacore/casa/IO/ArrayIO.h>
      40             : #include <casacore/casa/Arrays/ArrayMath.h>
      41             : #include <casacore/casa/BasicSL/String.h>
      42             : #include <casacore/casa/Quanta/Quantum.h>
      43             : #include <casacore/casa/Containers/Block.h>
      44             : #include <casacore/casa/Utilities/BinarySearch.h>
      45             : #include <casacore/casa/Logging/LogIO.h>
      46             : #include <casacore/tables/TaQL/ExprNode.h>
      47             : #include <casacore/ms/MSSel/MSSelection.h>
      48             : #include <casacore/measures/Measures/MPosition.h>
      49             : #include <casacore/measures/Measures/MEpoch.h>
      50             : #include <casacore/measures/Measures/MDirection.h>
      51             : // CAS-8418 NEW //
      52             : #include <synthesis/Utilities/SDPosInterpolator.h>
      53             : 
      54             : using namespace casacore;
      55             : using namespace casacore;
      56             : using namespace std;
      57             : 
      58             : // Debug Message Handling
      59             : // if DIRECTIONCALC_DEBUG is defined, the macro debuglog and
      60             : // debugpost point standard output stream (std::cout and
      61             : // std::endl so that debug messages are sent to standard
      62             : // output. Otherwise, these macros basically does nothing.
      63             : // "Do nothing" behavior is implemented in NullLogger
      64             : // and its associating << operator below.
      65             : //
      66             : // Usage:
      67             : // Similar to standard output stream.
      68             : //
      69             : //   debuglog << "Any message" << any_value << debugpost;
      70             : //
      71             : 
      72             : //   #define DIRECTIONCALC_DEBUG
      73             : 
      74             : namespace {
      75             : struct NullLogger {
      76             : };
      77             : 
      78             : template<class T>
      79    22610848 : inline NullLogger &operator<<(NullLogger &logger, T /*value*/) {
      80    22610848 :     return logger;
      81             : }
      82             : 
      83             : #ifndef DIRECTIONCALC_DEBUG
      84             : NullLogger nulllogger;
      85             : #endif
      86             : }
      87             : 
      88             : #ifdef DIRECTIONCALC_DEBUG
      89             : #define debuglog cout << "PointingDirectionCalculator::DEBUG "
      90             : #define debugpost endl
      91             : #else
      92             : #define debuglog nulllogger
      93             : #define debugpost 0
      94             : #endif
      95             : 
      96             : namespace {
      97             : #define ARRAY_DIRECTION(ColumnName) \
      98             : inline MDirection ColumnName ## Accessor(MSPointingColumns &pointingColumns, uInt rownr) { \
      99             :     return pointingColumns.ColumnName ## Meas(rownr); \
     100             : }
     101             : 
     102             : #define SCALAR_DIRECTION(ColumnName) \
     103             : inline MDirection ColumnName ## Accessor(MSPointingColumns &pointingColumns, uInt rownr) { \
     104             :     return pointingColumns.ColumnName ## Meas()(rownr); \
     105             : }
     106             : 
     107     1581602 : ARRAY_DIRECTION(direction)
     108           0 : ARRAY_DIRECTION(target)
     109           0 : ARRAY_DIRECTION(pointingOffset)
     110           0 : ARRAY_DIRECTION(sourceOffset)
     111           0 : SCALAR_DIRECTION(encoder)
     112             : 
     113             : // working function for moving source correction
     114             : // convertToAzel must be configured with moving source direction and
     115             : // proper reference frame. Also, convertToCelestial must refer proper
     116             : // reference frame.
     117       30445 : inline void performMovingSourceCorrection(
     118             :         CountedPtr<MDirection::Convert> &convertToAzel,
     119             :         CountedPtr<MDirection::Convert> &convertToCelestial,
     120             :         Vector<Double> &direction) {
     121             :     // moving source handling
     122             :     // If moving source is specified, output direction list is always
     123             :     // offset from reference position of moving source
     124             : 
     125       30445 :         debuglog << "MovingSourceCorrection <Working>." << debugpost;
     126             : 
     127             :     // DEBUG (CAS-11818) //
     128       30445 :     assert( convertToCelestial != nullptr );
     129       30445 :     assert( convertToAzel != nullptr );
     130             : 
     131       60890 :     MDirection srcAzel = (*convertToAzel)();
     132       60890 :     MDirection srcDirection = (*convertToCelestial)(srcAzel);
     133       91335 :     Vector<Double> srcDirectionVal = srcDirection.getAngle("rad").getValue();
     134       30445 :     direction -= srcDirectionVal;
     135       30445 : }
     136             : 
     137      436663 : inline void skipMovingSourceCorrection(
     138             :         CountedPtr<MDirection::Convert> &/*convertToAzel*/,
     139             :         CountedPtr<MDirection::Convert> &/*convertToCelestial*/,
     140             :         Vector<Double> &/*direction*/) {
     141             : 
     142      436663 :         debuglog << "MovingSourceCorrection <NO ACTION>" << debugpost;
     143             : 
     144             :     // do nothing
     145      436663 : }
     146             : } // anonymous namespace
     147             : 
     148             : using namespace casacore;
     149             : namespace casa {
     150             : 
     151             : //+
     152             : // Original Constructor
     153             : //-
     154         288 : PointingDirectionCalculator::PointingDirectionCalculator(
     155         288 :         MeasurementSet const &ms) :
     156         288 :         originalMS_(new MeasurementSet(ms)), selectedMS_(), pointingTable_(),
     157             :         pointingColumns_(), timeColumn_(), intervalColumn_(), antennaColumn_(),
     158             :         directionColumnName_(), accessor_(NULL), antennaPosition_(), referenceEpoch_(),
     159             :         referenceFrame_(referenceEpoch_, antennaPosition_),
     160             :         directionConvert_(NULL), directionType_(MDirection::J2000), movingSource_(NULL),
     161             :         movingSourceConvert_(NULL), movingSourceCorrection_(NULL),
     162             :         antennaBoundary_(), numAntennaBoundary_(0), pointingTimeUTC_(), lastTimeStamp_(-1.0),
     163             :         lastAntennaIndex_(-1), pointingTableIndexCache_(0),
     164             :         shape_(PointingDirectionCalculator::COLUMN_MAJOR),
     165             : 
     166             :   /*CAS-8418*/ useSplineInterpolation_(true),   ////!!  Set, when Spline is used.  ////
     167             :   /*CAS-8418*/ currSpline_(nullptr),
     168             :   /*CAS-8418*/ splineObj_(PointingDirectionCalculator::PtColID::nItems),
     169             :   /*CAS-8418*/ initializeReady_(PointingDirectionCalculator::PtColID::nItems,false),// Spline initialization Ready
     170             :   /*CAS-8418*/ coefficientReady_(PointingDirectionCalculator::PtColID::nItems,false), // Spline Coefficient Ready
     171         576 :   /*CAS-8418*/ accessorId_(DIRECTION)               // specify default accessor ID
     172             : {
     173             : // -- original code -- //
     174         288 :     accessor_ = directionAccessor;
     175             : 
     176         288 :     Block<String> sortColumns(2);
     177         288 :     sortColumns[0] = "ANTENNA1";
     178         288 :     sortColumns[1] = "TIME";
     179             : 
     180         288 :     selectedMS_ = new MeasurementSet(originalMS_->sort(sortColumns));
     181         288 :     debuglog << "Calling init()" << debugpost;
     182         288 :     init();
     183             : 
     184             :     // set default output direction reference frame
     185         288 :     debuglog << "Calling setFrame(J2000)" << debugpost;
     186         288 :     setFrame("J2000");
     187             : 
     188             :     // set default direction column name
     189         288 :     setDirectionColumn("DIRECTION");
     190         288 : }
     191             : 
     192             : 
     193         288 : PointingDirectionCalculator::~PointingDirectionCalculator()
     194             : {
     195             :   // Nothing at the moment. //
     196         288 : }
     197             : 
     198         539 : void PointingDirectionCalculator::init() {
     199             :     // attach column
     200         539 :     timeColumn_.attach(*selectedMS_, "TIME");
     201         539 :     intervalColumn_.attach(*selectedMS_, "INTERVAL");
     202         539 :     antennaColumn_.attach(*selectedMS_, "ANTENNA1");
     203             : 
     204             :     // initial setup
     205         539 :     debuglog << "inspectAntenna" << debugpost;
     206         539 :     inspectAntenna();
     207         539 :     debuglog << "done" << debugpost;
     208             : 
     209         539 :     resetAntennaPosition(antennaColumn_(0));
     210         539 : }
     211             : 
     212         277 : void PointingDirectionCalculator::selectData(String const &antenna,
     213             :         String const &spw, String const &field, String const &time,
     214             :         String const &scan, String const &feed, String const &intent,
     215             :         String const &observation, String const &uvrange,
     216             :         String const &msselect) {
     217             :     // table selection
     218         554 :     MSSelection thisSelection;
     219         277 :     thisSelection.setAntennaExpr(antenna);
     220         277 :     thisSelection.setSpwExpr(spw);
     221         277 :     thisSelection.setFieldExpr(field);
     222         277 :     thisSelection.setTimeExpr(time);
     223         277 :     thisSelection.setScanExpr(scan);
     224         277 :     thisSelection.setStateExpr(intent);
     225         277 :     thisSelection.setObservationExpr(observation);
     226         277 :     thisSelection.setUvDistExpr(uvrange);
     227         277 :     thisSelection.setTaQLExpr(msselect);
     228             : 
     229         530 :     TableExprNode exprNode = thisSelection.getTEN(&(*originalMS_));
     230             : 
     231             :     // sort by ANTENNA1 and TIME for performance reason
     232         506 :     Block<String> sortColumns(2);
     233         253 :     sortColumns[0] = "ANTENNA1";
     234         253 :     sortColumns[1] = "TIME";
     235         253 :     if (exprNode.isNull()) {
     236           0 :         debuglog << "NULL selection" << debugpost;
     237           0 :         selectedMS_ = new MeasurementSet(originalMS_->sort(sortColumns));
     238             :     } else {
     239         253 :         debuglog << "Sort of selection" << debugpost;
     240         253 :         MeasurementSet tmp = (*originalMS_)(exprNode);
     241         253 :         selectedMS_ = new MeasurementSet(tmp.sort(sortColumns));
     242             :     }
     243         253 :     debuglog << "selectedMS_->nrow() = " << selectedMS_->nrow() << debugpost;
     244         253 :     if (selectedMS_->nrow() == 0) {
     245           4 :         stringstream ss;
     246           2 :         ss << "Selected MS is empty for given selection: " << endl;
     247           2 :         if (!antenna.empty()) {
     248           2 :             ss << "\tantenna \"" << antenna << "\"" << endl;
     249             :         }
     250           2 :         if (!spw.empty()) {
     251           2 :             ss << "\tspw \"" << spw << "\"" << endl;
     252             :         }
     253           2 :         if (!field.empty()) {
     254           2 :             ss << "\tfield \"" << field << "\"" << endl;
     255             :         }
     256           2 :         if (!time.empty()) {
     257           0 :             ss << "\ttime \"" << time << "\"" << endl;
     258             :         }
     259           2 :         if (!scan.empty()) {
     260           0 :             ss << "\tscan \"" << scan << "\"" << endl;
     261             :         }
     262           2 :         if (!feed.empty()) {
     263           0 :             ss << "\tfeed \"" << feed << "\"" << endl;
     264             :         }
     265           2 :         if (!intent.empty()) {
     266           0 :             ss << "\tintent \"" << intent << "\"" << endl;
     267             :         }
     268           2 :         if (!observation.empty()) {
     269           0 :             ss << "\tobservation \"" << observation << "\"" << endl;
     270             :         }
     271           2 :         if (!uvrange.empty()) {
     272           0 :             ss << "\tuvrange \"" << uvrange << "\"" << endl;
     273             :         }
     274           2 :         if (!msselect.empty()) {
     275           0 :             ss << "\tmsselect \"" << msselect << "\"" << endl;
     276             :         }
     277             : 
     278           2 :         throw AipsError(ss.str());
     279             :     }
     280             : 
     281         251 :     init();
     282             : 
     283         251 :     debuglog << "done selectdata" << debugpost;
     284         251 : }
     285             : 
     286         576 : void PointingDirectionCalculator::configureMovingSourceCorrection() {
     287             : #if 0   // Causes Crash //
     288             :     if (!movingSource_.null() || directionColumnName_.contains("OFFSET")) {
     289             : #else   // FIXED //
     290         576 :     if ( !movingSource_.null() && !directionColumnName_.contains("OFFSET") )
     291             :     {
     292             : #endif
     293           9 :         debuglog << "configureMovingSourceCorrection::Perfrom." << debugpost;
     294           9 :         movingSourceCorrection_ = performMovingSourceCorrection;
     295             :     } else {
     296         567 :         debuglog << "configureMovingSourceCorrection::Skip." << debugpost;
     297         567 :         movingSourceCorrection_ = skipMovingSourceCorrection;
     298             :     }
     299         576 : }
     300             : 
     301             : 
     302         567 : void PointingDirectionCalculator::setDirectionColumn(String const &columnName) {
     303        1134 :     String columnNameUpcase = columnName;
     304         567 :     columnNameUpcase.upcase();
     305         567 :     if (!(originalMS_->pointing().tableDesc().isColumn(columnNameUpcase))) {
     306           0 :         stringstream ss;
     307           0 :         ss << "Column \"" << columnNameUpcase
     308           0 :                 << "\" doesn't exist in POINTING table.";
     309           0 :         throw AipsError(ss.str());
     310             :     }
     311             : 
     312         567 :     directionColumnName_ = columnNameUpcase;
     313             : 
     314             : //+
     315             : // New code reuired by CAS-8418
     316             : //   - When setDirectionColumn is called ,
     317             : //   - new spline coeffcient table corresoinding to specified Direction column is generated.
     318             : //      Once generated and from next time, lately created Obj. is pointed and used.
     319             : //   - from init(), this function is called.
     320             : //   - See indetal in;
     321             : //         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     322             : //-
     323             : 
     324         567 :     if (directionColumnName_ == "DIRECTION") {
     325         567 :         accessor_ = directionAccessor;
     326         567 :         accessorId_ =  DIRECTION;
     327         567 :         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     328             : 
     329           0 :     } else if (directionColumnName_ == "TARGET") {
     330           0 :         accessor_ = targetAccessor;
     331           0 :         accessorId_ = TARGET;
     332           0 :         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     333             : 
     334           0 :     } else if (directionColumnName_ == "POINTING_OFFSET") {
     335           0 :         accessor_ = pointingOffsetAccessor;
     336           0 :         accessorId_ = POINTING_OFFSET;
     337           0 :         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     338             : 
     339           0 :     } else if (directionColumnName_ == "SOURCE_OFFSET") {
     340           0 :         accessor_ = sourceOffsetAccessor;
     341           0 :         accessorId_ = SOURCE_OFFSET;
     342           0 :         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     343             : 
     344           0 :     } else if (directionColumnName_ == "ENCODER") {
     345           0 :         accessor_ = encoderAccessor;
     346           0 :         accessorId_ = ENCODER;
     347           0 :         initializeSplinefromPointingColumn(*originalMS_, accessorId_ );
     348             : 
     349             :     } else {
     350           0 :         stringstream ss;
     351           0 :         ss << "Column \"" << columnNameUpcase << "\" is not supported.";
     352           0 :         throw AipsError(ss.str());
     353             :     }
     354             : 
     355             :     //+
     356             :     // CAS:8418::Limmited service,
     357             :     // when indeicated by flag,force to use traditional Linear Interpolation.
     358             :     //-
     359             : 
     360         567 :      if (getCurrentSplineObj()->isCoefficientReady() == false )
     361             :      {
     362          68 :          useSplineInterpolation_ = false;
     363             :      }
     364             : 
     365         567 :      debuglog << "initializeSplinefromPointingColumn, Normal End." << debugpost;
     366             : 
     367             :      // ---org code ---
     368         567 :      configureMovingSourceCorrection();
     369         567 : }
     370             : 
     371         567 : void PointingDirectionCalculator::setFrame(String const frameType) {
     372         567 :     Bool status = MDirection::getType(directionType_, frameType);
     373         567 :     if (!status) {
     374           0 :         LogIO os(LogOrigin("PointingDirectionCalculator", "setFrame", WHERE));
     375             :         os << LogIO::WARN << "Conversion of frame string \"" << frameType
     376             :                 << "\" into direction type enum failed. Use J2000."
     377           0 :                 << LogIO::POST;
     378           0 :         directionType_ = MDirection::J2000;
     379             :     }
     380             : 
     381             :     // create conversion engine
     382             : 
     383             :     // Accessor
     384        1134 :     MDirection nominalInputMeasure = accessor_(*pointingColumns_, 0);
     385             : 
     386             :     // RefFrame
     387         567 :     MDirection::Ref outReference(directionType_, referenceFrame_);
     388             : 
     389             :     // Conversion
     390             :     directionConvert_ = new MDirection::Convert(nominalInputMeasure,
     391         567 :             outReference);
     392             :     // Epoch
     393         567 :     const MEpoch *e = dynamic_cast<const MEpoch *>(referenceFrame_.epoch());
     394             :     const MPosition *p =
     395         567 :             dynamic_cast<const MPosition *>(referenceFrame_.position());
     396             :     debuglog << "Conversion Setup: Epoch "
     397        1701 :             << e->get("s").getValue() << " " << e->getRefString() << " Position "
     398        2268 :             << p->get("m").getValue() << " " << p->getRefString()
     399        3402 :             << debugpost;
     400         567 : }
     401             : 
     402         288 : void PointingDirectionCalculator::setDirectionListMatrixShape(
     403             :         PointingDirectionCalculator::MatrixShape const shape) {
     404         288 :     shape_ = shape;
     405         288 : }
     406             : 
     407           9 : void PointingDirectionCalculator::setMovingSource(String const sourceName) {
     408          27 :     MDirection sourceDirection(Quantity(0.0, "deg"), Quantity(90.0, "deg"));
     409           9 :     sourceDirection.setRefString(sourceName);
     410           9 :     setMovingSource(sourceDirection);
     411           9 : }
     412             : 
     413           9 : void PointingDirectionCalculator::setMovingSource(
     414             :         MDirection const &sourceDirection) {
     415           9 :     movingSource_ = dynamic_cast<MDirection *>(sourceDirection.clone());
     416             : 
     417             :     // create conversion engine for moving source
     418          18 :     MDirection::Ref refAzel(MDirection::AZEL, referenceFrame_);
     419           9 :     movingSourceConvert_ = new MDirection::Convert(*movingSource_, refAzel);
     420             : 
     421           9 :     configureMovingSourceCorrection();
     422           9 : }
     423             : 
     424          16 : void PointingDirectionCalculator::unsetMovingSource() {
     425          16 :   if (!movingSource_.null()) {
     426           0 :     movingSource_ = nullptr;
     427             :   }
     428          16 : }
     429             : 
     430             : 
     431         288 : Matrix<Double> PointingDirectionCalculator::getDirection() {
     432         288 :     assert(!selectedMS_.null());
     433         288 :     uInt const nrow = selectedMS_->nrow();
     434         288 :     debuglog << "selectedMS_->nrow() = " << nrow << debugpost;
     435         576 :     Vector<Double> outDirectionFlattened(2 * nrow);
     436             :     // column major data offset and increment for outDirectionFlattened,
     437             :     // and output matrix shape
     438         288 :     uInt offset = nrow;
     439         288 :     uInt increment = 1;
     440             :     // matrix shape: number of rows is nrow and number of columns is 2
     441         576 :     IPosition outShape(2, nrow, 2);
     442         288 :     if (shape_ == PointingDirectionCalculator::ROW_MAJOR) {
     443             :         // column major specific offset, increment and output shape
     444          18 :         offset = 1;
     445          18 :         increment = 2;
     446             :         // matrix shape: number of rows is 2 and number of columns is nrow
     447          18 :         outShape = IPosition(2, 2, nrow);
     448             :     }
     449             : 
     450         577 :     for (uInt i = 0; i < numAntennaBoundary_ - 1; ++i) {
     451         289 :         uInt start = antennaBoundary_[i];
     452         289 :         uInt end = antennaBoundary_[i + 1];
     453         289 :         uInt currentAntenna = antennaColumn_(start);
     454             : 
     455         289 :         resetAntennaPosition(currentAntenna);
     456             : 
     457             :         debuglog << "antenna " << currentAntenna << " start " << start
     458         289 :                 << " end " << end << debugpost;
     459         289 :         uInt const nrowPointing = pointingTimeUTC_.nelements();
     460         289 :         debuglog << "nrowPointing = " << nrowPointing << debugpost;
     461             :         debuglog << "pointingTimeUTC = " << min(pointingTimeUTC_) << "~"
     462         289 :         << max(pointingTimeUTC_) << debugpost;
     463             : 
     464      467397 :         for (uInt j = start; j < end; ++j) {
     465      467108 :             debuglog << "start index " << j << debugpost;
     466             : 
     467             :             // doGetDirection call //
     468             : 
     469      467108 :             Vector<Double> direction = doGetDirection(j,currentAntenna); // CAS-8418 args werre changed.
     470             : 
     471             :             debuglog << "index for lat: " << (j * increment)
     472             :                     << " (cf. outDirectionFlattened.nelements()="
     473      467108 :                     << outDirectionFlattened.nelements() << ")" << debugpost;
     474      467108 :             debuglog << "index for lon: " << (offset + j * increment)
     475      467108 :                     << debugpost;
     476      467108 :             outDirectionFlattened[j * increment] = direction[0];
     477      467108 :             outDirectionFlattened[offset + j * increment] = direction[1];
     478             :         }
     479         289 :         debuglog << "done antenna " << currentAntenna << debugpost;
     480             :     }
     481         288 :     debuglog << "done getDirection" << debugpost;
     482         576 :     return Matrix < Double > (outShape, outDirectionFlattened.data());
     483             : }
     484             : 
     485             : //**************************************************
     486             : // CAS-8418
     487             : // doGetDirection(irow)
     488             : // - Spline Interpolation is executed, except
     489             : //   number of data is insufficient
     490             : // - Interpolation path in the module was separated.
     491             : //***************************************************
     492      467108 : Vector<Double> PointingDirectionCalculator::doGetDirection(uInt irow, uInt antID) {
     493      467108 :      debuglog << "doGetDirection(" << irow << "," << antID << ")" << debugpost;
     494             : 
     495             : // sec:1 Linear , Spline common//
     496      467108 :     Double currentTime =  timeColumn_.convert(irow, MEpoch::UTC).get("s").getValue();
     497      467108 :     resetTime(currentTime);
     498             : 
     499             :     // search and interpolate if necessary
     500             :     Bool exactMatch;
     501      467108 :     uInt const nrowPointing = pointingTimeUTC_.nelements();
     502             :     // pointingTableIndexCache_ is not so effective in terms of performance
     503             :     // simple binary search may be enough,
     504      467108 :     Int index = binarySearch(exactMatch, pointingTimeUTC_, currentTime,
     505             :             nrowPointing, 0);
     506      467108 :     debuglog << "binarySearch result " << index << debugpost;
     507             :     debuglog << "Time " << setprecision(16) << currentTime << " idx=" << index
     508      467108 :             << debugpost;
     509             :     //+
     510             :     // Check section on series of pointing data
     511             :     // by 'Binary match' wth Pointing Table
     512             :     // -
     513      934216 :     MDirection direction;
     514      467108 :     assert(accessor_ != NULL);
     515      467108 :     if (exactMatch) {
     516      360792 :         debuglog << "exact match" << debugpost;
     517      360792 :         direction = accessor_(*pointingColumns_, index);
     518      106316 :     } else if (index <= 0) {
     519         120 :         debuglog << "take 0th row" << debugpost;
     520         120 :         direction = accessor_(*pointingColumns_, 0);
     521      106196 :     } else if (index > (Int) (nrowPointing - 1)) {
     522          72 :         debuglog << "take final row" << debugpost;
     523          72 :         direction = accessor_(*pointingColumns_, nrowPointing - 1);
     524             :     } else {
     525      106124 :         debuglog << "linear interpolation " << debugpost;
     526             : 
     527             :         // commonly used result buffer .. //
     528      212248 :         Vector<Double> interpolated(2);
     529             : 
     530             :         //*
     531             :         // CAS-8418 Time Gap
     532             :         //*
     533      106124 :         bool fgsw = getCurrentSplineObj()->isTimeGap(antID, index);
     534      106124 :         if((fgsw==false) &&                // Not specially Marled. (CAS-8418)
     535      103728 :            (useSplineInterpolation_) )     // SPLINE //
     536             :         {
     537             :             //+
     538             :             // CAS-8418::  Spline Interpolation section.
     539             :             //-
     540             : 
     541      103728 :             Double t0 = pointingTimeUTC_[index - 1];
     542      103728 :             Double dtime =  (currentTime - t0) ;
     543             : 
     544             :             // determin section on 'uIndex'
     545             :             uInt uIndex;
     546      103728 :             if( index >=1 ){
     547      103728 :                 uIndex = index-1;
     548           0 :             } else if (index > (Int)(nrowPointing-1) ) {
     549           0 :                  uIndex = nrowPointing-1;
     550             :             } else  {
     551           0 :                  stringstream ss; ss  << "BUGCHECK, never come here. "  << endl;
     552           0 :                  throw AipsError( ss.str() );
     553             :             }
     554             : 
     555             :             //+
     556             :             // Execute Interpolation
     557             :             //-
     558             : 
     559      103728 :               if(getCurrentSplineObj() == nullptr){
     560           0 :                   stringstream  ss; ss << "FAITAL ERROR: Invalid Current Spline Object pointer.";
     561           0 :                   throw AipsError(ss.str());
     562             :               }
     563      103728 :               interpolated = getCurrentSplineObj()-> calculate(uIndex, dtime, antID );
     564             : 
     565             :             // obtain refType1 (original copied)//
     566             : 
     567      207456 :               MDirection         dir1 = accessor_(*pointingColumns_, index - 1);
     568      103728 :               String             dirRef1 = dir1.getRefString();
     569             :               MDirection::Types  refType1;
     570      103728 :               MDirection::getType(refType1, dirRef1);
     571             : 
     572             :             // LINEAR/SPLINE common
     573             :             // Convert the interpolated diretion from MDirection to Vector //
     574      207456 :               direction = MDirection(Quantum<Vector<Double> >(interpolated, "rad"),refType1);
     575             :         }
     576             :         else // LINEAR (basically same as original code)//
     577             :         {
     578        2396 :             Double t0 = pointingTimeUTC_[index - 1];
     579        2396 :             Double t1 = pointingTimeUTC_[index];
     580        2396 :             Double dt = t1 - t0;
     581             : 
     582             :             debuglog << "Interpolate between " << setprecision(16) << index - 1
     583             :                   << " (" << t0 << ") and " << index << " (" << t1 << ")"
     584        2396 :                   << debugpost;
     585             : 
     586        4792 :             MDirection dir1 = accessor_(*pointingColumns_, index - 1);
     587        4792 :             MDirection dir2 = accessor_(*pointingColumns_, index);
     588             : 
     589             :             // obtain Ref type //
     590        4792 :             String dirRef1 = dir1.getRefString();
     591        4792 :             String dirRef2 = dir2.getRefString();
     592             : 
     593             :             MDirection::Types refType1, refType2;
     594        2396 :             MDirection::getType(refType1, dirRef1);
     595        2396 :             MDirection::getType(refType2, dirRef2);
     596             : 
     597             :             debuglog << "dirRef1 = " << dirRef1 << " ("
     598        2396 :                     << MDirection::showType(refType1) << ")" << debugpost;
     599             : 
     600        2396 :             if (dirRef1 != dirRef2) {
     601           0 :                 MeasFrame referenceFrameLocal((pointingColumns_->timeMeas())(index),
     602           0 :                          *(referenceFrame_.position()));
     603           0 :                 dir2 = MDirection::Convert(dir2,
     604           0 :                          MDirection::Ref(refType1, referenceFrameLocal))();
     605             :             }
     606             : 
     607        7188 :             Vector<Double> dirVal1 = dir1.getAngle("rad").getValue();
     608        7188 :             Vector<Double> dirVal2 = dir2.getAngle("rad").getValue();
     609        2396 :             Vector<Double> scanRate = dirVal2 - dirVal1;
     610             : 
     611        2396 :             interpolated = dirVal1 + scanRate * (currentTime - t0) / dt;
     612             : 
     613             :             // LINEAR/SPLINE common
     614             :             // Convert the interpolated diretion from MDirection to Vector //
     615        2396 :               direction = MDirection(Quantum<Vector<Double> >(interpolated, "rad"),refType1);
     616             : 
     617             :         }
     618             :     }
     619             : 
     620             :     // CAS-8418:: Ending Section,following section is same as original //
     621             :     debuglog << "direction = "
     622      934216 :             << direction.getAngle("rad").getValue() << " (unit rad reference frame "
     623      934216 :             << direction.getRefString()
     624     1868432 :             << ")" << debugpost;
     625      467108 :     Vector<Double> outVal(2);
     626      467108 :     if (direction.getRefString() == MDirection::showType(directionType_)) {
     627      360384 :         outVal = direction.getAngle("rad").getValue();
     628             :     } else {
     629      106724 :         MDirection converted = (*directionConvert_)(direction);
     630      106724 :         outVal = converted.getAngle("rad").getValue();
     631             :         debuglog << "converted = " << outVal << "(unit rad reference frame "
     632      106724 :                 << converted.getRefString() << ")" << debugpost;
     633             :     }
     634             : 
     635             :     // moving source correction
     636      467108 :     assert(movingSourceCorrection_ != NULL);
     637      467108 :     movingSourceCorrection_(movingSourceConvert_, directionConvert_, outVal);
     638             : 
     639      934216 :     return outVal;
     640             : }
     641             : 
     642           0 : Vector<Double> PointingDirectionCalculator::getDirection(uInt i) {
     643           0 :     if (i >= selectedMS_->nrow()) {
     644           0 :         stringstream ss;
     645           0 :         ss << "Out of range row index: " << i << " (nrow for selected MS "
     646           0 :                 << getNrowForSelectedMS() << ")" << endl;
     647           0 :         throw AipsError(ss.str());
     648             :     }
     649           0 :     debuglog << "start row " << i << debugpost;
     650           0 :     Int currentAntennaIndex = antennaColumn_(i);
     651             :     debuglog << "currentAntennaIndex = " << currentAntennaIndex
     652           0 :             << " lastAntennaIndex_ = " << lastAntennaIndex_ << debugpost;
     653             :     Double currentTime =
     654           0 :             timeColumn_.convert(i, MEpoch::UTC).get("s").getValue();
     655           0 :     resetAntennaPosition(currentAntennaIndex);
     656             :     debuglog << "currentTime = " << currentTime << " lastTimeStamp_ = "
     657           0 :             << lastTimeStamp_ << debugpost;
     658           0 :     if (currentTime != lastTimeStamp_) {
     659           0 :         resetTime(i);
     660             :     }
     661           0 :     debuglog << "doGetDirection" << debugpost;
     662             : 
     663           0 :     Vector<Double> direction = doGetDirection(i,currentAntennaIndex);  // CAS-8418 args were changed
     664             : 
     665           0 :     return direction;
     666             : }
     667             : 
     668           0 : Vector<rownr_t> PointingDirectionCalculator::getRowId() {
     669           0 :     return selectedMS_->rowNumbers();
     670             : }
     671             : 
     672           9 : Vector<rownr_t> PointingDirectionCalculator::getRowIdForOriginalMS() {
     673           9 :     return selectedMS_->rowNumbers(*originalMS_, True);
     674             : }
     675             : 
     676           0 : rownr_t PointingDirectionCalculator::getRowId(uInt i) {
     677           0 :     return selectedMS_->rowNumbers()[i];
     678             : }
     679             : 
     680             : 
     681         539 : void PointingDirectionCalculator::inspectAntenna() {
     682             :     // selectedMS_ must be sorted by ["ANTENNA1", "TIME"]
     683         539 :     antennaBoundary_.resize(selectedMS_->antenna().nrow() + 1);
     684         539 :     antennaBoundary_ = -1;
     685         539 :     uInt count = 0;           // CAS-8418 :: Int ->iUnt //
     686         539 :     antennaBoundary_[count] = 0;
     687             : 
     688         539 :     ++count;
     689             : 
     690         539 :     Vector<Int> antennaList = antennaColumn_.getColumn();
     691         539 :     uInt nrow = antennaList.nelements();
     692         539 :     Int lastAnt = antennaList[0];
     693             : 
     694      827254 :     for (uInt i = 0; i < nrow; ++i) {
     695      826715 :         if (antennaList[i] != lastAnt) {
     696           6 :             antennaBoundary_[count] = i;
     697           6 :             ++count;
     698           6 :             lastAnt = antennaList[i];
     699             :         }
     700             :     }
     701             :     //+
     702             :     // CAS-8418 access violation check
     703             :     //-
     704         539 :       assert( count <= selectedMS_->antenna().nrow() );
     705             :     // end add
     706             : 
     707         539 :     antennaBoundary_[count] = nrow;
     708         539 :     ++count;
     709         539 :     numAntennaBoundary_ = count;
     710         539 :     debuglog << "antennaBoundary_=" << antennaBoundary_ << debugpost;
     711         539 : }
     712             : 
     713         289 : void PointingDirectionCalculator::initPointingTable(Int const antennaId) {
     714         290 :     if (!pointingTable_.null() && !pointingColumns_.null()
     715           1 :             && pointingTable_->nrow() > 0
     716         290 :             && pointingColumns_->antennaId()(0) == antennaId) {
     717             :         // no need to update
     718           0 :         return;
     719             :     }
     720         289 :     debuglog << "update pointing table for antenna " << antennaId << debugpost;
     721         578 :     MSPointing original = selectedMS_->pointing();
     722         867 :     MSPointing selected = original(original.col("ANTENNA_ID") == antennaId);
     723         289 :     if (selected.nrow() == 0) {
     724             :         debuglog << "no rows for antenna " << antennaId << " try -1"
     725           0 :                 << debugpost;
     726             :         // try ANTENNA_ID == -1
     727           0 :         selected = original(original.col("ANTENNA_ID") == -1);
     728             : 
     729             : #if 0   // follwing assert() invalidate throw AipsError() //
     730             :         assert(selected.nrow() > 0);
     731             : #endif
     732           0 :         if (selected.nrow() == 0) {
     733           0 :             stringstream ss;
     734           0 :             ss << "Internal Error: POINTING table has no entry for antenna "
     735           0 :                     << antennaId << "." << endl;
     736           0 :             throw AipsError(ss.str());
     737             :         }
     738             :     }
     739         289 :     debuglog << "selected pointing rows " << selected.nrow() << debugpost;
     740         289 :     pointingTable_ = new MSPointing(selected.sort("TIME"));
     741             : 
     742             :     // attach columns
     743         289 :     pointingColumns_ = new MSPointingColumns(*pointingTable_);
     744             : 
     745             :     // initialize pointingTimeUTC_
     746         289 :     uInt const nrowPointing = pointingTable_->nrow();
     747         289 :     pointingTimeUTC_.resize(nrowPointing);
     748             :     ScalarMeasColumn<MEpoch> pointingTimeColumn =
     749         578 :             pointingColumns_->timeMeas();
     750      960497 :     for (uInt i = 0; i < nrowPointing; ++i) {
     751     1920416 :         MEpoch e = pointingTimeColumn(i);
     752      960208 :         if (e.getRefString() == MEpoch::showType(MEpoch::UTC)) {
     753      960208 :             pointingTimeUTC_[i] = e.get("s").getValue();
     754             :         } else {
     755           0 :             pointingTimeUTC_[i] =
     756           0 :                     MEpoch::Convert(e, MEpoch::UTC)().get("s").getValue();
     757             :         }
     758             :     }
     759             : 
     760             :     // reset index cache for pointing table
     761         289 :     pointingTableIndexCache_ = 0;
     762             : 
     763         289 :     debuglog << "done initPointingTable" << debugpost;
     764             : }
     765             : 
     766         828 : void PointingDirectionCalculator::resetAntennaPosition(Int const antennaId) {
     767        1656 :     MSAntenna antennaTable = selectedMS_->antenna();
     768         828 :     uInt nrow = antennaTable.nrow();
     769         828 :     if (antennaId < 0 || (Int) nrow <= antennaId) {
     770           0 :         stringstream ss;
     771           0 :         ss << "Internal Error: Invalid ANTENNA_ID is specified (" << antennaId
     772           0 :                 << ")." << endl;
     773           0 :         throw AipsError(ss.str());
     774         828 :     } else if (antennaId != lastAntennaIndex_ || lastAntennaIndex_ == -1) {
     775             :         ScalarMeasColumn < MPosition
     776         289 :                 > antennaPositionColumn(antennaTable, "POSITION");
     777         289 :         antennaPosition_ = antennaPositionColumn(antennaId);
     778             :         debuglog << "antenna position: "
     779         289 :                 << antennaPosition_.getRefString() << " "
     780         578 :                 << setprecision(16) << antennaPosition_.get("m").getValue() << debugpost;
     781         289 :         referenceFrame_.resetPosition(antennaPosition_);
     782             : 
     783         289 :         initPointingTable(antennaId);
     784             : 
     785         289 :         lastAntennaIndex_ = antennaId;
     786             :     }
     787         828 : }
     788             : 
     789      467108 : void PointingDirectionCalculator::resetTime(Double const timestamp) {
     790      467108 :     debuglog << "resetTime(Double " << timestamp << ")" << debugpost;
     791             :     debuglog << "lastTimeStamp_ = " << lastTimeStamp_ << " timestamp = "
     792      467108 :             << timestamp << debugpost;
     793      467108 :     if (timestamp != lastTimeStamp_ || lastTimeStamp_ < 0.0) {
     794      467108 :         referenceEpoch_ = MEpoch(Quantity(timestamp, "s"), MEpoch::UTC);
     795      467108 :         referenceFrame_.resetEpoch(referenceEpoch_);
     796             : 
     797      467108 :         lastTimeStamp_ = timestamp;
     798             :     }
     799      467108 : }
     800             : 
     801             : //*********************************************************
     802             : //  CAS-8418::
     803             : //  Extended dunctions in PointingDirectionCalculator
     804             : //   for initializing Spline Interpolation
     805             : //*********************************************************
     806             : 
     807             : //+
     808             : // Direction Columns and
     809             : // AccessorId and accessor_ (function pointer)
     810             : //-
     811             : 
     812             : std::vector<string>   dirColList
     813             : = { "DIRECTION","TARGET","POINTING_OFFSET","SOURCE_OFFSET","ENCODER" };
     814             : 
     815             : std::vector<PointingDirectionCalculator::ACCESSOR> accList
     816             : = {  directionAccessor, targetAccessor,pointingOffsetAccessor,
     817             :    sourceOffsetAccessor, encoderAccessor };
     818             : 
     819             : // Column checck in Pointing Table //
     820         288 : bool PointingDirectionCalculator::checkColumn(MeasurementSet const &ms,String const &columnName )
     821             : {
     822         576 :     String columnNameUpcase = columnName;
     823         288 :     columnNameUpcase.upcase();
     824         288 :     if (true == (ms.pointing().tableDesc().isColumn(columnNameUpcase))) return true;
     825           0 :     else return false;
     826             : }
     827             : //+
     828             : // Activate Spline Interpolation
     829             : // - check specified Column if exist
     830             : // - create Spline object from specified Direction column
     831             : // - prepare Coeffient table for calulation.
     832             : //-
     833         567 : bool PointingDirectionCalculator::initializeSplinefromPointingColumn(MeasurementSet const &ms,
     834             :                                      PointingDirectionCalculator::PtColID  DirColNo )
     835             : {
     836         567 :     debuglog << "initializeSplinefromPointingColumn, columNo=" << DirColNo << debugpost;
     837             : 
     838        1134 :     String colName = dirColList[DirColNo] ;
     839         567 :     PointingDirectionCalculator::ACCESSOR acc   = accList[DirColNo] ;
     840             : 
     841             :     //+
     842             :     // Column Range check
     843             :     //-
     844         567 :     if( DirColNo >PointingDirectionCalculator::PtColID::nItems )
     845             :     {
     846           0 :         stringstream ss;
     847           0 :         ss << "Bugcheck. No column on Pointing Table." << endl;
     848           0 :         throw AipsError(ss.str());
     849             :         return false;  // Bad Param //
     850             :     }
     851             : 
     852             :     //+
     853             :     // CASE 1: Spline Object is already available.
     854             :     //-
     855         567 :     if( initializeReady_[DirColNo] == true )
     856             :     {
     857         279 :         debuglog << "initializeSplinefromPointingColumn, Normal,already active."  << debugpost;
     858             : 
     859             :         // SWITCH Master pointer  //
     860         279 :         currSpline_ = splineObj_[DirColNo].get();
     861         279 :         assert(currSpline_ !=nullptr);
     862             : 
     863         279 :         return true;   // Servece already OK //
     864             :     }
     865             :     //+
     866             :     // CASE 2: New Direction Colomn, initialize Spline Obj.
     867             :     //-
     868         288 :     if(checkColumn(ms, colName))
     869             :     {
     870         288 :         debuglog << "Spline Obj:: attempt to construct by " << colName.c_str() << debugpost;
     871             : 
     872             :         // Temporary Obj. //
     873         288 :           unique_ptr<SplineInterpolation> spTemp( new SplineInterpolation(ms,acc));
     874             : 
     875             :         // Spline Available (N>4)
     876         288 :           coefficientReady_ [DirColNo] = spTemp-> isCoefficientReady();
     877             : 
     878             :         // move to Spline obj. //
     879         288 :           assert(splineObj_[DirColNo] == nullptr);
     880         288 :           splineObj_[DirColNo] = std::move(spTemp);
     881             : 
     882             :         // copy to Master pointer, if this is desired.  //
     883         288 :           currSpline_ = splineObj_[DirColNo].get();
     884             : 
     885             :         // Obj. available //
     886         288 :            initializeReady_[DirColNo] = true;
     887             : 
     888         288 :         return true;
     889             :     }
     890             : 
     891             :     //+
     892             :     // Initialize Faiure.
     893             :     //-
     894             : 
     895           0 :     stringstream ss;
     896           0 :     ss << "FAILED:: No spline obj, atempted to make. No column on Pointing Table." << endl;
     897           0 :     throw AipsError(ss.str());
     898             : 
     899             : }
     900             : 
     901             : //+
     902             : // CAS-8418::
     903             : // Exporting Internal Status/Object Service
     904             : //-
     905             : 
     906             : // Export  COEFF:  returns Coefficitent Table of the current Spline-Object
     907           0 : PointingDirectionCalculator::COEFF  PointingDirectionCalculator::exportCoeff()
     908             : {
     909           0 :     SplineInterpolation *sp =  this->getCurrentSplineObj();
     910           0 :     return (sp->getCoeff());
     911             : }
     912             : 
     913             : // Export status of COEFF: returns true if COEFF is available.
     914           0 : bool PointingDirectionCalculator::isCoefficientReady()
     915             : {
     916           0 :     SplineInterpolation *sp =  this->getCurrentSplineObj();
     917           0 :     return (sp->isCoefficientReady() );
     918             : }
     919             : 
     920             : //***************************************************
     921             : //  CAS-8418:
     922             : //  Antenna Boundary (for Pointing Table ) methods
     923             : //  - create antenna information on Pointing Table.
     924             : //***************************************************
     925             : 
     926             : //+
     927             : // Antenna Boundary Class
     928             : //-
     929             : class AntennaBoundary {
     930             : public:
     931             :          AntennaBoundary(casacore::MeasurementSet const &ms) ;
     932         288 :         ~AntennaBoundary() { };
     933             : 
     934             :         std::pair<casacore::uInt, casacore::uInt>  getAntennaBoundary( casacore::uInt n );
     935             : 
     936         288 :         casacore::uInt  getNumOfAntenna() {return numAntennaBoundary_ - 1;}
     937             : 
     938         288 :         casacore::MSPointing  getPointingHandle() { return hPointing_; };
     939             : 
     940             : private:
     941             :        //  AntennaBoundary on Pointing Tablle
     942             :          casacore::Vector<casacore::uInt>            antennaBoundary_;
     943             :          casacore::uInt                              numAntennaBoundary_;
     944             : 
     945             :        // Pointing Table handle
     946             :          casacore::MSPointing hPointing_;
     947             : 
     948             : };
     949             : 
     950             : // Constructor //
     951         288 : AntennaBoundary::AntennaBoundary(MeasurementSet const &ms)
     952             : {
     953             :         // Antenna Boundary body //
     954         288 :         antennaBoundary_.resize(ms.antenna().nrow() + 1);
     955         288 :         antennaBoundary_ = -1;
     956             : 
     957         288 :         Int count = 0;
     958         288 :         antennaBoundary_[count] = 0;
     959         288 :         ++count;
     960             : 
     961             :         // Pointing Table Handle and the Columns Handle//
     962             :         //   with sorting by AntennaID and Time
     963             : 
     964         576 :         MSPointing hPointing_org  = ms.pointing();
     965             : 
     966             :         // Sort keys //
     967         576 :         Block<String> sortColumns(2);
     968         288 :         sortColumns[0]="ANTENNA_ID";
     969         288 :         sortColumns[1]="TIME";
     970             : 
     971             :         // Pointing Table handle //
     972         576 :         MSPointing hPointingTmp(hPointing_org.sort(sortColumns));
     973         288 :         hPointing_ = hPointingTmp;
     974             : 
     975             :         // Column Handle //
     976             :         std::unique_ptr<casacore::MSPointingColumns>
     977         576 :                 columnPointing( new casacore::MSPointingColumns( hPointing_ ));
     978             : 
     979             :         // Antenna List //
     980             : 
     981         576 :         ScalarColumn<casacore::Int>  antennaColumn = columnPointing->antennaId();
     982         288 :         Vector<Int> antennaList =  antennaColumn.getColumn();
     983             : 
     984         288 :         uInt nrow = antennaList.nelements();
     985         288 :         Int lastAnt = antennaList[0];
     986             : 
     987     1111819 :         for (uInt i = 0; i < nrow; ++i)
     988             :         {
     989     1111531 :             if (antennaList[i] > lastAnt)
     990             :             {
     991          30 :                 antennaBoundary_[count] = i;
     992          30 :                 count++;
     993          30 :                 lastAnt = antennaList[i];
     994             :             }
     995     1111501 :             else if (antennaList[i] < lastAnt )
     996             :             {
     997           0 :                  stringstream ss;
     998           0 :                  ss << "Bugcheck. Bad sort in creating antenna list." << endl;
     999           0 :                  throw AipsError(ss.str());
    1000             :             }
    1001             :         }
    1002             : 
    1003         288 :         antennaBoundary_[count] = nrow;
    1004         288 :         ++count;
    1005         288 :         numAntennaBoundary_ = count;
    1006             : 
    1007             : 
    1008         288 : }
    1009             : // getAntenaBoundary(start, end) //
    1010         318 : std::pair<casacore::uInt, casacore::uInt> AntennaBoundary::getAntennaBoundary( casacore::uInt n )
    1011             : {
    1012         318 :     std::pair<casacore::uInt, casacore::uInt> pos(antennaBoundary_[n],antennaBoundary_[n+1]);
    1013         318 :     return pos;
    1014             : }
    1015             : 
    1016             : //***************************************************
    1017             : //  CAS-8418:
    1018             : //  Spline Inerpolation  methods
    1019             : //***************************************************
    1020             : 
    1021             : // constructor (for each accessor) //
    1022         288 : SplineInterpolation::SplineInterpolation(MeasurementSet const &ms,
    1023         288 :                                          PointingDirectionCalculator::ACCESSOR accessor )
    1024             : {
    1025         288 :     stsCofficientReady  = false;
    1026         288 :     init(ms, accessor);
    1027         288 : }
    1028             : 
    1029             : // initialize //
    1030         288 : void SplineInterpolation::init(MeasurementSet const &ms,
    1031             :                                PointingDirectionCalculator::ACCESSOR const my_accessor)
    1032             : {
    1033             :     // Antenna Bounday //
    1034             : 
    1035         288 :         AntennaBoundary  antb(ms);
    1036         288 :         uInt numAnt = antb.getNumOfAntenna();
    1037             : 
    1038             :     // prepere MS handle from selectedMS_
    1039         288 :         MSPointing hPoint = antb.getPointingHandle();
    1040             :         std::unique_ptr<casacore::MSPointingColumns>
    1041         288 :                 columnPointing( new casacore::MSPointingColumns( hPoint ));
    1042             : 
    1043             :     // Resize (top level) //
    1044         288 :       tmp_time.        resize(numAnt);
    1045         288 :       tmp_dir.         resize(numAnt);
    1046             : 
    1047             :     // CAS-8418 Time Gap //
    1048         288 :       tmp_dtime.         resize(numAnt);
    1049         288 :       tmp_timegap.       resize(numAnt);
    1050             : 
    1051             :     // Column handle (only time,direction are needed, others are reserved) //
    1052             : 
    1053         288 :       ScalarColumn<Double> pointingTime           = columnPointing ->time();
    1054         288 :       ScalarColumn<Double> pointingInterval       = columnPointing ->interval();
    1055             : 
    1056             :     // Following columns are accessed by 'accessor_'   //
    1057             : 
    1058         288 :       ArrayColumn<Double>  pointingDirection      = columnPointing ->direction();
    1059         288 :       ArrayColumn<Double>  pointingTarget         = columnPointing ->target();
    1060         288 :       ArrayColumn<Double>  pointingPointingOffset = columnPointing ->pointingOffset();
    1061         288 :       ArrayColumn<Double>  pointingSourceOffset   = columnPointing ->sourceOffset();
    1062         288 :       ArrayColumn<Double>  pointingencoder        = columnPointing ->encoder();
    1063             : 
    1064         606 :     for(uInt ant=0; ant <numAnt; ant++)
    1065             :     {
    1066             :         // Antenna Bounday Pos(start,end) //
    1067         318 :           std::pair<uInt,uInt> pos = antb.getAntennaBoundary(ant);
    1068         318 :           uInt startPos = pos.first;
    1069         318 :           uInt endPos   = pos.second;
    1070             : 
    1071             :         // define size of each antenna
    1072         318 :           uInt size = endPos - startPos;
    1073         318 :           tmp_dir [ant]. resize(size);
    1074         318 :           tmp_time[ant]. resize(size);
    1075             : 
    1076             :          // CAS-8418 Time Gap //
    1077         318 :           tmp_dtime[ant]. resize(size);
    1078         318 :           tmp_timegap[ant]. resize(size);
    1079             : 
    1080             :         // set up //
    1081         318 :           std::fill(tmp_timegap[ant].begin(), tmp_timegap[ant].end(), false); // DEFAULT = false //
    1082         318 :           Double prv_time =  pointingTime.get(startPos); // For making diff time
    1083             :         // for each row //
    1084     1111849 :         for (uInt row = startPos; row < endPos; row++)
    1085             :         {
    1086     1111531 :             uInt index = row - startPos;
    1087             : 
    1088             :             // resizei (for Dir) //
    1089     1111531 :             tmp_dir[ant][index].resize(2);
    1090             : 
    1091     1111531 :             Double        time    = pointingTime.get(row);
    1092     2223062 :             MDirection     dir    = my_accessor(*columnPointing, row);
    1093     3334593 :             Vector<Double> dirVal = dir.getAngle("rad").getValue();
    1094             : 
    1095             :             // set on Vector //
    1096     1111531 :             tmp_time[ant][index] = time;
    1097     1111531 :             tmp_dir [ant][index] = dirVal;
    1098             : 
    1099             :             // CAS-8418 Time Gap //
    1100             : 
    1101             :               /* Pointing Interval */
    1102     1111531 :               Double p_interval =  pointingInterval.  get(row);
    1103     1111531 :               p_interval  = round(10000.0 * p_interval)/10000.0;  // Round at 0.0001 order
    1104             : 
    1105             :               /* Measured Interval */
    1106     1111531 :               Double dd = time - prv_time;
    1107     1111531 :               dd  = round(10000.0 * dd)/10000.0;  // Round at 0.0001 order
    1108             : 
    1109     1111531 :               tmp_dtime[ant][index] = dd; // record backward diff //
    1110     1111531 :               prv_time  = time;
    1111             : 
    1112             :               /* Mark the position (force to exec LINEAR) */
    1113     1111531 :              if(size>=7)
    1114             :              {
    1115     1111469 :                if(dd >  p_interval){
    1116        7042 :                    if((index < size-3 )&&(index >=3)) {
    1117        7032 :                       tmp_timegap [ant][index+3] =true; // forward
    1118        7032 :                       tmp_timegap [ant][index+2] =true;
    1119        7032 :                       tmp_timegap [ant][index+1] =true;
    1120             : 
    1121        7032 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1122             : 
    1123        7032 :                       tmp_timegap [ant][index-1] =true;
    1124        7032 :                       tmp_timegap [ant][index-2] =true;
    1125        7032 :                       tmp_timegap [ant][index-3] =true; // backward
    1126             : 
    1127             :                    }
    1128             :                    //*
    1129             :                    // In case, marking on edges;
    1130             :                    // (note: time diff(=dd) is backward difference)
    1131             :                    //*
    1132          10 :                    else if (index == 1) {
    1133           2 :                       tmp_timegap [ant][index+3] =true; // forward
    1134           2 :                       tmp_timegap [ant][index+2] =true;
    1135           2 :                       tmp_timegap [ant][index+1] =true;
    1136           2 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1137           2 :                       tmp_timegap [ant][index-1] =true;
    1138             :                    }
    1139           8 :                    else if (index == 2) {
    1140           2 :                       tmp_timegap [ant][index+3] =true; // forward
    1141           2 :                       tmp_timegap [ant][index+2] =true;
    1142           2 :                       tmp_timegap [ant][index+1] =true;
    1143           2 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1144           2 :                       tmp_timegap [ant][index-1] =true;
    1145           2 :                       tmp_timegap [ant][index-2] =true;
    1146             :                    }
    1147           6 :                    else if (index == size-3) {
    1148           2 :                       tmp_timegap [ant][index+2] =true;
    1149           2 :                       tmp_timegap [ant][index+1] =true;
    1150           2 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1151           2 :                       tmp_timegap [ant][index-1] =true;
    1152           2 :                       tmp_timegap [ant][index-2] =true;
    1153           2 :                       tmp_timegap [ant][index-3] =true; // backward
    1154             :                    }
    1155           4 :                    else if (index == size-2) {
    1156           2 :                       tmp_timegap [ant][index+1] =true;
    1157           2 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1158           2 :                       tmp_timegap [ant][index-1] =true;
    1159           2 :                       tmp_timegap [ant][index-2] =true;
    1160           2 :                       tmp_timegap [ant][index-3] =true; // backward
    1161             :                    }
    1162           2 :                    else if (index == size-1) {
    1163           2 :                       tmp_timegap [ant][index  ] =true; // center (detected point)
    1164           2 :                       tmp_timegap [ant][index-1] =true;
    1165           2 :                       tmp_timegap [ant][index-2] =true;
    1166           2 :                       tmp_timegap [ant][index-3] =true; // backward
    1167             :                    }
    1168             :                }
    1169             :              }
    1170             :         }
    1171             :     }
    1172             : 
    1173             :     //+
    1174             :     // Minimum Condition Inspection
    1175             :     // (N >=4)
    1176             :     //-
    1177             : 
    1178         572 :     for(uInt ant=0; ant <numAnt; ant++)
    1179             :     {
    1180         318 :         uInt s_time =tmp_time[ant].size();
    1181         318 :         uInt s_dir  =tmp_dir [ant].size();
    1182         318 :         if ((s_time < 4)||(s_dir < 4))
    1183             :         {
    1184             :           // Warning .. //
    1185          68 :             LogIO os(LogOrigin("SplineInterpolation", "init()", WHERE));
    1186             :             os << LogIO::WARN << "INSUFFICIENT NUMBER OF POINTING DATA, must be ge. 4 "
    1187          34 :                << "Alternatively, Linear Interpolation will be used. " << LogIO::POST;
    1188             : 
    1189          34 :            stsCofficientReady = false; // initially in-usable ..
    1190          34 :            return;
    1191             :         }
    1192             :     }
    1193             : 
    1194             :     //+
    1195             :     // SDPosInterpolator Objct
    1196             :     //   - create Coefficient Table -
    1197             :     //-
    1198         254 :       SDPosInterpolator  sdp (tmp_time, tmp_dir);
    1199             : 
    1200             :     // Obtain Coeff (copy object) //
    1201         254 :       coeff_ = sdp.getSplineCoeff();
    1202             : 
    1203             :     // Table Active ..
    1204         254 :       stsCofficientReady = true;
    1205             : 
    1206             :     // In case COEFF inspection needed, locate dump here. //
    1207             : 
    1208             : }
    1209             : 
    1210             : //+
    1211             : // Interpolation Calculation
    1212             : //-
    1213      103728 : casacore::Vector<casacore::Double> SplineInterpolation::calculate(uInt index,
    1214             :                                                                   Double dt,
    1215             :                                                                   uInt antID )
    1216             : {
    1217      103728 :     debuglog << "SplineInterpolation::calculate()" << debugpost;
    1218             : 
    1219             :     // Error check //
    1220      103728 :     uInt arraySize = coeff_[antID].size();
    1221      103728 :     if(  index >= arraySize)
    1222             :     {
    1223             :         // Exception handling is to be here... //
    1224           0 :         stringstream ss;
    1225           0 :         ss << "Bugcheck. Requested Index is too large." << endl;
    1226           0 :         throw AipsError(ss.str());
    1227             :     }
    1228             :     // Coefficient //
    1229             : 
    1230      207456 :     auto pCoeff_1 =coeff_[antID][index][0];
    1231      207456 :     auto pCoeff_2 =coeff_[antID][index][1];
    1232             : 
    1233      103728 :     Double a0 = pCoeff_1[0];
    1234      103728 :     Double a1 = pCoeff_1[1];
    1235      103728 :     Double a2 = pCoeff_1[2];
    1236      103728 :     Double a3 = pCoeff_1[3];
    1237             : 
    1238      103728 :     Double b0 = pCoeff_2[0];
    1239      103728 :     Double b1 = pCoeff_2[1];
    1240      103728 :     Double b2 = pCoeff_2[2];
    1241      103728 :     Double b3 = pCoeff_2[3];
    1242             : 
    1243             :    // Spline Calc //
    1244             : 
    1245      103728 :     Double Xs =  (((0* dt + a3)*dt + a2)*dt + a1)*dt + a0;
    1246      103728 :     Double Ys =  (((0* dt + b3)*dt + b2)*dt + b1)*dt + b0;
    1247             : 
    1248             :     // Return //
    1249             : 
    1250      103728 :     Vector<Double> outval(2);
    1251      103728 :     outval[0] = Xs;
    1252      103728 :     outval[1] = Ys;
    1253             : 
    1254      103728 :     debuglog << "SplineInterpolation::calculate() Normal return." << debugpost;
    1255             : 
    1256      207456 :     return outval;
    1257             : 
    1258             : }
    1259             : 
    1260             : 
    1261             : }  //# NAMESPACE CASA - END

Generated by: LCOV version 1.16