LCOV - code coverage report
Current view: top level - flagging/Flagging - FlagAgentAntennaIntegrations.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 111 131 84.7 %
Date: 2024-11-06 17:42:47 Functions: 8 9 88.9 %

          Line data    Source code
       1             : //# FlagAgentRFlag.cc: This file contains the implementation of the FlagAgentAntennaIntegrations class.
       2             : //#
       3             : //#  CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
       4             : //#  Copyright (C) Associated Universities, Inc. Washington DC, USA 2017, All rights reserved.
       5             : //#  Copyright (C) European Southern Observatory, 2017, 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 <flagging/Flagging/FlagAgentAntennaIntegrations.h>
      24             : 
      25             : #include <sstream>
      26             : 
      27             : #include <casacore/casa/Quanta/MVTime.h>
      28             : #include <casacore/casa/Utilities/DataType.h>
      29             : 
      30             : namespace casa { //# NAMESPACE CASA - BEGIN
      31             : 
      32             : /**
      33             :  * Will use the per-row iteration approach, with vis-buffer preprocessing.
      34             :  *
      35             :  * @param dh Data handler, just passed to the base class 
      36             :  * @param config Flag agent configuration object, antint specific parameters are processed
      37             :  * @param writePrivateFlagCube Write option for the base class
      38             :  * @param flag Flag for the base class
      39             :  */
      40          10 : FlagAgentAntennaIntegrations::FlagAgentAntennaIntegrations(
      41             :                               FlagDataHandler *dh, casacore::Record config,
      42             :                               casacore::Bool writePrivateFlagCube, 
      43          10 :                               casacore::Bool flag):
      44             :   FlagAgentBase(dh, config, FlagAgentBase::ROWS_PREPROCESS_BUFFER, writePrivateFlagCube,
      45          10 :                 flag)
      46             : {
      47          10 :   logger_p->origin(casacore::LogOrigin(agentName_p,__FUNCTION__,WHERE));
      48             : 
      49          10 :   setAgentParameters(config, flagDataHandler_p->antennaNames_p);
      50          10 : }
      51             : 
      52             : /**
      53             :  * Deal with parameters specific to 'antint'.
      54             :  *
      55             :  * minchanfrac: fraction of channels with flagged antenna to initiate flagging.
      56             :  * verbose: boolean to print the timestamps of the integrations that are flagged
      57             :  *
      58             :  * @param config A flagdata configuration/parameters object
      59             :  */
      60          10 : void FlagAgentAntennaIntegrations::setAgentParameters(casacore::Record config,
      61             :                                                       casacore::Vector<casacore::String> *antennaNames)
      62             : {
      63          10 :   const auto fields = config.nfields();
      64          10 :   *logger_p << casacore::LogIO::NORMAL << "The configuration received by this agent has " 
      65          10 :             << fields << " fields with the following values:" << casacore::LogIO::POST;
      66          10 :   std::ostringstream ostr;
      67          10 :   config.print(ostr);
      68          10 :   *logger_p << casacore::LogIO::NORMAL << ostr.str() << casacore::LogIO::POST;
      69             : 
      70             : 
      71          10 :   const auto minChanOpt = "minchanfrac";
      72          10 :   int found = config.fieldNumber(minChanOpt);
      73          10 :   if (found >= 0) {
      74           9 :     minChanThreshold_p = config.asDouble(minChanOpt);
      75             :   }
      76             : 
      77          10 :   const auto antOpt = "antint_ref_antenna";
      78          10 :   found = config.fieldNumber(antOpt);
      79          10 :   if (found >= 0) {
      80          10 :     casacore::String antintAnt = config.asString(antOpt);
      81          10 :     antIdx_p = findAntennaID(antintAnt, antennaNames);
      82          10 :     *logger_p << casacore::LogIO::NORMAL << "Found requested antenna of interest, with "
      83          10 :       "name: " << antintAnt << ", and index: " << antIdx_p << casacore::LogIO::POST;
      84             : 
      85          10 :   } else {
      86           0 :     throw casacore::AipsError(casacore::String("The parameter ") + antOpt + " was not "
      87           0 :                               "given. This parameter is mandatory in this flagging mode.");
      88             :   }
      89             : 
      90          10 :   const auto verboseOpt = "verbose";
      91          10 :   found = config.fieldNumber(verboseOpt);
      92          10 :   if (found >= 0) {
      93           8 :     verbose_p = config.asBool(verboseOpt);
      94             :   }
      95          10 : }
      96             : 
      97             : /**
      98             :  * Find the antenna ID for an antenna name
      99             :  *
     100             :  * @param name the name of an antenna 
     101             :  * @param antennaNames gives antena names by idx
     102             :  *
     103             :  * @return the antenna id if found for the given name
     104             :  *
     105             :  * @throws AipsError if no antenna is found by the name given..
     106             :  */
     107             : casacore::uInt
     108          10 : FlagAgentAntennaIntegrations::findAntennaID(const casacore::String &name,
     109             :                                             const casacore::Vector<casacore::String> *antennaNames) {
     110          10 :   casacore::uInt idx = 0;
     111          10 :   for( ; idx < antennaNames->nelements(); ++idx) {
     112          10 :     if (name == antennaNames->operator()(idx)) {
     113          10 :         break;
     114             :     }
     115             :   }
     116             : 
     117          10 :   if (idx >= antennaNames->nelements()) {
     118           0 :     throw casacore::AipsError("The antenna requested (" + name + ") could not be found in "
     119           0 :                               "the input dataset");
     120             :   }
     121          10 :   return idx;
     122             : }
     123             :   
     124             : /*
     125             :  * Processes blocks of rows by every point in time, 
     126             :  * Checking all the baselines to the antenna of interest
     127             :  *
     128             :  * @param visBuffer Buffer to pre-process
     129             :  */
     130             : void
     131        1290 : FlagAgentAntennaIntegrations::preProcessBuffer(const vi::VisBuffer2 &visBuffer)
     132             : {
     133        1290 :   const auto &time_p = visBuffer.time();
     134        1290 :   auto rowCnt = time_p.size();
     135        1290 :   if (rowCnt <= 0)
     136           0 :     return;
     137             : 
     138        1290 :   auto antennasCnt = visBuffer.nAntennas();
     139        1290 :   auto channelsCnt = visBuffer.nChannels();
     140        1290 :   *logger_p << casacore::LogIO::DEBUG1 << "Pre-processing visibility buffer, with "
     141        1290 :             << " nRows: " << visBuffer.nRows()
     142        1290 :             << " nCorrelations: " << visBuffer.nCorrelations()
     143             :             << " nChannels: " << channelsCnt << ", nAntennas:: " 
     144        1290 :             << antennasCnt << casacore::LogIO::POST;  
     145             : 
     146             :   // TODO: use a casacore::Matrix here?
     147        1290 :   TableFlagPerBaselinePerChannel flagPerBaselinePerChannel;
     148        1290 :   flagPerBaselinePerChannel.resize(antennasCnt - 1);
     149        5270 :   for(auto &row : flagPerBaselinePerChannel) {
     150        3980 :     row.assign(channelsCnt, false);
     151             :   }
     152             : 
     153        1290 :   const auto ant1 = visBuffer.antenna1();
     154        1290 :   const auto ant2 = visBuffer.antenna2(); 
     155        1290 :   const auto &polChanRowFlags = visBuffer.flagCube();
     156        1290 :   auto currentTime = time_p[0];
     157        1290 :   auto baselineIdx = 0;
     158       19073 :   for (casacore::uInt rowIdx = 0; rowIdx < rowCnt; ++rowIdx) {
     159       17783 :     if (ant1[rowIdx] != antIdx_p and ant2[rowIdx] != antIdx_p)
     160        9579 :       continue;
     161             : 
     162        8204 :     auto rowTime = time_p[rowIdx];
     163        8204 :     if (rowTime != currentTime) {
     164        1408 :       doPreProcessingTimePoint(doFlagTime_p, currentTime, flagPerBaselinePerChannel);
     165        1408 :       currentTime = rowTime;
     166        1408 :       baselineIdx = 0;
     167             :     }
     168             : 
     169        8204 :     checkAnyPolarizationFlagged(polChanRowFlags, flagPerBaselinePerChannel,
     170        8204 :                                 rowIdx, baselineIdx++);
     171             : 
     172             :   }
     173             :   // last time
     174        1290 :   doPreProcessingTimePoint(doFlagTime_p, currentTime, flagPerBaselinePerChannel);
     175        1290 : }
     176             : 
     177             : /**
     178             :  * Checks channel by channel. Count if there are any polarizations flagged per channel
     179             :  * once all the rows for a time point are scanned, doPreProcessingTimePoint() will
     180             :  * decide whether to flag all the integrations of the antenna of interest
     181             :  *
     182             :  * @param polChanRowFlags flag cube from a row, with [polarizations, channels, rows]
     183             :  * @param flagPerBaselinePerChannel
     184             :  * @param row row index for 
     185             :  * @param baselineIdx index for the table of baseline-channel flags. Counting from 0.
     186             :  */
     187        8204 : void FlagAgentAntennaIntegrations::checkAnyPolarizationFlagged(const casacore::Cube<casacore::Bool> &polChanRowFlags, 
     188             :                                                                TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel,
     189             :                                                                casacore::uInt row, casacore::uInt baselineIdx) {
     190             : 
     191        8204 :   const auto channelCnt = polChanRowFlags.ncolumn();
     192        8204 :   const auto polCnt = polChanRowFlags.nrow();
     193      291340 :   for (casacore::uInt chanIdx = 0; chanIdx < channelCnt; ++chanIdx) {
     194     1415680 :     for (casacore::uInt polIdx = 0; polIdx < polCnt; ++polIdx) {
     195             :       // assume that all polarization products must be unflagged for a baseline to be
     196             :       // deemed unflagged
     197     1132544 :       if (polChanRowFlags(polIdx, chanIdx, row)) {
     198           0 :           flagPerBaselinePerChannel[baselineIdx][chanIdx] = true;
     199           0 :           break;
     200             :       }
     201             :     }
     202             :   }
     203        8204 : }
     204             : 
     205             : /**
     206             :  * Once all the rows for a point in time have been processed, we know
     207             :  * what baselines to the antenna of interest are flagged. If all these
     208             :  * baselines are flagged, note down that all integrations for this
     209             :  * point in time should be flagged.
     210             :  *
     211             :  * @param flaggedTimes Structure to record what times must be flagged
     212             :  * @param rowTime value of the TIME column
     213             :  * @param flagPerBaselinePerChannel table with flag values of every baseline for the
     214             :  *        different channels
     215             :  */
     216             : void
     217        2698 : FlagAgentAntennaIntegrations::doPreProcessingTimePoint(FlaggedTimesMap &flaggedTimes, 
     218             :                                                        casacore::Double rowTime,
     219             :                                                        TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel)
     220             : {
     221             : 
     222        2698 :   const auto channelCnt = flagPerBaselinePerChannel.front().size();
     223        2698 :   if (1 == channelCnt) {
     224           0 :     doPreProcessingTimePointSingleChannel(flaggedTimes, rowTime, flagPerBaselinePerChannel);
     225             :   } else {
     226        2698 :     doPreProcessingTimePointMultiChannel(flaggedTimes, rowTime, flagPerBaselinePerChannel);
     227             :   }
     228             : 
     229             :   // clear flag counting table
     230       10902 :   for (auto row : flagPerBaselinePerChannel) {
     231        8204 :     row.assign(row.size(), false);
     232        8204 :   }
     233        2698 : }
     234             : 
     235             : /**
     236             :  * Pre-process with multiple channels (requires calculating the
     237             :  * fraction of channels flagged).
     238             :  *
     239             :  * Same parameters as doPreProcessingTimePoint()
     240             :  */
     241             : void
     242        2698 : FlagAgentAntennaIntegrations::doPreProcessingTimePointMultiChannel(FlaggedTimesMap &flaggedTimes,
     243             :                                                                    casacore::Double rowTime,
     244             :                                                                    const TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel)
     245             : {
     246             : 
     247        2698 :   const auto baseCnt = flagPerBaselinePerChannel.size();
     248        2698 :   const auto channelCnt = flagPerBaselinePerChannel.front().size();
     249             : 
     250        2698 :   casacore::uInt flaggedChannelsCnt = 0;
     251       94730 :   for (casacore::uInt chanIdx = 0; chanIdx < channelCnt; ++chanIdx) {
     252       92032 :     auto allBaselinesFlagged = true;
     253       92032 :     for (casacore::uInt baseIdx = 0; baseIdx < baseCnt; ++baseIdx) {
     254       92032 :       if (!flagPerBaselinePerChannel[baseIdx][chanIdx]) {
     255       92032 :         allBaselinesFlagged = false;
     256       92032 :         break;
     257             :       }
     258             :     }
     259             : 
     260       92032 :     if (allBaselinesFlagged)
     261           0 :       flaggedChannelsCnt++;
     262             :   }
     263             :   // Baselines will be considered flagged if a fraction greater than a nominated fraction
     264             :   // of channels is flagged.
     265        2698 :   auto frac = static_cast<double>(flaggedChannelsCnt) / channelCnt;
     266        2698 :   if (frac <= minChanThreshold_p) {
     267        2514 :     return;
     268             :   }
     269             : 
     270             :   // all baselines are flagged for a fraction of channels greater than the threshold
     271         184 :   flaggedTimes[rowTime] = true;
     272         184 :   if (verbose_p) {
     273           5 :     casacore::MVTime time(rowTime/casacore::C::day);
     274           5 :     auto fracAlreadyFlagged = static_cast<float>(flaggedChannelsCnt) / channelCnt;
     275           5 :     *logger_p << casacore::LogIO::NORMAL << "Flagging integration at time: "
     276           5 :               << time.string(casacore::MVTime::YMD,7) 
     277             :               << " (fraction of flagged channels found: " << fracAlreadyFlagged << ")"
     278           5 :               << casacore::LogIO::POST;  
     279           5 :   }
     280             : }
     281             : 
     282             : 
     283             : /**
     284             :  * If the selected channel is flagged for all the baselines, mark this time for flagging.
     285             :  *
     286             :  * This method Is not exactly the same as the MultiChannel version. When minchanfrac=1
     287             :  * MultiChannel would never flag, as the comparison requires that the 'fraction of channels
     288             :  * flagged' be > minchanfrac.
     289             :  *
     290             :  * Same parameters as doPreProcessingTimePoint()
     291             :  */
     292             : void
     293           0 : FlagAgentAntennaIntegrations::doPreProcessingTimePointSingleChannel(FlaggedTimesMap &flaggedTimes, 
     294             :                                                                     casacore::Double rowTime,
     295             :                                                                     const TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel)
     296             : {
     297             : 
     298           0 :   const auto baseCnt = flagPerBaselinePerChannel.size();
     299           0 :   for (casacore::uInt baseIdx = 0; baseIdx < baseCnt; ++baseIdx) {
     300             :     // A baseline is flagged if the only channel selected is flagged
     301             :     // Found a baseline that is not flagged:
     302           0 :     if (!flagPerBaselinePerChannel[baseIdx].front())
     303           0 :       return;
     304             :   }
     305             : 
     306             :   // all baselines are flagged for a fraction of channels greater than the threshold
     307           0 :   flaggedTimes[rowTime] = true;
     308           0 :   if (verbose_p) {
     309           0 :     casacore::MVTime time(rowTime/casacore::C::day);
     310           0 :     *logger_p << casacore::LogIO::NORMAL << "Flagging integration at time:"
     311           0 :               << time.string(casacore::MVTime::YMD,7) << casacore::LogIO::POST;
     312           0 :   }
     313             : }
     314             : 
     315             : bool
     316       26327 : FlagAgentAntennaIntegrations::computeRowFlags(const vi::VisBuffer2 &visBuffer,
     317             :                                               FlagMapper &/*flags*/, casacore::uInt row)
     318             : {
     319       26327 :   auto flag = false;
     320             :   // As per preprocessBuffer(), all rows for this point in time have to be flagged
     321       26327 :   const auto rowTime = visBuffer.time()[row];
     322       26327 :   if (doFlagTime_p.cend() != doFlagTime_p.find(rowTime)) {
     323        2699 :     flag = true;
     324             :   }
     325             : 
     326       26327 :   return flag;
     327             : }
     328             : 
     329             : 
     330             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16