LCOV - code coverage report
Current view: top level - flagging/Flagging - Flagger.cc (source / functions) Hit Total Coverage
Test: casa_coverage.info Lines: 0 1008 0.0 %
Date: 2023-10-25 08:47:59 Functions: 0 33 0.0 %

          Line data    Source code
       1             : ///# Flagger.cc: this defines Flagger
       2             : //# Copyright (C) 2000,2001,2002
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: aips2-request@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : #include <casacore/casa/Arrays/Vector.h>
      28             : #include <casacore/casa/Arrays/ArrayMath.h>
      29             : #include <casacore/casa/Arrays/ArrayLogical.h>
      30             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      31             : #include <casacore/ms/MeasurementSets/MSSpWindowColumns.h>
      32             : #include <casacore/casa/BasicSL/Complex.h>
      33             : #include <casacore/measures/Measures/Stokes.h>
      34             : #include <casacore/casa/Utilities/Regex.h>
      35             : #include <casacore/casa/OS/HostInfo.h>
      36             : #include <flagging/Flagging/Flagger.h>
      37             : #include <flagging/Flagging/RFAFlagExaminer.h>
      38             : #include <flagging/Flagging/RFAMedianClip.h>
      39             : #include <flagging/Flagging/RFASpectralRej.h>
      40             : #include <flagging/Flagging/RFASelector.h>
      41             : #include <flagging/Flagging/RFAUVBinner.h>
      42             : #include <flagging/Flagging/RFATimeFreqCrop.h>
      43             : #include <msvis/MSVis/VisibilityIterator.h>
      44             : #include <msvis/MSVis/VisBuffer.h>
      45             : #include <casacore/casa/System/ProgressMeter.h>
      46             : #include <stdarg.h>
      47             : 
      48             : #include <casacore/tables/Tables/Table.h>
      49             : #include <casacore/tables/TaQL/TableParse.h>
      50             : #include <casacore/tables/Tables/TableRecord.h>
      51             : #include <casacore/tables/Tables/TableDesc.h>
      52             : #include <casacore/tables/Tables/TableLock.h>
      53             : #include <casacore/tables/Tables/SetupNewTab.h>
      54             : 
      55             : #include <casacore/tables/TaQL/ExprNode.h>
      56             : #include <msvis/MSVis/VisSet.h>
      57             : #include <msvis/MSVis/VisSetUtil.h>
      58             : 
      59             : #include <casacore/measures/Measures/Stokes.h>
      60             : #include <casacore/casa/Quanta/UnitMap.h>
      61             : #include <casacore/casa/Quanta/UnitVal.h>
      62             : #include <casacore/casa/Quanta/MVAngle.h>
      63             : #include <casacore/measures/Measures/MDirection.h>
      64             : #include <casacore/measures/Measures/MPosition.h>
      65             : #include <casacore/casa/Quanta/MVEpoch.h>
      66             : #include <casacore/measures/Measures/MEpoch.h>
      67             : #include <casacore/measures/Measures/MeasTable.h>
      68             : 
      69             : #include <flagging/Flagging/RFANewMedianClip.h>
      70             : 
      71             : #include <algorithm>
      72             : 
      73             : #include <sstream>
      74             : 
      75             : using namespace casacore;
      76             : namespace casa {
      77             : 
      78             : const bool Flagger::dbg = false;
      79             : 
      80             : LogIO Flagger::os( LogOrigin("Flagger") );
      81             : static char str[1024];
      82             : // uInt debug_ifr=9999,debug_itime=9999;
      83             : 
      84             : 
      85             : // -----------------------------------------------------------------------
      86             : // Default Constructor
      87             : // -----------------------------------------------------------------------
      88           0 : Flagger::Flagger ():mssel_p(0), vs_p(0), scan_looping(false)
      89             : {
      90           0 :         msselection_p = new MSSelection();
      91           0 :         spw_selection = false;
      92             : 
      93           0 :         agents_p = NULL;
      94           0 :         agentCount_p=0;
      95           0 :         opts_p = NULL;
      96             : 
      97           0 :         logSink_p = LogSink(LogMessage::NORMAL, false);
      98             : 
      99           0 :         nant = 0;
     100           0 :         nifr = 0;
     101           0 :         nfeed = 0;
     102           0 :         nfeedcorr = 0;
     103             : 
     104           0 :         setdata_p = false;
     105           0 :         selectdata_p = false;
     106             :         // setupAgentDefaults();
     107             : 
     108           0 :         quack_agent_exists = false;
     109           0 : }
     110             : 
     111             : // -----------------------------------------------------------------------
     112             : // Constructor
     113             : // constructs and attaches to MS
     114             : // -----------------------------------------------------------------------
     115           0 : Flagger::Flagger ( MeasurementSet &mset ) : mssel_p(0), vs_p(0), scan_looping(false)
     116             : {
     117           0 :         msselection_p = new MSSelection();
     118           0 :         spw_selection = false;
     119             : 
     120           0 :         agents_p = NULL;
     121           0 :         agentCount_p=0;
     122           0 :         opts_p = NULL;
     123             : 
     124           0 :         logSink_p = LogSink(LogMessage::NORMAL, false);
     125             : 
     126           0 :         nant = 0;
     127           0 :         setdata_p = false;
     128           0 :         selectdata_p = false;
     129           0 :         attach(mset);
     130             : 
     131           0 :         quack_agent_exists = false;
     132           0 : }
     133             : 
     134           0 : Flagger::~Flagger ()
     135             : {
     136             :         /*
     137             :           jmlarsen: Eh? The following code is probably a bug
     138             :           (it closes the MS when the length() is 0)
     139             :           What about calling detach()?
     140             :          */
     141             : 
     142           0 :         if ( !ms.tableName().length()) {
     143           0 :                 os << "Flagger closing out " << ms.tableName() << LogIO::POST;
     144           0 :                 ms.flush();
     145           0 :                 ms.relinquishAutoLocks(true);
     146           0 :                 ms.unlock();
     147             : 
     148             :                 //originalms = NULL;
     149           0 :                 originalms_p = NULL;
     150             :         }
     151             : 
     152           0 :         if (vs_p)  delete vs_p;
     153           0 :         vs_p = 0;
     154             : 
     155             :         if (dbg) cout << "Flagger destructor :: about to clean mssel_p" << endl;
     156             : 
     157           0 :         if (mssel_p) delete mssel_p;
     158           0 :         mssel_p = 0;
     159             : 
     160             :         if (dbg) cout << "Flagger destructor :: cleaned mssel_p" << endl;
     161             : 
     162           0 :         if (msselection_p) delete msselection_p;
     163           0 :         msselection_p = 0;
     164             : 
     165           0 :         if (agents_p) delete agents_p;
     166           0 :         agents_p = NULL;
     167             : 
     168           0 :         if (opts_p) delete opts_p;
     169           0 :         opts_p = NULL;
     170           0 : }
     171             : 
     172             : // -----------------------------------------------------------------------
     173             : // queryOptions
     174             : // Returns record of available options and their default values
     175             : // -----------------------------------------------------------------------
     176           0 : const RecordInterface & Flagger::defaultOptions ()
     177             : {
     178           0 :         static Record rec;
     179             :         // create record description on first entry
     180           0 :         if ( !rec.nfields() )
     181             :         {
     182           0 :                 rec.defineRecord(RF_GLOBAL, Record());
     183           0 :                 rec.define(RF_TRIAL, false);
     184           0 :                 rec.define(RF_RESET, false);
     185             : 
     186           0 :                 rec.setComment(RF_GLOBAL, "Record of global parameters applied to all methods");
     187           0 :                 rec.setComment(RF_TRIAL, "T for trial run (no flags written out)");
     188           0 :                 rec.setComment(RF_RESET, "T to reset existing flags before running");
     189             :         }
     190           0 :         return rec;
     191             : }
     192             : 
     193             : // -----------------------------------------------------------------------
     194             : // Flagger::attach
     195             : // attaches to MS
     196             : // -----------------------------------------------------------------------
     197             : 
     198           0 : bool Flagger::attach( MeasurementSet &mset, Bool setAgentDefaults )
     199             : {
     200           0 :         nant = 0;
     201           0 :         setdata_p = false;
     202           0 :         selectdata_p = false;
     203           0 :         if (vs_p)
     204           0 :                 delete vs_p;
     205           0 :         vs_p = 0;
     206           0 :         if (mssel_p)
     207           0 :                 delete mssel_p;
     208           0 :         mssel_p = 0;
     209           0 :         if (setAgentDefaults)
     210           0 :                 setupAgentDefaults();
     211           0 :         ms = mset;
     212             : 
     213           0 :         originalms = mset;
     214           0 :         originalms_p = &mset;
     215             : 
     216             :         //      Matrix<Int> noselection;
     217             :         // Use default sort order - and no scratch cols....
     218             :         //        vs_p = new VisSet(*originalms_p,noselection,0.0);
     219             :         //      vs_p->resetVisIter(sort, 0.0);
     220             : 
     221           0 :         Matrix<Int> noselection;
     222           0 :         Block<Int> bsort(3);
     223           0 :         bsort[0] = MS::FIELD_ID;
     224           0 :         bsort[1] = MS::DATA_DESC_ID;
     225           0 :         bsort[2] = MS::TIME;
     226             : 
     227             :         // extract various interesting info from the MS
     228             :         // obtain number of distinct time slots
     229           0 :         MSColumns msc(ms);
     230           0 :         Vector<Double> time( msc.time().getColumn() );
     231             : 
     232           0 :         uInt nrows = time.nelements();
     233             :         unsigned ntime;
     234             : 
     235           0 :         if (nrows == 0) ntime = 0;
     236             :         else {
     237             :                 Bool dum;
     238           0 :                 Double *tp = time.getStorage(dum);
     239             : 
     240           0 :                 std::sort(tp, tp + nrows);
     241             : 
     242           0 :                 ntime = 1;
     243           0 :                 for (unsigned i = 0; i < nrows-1; i++) {
     244           0 :                         if (tp[i] < tp[i+1]) ntime += 1;
     245             :                 }
     246             :         }
     247             : 
     248             :         // obtain central frequencies of spws.
     249           0 :         const MSSpectralWindow spwin( ms.spectralWindow() );
     250           0 :         ScalarColumn<Double> sfreqs(spwin, "REF_FREQUENCY");
     251           0 :         spwfreqs.resize();
     252           0 :         spwfreqs = sfreqs.getColumn();
     253           0 :         spwfreqs *= 1e+6;
     254             : 
     255             :         // obtain number of antennas and interferometers
     256           0 :         const MSAntenna msant( ms.antenna() );
     257           0 :         nant = msant.nrow();
     258           0 :         nifr = nant*(nant+1)/2; // cheap & dirty
     259           0 :         ScalarColumn<String> names(msant,"NAME");
     260           0 :         antnames.resize();
     261           0 :         antnames = names.getColumn();
     262           0 :         antnames.apply(stringUpper);
     263             :         //  cerr<<"Antenna names: "<<antnames<<endl;
     264             :         // map ifrs to antennas
     265           0 :         ifr2ant1.resize(nifr);
     266           0 :         ifr2ant1.set(-1);
     267           0 :         ifr2ant2.resize(nifr);
     268           0 :         ifr2ant2.set(-1);
     269           0 :         for( uInt i1=0; i1<nant; i1++ ) {
     270           0 :                 for( uInt i2=0; i2<=i1; i2++ ) {
     271           0 :                         uInt ifr = ifrNumber(i1,i2);
     272           0 :                         ifr2ant1(ifr) = i1;
     273           0 :                         ifr2ant2(ifr) = i2;
     274             :                 }
     275             :         }
     276             : 
     277             :         // get feed info
     278           0 :         const MSFeed msfeed( ms.feed() );
     279           0 :         nfeed = msfeed.nrow();
     280           0 :         nfeedcorr = nfeed*(nfeed+1)/2;
     281             : 
     282           0 :         sprintf(str,"attached MS %s: %d rows, %d times, %d baselines\n",ms.tableName().chars(),nrows,ntime,nifr);
     283             :         //os << "--------------------------------------------------" << LogIO::POST;
     284           0 :         os<<str<<LogIO::POST;
     285             : 
     286           0 :         return true;
     287             : }
     288             : 
     289             : // -----------------------------------------------------------------------
     290             : // Flagger::detach
     291             : // detaches from MS
     292             : // -----------------------------------------------------------------------
     293           0 : void Flagger::detach()
     294             : {
     295           0 :         if ( ms.tableName().length() == 0) {
     296           0 :                 os << "no measurement set was attached" << LogIO::POST;
     297             :         }
     298             :         else {
     299           0 :                 os << "detaching from MS " << ms.tableName() << LogIO::POST;
     300           0 :                 nant = 0;
     301           0 :                 setdata_p = false;
     302           0 :                 selectdata_p = false;
     303           0 :                 ms.flush();
     304           0 :                 ms.relinquishAutoLocks(true);
     305           0 :                 ms.unlock();
     306           0 :                 ms = MeasurementSet();
     307             :         }
     308           0 : }
     309             : 
     310             : /************************************ DATA SELECTION **************************************/
     311             : /* return: true iff succesful
     312             :  */
     313           0 : Bool Flagger::selectdata(Bool useoriginalms,
     314             :                 String field, String spw, String array,
     315             :                 String feed, String scan,
     316             :                 String baseline, String uvrange, String time,
     317             :                 String correlation, String intent, String observation)
     318             : {
     319             :         if (dbg) cout << "selectdata: "
     320             :                         << "useoriginalms=" << useoriginalms
     321             :                         << " field=" << field << " spw=" << spw
     322             :                         << " array=" << array << " feed=" << feed
     323             :                         << " scan=" << scan << " baseline=" << baseline
     324             :                         << " uvrange=" << uvrange << " time=" << time
     325             :                         << " correlation=" << correlation << " scan intent="<< intent
     326             :                         << " observation=" << observation << endl;
     327             : 
     328           0 :         LogIO os(LogOrigin("Flagger", "selectdata()", WHERE));
     329           0 :         if (ms.isNull()) {
     330             :                 os << LogIO::SEVERE << "NO MeasurementSet attached"
     331           0 :                                 << LogIO::POST;
     332           0 :                 return false;
     333             :         }
     334             : 
     335             :         /* If a diff sort-order is required, put it in here, and
     336             :        create the MSs with the new ordering */
     337             : 
     338           0 :         MeasurementSet *tms = NULL;
     339           0 :         if ( useoriginalms ) tms = &originalms;
     340             :         else
     341             :         {
     342           0 :                 if (!mssel_p)
     343             :                 {
     344           0 :                         cout << "Flagger::selectdata -> mssel_p is NULL !!!" << endl;
     345           0 :                         return false;
     346             :                 }
     347           0 :                 tms = mssel_p;
     348             :         }
     349             : 
     350             :         if (dbg) cout << "Setting selection strings" << endl;
     351             : 
     352             : 
     353             :         /* Row-Selection */
     354             : 
     355           0 :         if (spw.length() == 0 && uvrange.length() > 0) {
     356           0 :                 spw = String("*");
     357             :         }
     358             : 
     359           0 :         const String dummyExpr = String("");
     360           0 :         if (msselection_p) {
     361           0 :                 delete msselection_p;
     362           0 :                 msselection_p = NULL;
     363           0 :                 spw_selection = false;
     364             : 
     365             :         }
     366           0 :         msselection_p = new MSSelection(*tms,
     367             :                         MSSelection::PARSE_NOW,
     368           0 :                         (const String)time,
     369           0 :                         (const String)baseline,
     370           0 :                         (const String)field,
     371           0 :                         (const String)spw,
     372           0 :                         (const String)uvrange,
     373             :                         dummyExpr, // taqlExpr
     374             :                         dummyExpr, // corrExpr
     375           0 :                         (const String)scan,
     376           0 :                         (const String)array,
     377           0 :                         (const String)intent,
     378           0 :                         (const String)observation);
     379           0 :         spw_selection = ((spw != "" && spw != "*") || uvrange.length() > 0);
     380             :         // multiple spw agents are also needed for uvrange selections...
     381             : 
     382           0 :         selectdata_p = false;
     383             :         /* Print out selection info - before selecting ! */
     384             :         if (dbg)
     385             :         {
     386             :                 cout.precision(16);
     387             :                 cout << "Antenna 1 : " << msselection_p->getAntenna1List() << endl;
     388             :                 cout << "Antenna 2 : " << msselection_p->getAntenna2List() << endl;
     389             :                 Matrix<Int> baselinelist(msselection_p->getBaselineList());
     390             :                 IPosition shp = baselinelist.shape();
     391             :                 if (shp.product() < 20)
     392             :                 {
     393             :                         IPosition transposed = shp;
     394             :                         transposed[0]=shp[1]; transposed[1]=shp[0];
     395             :                         Matrix<Int> blist(transposed);
     396             :                         for (Int i=0;i<shp[0];i++)
     397             :                                 for (Int j=0;j<shp[1];j++)
     398             :                                         blist(j,i) = baselinelist(i,j);
     399             :                         cout << "Baselines : " << blist << endl;
     400             :                 }
     401             :                 cout << "Fields : " << msselection_p->getFieldList() << endl;
     402             :                 cout << "Spw : " << msselection_p->getSpwList() << endl;
     403             :                 cout << "SpwChans : " << msselection_p->getChanList() << endl;
     404             :                 Matrix<Double> tlist(msselection_p->getTimeList());
     405             :                 cout << "Time : " << tlist << endl;
     406             :                 cout << "Time : " << endl;
     407             :                 for(Int i=0;i<(tlist.shape())[1];i++)
     408             :                         cout << "[" << MVTime(tlist(0,i)/C::day).string(MVTime::DMY,7) << " ~ " << MVTime(tlist(1,i)/C::day).string(MVTime::DMY,7) << "]" << endl;
     409             :                 cout << "UVrange : " << msselection_p->getUVList() << endl;
     410             :                 cout << "UV Units : " << msselection_p->getUVUnitsList() << endl;
     411             :                 cout << "Scans : " << msselection_p->getScanList() << endl;
     412             :                 cout << "Arrays : " << msselection_p->getSubArrayList() << endl;
     413             :                 // cout << "Feeds : " << msselection_p->getFeedList() << endl;
     414             :                 cout << "Scan intent : " << msselection_p->getStateObsModeList() << endl;
     415             :                 cout << "Observation : " << msselection_p->getObservationList() << endl;
     416             : 
     417             :         }
     418             : 
     419             :         /* Correlations */
     420           0 :         correlations_p.resize(0);
     421           0 :         string tcorr[50];
     422           0 :         Regex delim("(,| )+");
     423           0 :         Int ncorr = split(correlation, tcorr, 50, delim);
     424           0 :         correlations_p.resize(ncorr);
     425           0 :         for(Int i=0;i<ncorr;i++) correlations_p[i] = upcase(String(tcorr[i]));
     426             : 
     427             :         if (dbg) cout << "Correlations : " << correlations_p << endl;
     428             : 
     429           0 :         selectdata_p = true;
     430           0 :         return true;
     431             : }
     432             : 
     433           0 : Bool Flagger::setdata(
     434             :                 String field, String spw, String array,
     435             :                 String feed, String scan,
     436             :                 String baseline,  String uvrange,  String time,
     437             :                 String correlation, String intent, String observation)
     438             : {
     439             :         if (dbg) cout << "setdata: "
     440             :                         << " field=" << field << " spw=" << spw
     441             :                         << " array=" << array << " feed=" << feed
     442             :                         << " scan=" << scan << " baseline=" << baseline
     443             :                         << " uvrange=" << uvrange << " time=" << time
     444             :                         << " correlation=" << correlation << " scan intent=" << intent
     445             :                         << " observation=" << observation << endl;
     446             : 
     447           0 :         LogIO os(LogOrigin("Flagger", "setdata()", WHERE));
     448           0 :         setdata_p = false;
     449             : 
     450             : 
     451             :         /* check the MS */
     452           0 :         if (ms.isNull()) {
     453             :                 os << LogIO::SEVERE << "NO MeasurementSet attached"
     454           0 :                                 << LogIO::POST;
     455           0 :                 return false;
     456             :         }
     457             : 
     458             :         /* Parse selection parameters */
     459           0 :         if (!spw.length()) spw = String("*");
     460             : 
     461           0 :         if (!selectdata(true,field,spw,array,feed,scan, baseline,uvrange,time,correlation,intent,observation))
     462             :         {
     463             :                 os << LogIO::SEVERE << "Selection failed !!"
     464           0 :                                 << LogIO::POST;
     465           0 :                 return false;
     466             :         }
     467             : 
     468             :         /* Create selected reference MS */
     469           0 :         MeasurementSet mssel_p2(*originalms_p);
     470             : 
     471           0 :         msselection_p->getSelectedMS(mssel_p2, String(""));
     472             : 
     473             :         if (dbg) cout << "Original ms has nrows : " << originalms.nrow() << LogIO::POST;
     474             :         if (dbg) cout << "Selected ms has " << mssel_p2.nrow() << " rows." << LogIO::POST;
     475             : 
     476           0 :         if ( mssel_p2.nrow() ) {
     477           0 :                 if (mssel_p) {
     478           0 :                         delete mssel_p;
     479           0 :                         mssel_p=NULL;
     480             :                 }
     481           0 :                 if (mssel_p2.nrow() == originalms_p->nrow()) {
     482           0 :                         mssel_p = new MeasurementSet(*originalms_p);
     483             :                 }
     484             :                 else {
     485           0 :                         mssel_p = new MeasurementSet(mssel_p2);
     486             :                 }
     487             :                 if (dbg)cout << "assigned new MS to mssel_p" << endl;
     488           0 :                 ScalarColumn<String> fname( mssel_p->field(),"NAME" );
     489             :                 if (dbg)cout << "fields : " << fname.getColumn() << endl;
     490             : 
     491             :                 //mssel_p->rename("selectedms",Table::New);
     492             :                 //mssel_p->flush();
     493             :         }
     494             :         else {
     495           0 :                 os << LogIO::WARN << "Selected MS has zero rows" << LogIO::POST;
     496             :                 //mssel_p = &originalms;
     497           0 :                 if (mssel_p) {
     498           0 :                         delete mssel_p; 
     499           0 :                         mssel_p=NULL;
     500             :                 }
     501           0 :                 return false;
     502             :         }
     503             : 
     504             :         /* Print out selection info - before selecting ! */
     505           0 :         if (mssel_p->nrow()!=ms.nrow()) {
     506             :                 os << "By selection " << originalms.nrow() << " rows are reduced to "
     507           0 :                                 << mssel_p->nrow() << LogIO::POST;
     508             :         }
     509             :         else {
     510           0 :                 os << "Selection did not drop any rows" << LogIO::NORMAL3;
     511             :         }
     512             :         /* Create a vis iter */
     513           0 :         Matrix<Int> noselection;
     514           0 :         Block<int> sort2(4);
     515             :         //sort2[0] = MS::SCAN_NUMBER;
     516             :         // Do scan priority only if quacking
     517           0 :         sort2[0]= MS::ARRAY_ID;
     518           0 :         sort2[1]= MS::FIELD_ID;
     519           0 :         sort2[2]= MS::DATA_DESC_ID;
     520           0 :         sort2[3] = MS::TIME;
     521             :         /* Set the chunk time interval to be the full time-range.
     522             :           - FlagExaminer counters depend on this.
     523             :        However, autoflag agents like tfcrop will take a performance hit
     524             :        since it will store flags for the entire chunk in memory
     525             :          */
     526           0 :         Double timeInterval = 7.0e9; //a few thousand years
     527             :         //Double timeInterval = 6000; // seconds : 100 minutes.
     528             : 
     529           0 :         if (vs_p) {
     530           0 :                 delete vs_p; vs_p = NULL;
     531             :         }
     532           0 :         if (!vs_p) {
     533           0 :                 if (!mssel_p)
     534           0 :                         throw AipsError("No measurement set selection available");
     535             :                 //vs_p = new VisSet(*mssel_p,sort,noselection,0.0);
     536             : 
     537           0 :                 Bool addScratch = false;
     538           0 :                 vs_p = new VisSet(*mssel_p, sort2, noselection,
     539           0 :                                 addScratch, timeInterval);
     540             :                 // Use default sort order - and no scratch cols....
     541             :                 //vs_p = new VisSet(*mssel_p,noselection,0.0);
     542             :         }
     543           0 :         vs_p->resetVisIter(sort2, timeInterval);
     544             : 
     545             :         // Optimize for iterating randomly through one MS
     546           0 :         vs_p->iter().slurp();
     547             : 
     548             :         /* Channel selection */ // Always select all chans
     549           0 :         selectDataChannel();
     550           0 :         ms = *mssel_p;
     551             : 
     552             : 
     553           0 :         setdata_p = true;
     554           0 :         return true;
     555             : }
     556             : 
     557             : 
     558           0 : Bool Flagger::selectDataChannel(){
     559             : 
     560           0 :         if (!vs_p || !msselection_p) return false;
     561             :         /* Set channel selection in visiter */
     562             :         /* Set channel selection per spectral window - from msselection_p->getChanList(); */
     563             :         // this is needed when "setdata" is used to select data for autoflag algorithms
     564             :         // This should not be done for manual flagging, because the channel indices for the
     565             :         //  selected subset start from zero - and throw everything into confusion.
     566           0 :         Vector<Int> spwlist = msselection_p->getSpwList();
     567             : 
     568           0 :         if ( spwlist.nelements() && spw_selection ) {
     569           0 :                 Matrix<Int> spwchan = msselection_p->getChanList();
     570           0 :                 IPosition cshp = spwchan.shape();
     571           0 :                 if ( (Int)spwlist.nelements() > (spwchan.shape())[0] )
     572           0 :                         cout << "WARN : Using only the first channel range per spw" << endl;
     573           0 :                 for( uInt i=0;i<spwlist.nelements();i++ )
     574             :                 {
     575           0 :                         Int j=0;
     576           0 :                         for ( j=0;j<(spwchan.shape())[0];j++ )
     577           0 :                                 if ( spwchan(j,0) == spwlist[i] ) break;
     578           0 :                         vs_p->iter().selectChannel(1, Int(spwchan(j,1)),
     579           0 :                                         Int(spwchan(j,2)-spwchan(j,1)+1),
     580           0 :                                         Int(spwchan(j,3)), spwlist[i]);
     581             :                 }
     582             :         }
     583             :         else{
     584           0 :                 return false;
     585             :         }
     586             : 
     587             : 
     588           0 :         return true;
     589             : }
     590             : 
     591             : 
     592             : 
     593             : /************************** Set Manual Flags ***************************/
     594             : 
     595           0 : Bool Flagger::fillSelections(Record &rec)
     596             : {
     597             : 
     598             :         //TableExprNode ten = msselection_p->toTableExprNode(originalms_p);
     599             : 
     600             :         /* Fill in record for selected values. */
     601             :         /* Field ID */
     602           0 :         Vector<Int> fieldlist = msselection_p->getFieldList();
     603           0 :         if (fieldlist.nelements())
     604             :         {
     605           0 :                 RecordDesc flagDesc;
     606           0 :                 flagDesc.addField(RF_FIELD, TpArrayInt);
     607           0 :                 Record flagRec(flagDesc);
     608           0 :                 flagRec.define(RF_FIELD, fieldlist);
     609           0 :                 rec.mergeField(flagRec, RF_FIELD, RecordInterface::OverwriteDuplicates);
     610             :         }
     611             :         /* BASELINE */
     612           0 :         Matrix<Int> baselinelist = msselection_p->getBaselineList();
     613             : 
     614             :         /* Here, it may be necessary to convert negative indices to positive ones
     615             :        (see CAS-2021).
     616             : 
     617             :        For now, fail cleanly if getBaselineList returned negative indices.
     618             :          */
     619             : 
     620           0 :         if (baselinelist.nelements())
     621             :         {
     622           0 :                 IPosition shp = baselinelist.shape();
     623             :                 if (dbg)cout << "Original shape of baselinelist : " << shp << endl;
     624           0 :                 IPosition transposed = shp;
     625           0 :                 transposed[0] = shp[1]; transposed[1] = shp[0];
     626           0 :                 Matrix<Int> blist(transposed);
     627             : 
     628           0 :                 for(Int i=0; i < shp[0]; i++)
     629           0 :                         for(Int j=0; j < shp[1]; j++) {
     630             : 
     631           0 :                                 if (baselinelist(i, j) < 0) {
     632           0 :                                         throw AipsError("Sorry, negated antenna selection (such as '!2') is not supported by flagger (CAS-2021)");
     633             :                                 }
     634           0 :                                 blist(j, i) = baselinelist(i, j);
     635             :                         }
     636             : 
     637           0 :                 RecordDesc flagDesc;
     638           0 :                 flagDesc.addField(RF_BASELINE, TpArrayInt);
     639           0 :                 Record flagRec(flagDesc);
     640           0 :                 flagRec.define(RF_BASELINE, blist);
     641           0 :                 rec.mergeField(flagRec, RF_BASELINE, RecordInterface::OverwriteDuplicates);
     642             :         }
     643             :         /* FEED */
     644             :         /*
     645             :       Matrix<Int> feedlist = msselection_p->getFeedList();
     646             :       if (feedlist.nelements())
     647             :       {
     648             :       IPosition shp = feedlist.shape();
     649             :       if (dbg)cout << "Original shape of feedlist : " << shp << endl;
     650             :       IPosition transposed = shp;
     651             :       transposed[0]=shp[1]; transposed[1]=shp[0];
     652             :       Matrix<Int> blist(transposed);
     653             :       for(Int i=0;i<shp[0];i++)
     654             :       for(Int j=0;j<shp[1];j++)
     655             :       blist(j,i) = feedlist(i,j);
     656             :       // need to add 1 because RFASelector expects 1-based indices.
     657             : 
     658             :       RecordDesc flagDesc;       
     659             :       flagDesc.addField(RF_FEED, TpArrayInt);
     660             :       Record flagRec(flagDesc);  
     661             :       flagRec.define(RF_FEED, blist);
     662             :       rec.mergeField(flagRec, RF_FEED, RecordInterface::OverwriteDuplicates);
     663             :       }
     664             :          */
     665             :         /* TIME */
     666           0 :         Matrix<Double> timelist = msselection_p->getTimeList();
     667           0 :         if (timelist.nelements())
     668             :         {
     669             :                 /* Times need to be in MJD */
     670           0 :                 for( Int i=0;i<(timelist.shape())[0];i++ )
     671           0 :                         for( Int j=0;j<(timelist.shape())[1];j++ )
     672           0 :                                 timelist(i,j) /= (Double)(24*3600);
     673             :                 //for( Int i=0;i<(timelist.shape())[0];i++ )
     674             :                 //  for( Int j=0;j<(timelist.shape())[1];j++ )
     675             :                 //    cout << "timelist(" << i << ", " << j << ")="
     676             :                 //           << timelist(i,j) << endl;
     677           0 :                 RecordDesc flagDesc;
     678           0 :                 flagDesc.addField(RF_TIMERANGE, TpArrayDouble);
     679           0 :                 Record flagRec(flagDesc);
     680           0 :                 flagRec.define(RF_TIMERANGE, timelist);
     681           0 :                 rec.mergeField(flagRec, RF_TIMERANGE, RecordInterface::OverwriteDuplicates);
     682             :         }
     683             :         /* RF_CORR */
     684           0 :         if (correlations_p.nelements())
     685             :         {
     686           0 :                 RecordDesc flagDesc;
     687           0 :                 flagDesc.addField(RF_CORR, TpArrayString);
     688           0 :                 Record flagRec(flagDesc);
     689           0 :                 flagRec.define(RF_CORR, correlations_p);
     690           0 :                 rec.mergeField(flagRec, RF_CORR, RecordInterface::OverwriteDuplicates);
     691             :         }
     692             :         /* Array ID */
     693           0 :         Vector<Int> arraylist = msselection_p->getSubArrayList();
     694           0 :         if (arraylist.nelements())
     695             :         {
     696           0 :                 RecordDesc flagDesc;
     697           0 :                 flagDesc.addField(RF_ARRAY, TpArrayInt);
     698           0 :                 Record flagRec(flagDesc);
     699           0 :                 flagRec.define(RF_ARRAY, arraylist);
     700           0 :                 rec.mergeField(flagRec, RF_ARRAY, RecordInterface::OverwriteDuplicates);
     701             :         }
     702             :         /* Scan ID */
     703           0 :         Vector<Int> scanlist = msselection_p->getScanList();
     704           0 :         if (scanlist.nelements())
     705             :         {
     706           0 :                 RecordDesc flagDesc;
     707           0 :                 flagDesc.addField(RF_SCAN, TpArrayInt);
     708           0 :                 Record flagRec(flagDesc);
     709           0 :                 flagRec.define(RF_SCAN, scanlist);
     710           0 :                 rec.mergeField(flagRec, RF_SCAN, RecordInterface::OverwriteDuplicates);
     711             :         }
     712             :         /* State ID  (obsMode) */
     713           0 :         Vector<Int> stateobsmodelist = msselection_p->getStateObsModeList();
     714           0 :         if (stateobsmodelist.nelements())
     715             :         {
     716           0 :                 RecordDesc flagDesc;
     717           0 :                 flagDesc.addField(RF_INTENT, TpArrayInt);
     718           0 :                 Record flagRec(flagDesc);
     719           0 :                 flagRec.define(RF_INTENT, stateobsmodelist);
     720           0 :                 rec.mergeField(flagRec, RF_INTENT, RecordInterface::OverwriteDuplicates);
     721             :         }
     722             :         /* Observation ID */
     723           0 :         Vector<Int> observationlist = msselection_p->getObservationList();
     724           0 :         if (observationlist.nelements())
     725             :         {
     726           0 :                 RecordDesc flagDesc;
     727           0 :                 flagDesc.addField(RF_OBSERVATION, TpArrayInt);
     728           0 :                 Record flagRec(flagDesc);
     729           0 :                 flagRec.define(RF_OBSERVATION, observationlist);
     730           0 :                 rec.mergeField(flagRec, RF_OBSERVATION, RecordInterface::OverwriteDuplicates);
     731             :         }
     732             : 
     733           0 :         return true;
     734             : }
     735             : 
     736             : 
     737             : 
     738             : /*
     739             :       Sets up agents for mode = 'manualflag' and mode = 'summary'
     740             :  */
     741             : 
     742           0 : Bool Flagger::setmanualflags(Bool autocorr,
     743             :                 Bool unflag,
     744             :                 String clipexpr,
     745             :                 Vector<Double> cliprange,
     746             :                 String clipcolumn,
     747             :                 Bool outside,
     748             :                 Bool channel_average,
     749             :                 Double quackinterval,
     750             :                 String quackmode,
     751             :                 Bool quackincrement,
     752             :                 String opmode,
     753             :                 Double diameter,
     754             :                 Double lowerlimit,
     755             :                 Double upperlimit)
     756             : {
     757             :         if (dbg)
     758             :                 cout << "setmanualflags: "
     759             :                 << "autocorr=" << autocorr
     760             :                 << " unflag=" << unflag
     761             :                 << " clipexpr=" << clipexpr
     762             :                 << " cliprange=" << cliprange
     763             :                 << " clipcolumn=" << clipcolumn
     764             :                 << " outside=" << outside
     765             :                 << " quackinterval=" << quackinterval
     766             :                 << " quackmode=" << quackmode
     767             :                 << " quackincrement=" << quackincrement
     768             :                 << " opmode=" << opmode
     769             :                 << " diameter=" << diameter
     770             :                 << endl;
     771             : 
     772           0 :         LogIO os(LogOrigin("Flagger", "setmanualflags()", WHERE));
     773           0 :         if (ms.isNull()) {
     774             :                 os << LogIO::SEVERE << "NO MeasurementSet attached"
     775           0 :                                 << LogIO::POST;
     776           0 :                 return false;
     777             :         }
     778           0 :         if (!selectdata_p) {
     779             :                 os << LogIO::SEVERE << "Please run selectdata with/without arguments before setmanualflags"
     780           0 :                                 << LogIO::POST;
     781           0 :                 return false;
     782             :         }
     783             : 
     784             :         /* Fill in an agent record */
     785             :         /* This assumes that selectdata has already been called */
     786             : 
     787             :         /* Loop over SPW and chan ranges. */
     788             : 
     789           0 :         Vector<Int> spwlist = msselection_p->getSpwList();
     790             : 
     791           0 :         Matrix<Int> spwchan = msselection_p->getChanList();
     792           0 :         Matrix<Double> uvrangelist = msselection_p->getUVList();
     793           0 :         Vector<Bool> uvrangeunits = msselection_p->getUVUnitsList();
     794           0 :         IPosition cshp = spwchan.shape();
     795             : 
     796             :         /* If no selection depends on spw, ( i.e. no spw, chan, uvrange )
     797             :        then no need to make separate records for each spw. */
     798           0 :         bool separatespw = false;
     799             :         Int nrec;
     800           0 :         if (spwlist.nelements() && spw_selection) {
     801           0 :                 separatespw = true;
     802           0 :                 nrec = spwlist.nelements();
     803             :         }
     804             :         else {
     805           0 :                 separatespw = false; nrec = 1;
     806             :         }
     807             : 
     808             :         if (dbg) {
     809             :                 cout << "separatespw = " << separatespw << endl;
     810             :                 cout << spwlist << endl;
     811             :         }
     812             : 
     813           0 :         scan_looping = false;
     814             : 
     815           0 :         for ( Int i=0; i < nrec; i++ ) {
     816           0 :                 Record selrec;
     817           0 :                 if (upcase(opmode).matches("FLAG") ||
     818           0 :                                 upcase(opmode).matches("SHADOW") ||
     819           0 :                                 upcase(opmode).matches("ELEVATION")) {
     820           0 :                         selrec.define("id", String("select"));
     821             : 
     822           0 :                         if (upcase(opmode).matches("SHADOW")) {
     823           0 :                                 selrec.define(RF_DIAMETER, Double(diameter));
     824             :                         }
     825           0 :                         else if (upcase(opmode).matches("ELEVATION")) {
     826           0 :                                 selrec.define(RF_LOWERLIMIT, Double(lowerlimit));
     827           0 :                                 selrec.define(RF_UPPERLIMIT, Double(upperlimit));
     828             :                         }
     829             :                 }
     830           0 :                 else if (upcase(opmode).matches("SUMMARY")) {
     831           0 :                         selrec.define("id", String("flagexaminer"));
     832             :                 }
     833             :                 else {
     834           0 :                         throw AipsError("Unknown mode " + upcase(opmode));
     835             :                 }
     836             : 
     837             :                 /* Fill selections for all but spw, chan, corr */
     838           0 :                 fillSelections(selrec);
     839             : 
     840           0 :                 if (separatespw) {
     841             :                         /* SPW ID */
     842             :                         {
     843           0 :                                 RecordDesc flagDesc;
     844           0 :                                 flagDesc.addField(RF_SPWID, TpArrayInt);
     845           0 :                                 Record flagRec(flagDesc);
     846           0 :                                 Vector<Int> t_spw(1); t_spw[0] = spwlist[i];
     847           0 :                                 flagRec.define(RF_SPWID, t_spw);
     848           0 :                                 selrec.mergeField(flagRec, RF_SPWID, RecordInterface::OverwriteDuplicates);
     849             :                         }
     850             : 
     851             :                         /* reform chan ranges */
     852           0 :                         Int ccount=0;
     853           0 :                         for( Int j=0;j<cshp[0];j++ ) if ( spwlist[i] == spwchan(j,0) ) ccount++;
     854           0 :                         Matrix<Int> chanlist(2,ccount); chanlist.set(0);
     855             : 
     856           0 :                         ccount=0;
     857           0 :                         for( Int j=0;j<cshp[0];j++ )
     858             :                         {
     859           0 :                                 if ( spwlist[i] == spwchan(j,0) )
     860             :                                 {
     861           0 :                                         chanlist(0,ccount) = spwchan(j,1);
     862           0 :                                         chanlist(1,ccount) = spwchan(j,2);
     863           0 :                                         if ( spwchan(j,3) > 1 )
     864           0 :                                                 os << LogIO::WARN << ".... ignoring chan 'step' for manual flags" << LogIO::POST;
     865           0 :                                         ccount++;
     866             :                                 }
     867             :                         }
     868             :                         /* RF_CHANS */
     869             :                         {
     870           0 :                                 RecordDesc flagDesc;
     871           0 :                                 flagDesc.addField(RF_CHANS, TpArrayInt);
     872           0 :                                 Record flagRec(flagDesc);
     873           0 :                                 flagRec.define(RF_CHANS, chanlist);
     874           0 :                                 selrec.mergeField(flagRec, RF_CHANS, RecordInterface::OverwriteDuplicates);
     875             :                         }
     876             : 
     877             :                         /* UV-RANGE */
     878           0 :                         if (uvrangelist.nelements())
     879             :                         {
     880           0 :                                 Matrix<Double> templist(uvrangelist.shape());
     881             :                                 /* Convert to Metres... */
     882             :                                 /* or complain if units are not metres... */
     883             :                                 // current spw : spwlist[i];
     884             : 
     885           0 :                                 if ( (templist.shape())[1] != (Int)uvrangeunits.nelements() )
     886           0 :                                         cout << "UVRANGE units are wrong length ! " << endl;
     887           0 :                                 for( Int j=0;j<(templist.shape())[1];j++ )
     888             :                                 {
     889           0 :                                         Double unit=1.0;
     890           0 :                                         if ( ! uvrangeunits[j] ) unit = C::c/(spwfreqs[spwlist[i]]/1e+6);
     891           0 :                                         for( Int k=0;k<(templist.shape())[0];k++ )
     892           0 :                                                 templist(k,j) = uvrangelist(k,j) * unit ;
     893             :                                 }
     894             : 
     895           0 :                                 RecordDesc flagDesc;
     896           0 :                                 flagDesc.addField(RF_UVRANGE, TpArrayDouble);
     897           0 :                                 Record flagRec(flagDesc);
     898           0 :                                 flagRec.define(RF_UVRANGE, templist);
     899           0 :                                 selrec.mergeField(flagRec, RF_UVRANGE, RecordInterface::OverwriteDuplicates);
     900             :                                 if (dbg) cout << "uv list (m) : " << templist << endl;
     901             :                         }
     902             :                 }
     903             : 
     904             :                 // Operation related parameters.
     905           0 :                 if (upcase(opmode).matches("SHADOW") ) {
     906           0 :                         RecordDesc flagDesc;
     907           0 :                         flagDesc.addField(RF_SHADOW, TpBool);
     908           0 :                         Record flagRec(flagDesc);
     909           0 :                         flagRec.define(RF_SHADOW, true);
     910           0 :                         selrec.mergeField(flagRec, RF_SHADOW, RecordInterface::OverwriteDuplicates);
     911             :                 }
     912             : 
     913           0 :                 else if (upcase(opmode).matches("ELEVATION") ) {
     914           0 :                         RecordDesc flagDesc;
     915           0 :                         flagDesc.addField(RF_ELEVATION, TpBool);
     916           0 :                         Record flagRec(flagDesc);
     917           0 :                         flagRec.define(RF_ELEVATION, true);
     918           0 :                         selrec.mergeField(flagRec, RF_ELEVATION, RecordInterface::OverwriteDuplicates);
     919             :                 }
     920             : 
     921             :                 /* Flag Autocorrelations too? */
     922           0 :                 if (autocorr) {
     923           0 :                         RecordDesc flagDesc;
     924           0 :                         flagDesc.addField(RF_AUTOCORR, TpBool);
     925           0 :                         Record flagRec(flagDesc);
     926           0 :                         flagRec.define(RF_AUTOCORR, autocorr);
     927           0 :                         selrec.mergeField(flagRec, RF_AUTOCORR, RecordInterface::OverwriteDuplicates);
     928             :                 }
     929             : 
     930             :                 /* Unflag! */
     931           0 :                 if (unflag) {
     932           0 :                         RecordDesc flagDesc;
     933           0 :                         flagDesc.addField(RF_UNFLAG, TpBool);
     934           0 :                         Record flagRec(flagDesc);
     935           0 :                         flagRec.define(RF_UNFLAG, unflag);
     936           0 :                         selrec.mergeField(flagRec, RF_UNFLAG, RecordInterface::OverwriteDuplicates);
     937             :                 }
     938             : 
     939             :                 /* Reset flags before applying new ones */
     940             :                 // ( I think... )
     941             :                 /*
     942             :           {
     943             :           RecordDesc flagDesc;       
     944             :           flagDesc.addField(RF_RESET, TpBool);
     945             :           Record flagRec(flagDesc);  
     946             :           flagRec.define(RF_RESET, true);
     947             :           selrec.mergeField(flagRec, RF_RESET, RecordInterface::OverwriteDuplicates);
     948             :           }
     949             :                  */
     950             : 
     951             :                 /* Clip/FlagRange */
     952             :                 /* Jira Casa 212 : Check if "clipexpr" has multiple
     953             :           comma-separated expressions
     954             :           and loop here, creating multiple clipRecs. 
     955             :           The RFASelector will handle it. */
     956           0 :                 if (clipexpr.length() && cliprange.nelements() == 2 &&
     957           0 :                                 (cliprange[0] < cliprange[1] ||
     958           0 :                                                 (cliprange[0] <= cliprange[1] && !outside) // i.e. exact matching
     959             :                                 )
     960             :                 )
     961             :                 {
     962           0 :                         RecordDesc flagDesc;
     963           0 :                         if ( outside )
     964           0 :                                 flagDesc.addField(RF_CLIP, TpRecord);
     965             :                         else
     966           0 :                                 flagDesc.addField(RF_FLAGRANGE, TpRecord);
     967             : 
     968           0 :                         Record flagRec(flagDesc);
     969             : 
     970           0 :                         RecordDesc clipDesc;
     971           0 :                         clipDesc.addField(RF_EXPR, TpString);
     972           0 :                         clipDesc.addField(RF_MIN, TpDouble);
     973           0 :                         clipDesc.addField(RF_MAX, TpDouble);
     974           0 :                         clipDesc.addField(RF_CHANAVG, TpBool);
     975           0 :                         Record clipRec(clipDesc);
     976           0 :                         clipRec.define(RF_EXPR, clipexpr);
     977           0 :                         clipRec.define(RF_MIN, cliprange[0]);
     978           0 :                         clipRec.define(RF_MAX, cliprange[1]);
     979           0 :                         clipRec.define(RF_CHANAVG, channel_average);
     980             : 
     981           0 :                         if ( outside )
     982             :                         {
     983           0 :                                 flagRec.defineRecord(RF_CLIP, clipRec);
     984           0 :                                 selrec.mergeField(flagRec, RF_CLIP, RecordInterface::OverwriteDuplicates);
     985             :                         }
     986             :                         else
     987             :                         {
     988           0 :                                 flagRec.defineRecord(RF_FLAGRANGE, clipRec);
     989           0 :                                 selrec.mergeField(flagRec, RF_FLAGRANGE, RecordInterface::OverwriteDuplicates);
     990             :                         }
     991             : 
     992             :                         /* clip column */
     993           0 :                         if (!clipcolumn.length()) clipcolumn=String("DATA");
     994           0 :                         RecordDesc flagDesc2;
     995           0 :                         flagDesc2.addField(RF_COLUMN, TpString);
     996           0 :                         Record flagRec2(flagDesc2);
     997           0 :                         flagRec2.define(RF_COLUMN, clipcolumn);
     998           0 :                         selrec.mergeField(flagRec2, RF_COLUMN, RecordInterface::OverwriteDuplicates);
     999             : 
    1000             :                 }
    1001             : 
    1002             :                 /* Quack! */
    1003           0 :                 if (quackinterval > 0.0) {
    1004             :                         //Reset the Visiter to have SCAN before time
    1005           0 :                         scan_looping = true;
    1006           0 :                         Block<int> sort2(5);
    1007           0 :                         sort2[0] = MS::ARRAY_ID;
    1008           0 :                         sort2[1] = MS::FIELD_ID;
    1009           0 :                         sort2[2] = MS::DATA_DESC_ID;
    1010           0 :                         sort2[3] = MS::SCAN_NUMBER;
    1011           0 :                         sort2[4] = MS::TIME;
    1012           0 :                         Double timeInterval = 7.0e9; //a few thousand years
    1013             : 
    1014           0 :                         vs_p->resetVisIter(sort2, timeInterval);
    1015           0 :                         vs_p->iter().slurp();
    1016             :                         //lets make sure the data channel selection is done
    1017           0 :                         selectDataChannel();
    1018             : 
    1019           0 :                         RecordDesc flagDesc;
    1020           0 :                         flagDesc.addField(RF_QUACK, TpArrayDouble);
    1021           0 :                         flagDesc.addField(RF_QUACKMODE, TpString);
    1022           0 :                         flagDesc.addField(RF_QUACKINC, TpBool);
    1023             : 
    1024           0 :                         Vector<Double> quackparams(2);
    1025           0 :                         quackparams[0] = quackinterval;
    1026           0 :                         quackparams[1] = 0.0;
    1027             : 
    1028           0 :                         Record flagRec(flagDesc);
    1029           0 :                         flagRec.define(RF_QUACK, quackparams);
    1030           0 :                         flagRec.define(RF_QUACKMODE, quackmode);
    1031           0 :                         flagRec.define(RF_QUACKINC, quackincrement);
    1032           0 :                         selrec.mergeField(flagRec, RF_QUACK    , RecordInterface::OverwriteDuplicates);
    1033           0 :                         selrec.mergeField(flagRec, RF_QUACKMODE, RecordInterface::OverwriteDuplicates);
    1034           0 :                         selrec.mergeField(flagRec, RF_QUACKINC , RecordInterface::OverwriteDuplicates);
    1035             : 
    1036           0 :                         quack_agent_exists = true;
    1037             :                 }
    1038             :                 /* end if opmode = ... */
    1039             : 
    1040             :                 /* Add this agent to the list */
    1041           0 :                 addAgent(selrec);
    1042             :         }
    1043             : 
    1044           0 :         return true;
    1045             : }
    1046             : 
    1047           0 : Bool Flagger::setautoflagparams(String algorithm,Record &parameters)
    1048             : {
    1049           0 :         LogIO os(LogOrigin("Flagger", "setautoflagparams()", WHERE));
    1050           0 :         if (ms.isNull()) {
    1051             :                 os << LogIO::SEVERE << "NO MeasurementSet attached"
    1052           0 :                                 << LogIO::POST;
    1053           0 :                 return false;
    1054             :         }
    1055           0 :         if (!selectdata_p) {
    1056             :                 os << LogIO::SEVERE << "Please run setdata with/without arguments before setautoflagparams"
    1057           0 :                                 << LogIO::POST;
    1058           0 :                 return false;
    1059             :         }
    1060             : 
    1061             :         /* Create an agent record */
    1062           0 :         Record selrec;
    1063           0 :         selrec = getautoflagparams(algorithm);
    1064           0 :         selrec.merge(parameters,Record::OverwriteDuplicates);
    1065             : 
    1066             :         /* special case for "sprej". need to parse a param.*/
    1067           0 :         if (algorithm.matches("sprej") && selrec.isDefined("fitspwchan")) {
    1068             :                 /* Get the "fitspwchan" string" */
    1069             :                 /* Pass this through the msselection parser and getChanList */
    1070             :                 /* Construct a list of regions records from this list */
    1071           0 :                 String fitspwchan;
    1072           0 :                 selrec.get(RecordFieldId("fitspwchan"),fitspwchan);
    1073             : 
    1074           0 :                 if (fitspwchan.length())
    1075             :                 {
    1076             :                         /* Parse it */
    1077           0 :                         const String dummy("");
    1078           0 :                         MSSelection tmpmss(*mssel_p,MSSelection::PARSE_NOW,
    1079             :                                         dummy,dummy, dummy, fitspwchan, dummy,
    1080           0 :                                         dummy, dummy, dummy, dummy);
    1081           0 :                         Matrix<Int> spwchanlist = tmpmss.getChanList();
    1082           0 :                         Vector<Int> spwlist = tmpmss.getSpwList();
    1083             : 
    1084             :                         /* Create region record template */
    1085           0 :                         RecordDesc regdesc;
    1086           0 :                         for(uInt i=0;i<spwlist.nelements();i++)
    1087           0 :                                 regdesc.addField(String(i),TpRecord);
    1088           0 :                         Record regions(regdesc);
    1089             : 
    1090             :                         /* reform chan ranges */
    1091           0 :                         Int ccount=0;
    1092           0 :                         IPosition cshp = spwchanlist.shape();
    1093           0 :                         for(uInt i=0;i<spwlist.nelements();i++)
    1094             :                         {
    1095           0 :                                 ccount=0;
    1096           0 :                                 for( Int j=0;j<cshp[0];j++ )
    1097           0 :                                         if ( spwlist[i] == spwchanlist(j,0) ) ccount++;
    1098           0 :                                 Matrix<Int> chanlist(2,ccount); chanlist.set(0);
    1099             : 
    1100           0 :                                 ccount=0;
    1101           0 :                                 for( Int j=0;j<cshp[0];j++ )
    1102             :                                 {
    1103           0 :                                         if ( spwlist[i] == spwchanlist(j,0) )
    1104             :                                         {
    1105           0 :                                                 chanlist(0,ccount) = spwchanlist(j,1);
    1106           0 :                                                 chanlist(1,ccount) = spwchanlist(j,2);
    1107           0 :                                                 if ( spwchanlist(j,3) > 1 )
    1108           0 :                                                         os << LogIO::WARN << ".... ignoring chan 'step' for 'sprej' fitting" << LogIO::POST;
    1109           0 :                                                 ccount++;
    1110             :                                         }
    1111             :                                 }
    1112             : 
    1113           0 :                                 RecordDesc spwDesc;
    1114           0 :                                 spwDesc.addField(RF_SPWID, TpInt);
    1115           0 :                                 spwDesc.addField(RF_CHANS, TpArrayInt);
    1116           0 :                                 Record spwRec(spwDesc);
    1117           0 :                                 spwRec.define(RF_SPWID, spwlist[i]);
    1118           0 :                                 spwRec.define(RF_CHANS, chanlist);
    1119             : 
    1120             :                                 /* create a single region record */
    1121             :                                 /* add this to the list of region records */
    1122           0 :                                 regions.defineRecord(String(i),spwRec);
    1123             :                         }
    1124             : 
    1125             :                         /* Attach the list of region records */
    1126           0 :                         selrec.defineRecord(RF_REGION, regions);
    1127             :                 }
    1128             :         }
    1129             : 
    1130             :         /* Add this agent to the list */
    1131           0 :         addAgent(selrec);
    1132             : 
    1133           0 :         return true;
    1134             : }
    1135             : 
    1136             : 
    1137           0 : Record Flagger::getautoflagparams(String algorithm)
    1138             : {
    1139           0 :         LogIO os(LogOrigin("Flagger", "getautoflagparams()", WHERE));
    1140             : 
    1141             :         // Use "RFATimeMedian::getDefaults()" !!!!!!!
    1142             : 
    1143           0 :         Record defrecord;
    1144           0 :         if ( agent_defaults.isDefined(algorithm) )
    1145             :         {
    1146           0 :                 RecordFieldId rid(algorithm);
    1147           0 :                 defrecord = agent_defaults.asRecord(rid);
    1148           0 :                 defrecord.define("id",algorithm);
    1149             : 
    1150           0 :                 if (defrecord.isDefined("expr")) defrecord.define("expr","ABS I");
    1151             :         }
    1152           0 :         return defrecord;
    1153             : 
    1154             : }
    1155             : 
    1156             : /* Clean up all selections */
    1157             : // TODO Later add in the ability to clear specified
    1158             : // agent types.
    1159             : //
    1160             : // subRecord = agents_p->getField(RecordFieldId(x));
    1161             : // if ( subRecord.isDefined('id') && 'id' is "select" )
    1162             : //         agents_p->removeField(RecordFieldId(x));
    1163             : //
    1164           0 : Bool Flagger::clearflagselections(Int recordindex)
    1165             : {
    1166           0 :         LogIO os(LogOrigin("Flagger", "clearflagselections()", WHERE));
    1167             : 
    1168           0 :         if ( agents_p && agents_p->nfields() )
    1169             :         {
    1170           0 :                 if ( recordindex >= 0 )
    1171             :                 {
    1172             :                         if (dbg) cout << "Deleting only agent : " << recordindex << endl;
    1173           0 :                         agents_p->removeField(RecordFieldId(recordindex));
    1174             :                 }
    1175             :                 else
    1176             :                 {
    1177             :                         if (dbg) cout << "Deleting all agents" << endl;
    1178           0 :                         delete agents_p;
    1179           0 :                         agents_p =0;
    1180           0 :                         agentCount_p = 0;
    1181             :                 }
    1182             :         }
    1183             : 
    1184             :         //      printflagselections();
    1185             : 
    1186           0 :         return true;
    1187             : }
    1188             : 
    1189           0 : Bool Flagger::printflagselections()
    1190             : {
    1191           0 :         LogIO os(LogOrigin("Flagger", "printflagselections()", WHERE));
    1192           0 :         if ( agents_p )
    1193             :         {
    1194           0 :                 os << "Current list of agents : " << agents_p << LogIO::POST;
    1195           0 :                 ostringstream out;
    1196           0 :                 agents_p->print(out);
    1197           0 :                 os << out.str() << LogIO::POST;
    1198             :         }
    1199           0 :         else os << " No current agents " << LogIO::POST;
    1200             : 
    1201           0 :         return true;
    1202             : }
    1203             : 
    1204           0 : Bool Flagger::addAgent(RecordInterface &newAgent)
    1205             : {
    1206           0 :         if (!agents_p)
    1207             :         {
    1208           0 :                 agentCount_p = 0;
    1209           0 :                 agents_p = new Record;
    1210             :                 if (dbg) cout << "creating new agent" << endl;
    1211             :         }
    1212             : 
    1213           0 :         ostringstream fieldName;
    1214           0 :         fieldName << agentCount_p++;
    1215           0 :         agents_p->defineRecord(fieldName.str(), newAgent);
    1216             : 
    1217             :         //      printflagselections();
    1218             : 
    1219           0 :         return true;
    1220             : }
    1221             : 
    1222             : 
    1223             : // computes IFR index, given two antennas
    1224           0 : uInt Flagger::ifrNumber ( Int ant1,Int ant2 ) const
    1225             : {
    1226           0 :         if ( ant1<ant2 )
    1227           0 :                 return ifrNumber(ant2,ant1);
    1228           0 :         return ant1*(ant1+1)/2 + ant2;
    1229             : }
    1230             : //TODO
    1231             : // Here, fill in correct indices for the baseline ordering in the MS
    1232             : // All agents will see this and will be fine.
    1233             : 
    1234             : // computes vector of IFR indeces, given two antennas
    1235           0 : Vector<Int> Flagger::ifrNumbers ( Vector<Int> ant1,Vector<Int> ant2 ) const
    1236             : {
    1237           0 :         unsigned n = ant1.nelements();
    1238           0 :         Vector<Int> r(n);
    1239             : 
    1240           0 :         for (unsigned i = 0; i < n; i++) {
    1241           0 :                 Int a1 = ant1(i);
    1242           0 :                 Int a2 = ant2(i);
    1243           0 :                 if (a1 > a2) {
    1244           0 :                         r(i) = a1*(a1+1)/2 + a2;
    1245             :                 }
    1246             :                 else {
    1247           0 :                         r(i) = a2*(a2+1)/2 + a1;
    1248             :                 }
    1249             :         }
    1250           0 :         return r;
    1251             : }
    1252             : 
    1253           0 : void Flagger::ifrToAnt ( uInt &ant1,uInt &ant2,uInt ifr ) const
    1254             : {
    1255           0 :         ant1 = ifr2ant1(ifr);
    1256           0 :         ant2 = ifr2ant2(ifr);
    1257           0 : }
    1258             : 
    1259             : // -----------------------------------------------------------------------
    1260             : // Flagger::setupAgentDefaults
    1261             : // Sets up record of available agents and their default parameters
    1262             : // -----------------------------------------------------------------------
    1263           0 : const RecordInterface & Flagger::setupAgentDefaults ()
    1264             : {
    1265           0 :         agent_defaults = Record();
    1266           0 :         agent_defaults.defineRecord("timemed", RFATimeMedian::getDefaults());
    1267           0 :         agent_defaults.defineRecord("newtimemed", RFANewMedianClip::getDefaults());
    1268           0 :         agent_defaults.defineRecord("freqmed", RFAFreqMedian::getDefaults());
    1269           0 :         agent_defaults.defineRecord("sprej", RFASpectralRej::getDefaults());
    1270           0 :         agent_defaults.defineRecord("select", RFASelector::getDefaults());
    1271           0 :         agent_defaults.defineRecord("flagexaminer", RFAFlagExaminer::getDefaults());
    1272           0 :         agent_defaults.defineRecord("uvbin", RFAUVBinner::getDefaults());
    1273           0 :         agent_defaults.defineRecord("tfcrop", RFATimeFreqCrop::getDefaults());
    1274           0 :         return agent_defaults;
    1275             : }
    1276             : 
    1277             : // -----------------------------------------------------------------------
    1278             : // Flagger::createAgent
    1279             : // Creates flagging agent based on name
    1280             : // -----------------------------------------------------------------------
    1281           0 : std::shared_ptr<RFABase> Flagger::createAgent (const String &id,
    1282             :                 RFChunkStats &chunk,
    1283             :                 const RecordInterface &parms,
    1284             :                 bool &only_selector)
    1285             : {
    1286           0 :         if (id != "select" && id != "flagexaminer") {
    1287           0 :                 only_selector = false;
    1288             :         }
    1289             :         // cerr << "Agent id: " << id << endl;
    1290           0 :         if ( id == "timemed" )
    1291           0 :                 return std::shared_ptr<RFABase>(new RFATimeMedian(chunk, parms));
    1292           0 :         else if ( id == "newtimemed" )
    1293           0 :                 return std::shared_ptr<RFABase>(new RFANewMedianClip(chunk, parms));
    1294           0 :         else if ( id == "freqmed" )
    1295           0 :                 return std::shared_ptr<RFABase>(new RFAFreqMedian(chunk, parms));
    1296           0 :         else if ( id == "sprej" )
    1297           0 :                 return std::shared_ptr<RFABase>(new RFASpectralRej(chunk, parms));
    1298           0 :         else if ( id == "select" )
    1299           0 :                 return std::shared_ptr<RFABase>(new RFASelector(chunk, parms));
    1300           0 :         else if ( id == "flagexaminer" )
    1301           0 :                 return std::shared_ptr<RFABase>(new RFAFlagExaminer(chunk, parms));
    1302           0 :         else if ( id == "uvbin" )
    1303           0 :                 return std::shared_ptr<RFABase>(new RFAUVBinner(chunk, parms));
    1304           0 :         else if ( id == "tfcrop" )
    1305           0 :                 return std::shared_ptr<RFABase>(new RFATimeFreqCrop(chunk, parms));
    1306             :         else
    1307           0 :                 return std::shared_ptr<RFABase>();
    1308             : }
    1309             : 
    1310             : 
    1311           0 : void Flagger::summary( const RecordInterface &agents )
    1312             : {
    1313             :         //os << "Autoflag summary will report results here" << LogIO::POST;
    1314           0 :         for(uInt i=0;i<agents.nfields(); i++){
    1315             : 
    1316           0 :                 if (agents.dataType(i) != TpRecord){
    1317           0 :                         os << "Unrecognized field: " << agents.name(i) << LogIO::EXCEPTION;
    1318             :                 }
    1319           0 :                 String agent_id(downcase(agents.name(i)));
    1320             :                 // cerr << i << " " << agent_id << endl;
    1321           0 :                 printAgentRecord(agent_id, i, agents.asRecord(i));
    1322             :         }
    1323           0 : }
    1324             : 
    1325             : /*
    1326             :       Well, for boolean values this function gives you 1 + 1 = 2,
    1327             :       where the AIPS++ built-in, never-should-have-been-written, sum()
    1328             :       surprisingly gives you 1 + 1 = 1.
    1329             :  */
    1330           0 : int Flagger::my_aipspp_sum(const Array<Bool> &a)
    1331             : {
    1332           0 :         return a.contiguousStorage() ?
    1333           0 :                         std::accumulate(a.cbegin(), a.cend(), 0) :
    1334           0 :                         std::accumulate(a.begin(),  a.end(),  0);
    1335             : }
    1336             : 
    1337           0 : void Flagger::printAgentRecord(String &agent_id, uInt agentCount,
    1338             :                 const RecordInterface &agent_rec){
    1339             :         // but if an id field is set in the sub-record, use that instead
    1340           0 :         if ( agent_rec.isDefined("id") && agent_rec.dataType("id") == TpString ){
    1341           0 :                 agent_id = agent_rec.asString("id");
    1342             :         }
    1343           0 :         for(uInt i=0; i<agent_rec.nfields(); i++){
    1344           0 :                 os << agent_id << "[" << agentCount+1 << "] : ";
    1345           0 :                 String myName(agent_rec.name(i));
    1346           0 :                 os << myName << ": ";
    1347           0 :                 switch(agent_rec.type(i)){
    1348           0 :                 case TpRecord :
    1349           0 :                         printAgentRecord(myName, i, agent_rec.asRecord(i));
    1350           0 :                         break;
    1351           0 :                 case TpArrayBool :
    1352           0 :                         os << agent_rec.asArrayBool(i);
    1353           0 :                         break;
    1354           0 :                 case TpArrayUChar :
    1355           0 :                         os << agent_rec.asArrayuChar(i);
    1356           0 :                         break;
    1357           0 :                 case TpArrayShort:
    1358           0 :                         os << agent_rec.asArrayShort(i);
    1359           0 :                         break;
    1360           0 :                 case TpArrayInt:
    1361           0 :                         os << agent_rec.asArrayInt(i);
    1362           0 :                         break;
    1363           0 :                 case TpArrayUInt:
    1364           0 :                         os << agent_rec.asArrayuInt(i);
    1365           0 :                         break;
    1366           0 :                 case TpArrayFloat:
    1367           0 :                         os << agent_rec.asArrayFloat(i);
    1368           0 :                         break;
    1369           0 :                 case TpArrayDouble:
    1370           0 :                         os << agent_rec.asArrayDouble(i);
    1371           0 :                         break;
    1372           0 :                 case TpArrayComplex:
    1373           0 :                         os << agent_rec.asArrayComplex(i);
    1374           0 :                         break;
    1375           0 :                 case TpArrayDComplex:
    1376           0 :                         os << agent_rec.asArrayDComplex(i);
    1377           0 :                         break;
    1378           0 :                 case TpArrayString:
    1379           0 :                         os << agent_rec.asArrayString(i);
    1380           0 :                         break;
    1381           0 :                 case TpBool:
    1382           0 :                         os << agent_rec.asBool(i);
    1383           0 :                         break;
    1384           0 :                 case TpUChar:
    1385           0 :                         os << agent_rec.asuChar(i);
    1386           0 :                         break;
    1387           0 :                 case TpShort:
    1388           0 :                         os << agent_rec.asShort(i);
    1389           0 :                         break;
    1390           0 :                 case TpInt:
    1391           0 :                         os << agent_rec.asInt(i);
    1392           0 :                         break;
    1393           0 :                 case TpUInt:
    1394           0 :                         os << agent_rec.asuInt(i);
    1395           0 :                         break;
    1396           0 :                 case TpFloat:
    1397           0 :                         os << agent_rec.asFloat(i);
    1398           0 :                         break;
    1399           0 :                 case TpDouble:
    1400           0 :                         os << agent_rec.asDouble(i);
    1401           0 :                         break;
    1402           0 :                 case TpComplex:
    1403           0 :                         os << agent_rec.asComplex(i);
    1404           0 :                         break;
    1405           0 :                 case TpDComplex:
    1406           0 :                         os << agent_rec.asDComplex(i);
    1407           0 :                         break;
    1408           0 :                 case TpString:
    1409           0 :                         os << agent_rec.asString(i);
    1410           0 :                         break;
    1411           0 :                 default :
    1412           0 :                         break;
    1413             :                 }
    1414           0 :                 os << endl << LogIO::POST;
    1415             :         }
    1416             :         //
    1417           0 : }
    1418             : 
    1419             : // -----------------------------------------------------------------------
    1420             : // Flagger::run
    1421             : // Performs the actual flagging
    1422             : // -----------------------------------------------------------------------
    1423           0 : Record Flagger::run (Bool trial, Bool reset)
    1424             : {
    1425           0 :         if (!agents_p)
    1426             :         {
    1427           0 :                 agentCount_p = 0;
    1428           0 :                 agents_p = new Record;
    1429             :                 if (dbg) cout << "creating new EMPTY agent and returning" << endl;
    1430           0 :                 return Record();
    1431             :         }
    1432           0 :         Record agents = *agents_p;
    1433             : 
    1434             :         if (dbg) cout << agents << endl;
    1435             : 
    1436           0 :         if (!opts_p)
    1437             :         {
    1438           0 :                 opts_p = new Record();
    1439             :         }
    1440           0 :         *opts_p = defaultOptions();
    1441           0 :         opts_p->define(RF_RESET,reset);
    1442           0 :         opts_p->define(RF_TRIAL,trial);
    1443           0 :         Record opt = *opts_p;
    1444             : 
    1445           0 :         if (!setdata_p) {
    1446             :                 os << LogIO::SEVERE << "Please run setdata with/without arguments before any setmethod"
    1447           0 :                                 << LogIO::POST;
    1448           0 :                 return Record();
    1449             :         }
    1450             : 
    1451             : 
    1452           0 :         Record result;
    1453             : 
    1454             :         //printflagselections();
    1455             : 
    1456           0 :         if ( !nant )
    1457           0 :                 os<<"No Measurement Set has been attached\n"<<LogIO::EXCEPTION;
    1458             : 
    1459           0 :         RFABase::setIndexingBase(0);
    1460             :         // set debug level
    1461           0 :         Int debug_level = 0;
    1462           0 :         if ( opt.isDefined("debug") )
    1463           0 :                 debug_level = opt.asInt("debug");
    1464             : 
    1465             :         // reset existing flags?
    1466           0 :         Bool reset_flags = isFieldSet(opt, RF_RESET);
    1467             : 
    1468             :         /* Don't use the progmeter if less than this
    1469             :        number of timestamps (for performance reasons;
    1470             :        just creating a ProgressMeter is relatively
    1471             :        expensive). */
    1472           0 :         const unsigned progmeter_limit = 1000;
    1473             : 
    1474             :         try { // all exceptions to be caught below
    1475             : 
    1476           0 :                 bool didSomething=0;
    1477             :                 // create iterator, visbuffer & chunk manager
    1478             :                 // Block<Int> sortCol(1);
    1479             :                 // sortCol[0] = MeasurementSet::SCAN_NUMBER;
    1480             :                 //sortCol[0] = MeasurementSet::TIME;
    1481             :                 // Setdata already made a data selection
    1482             : 
    1483           0 :                 VisibilityIterator &vi(vs_p->iter());
    1484           0 :                 vi.slurp();
    1485           0 :                 VisBuffer vb(vi);
    1486             : 
    1487             :                 RFChunkStats chunk(vi, vb,
    1488           0 :                                 *this);
    1489             : 
    1490             :                 // setup global options for flagging agents
    1491           0 :                 Record globopt(Record::Variable);
    1492           0 :                 if ( opt.isDefined(RF_GLOBAL) )
    1493           0 :                         globopt = opt.asRecord(RF_GLOBAL);
    1494             : 
    1495             :                 // generate new array of agents by iterating through agents record
    1496           0 :                 Record agcounts; // record of agent instance counts
    1497             : 
    1498           0 :                 acc.resize(agents.nfields());
    1499             : 
    1500           0 :                 for (uInt i=0; i<agents.nfields(); i++) {
    1501           0 :                         acc[i] = std::shared_ptr<RFABase>();
    1502             :                 }
    1503             : 
    1504           0 :                 uInt nacc = 0;
    1505           0 :                 bool only_selector = true;  // only RFASelector agents?
    1506           0 :                 for (uInt i=0; i<agents.nfields(); i++) {
    1507           0 :                         if (  agents.dataType(i) != TpRecord )
    1508           0 :                                 os << "Unrecognized field '" << agents.name(i) << "' in agents\n" << LogIO::EXCEPTION;
    1509             : 
    1510           0 :                         const RecordInterface & agent_rec( agents.asRecord(i) );
    1511             : 
    1512             :                         // normally, the field name itself is the agent ID
    1513             : 
    1514           0 :                         String agent_id( downcase(agents.name(i)) );
    1515             : 
    1516             :                         // but if an id field is set in the sub-record, use that instead
    1517           0 :                         if ( agent_rec.isDefined("id") && agent_rec.dataType("id") == TpString )
    1518             :                         {
    1519           0 :                                 agent_id = agent_rec.asString("id");
    1520             :                         }
    1521             :                         // check that this is agent really exists
    1522           0 :                         if ( !agent_defaults.isDefined(agent_id) )
    1523             :                         {
    1524             :                                 //cerr << agent_defaults;
    1525             :                                 os << "Unknown flagging method '" <<
    1526           0 :                                                 agents.name(i) << "'\n" << LogIO::EXCEPTION;
    1527             :                         }
    1528             : 
    1529             :                         // create parameter record by taking agent defaults, and merging in global
    1530             :                         // and specified options
    1531           0 :                         const RecordInterface & defparms(agent_defaults.asRecord(agent_id));
    1532           0 :                         Record parms(defparms);
    1533           0 :                         parms.merge(globopt,Record::OverwriteDuplicates);
    1534           0 :                         parms.merge(agent_rec,Record::OverwriteDuplicates);
    1535             : 
    1536             :                         // add the global reset argumnent
    1537           0 :                         parms.define(RF_RESET,reset_flags);
    1538             : 
    1539             :                         // see if this is a different instance of an already activated agent
    1540           0 :                         if (agcounts.isDefined(agent_id)) {
    1541             :                                 // increment the instance counter
    1542           0 :                                 Int count = agcounts.asInt(agent_id)+1;
    1543           0 :                                 agcounts.define(agent_id,count);
    1544             : 
    1545             :                                 // modify the agent name to include an instance count
    1546             :                                 char s[1024];
    1547           0 :                                 sprintf(s,"%s#%d",defparms.asString(RF_NAME).chars(),count);
    1548           0 :                                 parms.define(RF_NAME,s);
    1549             :                         }
    1550             :                         else
    1551           0 :                                 agcounts.define(agent_id,1);
    1552             :                         // create agent based on name
    1553             :                         std::shared_ptr<RFABase> agent =
    1554             :                                         createAgent(agent_id,
    1555             :                                                         chunk,
    1556             :                                                         parms,
    1557           0 :                                                         only_selector);
    1558           0 :                         if ( agent.get() == NULL )
    1559           0 :                                 os<<"Unrecognized method name '"<<agents.name(i)<<"'\n"<<LogIO::EXCEPTION;
    1560           0 :                         agent->init();
    1561           0 :                         agent->setNAgent(agents.nfields());
    1562           0 :                         String inp,st;
    1563             :                         //    agent->logSink()<<agent->getDesc()<<endl<<LogIO::POST;
    1564           0 :                         acc[nacc++] = agent;
    1565             :                 }
    1566             : 
    1567           0 :                 for (unsigned i = 0; i < nacc; i++) {
    1568           0 :                         acc[i]->setOnlySelector(only_selector);
    1569             :                 }
    1570           0 :                 acc.resize(nacc);
    1571             : 
    1572             :                 // begin iterating over chunks
    1573           0 :                 uInt nchunk=0;
    1574             : 
    1575           0 :                 bool new_field_spw = true;   /* Is the current chunk the first chunk for this (field,spw)? */
    1576             : 
    1577           0 :                 Int64 inRowFlags=0, outRowFlags=0, totalRows=0, inDataFlags=0, outDataFlags=0, totalData=0;
    1578             : 
    1579           0 :                 for (vi.originChunks();
    1580           0 :                                 vi.moreChunks();
    1581             :                 ) { //vi.nextChunk(), nchunk++) {
    1582             :                         //Start of loop over chunks
    1583           0 :                         didSomething = false;
    1584           0 :                         for (uInt i = 0; i < acc.size(); i++) {
    1585           0 :                                 acc[i]->initialize();
    1586             :                         }
    1587             : 
    1588           0 :                         chunk.newChunk(quack_agent_exists);
    1589             : 
    1590             :                         // limit frequency of progmeter updates
    1591           0 :                         Int pm_update_freq = chunk.num(TIME)/200;
    1592             : 
    1593             :                         // How much memory do we have?
    1594           0 :                         Int availmem = opt.isDefined("maxmem") ?
    1595           0 :                                         opt.asInt("maxmem") : HostInfo::memoryTotal()/1024;
    1596           0 :                         if ( debug_level>0 )
    1597           0 :                                 dprintf(os,"%d MB memory available\n",availmem);
    1598             : 
    1599             :                         // call newChunk() for all accumulators; determine which ones are active
    1600           0 :                         Vector<Int> iter_mode(acc.size(),RFA::DATA);
    1601           0 :                         Vector<Bool> active(acc.size());
    1602             : 
    1603           0 :                         for (uInt i = 0; i < acc.size(); i++)
    1604             :                         {
    1605             :                                 Int maxmem;
    1606           0 :                                 maxmem = availmem;
    1607           0 :                                 if ( ! (active(i) = acc[i]->newChunk(maxmem))  ) // refused this chunk?
    1608             :                                 {
    1609           0 :                                         iter_mode(i) = RFA::STOP;  // skip over it
    1610             :                                 }
    1611             :                                 else
    1612             :                                 { // active, so reserve its memory
    1613           0 :                                         if ( debug_level>0 )
    1614           0 :                                                 dprintf(os,"%s reserving %d MB of memory, %d left in pool\n",
    1615           0 :                                                                 acc[i]->name().chars(),availmem-maxmem,maxmem);
    1616           0 :                                         availmem = maxmem>0 ? maxmem : 0;
    1617             :                                 }
    1618             :                         }
    1619             :                         if (dbg) cout << "Active for this chunk: " << my_aipspp_sum(active) << endl;
    1620             : 
    1621             :                         // initially active agents
    1622           0 :                         Vector<Bool> active_init = active;
    1623             :                         // start executing passes
    1624             :                         char subtitle[1024];
    1625           0 :                         sprintf(subtitle,"Flagging %s chunk %d: ",ms.tableName().chars(),nchunk+1);
    1626           0 :                         String title(subtitle);
    1627             :                         //cout << "--------title=" << title << endl;
    1628             : 
    1629           0 :                         if ( !sum(active) )
    1630             :                         {
    1631             :                                 //os<<LogIO::WARN<<"Unable to process this chunk with any active method.\n"<<LogIO::POST;
    1632             : 
    1633           0 :                                 goto end_of_loop;
    1634             :                                 /* Oh no, an evil goto statement...
    1635             :                    This used to be a 
    1636             :                       continue;
    1637             :                    which (in this context) is just as evil. But goto is used because some
    1638             :                    looping code (the visIter update) needs to be always executed at the
    1639             :                    end of this loop.
    1640             : 
    1641             :                    The good solution would be to
    1642             :                    -  make the remainder of this loop
    1643             :                       work also in the special case with sum(active) == 0
    1644             :                    -  simplify this overly long loop
    1645             :                                  */
    1646             :                         }
    1647             : 
    1648           0 :                         for( uInt npass=0; anyNE(iter_mode,(Int)RFA::STOP); npass++ ) // repeat passes while someone is active
    1649             :                         {
    1650           0 :                                 uInt itime=0;
    1651           0 :                                 chunk.newPass(npass);
    1652             :                                 // count up who wants a data pass and who wants a dry pass
    1653           0 :                                 Int ndata = sum(iter_mode==(Int)RFA::DATA);
    1654           0 :                                 Int ndry  = sum(iter_mode==(Int)RFA::DRY);
    1655           0 :                                 Int nactive = ndata+ndry;
    1656           0 :                                 if ( !nactive ) // no-one? break out then
    1657           0 :                                         break;
    1658             :                                 //            didSomething++;
    1659             :                                 // Decide when to schedule a full data iteration, and when do dry runs only.
    1660             :                                 // There's probably room for optimizations here, but let's keep it simple
    1661             :                                 // for now: since data iterations are more expensive, hold them off as long
    1662             :                                 // as someone is requesting a dry run.
    1663           0 :                                 Bool data_pass = !ndry;
    1664             :                                 // Doing a full data iteration
    1665           0 :                                 if ( data_pass )
    1666             :                                 {
    1667             : 
    1668           0 :                                         sprintf(subtitle,"pass %d (data)",npass+1);
    1669             : 
    1670           0 :                                         std::unique_ptr<ProgressMeter> progmeter;
    1671           0 :                                         if (chunk.num(TIME) > progmeter_limit) {
    1672           0 :                                                 progmeter = std::unique_ptr<ProgressMeter>(new ProgressMeter(1.0,static_cast<Double>(chunk.num(TIME)+0.001),title+subtitle,"","","",true,pm_update_freq));
    1673             :                                         }
    1674             : 
    1675             :                                         // start pass for all active agents
    1676             :                                         //cout << "-----------subtitle=" << subtitle << endl;
    1677           0 :                                         for( uInt ival = 0; ival<acc.size(); ival++ )
    1678           0 :                                                 if ( active(ival) ) {
    1679           0 :                                                         if ( iter_mode(ival) == RFA::DATA )
    1680           0 :                                                                 acc[ival]->startData(new_field_spw);
    1681           0 :                                                         else if ( iter_mode(ival) == RFA::DRY )
    1682           0 :                                                                 acc[ival]->startDry(new_field_spw);
    1683             :                                                 }
    1684             :                                         // iterate over visbuffers
    1685           0 :                                         for( vi.origin(); vi.more() && nactive; vi++,itime++ ) {
    1686             : 
    1687           0 :                                                 if (progmeter.get() != NULL) {
    1688           0 :                                                         progmeter->update(itime);
    1689             :                                                 }
    1690           0 :                                                 chunk.newTime();
    1691           0 :                                                 Bool anyActive = false;
    1692           0 :                                                 anyActive=false;
    1693           0 :                                                 for( uInt i = 0; i<acc.size(); i++ )
    1694             :                                                 {
    1695             :                                                         //if ((acc[i]->getID() != "FlagExaminer") &&
    1696           0 :                                                         if (active_init(i)) {
    1697           0 :                                                                 anyActive=true;
    1698             :                                                         }
    1699             :                                                 }
    1700             : 
    1701           0 :                                                 for(uInt i=0;i<acc.size();i++) {
    1702           0 :                                                         if (anyActive) acc[i]->initializeIter(itime);
    1703             :                                                 }
    1704             : 
    1705           0 :                                                 inRowFlags += my_aipspp_sum(vb.flagRow());
    1706           0 :                                                 totalRows += vb.flagRow().nelements();
    1707           0 :                                                 totalData += vb.flagCube().shape().product();
    1708             : 
    1709           0 :                                                 inDataFlags += my_aipspp_sum(vb.flagCube());
    1710             : 
    1711             :                                                 // now, call individual VisBuffer iterators
    1712           0 :                                                 for( uInt ival = 0; ival<acc.size(); ival++ )
    1713           0 :                                                         if ( active(ival) ) {
    1714             :                                                                 // call iterTime/iterDry as appropriate
    1715           0 :                                                                 RFA::IterMode res = RFA::STOP;
    1716           0 :                                                                 if ( iter_mode(ival) == RFA::DATA ) {
    1717           0 :                                                                         res = acc[ival]->iterTime(itime);
    1718             :                                                                 }
    1719           0 :                                                                 else if ( iter_mode(ival) == RFA::DRY )
    1720           0 :                                                                         res = acc[ival]->iterDry(itime);
    1721             :                                                                 // change requested? Deactivate agent
    1722           0 :                                                                 if ( ! ( res == RFA::CONT || res == iter_mode(ival) ) )
    1723             :                                                                 {
    1724           0 :                                                                         active(ival) = false;
    1725           0 :                                                                         nactive--;
    1726           0 :                                                                         iter_mode(ival)==RFA::DATA ? ndata-- : ndry--;
    1727           0 :                                                                         iter_mode(ival) = res;
    1728           0 :                                                                         if ( nactive <= 0 )
    1729           0 :                                                                                 break;
    1730             :                                                                 }
    1731             :                                                         }
    1732             : 
    1733             :                                                 // also iterate over rows for data passes
    1734           0 :                                                 for( Int ir=0; ir<vb.nRow() && ndata; ir++ ) {
    1735           0 :                                                         for( uInt ival = 0; ival<acc.size(); ival++ )
    1736           0 :                                                                 if ( iter_mode(ival) == RFA::DATA )
    1737             :                                                                 {
    1738           0 :                                                                         RFA::IterMode res = acc[ival]->iterRow(ir);
    1739           0 :                                                                         if ( ! ( res == RFA::CONT || res == RFA::DATA ) )
    1740             :                                                                         {
    1741           0 :                                                                                 ndata--; nactive--;
    1742           0 :                                                                                 iter_mode(ival) = res;
    1743           0 :                                                                                 active(ival) = false;
    1744           0 :                                                                                 if ( ndata <= 0 )
    1745           0 :                                                                                         break;
    1746             :                                                                         }
    1747             :                                                                 }
    1748             :                                                 }
    1749             : 
    1750           0 :                                                 for( uInt ival = 0; ival<acc.size(); ival++ ) {
    1751           0 :                                                         if ( active(ival) ) {
    1752           0 :                                                                 acc[ival]->endRows(itime);
    1753             :                                                         }
    1754             :                                                 }
    1755             :                                         } /* for vi... */
    1756             : 
    1757             :                                         // end pass for all agents
    1758           0 :                                         for( uInt ival = 0; ival<acc.size(); ival++ )
    1759             :                                         {
    1760           0 :                                                 if ( active(ival) ) {
    1761           0 :                                                         if ( iter_mode(ival) == RFA::DATA )
    1762           0 :                                                                 iter_mode(ival) = acc[ival]->endData();
    1763           0 :                                                         else if ( iter_mode(ival) == RFA::DRY )
    1764           0 :                                                                 iter_mode(ival) = acc[ival]->endDry();
    1765             :                                                 }
    1766             :                                         }
    1767             :                                 }
    1768             :                                 else  // dry pass only
    1769             :                                 {
    1770           0 :                                         sprintf(subtitle,"pass %d (dry)",npass+1);
    1771             :                                         //cout << "-----------subtitle=" << subtitle << endl;
    1772             : 
    1773           0 :                                         std::unique_ptr<ProgressMeter> progmeter;
    1774           0 :                                         if (chunk.num(TIME) > progmeter_limit) {
    1775           0 :                                                 progmeter = std::unique_ptr<ProgressMeter>(new ProgressMeter (1.0,static_cast<Double>(chunk.num(TIME)+0.001),title+subtitle,"","","",true,pm_update_freq));
    1776             :                                         }
    1777             :                                         // start pass for all active agents
    1778           0 :                                         for( uInt ival = 0; ival<acc.size(); ival++ )
    1779           0 :                                                 if ( iter_mode(ival) == RFA::DRY )
    1780           0 :                                                         acc[ival]->startDry(new_field_spw);
    1781           0 :                                         for( uInt itime=0; itime<chunk.num(TIME) && ndry; itime++ )
    1782             :                                         {
    1783           0 :                                                 if (progmeter.get() != NULL) {
    1784           0 :                                                         progmeter->update(itime);
    1785             :                                                 }
    1786             :                                                 // now, call individual VisBuffer iterators
    1787           0 :                                                 for( uInt ival = 0; ival<acc.size(); ival++ )
    1788           0 :                                                         if ( iter_mode(ival) == RFA::DRY )
    1789             :                                                         {
    1790             :                                                                 // call iterTime/iterDry as appropriate
    1791           0 :                                                                 RFA::IterMode res = acc[ival]->iterDry(itime);
    1792             :                                                                 // change requested? Deactivate agent
    1793           0 :                                                                 if ( ! ( res == RFA::CONT || res == RFA::DRY ) )
    1794             :                                                                 {
    1795           0 :                                                                         iter_mode(ival) = res;
    1796           0 :                                                                         active(ival) = false;
    1797           0 :                                                                         if ( --ndry <= 0 )
    1798           0 :                                                                                 break;
    1799             :                                                                 }
    1800             :                                                         }
    1801             :                                         }
    1802             :                                         // end pass for all agents
    1803           0 :                                         for( uInt ival = 0; ival<acc.size(); ival++ )
    1804           0 :                                                 if ( iter_mode(ival) == RFA::DRY )
    1805           0 :                                                         iter_mode(ival) = acc[ival]->endDry();
    1806             :                                 } // end of dry pass
    1807             :                         } // end loop over passes
    1808             : 
    1809             :                         //cout << opt << endl;
    1810             :                         //cout << "any active = " << active_init << endl;
    1811             : 
    1812           0 :                         if ( !isFieldSet(opt, RF_TRIAL) && anyNE(active_init, false) )
    1813             :                         {
    1814           0 :                                 sprintf(subtitle,"pass (flag)");
    1815             :                                 //cout << "-----------subtitle=" << subtitle << endl;
    1816             : 
    1817           0 :                                 std::unique_ptr<ProgressMeter> progmeter;
    1818           0 :                                 if (chunk.num(TIME) > progmeter_limit) {
    1819           0 :                                         progmeter = std::unique_ptr<ProgressMeter>(new ProgressMeter(1.0,static_cast<Double>(chunk.num(TIME)+0.001),title+"storing flags","","","",true,pm_update_freq));
    1820             :                                 }
    1821           0 :                                 for (uInt i = 0; i<acc.size(); i++)
    1822           0 :                                         if (active_init(i))
    1823           0 :                                                 acc[i]->startFlag(new_field_spw);
    1824           0 :                                 uInt itime=0;
    1825           0 :                                 for( vi.origin(); vi.more(); vi++,itime++ ) {
    1826           0 :                                         if (progmeter.get() != NULL) {
    1827           0 :                                                 progmeter->update(itime);
    1828             :                                         }
    1829             : 
    1830           0 :                                         chunk.newTime();
    1831             :                                         //                inRowFlags += sum(chunk.nrfIfr());
    1832             : 
    1833           0 :                                         Bool anyActive = false;
    1834           0 :                                         anyActive=false;
    1835           0 :                                         for( uInt i = 0; i<acc.size(); i++ ) {
    1836             :                                                 //                    cout << i << " " << acc[i]->getID() << " " << active_init(i) << endl;
    1837           0 :                                                 if ((acc[i]->getID() != "FlagExaminer") &&
    1838           0 :                                                                 active_init(i))
    1839           0 :                                                         anyActive=true;
    1840             :                                         }
    1841             : 
    1842             :                                         //cout << "anyActive" << anyActive << endl;
    1843             : 
    1844           0 :                                         didSomething = (anyActive==true);
    1845           0 :                                         for( uInt i = 0; i<acc.size(); i++ ) {
    1846           0 :                                                 if ( active_init(i) ) {
    1847             :                                                         //if (acc[i]->getID() != "FlagExaminer" )
    1848           0 :                                                         acc[i]->iterFlag(itime);
    1849             :                                                 }
    1850           0 :                                                 if (anyActive) acc[i]->finalizeIter(itime);
    1851             :                                         }
    1852             : 
    1853             :                                         //                outRowFlags += sum(chunk.nrfIfr());
    1854             : 
    1855           0 :                                         outRowFlags += my_aipspp_sum(vb.flagRow());
    1856           0 :                                         outDataFlags += my_aipspp_sum(vb.flagCube());
    1857             : 
    1858             :                                 }  // for (vi ... ) loop over time
    1859           0 :                                 if (didSomething) {
    1860           0 :                                         for (uInt i = 0; i < acc.size(); i++) {
    1861           0 :                                                 if (acc[i].get()) acc[i]->finalize();
    1862             :                                         }
    1863             :                                 }
    1864           0 :                                 for (uInt i = 0; i < acc.size(); i++) {
    1865             : 
    1866           0 :                                         if ( active_init(i) ) {
    1867             : 
    1868           0 :                                                 acc[i]->endFlag();
    1869             :                                                 // summary mode prints here
    1870             : 
    1871             :                                                 // cerr << "Agent = " << acc[i]->getID() << endl;
    1872             :                                                 // cerr << "Agent's name = " << acc[i]->name() << endl;
    1873             :                                         }
    1874             :                                 }
    1875             :                                 {
    1876           0 :                                         logSink_p.clearLocally();
    1877           0 :                                         LogIO oss(LogOrigin("Flagger", "run()"), logSink_p);
    1878           0 :                                         os=oss;
    1879             :                                 }
    1880             :                         } /* end if not trial run and some agent is active */
    1881             : 
    1882           0 :                         end_of_loop:
    1883             : 
    1884             :                         // call endChunk on all agents
    1885           0 :                         for( uInt i = 0; i<acc.size(); i++ )
    1886           0 :                                 acc[i]->endChunk();
    1887             : 
    1888           0 :                         int field_id = chunk.visBuf().fieldId();
    1889           0 :                         int spw_id = chunk.visBuf().spectralWindow();
    1890           0 :                         int scan_number = chunk.visBuf().scan()(0);
    1891             : 
    1892             : 
    1893             :                         /* Is this the end of the current (field, spw)? */
    1894           0 :                         new_field_spw = ( !vi.moreChunks() ||
    1895           0 :                                         !scan_looping ||
    1896           0 :                                         ! (chunk.visBuf().fieldId() == field_id &&
    1897           0 :                                                         chunk.visBuf().spectralWindow() == spw_id &&
    1898           0 :                                                         chunk.visBuf().scan()(0) > scan_number )
    1899             :                         );
    1900             : 
    1901           0 :                         if (didSomething && new_field_spw) {
    1902             : 
    1903           0 :                                 LogIO osss(LogOrigin("Flagger", "run"),logSink_p);
    1904             : 
    1905           0 :                                 stringstream ss;
    1906           0 :                                 ss << "Chunk = " << chunk.nchunk()
    1907           0 :                                  << ", Field = " << field_id << " (" << chunk.visIter().fieldName() << ")"
    1908           0 :                                  << ", Spw Id = "  << spw_id << ", Corrs = [" << chunk.getCorrString() << "]"
    1909           0 :                                  << ", nTime = " << vi.nSubInterval() << ", Total rows = " << totalRows
    1910           0 :                                  << ", Total data = " << totalData << endl;
    1911             :                                 ss << "Input:    "
    1912           0 :                                                 << "  Rows flagged = " << inRowFlags << " "
    1913           0 :                                                 << "(" << 100.0*inRowFlags/totalRows << " %)."
    1914           0 :                                                 << "  Data flagged = " << inDataFlags << " "
    1915           0 :                                                 << "(" << 100.0*inDataFlags/totalData << " %)."
    1916           0 :                                                 << endl;
    1917             :                                 ss << "This run: "
    1918           0 :                                                 << "  Rows flagged = " << outRowFlags - inRowFlags << " "
    1919           0 :                                                 << "(" << 100.0*(outRowFlags-inRowFlags)/totalRows << " %)."
    1920           0 :                                                 << "  Data flagged = "  << outDataFlags - inDataFlags << " "
    1921           0 :                                                 << "(" << 100.0*(outDataFlags-inDataFlags)/totalData << " %)."
    1922           0 :                                                 << endl;
    1923           0 :                                 ss << "------------------------------------------------------------------------------------" << endl;
    1924             : 
    1925           0 :                                 osss << ss.str() << LogIO::POST;
    1926             : 
    1927             :                                 /* Reset counters */
    1928           0 :                                 inRowFlags = outRowFlags = totalRows = inDataFlags = outDataFlags = totalData = 0;
    1929             :                         }
    1930             : 
    1931             :                         // CAS-2798: moved vi.nextChunk() to here to avoid printing the wrong information above
    1932           0 :                         vi.nextChunk(); nchunk++;
    1933             : 
    1934             :                 } // end loop over chunks
    1935             : 
    1936             :                 // get results for all agents
    1937             :                 // (gets just last agent; doesn't work for multiple agents,
    1938             :                 // but only used in mode summary)
    1939           0 :                 for (uInt i = 0; i < acc.size(); i++) {
    1940           0 :                         result = acc[i]->getResult();
    1941             :                 }
    1942             : 
    1943             :                 if (dbg) {
    1944             :                         cout << "Total number of data chunks : " << nchunk << endl;
    1945             :                 }
    1946             : 
    1947             :         }
    1948           0 :         catch(AipsError &x)
    1949             :         {
    1950           0 :                 throw;
    1951             :         }
    1952           0 :         catch(std::exception &e)
    1953             :         {
    1954           0 :                 throw AipsError(e.what());
    1955             :         }
    1956             : 
    1957           0 :         ms.flush();
    1958             :         //os<<"Flagging complete\n"<<LogIO::POST;
    1959             : 
    1960             :         /* Clear the current flag selections */
    1961           0 :         clearflagselections(0);
    1962             : 
    1963           0 :         return result;
    1964             : }
    1965             : 
    1966             : // -----------------------------------------------------------------------
    1967             : // printSummaryReport
    1968             : // Generates a summary flagging report for current chunk
    1969             : // -----------------------------------------------------------------------
    1970           0 : void Flagger::printSummaryReport (RFChunkStats &chunk)
    1971             : {
    1972             :         if (dbg) cout << "Flagger:: printSummaryReport" << endl;
    1973             :         // generate a short text report in the first pane
    1974             :         char s[1024];
    1975           0 :         sprintf(s,"MS '%s'\nchunk %d (field %s, spw %d)",ms.tableName().chars(),
    1976           0 :                         chunk.nchunk(),chunk.visIter().fieldName().chars(),chunk.visIter().spectralWindow());
    1977           0 :         os << "---------------------------------------------------------------------" << LogIO::POST;
    1978           0 :         os<<s<<LogIO::POST;
    1979             : 
    1980             :         // print overall flagging stats
    1981           0 :         uInt n=0,n0;
    1982             : 
    1983           0 :         sprintf(s,"%s, %d channels, %d time slots, %d baselines, %d rows\n",
    1984           0 :                         chunk.getCorrString().chars(),chunk.num(CHAN),chunk.num(TIME),
    1985             :                         chunk.num(IFR),chunk.num(ROW));
    1986           0 :         os<<s<<LogIO::POST;
    1987             : 
    1988             :         // % of rows flagged
    1989           0 :         n  = sum(chunk.nrfIfr());
    1990           0 :         n0 = chunk.num(ROW);
    1991           0 :         sprintf(s,"%d (%0.2f%%) rows are flagged (all baselines/times/chans/corrs in this chunk).",n,n*100.0/n0);
    1992           0 :         os<<s<<LogIO::POST;
    1993             : 
    1994             :         // % of data points flagged
    1995           0 :         n  = sum(chunk.nfIfrTime());
    1996           0 :         n0 = chunk.num(ROW)*chunk.num(CHAN)*chunk.num(CORR);
    1997           0 :         sprintf(s,"%d of %d (%0.2f%%) data points are flagged (all baselines/times/chans/corrs in this chunk).",n,n0,n*100.0/n0);
    1998           0 :         os<<s<<LogIO::POST;
    1999             :         //os << "---------------------------------------------------------------------" << LogIO::POST;
    2000             : 
    2001             :         // % flagged per baseline (ifr)
    2002             :         // % flagged per timestep (itime)
    2003             :         // // there is info about (ifr,itime)
    2004             :         // % flagged per antenna (ifr) -> decompose into a1,a2
    2005             :         // % flagged per channel/corr -> (ich,ifr)
    2006             :         // % flagged per ( field, spw, array, scan ) are chunks - i think !!!
    2007             : 
    2008             : 
    2009             :         // print per-agent flagging summary
    2010             :         /*
    2011             :       for( uInt i=0; i<acc.size(); i++ )
    2012             :       {
    2013             :       String name(acc[i]->name() + "["+i+"]"+": ");
    2014             :       String stats( acc[i]->isActive() ? acc[i]->getStats() : String("can't process this chunk") );
    2015             :       os<<name+stats<<LogIO::POST;
    2016             :       }
    2017             :          */
    2018             :         if (dbg) cout << "end of.... Flagger:: printSummaryReport" << endl;
    2019           0 : }
    2020             : 
    2021             : // -----------------------------------------------------------------------
    2022             : // printAgentReport
    2023             : // Generates per-agent reports for current chunk of data
    2024             : // Meant to be called before doing endChunk() on all the flagging
    2025             : // agents.
    2026             : // -----------------------------------------------------------------------
    2027           0 : void Flagger::printAgentReports( )
    2028             : {
    2029             :         // call each agent to produce summary plots
    2030           0 :         for( uInt i=0; i<acc.size(); i++ )
    2031           0 :                 acc[i]->printFlaggingReport();
    2032           0 : }
    2033             : 
    2034             : /* FLAG VERSION SUPPORT */
    2035           0 : Bool Flagger::saveFlagVersion(String versionname, String comment, String merge )
    2036             : {
    2037             :         try
    2038             :         {
    2039           0 :                 FlagVersion fv(originalms.tableName(),"FLAG","FLAG_ROW");
    2040           0 :                 fv.saveFlagVersion(versionname, comment, merge);
    2041             :         }
    2042           0 :         catch (AipsError x)
    2043             :         {
    2044           0 :                 os << LogIO::SEVERE << "Could not save Flag Version : " << x.getMesg() << LogIO::POST;
    2045           0 :                 throw;
    2046             :         }
    2047           0 :         return true;
    2048             : }
    2049           0 : Bool Flagger::restoreFlagVersion(Vector<String> versionname, String merge )
    2050             : {
    2051             :         try
    2052             :         {
    2053           0 :                 FlagVersion fv(originalms.tableName(),"FLAG","FLAG_ROW");
    2054           0 :                 for(Int j=0;j<(Int)versionname.nelements();j++)
    2055           0 :                         fv.restoreFlagVersion(versionname[j], merge);
    2056             :         }
    2057           0 :         catch (AipsError x)
    2058             :         {
    2059           0 :                 os << LogIO::SEVERE << "Could not restore Flag Version : " << x.getMesg() << LogIO::POST;
    2060           0 :                 return false;
    2061             :         }
    2062           0 :         return true;
    2063             : }
    2064           0 : Bool Flagger::deleteFlagVersion(Vector<String> versionname)
    2065             : {
    2066             :         try
    2067             :         {
    2068           0 :                 FlagVersion fv(originalms.tableName(),"FLAG","FLAG_ROW");
    2069           0 :                 for(Int j=0;j<(Int)versionname.nelements();j++)
    2070           0 :                         fv.deleteFlagVersion(versionname[j]);
    2071             :         }
    2072           0 :         catch (AipsError x)
    2073             :         {
    2074           0 :                 os << LogIO::SEVERE << "Could not delete Flag Version : " << x.getMesg() << LogIO::POST;
    2075           0 :                 return false;
    2076             :         }
    2077           0 :         return true;
    2078             : }
    2079           0 : Bool Flagger::getFlagVersionList(Vector<String> &verlist)
    2080             : {
    2081             :         try
    2082             :         {
    2083           0 :                 verlist.resize(0);
    2084             :                 Int num;
    2085           0 :                 FlagVersion fv(originalms.tableName(),"FLAG","FLAG_ROW");
    2086           0 :                 Vector<String> vlist = fv.getVersionList();
    2087             : 
    2088           0 :                 num = verlist.nelements();
    2089           0 :                 verlist.resize( num + vlist.nelements() + 1, true );
    2090           0 :                 verlist[num] = String("\nMS : ") + originalms.tableName() + String("\n");
    2091           0 :                 for(Int j=0;j<(Int)vlist.nelements();j++)
    2092           0 :                         verlist[num+j+1] = vlist[j];
    2093             :         }
    2094           0 :         catch (AipsError x)
    2095             :         {
    2096           0 :                 os << LogIO::SEVERE << "Could not get Flag Version List : " << x.getMesg() << LogIO::POST;
    2097           0 :                 return false;
    2098             :         }
    2099           0 :         return true;
    2100             : }
    2101             : 
    2102             : 
    2103             : 
    2104             : 
    2105           0 : void Flagger::reform_baselinelist(Matrix<Int> &baselinelist, unsigned nant)
    2106             : {
    2107           0 :         for (unsigned i = 0; (int)i < baselinelist.shape()(1); i++) {
    2108           0 :                 int a1 = baselinelist(0, i);
    2109           0 :                 if (a1 < 0) {
    2110           0 :                         for (unsigned a = 0; a < nant; a++) {
    2111           0 :                                 if (a != (unsigned) (-a1)) {
    2112           0 :                                         IPosition longer = baselinelist.shape();
    2113           0 :                                         longer(1) += 1;
    2114           0 :                                         baselinelist.resize(longer);
    2115           0 :                                         baselinelist(0, longer(1)-1) = a;
    2116           0 :                                         baselinelist(1, longer(1)-1) = baselinelist(1, i);
    2117             :                                 }
    2118             :                         }
    2119             :                 }
    2120             :         }
    2121           0 : }
    2122             : 
    2123             : // -----------------------------------------------------------------------
    2124             : // dprintf
    2125             : // Function for printfing stuff to a debug stream
    2126             : // -----------------------------------------------------------------------
    2127           0 : int dprintf( LogIO &os,const char *format, ...) 
    2128             : {
    2129             :         char str[1024];
    2130             :         va_list ap;
    2131           0 :         va_start(ap, format);
    2132           0 :         int ret = vsnprintf(str, 1024, format, ap);
    2133           0 :         va_end(ap);
    2134           0 :         os << LogIO::DEBUGGING << str << LogIO::POST;
    2135           0 :         return ret;
    2136             : }
    2137             : 
    2138             : } //#end casa namespace

Generated by: LCOV version 1.16