LCOV - code coverage report
Current view: top level - flagging/Flagging - FlagAgentAntennaIntegrations.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 105 131 80.2 %
Date: 2024-10-12 00:35:29 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           8 : FlagAgentAntennaIntegrations::FlagAgentAntennaIntegrations(
      41             :                               FlagDataHandler *dh, casacore::Record config,
      42             :                               casacore::Bool writePrivateFlagCube, 
      43           8 :                               casacore::Bool flag):
      44             :   FlagAgentBase(dh, config, FlagAgentBase::ROWS_PREPROCESS_BUFFER, writePrivateFlagCube,
      45           8 :                 flag)
      46             : {
      47           8 :   logger_p->origin(casacore::LogOrigin(agentName_p,__FUNCTION__,WHERE));
      48             : 
      49           8 :   setAgentParameters(config, flagDataHandler_p->antennaNames_p);
      50           8 : }
      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           8 : void FlagAgentAntennaIntegrations::setAgentParameters(casacore::Record config,
      61             :                                                       casacore::Vector<casacore::String> *antennaNames)
      62             : {
      63           8 :   const auto fields = config.nfields();
      64           8 :   *logger_p << casacore::LogIO::NORMAL << "The configuration received by this agent has " 
      65           8 :             << fields << " fields with the following values:" << casacore::LogIO::POST;
      66           8 :   std::ostringstream ostr;
      67           8 :   config.print(ostr);
      68           8 :   *logger_p << casacore::LogIO::NORMAL << ostr.str() << casacore::LogIO::POST;
      69             : 
      70             : 
      71           8 :   const auto minChanOpt = "minchanfrac";
      72           8 :   int found = config.fieldNumber(minChanOpt);
      73           8 :   if (found >= 0) {
      74           8 :     minChanThreshold_p = config.asDouble(minChanOpt);
      75             :   }
      76             : 
      77           8 :   const auto antOpt = "antint_ref_antenna";
      78           8 :   found = config.fieldNumber(antOpt);
      79           8 :   if (found >= 0) {
      80           8 :     casacore::String antintAnt = config.asString(antOpt);
      81           8 :     antIdx_p = findAntennaID(antintAnt, antennaNames);
      82           8 :     *logger_p << casacore::LogIO::NORMAL << "Found requested antenna of interest, with "
      83           8 :       "name: " << antintAnt << ", and index: " << antIdx_p << casacore::LogIO::POST;
      84             : 
      85           8 :   } 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           8 :   const auto verboseOpt = "verbose";
      91           8 :   found = config.fieldNumber(verboseOpt);
      92           8 :   if (found >= 0) {
      93           7 :     verbose_p = config.asBool(verboseOpt);
      94             :   }
      95           8 : }
      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           8 : FlagAgentAntennaIntegrations::findAntennaID(const casacore::String &name,
     109             :                                             const casacore::Vector<casacore::String> *antennaNames) {
     110           8 :   casacore::uInt idx = 0;
     111           8 :   for( ; idx < antennaNames->nelements(); ++idx) {
     112           8 :     if (name == antennaNames->operator()(idx)) {
     113           8 :         break;
     114             :     }
     115             :   }
     116             : 
     117           8 :   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           8 :   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        1285 : FlagAgentAntennaIntegrations::preProcessBuffer(const vi::VisBuffer2 &visBuffer)
     132             : {
     133        1285 :   const auto &time_p = visBuffer.time();
     134        1285 :   auto rowCnt = time_p.size();
     135        1285 :   if (rowCnt <= 0)
     136           0 :     return;
     137             : 
     138        1285 :   auto antennasCnt = visBuffer.nAntennas();
     139        1285 :   auto channelsCnt = visBuffer.nChannels();
     140        1285 :   *logger_p << casacore::LogIO::DEBUG1 << "Pre-processing visibility buffer, with "
     141        1285 :             << " nRows: " << visBuffer.nRows()
     142        1285 :             << " nCorrelations: " << visBuffer.nCorrelations()
     143             :             << " nChannels: " << channelsCnt << ", nAntennas:: " 
     144        1285 :             << antennasCnt << casacore::LogIO::POST;  
     145             : 
     146             :   // TODO: use a casacore::Matrix here?
     147        1285 :   TableFlagPerBaselinePerChannel flagPerBaselinePerChannel;
     148        1285 :   flagPerBaselinePerChannel.resize(antennasCnt - 1);
     149        5140 :   for(auto &row : flagPerBaselinePerChannel) {
     150        3855 :     row.assign(channelsCnt, false);
     151             :   }
     152             : 
     153        1285 :   const auto ant1 = visBuffer.antenna1();
     154        1285 :   const auto ant2 = visBuffer.antenna2(); 
     155        1285 :   const auto &polChanRowFlags = visBuffer.flagCube();
     156        1285 :   auto currentTime = time_p[0];
     157        1285 :   auto baselineIdx = 0;
     158       17443 :   for (casacore::uInt rowIdx = 0; rowIdx < rowCnt; ++rowIdx) {
     159       16158 :     if (ant1[rowIdx] != antIdx_p and ant2[rowIdx] != antIdx_p)
     160        8079 :       continue;
     161             : 
     162        8079 :     auto rowTime = time_p[rowIdx];
     163        8079 :     if (rowTime != currentTime) {
     164        1408 :       doPreProcessingTimePoint(doFlagTime_p, currentTime, flagPerBaselinePerChannel);
     165        1408 :       currentTime = rowTime;
     166        1408 :       baselineIdx = 0;
     167             :     }
     168             : 
     169        8079 :     checkAnyPolarizationFlagged(polChanRowFlags, flagPerBaselinePerChannel,
     170        8079 :                                 rowIdx, baselineIdx++);
     171             : 
     172             :   }
     173             :   // last time
     174        1285 :   doPreProcessingTimePoint(doFlagTime_p, currentTime, flagPerBaselinePerChannel);
     175        1285 : }
     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        8079 : void FlagAgentAntennaIntegrations::checkAnyPolarizationFlagged(const casacore::Cube<casacore::Bool> &polChanRowFlags, 
     188             :                                                                TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel,
     189             :                                                                casacore::uInt row, casacore::uInt baselineIdx) {
     190             : 
     191        8079 :   const auto channelCnt = polChanRowFlags.ncolumn();
     192        8079 :   const auto polCnt = polChanRowFlags.nrow();
     193      283215 :   for (casacore::uInt chanIdx = 0; chanIdx < channelCnt; ++chanIdx) {
     194     1375680 :     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     1100544 :       if (polChanRowFlags(polIdx, chanIdx, row)) {
     198           0 :           flagPerBaselinePerChannel[baselineIdx][chanIdx] = true;
     199           0 :           break;
     200             :       }
     201             :     }
     202             :   }
     203        8079 : }
     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        2693 : FlagAgentAntennaIntegrations::doPreProcessingTimePoint(FlaggedTimesMap &flaggedTimes, 
     218             :                                                        casacore::Double rowTime,
     219             :                                                        TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel)
     220             : {
     221             : 
     222        2693 :   const auto channelCnt = flagPerBaselinePerChannel.front().size();
     223        2693 :   if (1 == channelCnt) {
     224           0 :     doPreProcessingTimePointSingleChannel(flaggedTimes, rowTime, flagPerBaselinePerChannel);
     225             :   } else {
     226        2693 :     doPreProcessingTimePointMultiChannel(flaggedTimes, rowTime, flagPerBaselinePerChannel);
     227             :   }
     228             : 
     229             :   // clear flag counting table
     230       10772 :   for (auto row : flagPerBaselinePerChannel) {
     231        8079 :     row.assign(row.size(), false);
     232        8079 :   }
     233        2693 : }
     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        2693 : FlagAgentAntennaIntegrations::doPreProcessingTimePointMultiChannel(FlaggedTimesMap &flaggedTimes,
     243             :                                                                    casacore::Double rowTime,
     244             :                                                                    const TableFlagPerBaselinePerChannel &flagPerBaselinePerChannel)
     245             : {
     246             : 
     247        2693 :   const auto baseCnt = flagPerBaselinePerChannel.size();
     248        2693 :   const auto channelCnt = flagPerBaselinePerChannel.front().size();
     249             : 
     250        2693 :   casacore::uInt flaggedChannelsCnt = 0;
     251       94405 :   for (casacore::uInt chanIdx = 0; chanIdx < channelCnt; ++chanIdx) {
     252       91712 :     auto allBaselinesFlagged = true;
     253       91712 :     for (casacore::uInt baseIdx = 0; baseIdx < baseCnt; ++baseIdx) {
     254       91712 :       if (!flagPerBaselinePerChannel[baseIdx][chanIdx]) {
     255       91712 :         allBaselinesFlagged = false;
     256       91712 :         break;
     257             :       }
     258             :     }
     259             : 
     260       91712 :     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        2693 :   auto frac = static_cast<double>(flaggedChannelsCnt) / channelCnt;
     266        2693 :   if (frac <= minChanThreshold_p) {
     267        2514 :     return;
     268             :   }
     269             : 
     270             :   // all baselines are flagged for a fraction of channels greater than the threshold
     271         179 :   flaggedTimes[rowTime] = true;
     272         179 :   if (verbose_p) {
     273           0 :     casacore::MVTime time(rowTime/casacore::C::day);
     274           0 :     auto fracAlreadyFlagged = static_cast<float>(flaggedChannelsCnt) / channelCnt;
     275           0 :     *logger_p << casacore::LogIO::NORMAL << "Flagging integration at time: "
     276           0 :               << time.string(casacore::MVTime::YMD,7) 
     277             :               << " (fraction of flagged channels found: " << fracAlreadyFlagged << ")"
     278           0 :               << casacore::LogIO::POST;  
     279           0 :   }
     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       24702 : FlagAgentAntennaIntegrations::computeRowFlags(const vi::VisBuffer2 &visBuffer,
     317             :                                               FlagMapper &/*flags*/, casacore::uInt row)
     318             : {
     319       24702 :   auto flag = false;
     320             :   // As per preprocessBuffer(), all rows for this point in time have to be flagged
     321       24702 :   const auto rowTime = visBuffer.time()[row];
     322       24702 :   if (doFlagTime_p.cend() != doFlagTime_p.find(rowTime)) {
     323        1074 :     flag = true;
     324             :   }
     325             : 
     326       24702 :   return flag;
     327             : }
     328             : 
     329             : 
     330             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16