LCOV - code coverage report
Current view: top level - flagging/Flagging - RFASelector2.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 825 0.0 %
Date: 2024-10-04 18:58:15 Functions: 0 24 0.0 %

          Line data    Source code
       1             : 
       2             : //# RFASelector.cc: this defines RFASelector
       3             : //# Copyright (C) 2000,2001,2002
       4             : //# Associated Universities, Inc. Washington DC, USA.
       5             : //#
       6             : //# This library is free software; you can redistribute it and/or modify it
       7             : //# under the terms of the GNU Library General Public License as published by
       8             : //# the Free Software Foundation; either version 2 of the License, or (at your
       9             : //# option) any later version.
      10             : //#
      11             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      12             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      14             : //# License for more details.
      15             : //#
      16             : //# You should have received a copy of the GNU Library General Public License
      17             : //# along with this library; if not, write to the Free Software Foundation,
      18             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      19             : //#
      20             : //# Correspondence concerning AIPS++ should be addressed as follows:
      21             : //#        Internet email: casa-feedback@nrao.edu.
      22             : //#        Postal address: AIPS++ Project Office
      23             : //#                        National Radio Astronomy Observatory
      24             : //#                        520 Edgemont Road
      25             : //#                        Charlottesville, VA 22903-2475 USA
      26             : //#
      27             : //# $Id$
      28             : #include <casacore/casa/Exceptions/Error.h>
      29             : #include <casacore/casa/Arrays/ArrayMath.h>
      30             : #include <casacore/casa/Arrays/ArrayLogical.h>
      31             : #include <casacore/casa/Arrays/MaskedArray.h>
      32             : #include <casacore/casa/Arrays/MaskArrMath.h>
      33             : #include <casacore/casa/Quanta/Quantum.h>
      34             : #include <casacore/casa/Quanta/MVTime.h>
      35             : #include <casacore/casa/Logging/LogIO.h>
      36             : #include <msvis/MSVis/VisibilityIterator.h>
      37             : #include <msvis/MSVis/VisBuffer.h>
      38             : #include <flagging/Flagging/RFASelector.h>
      39             : 
      40             : #include <iomanip>
      41             : #include <ostream>
      42             : #include <cassert>
      43             : 
      44             : using namespace casacore;
      45             : namespace casa { //# NAMESPACE CASA - BEGIN
      46             : 
      47             : Bool dbg2 = false;
      48             : Bool verbose2 = false;
      49             :         
      50             : // -----------------------------------------------------------------------
      51             : // reformRange
      52             : // Reforms an array of 2N elements into a [2,N] matrix
      53             : // -----------------------------------------------------------------------
      54             : 
      55           0 : template<> Array<Int> fieldToArray<Int>( const RecordInterface &parm,const String &id )
      56           0 : { return parm.toArrayInt(id); }
      57           0 : template<> Array<Double> fieldToArray<Double>( const RecordInterface &parm,const String &id )
      58           0 : { return parm.toArrayDouble(id); }
      59           0 : template<> Array<String> fieldToArray<String>( const RecordInterface &parm,const String &id )
      60           0 : { return parm.toArrayString(id); }
      61             : 
      62             : 
      63             : template Bool RFASelector::reformRange<Int>( Matrix<Int>&,const Array<Int>& );
      64             : template Bool RFASelector::reformRange<Double>( Matrix<Double>&,const Array<Double>& );
      65             : template Bool RFASelector::reformRange<String>( Matrix<String>&,const Array<String>& );
      66             : template Bool RFASelector::parseRange<Int>( Matrix<Int>&,const RecordInterface&,const String&);
      67             : template Bool RFASelector::parseRange<Double>( Matrix<Double>&,const RecordInterface&,const String&);
      68             : template Bool RFASelector::parseRange<String>( Matrix<String>&,const RecordInterface&,const String&);
      69             : 
      70             : // -----------------------------------------------------------------------
      71             : // RFA_selector::find
      72             : // Helper templated method to find an object in an array
      73             : // -----------------------------------------------------------------------
      74             : 
      75             : template Bool RFASelector::find<uInt>(uInt&,const uInt&,const Vector<uInt>&);
      76             : template Bool RFASelector::find<Int>(uInt&,const Int&,const Vector<Int>&);
      77             : template Bool RFASelector::find<String>(uInt&,const String&,const Vector<String>&);
      78             : 
      79             : // parseTimes
      80             : // Converts a field that is an array of Int/Double or Strings into 
      81             : // an array of Doubles. Numeric values are converted as is. Strings 
      82             : // are fed through MVTime::read to convert into MJDs (or MJSs, if 
      83             : // secs is true).
      84             : // -----------------------------------------------------------------------
      85           0 : Bool RFASelector::parseTimes ( Array<Double> &times,const RecordInterface &parm,const String &id,Bool secs )
      86             : {
      87           0 :   LogIO os(LogOrigin("RFASelector", "parseTimes()", WHERE));
      88           0 :   if( !isFieldSet(parm,id) )
      89           0 :     return false;
      90           0 :   if( fieldType(parm,id,TpString,TpArrayString) ) // String date/times
      91             :   {
      92           0 :     Array<String> tt( parm.asArrayString(id) );
      93           0 :     times.resize(tt.shape());
      94             :     Bool deltt,deltimes;
      95           0 :     const String *ptt = tt.getStorage(deltt);
      96           0 :     Double *ptimes = times.getStorage(deltimes);
      97           0 :     Int scale = secs ? 24*3600 : 1;
      98           0 :     for( uInt i=0; i<tt.nelements(); i++ )
      99             :     {
     100           0 :       Quantity q;
     101           0 :       if( !MVTime::read(q,ptt[i]) ) {
     102           0 :         os<<"bad "<<id<<" specified: "<<ptt[i]<<endl<<LogIO::EXCEPTION;
     103             :       }
     104           0 :       ptimes[i] = scale*(Double)MVTime(q);
     105           0 :     }
     106           0 :     tt.freeStorage(ptt,deltt);
     107           0 :     times.putStorage(ptimes,deltimes);
     108           0 :   }
     109           0 :     else if( isField(parm,id,isReal) ) // if not strings, try numeric MJDs
     110             :   {
     111           0 :     times = parm.toArrayDouble(id);
     112             :   }
     113             :   else                              // else can't parse
     114           0 :     return false;
     115           0 :   return true;
     116           0 : }
     117             : 
     118             : 
     119             : // -----------------------------------------------------------------------
     120             : // addString
     121             : // Helper method to build up description strings
     122             : // -----------------------------------------------------------------------
     123           0 : void RFASelector::addString( String &str,const String &s1,const char *sep )
     124             : {
     125           0 :   if( str.length() )
     126           0 :     str += sep;
     127           0 :   str += s1;
     128           0 : }
     129             : 
     130             : // -----------------------------------------------------------------------
     131             : // parseMinMax
     132             : // Helper function to parse a range specification
     133             : // -----------------------------------------------------------------------
     134           0 : Bool RFASelector::parseMinMax( Float &vmin,Float &vmax,const RecordInterface &spec,uInt f0 )
     135             : {
     136             :     
     137           0 :   vmin = -C::flt_max; vmax=C::flt_max;
     138             : // Option 1: fields named min/max exist... so use them
     139           0 :   Bool named = false;
     140           0 :   if( spec.isDefined(RF_MIN) )
     141           0 :     { vmin = spec.asFloat(RF_MIN); named = true; }
     142           0 :   if( spec.isDefined(RF_MAX) )
     143           0 :     { vmax = spec.asFloat(RF_MAX); named = true; }
     144           0 :   if( named )
     145           0 :     return true;
     146             : // Else look at first available field, if a 2-element array, assume
     147             : // [min,max] has been specified
     148           0 :   if (spec.nfields() < f0) {
     149           0 :       return false;
     150             :   }
     151           0 :   if( spec.shape(f0).nelements()==1 && spec.shape(f0)(0) == 2 )
     152             :   {
     153           0 :     Vector<Double> mm = spec.toArrayDouble(f0);
     154           0 :     vmin=mm(0); vmax=mm(1);
     155           0 :     return true;
     156           0 :   }
     157             : // Else assume next two record fields are {min,max}
     158           0 :   if( spec.nfields()-f0 > 2 )
     159             :   {
     160           0 :     vmin = spec.asFloat(f0);
     161           0 :     vmax = spec.asFloat(f0+1);
     162             :   }
     163             :   else
     164           0 :     vmax = spec.asFloat(f0);
     165           0 :   return true;
     166             : }
     167             : 
     168           0 : Bool RFASelector::fortestingonly_parseMinMax( Float &vmin,Float &vmax,const RecordInterface &spec,uInt f0 )
     169             : {
     170           0 :     return parseMinMax( vmin, vmax, spec, f0 );
     171             : }
     172             : 
     173             : 
     174             : // -----------------------------------------------------------------------
     175             : // normalize
     176             : // Helper function to shift a cyclic value (i.e. angle) into
     177             : // the interval [base,base+cycle) by adding/subtarcting an integer
     178             : // number of cycles
     179             : // -----------------------------------------------------------------------
     180           0 : static Double normalize( Double value,Double base,Double cycle )
     181             : {
     182           0 :   if( value < base )
     183           0 :     value += (floor((base-value)/cycle)+1)*cycle;
     184           0 :   else if( value >= base+cycle )
     185           0 :     value -= floor((value-base)/cycle)*cycle;
     186           0 :   return value;  
     187             : }
     188             :     
     189             : 
     190             : // -----------------------------------------------------------------------
     191             : // addClipInfo
     192             : // -----------------------------------------------------------------------
     193           0 : void RFASelector::addClipInfo( const Vector<String> &expr,
     194             :                                Float vmin,Float vmax,
     195             :                                Bool clip,
     196             :                                Bool channel_average)
     197             : {
     198             :     // create mapper and clipinfo block
     199           0 :     RFDataMapper *mapper = new RFDataMapper(expr,sel_column);
     200             : 
     201           0 :     ClipInfo clipinfo = { mapper,
     202             :                           vmin,vmax, 
     203             :                           channel_average,
     204           0 :                           clip,0.0 };
     205             : 
     206             :     // if dealing with cyclic values, normalize min/max accordingly
     207           0 :     Double cycle = mapper->getValueCycle();  // e.g. 360 for angles
     208             : 
     209           0 :     if (cycle > 0)  {
     210           0 :         Double base = mapper->getValueBase();  // e.g. -180 for angles
     211             : 
     212             :         // normalize min/max angle into [base,base+cycle)
     213           0 :         clipinfo.vmin = normalize(clipinfo.vmin, base, cycle);
     214           0 :         clipinfo.vmax = normalize(clipinfo.vmax, base, cycle);
     215             : 
     216             :         // if order is reversed, then we're spanning a cycle boundary (i.e. 355->5)
     217           0 :         if( clipinfo.vmin > clipinfo.vmax ) {
     218           0 :           clipinfo.vmax += cycle;   // ...so add a cycle
     219             :         }
     220             : 
     221             :         // use vmin as offset
     222           0 :         clipinfo.offset = clipinfo.vmin;
     223           0 :         clipinfo.vmin = 0;
     224           0 :         clipinfo.vmax -= clipinfo.offset;
     225             :     }
     226             :     // add block to appropriate list  
     227           0 :     Block<ClipInfo> & block( mapper->type()==RFDataMapper::MAPROW ? sel_clip_row : sel_clip );
     228           0 :     uInt ncl = block.nelements();
     229           0 :     block.resize(ncl+1,false,true);
     230           0 :     block[ncl] = clipinfo;
     231           0 : }
     232             : 
     233             : // -----------------------------------------------------------------------
     234             : // parseClipField
     235             : // Helper function to parse a clip specification
     236             : // -----------------------------------------------------------------------
     237           0 : void RFASelector::parseClipField( const RecordInterface &spec,Bool clip )
     238             : {
     239             :     //cerr << "spec: " << spec << endl;
     240             :     //cerr << "clip: " << clip << endl;
     241             :     //cerr << "spec.name(0): " << spec.name(0)<< endl;
     242             :     //cerr << "RF_EXPR: " << RF_EXPR << endl;
     243             : 
     244             :   try {
     245             : 
     246           0 :     bool ca = spec.asBool(RF_CHANAVG);
     247             :     
     248             : // Syntax one - we have a record of {expr,min,max} or {expr,[min,max]}
     249             : // or {expr,max}
     250           0 :     if( spec.name(0)== RF_EXPR )
     251             :     {
     252           0 :       Vector<String> expr = spec.asArrayString(0);
     253             : 
     254             :       Float vmin,vmax;
     255           0 :       if( !parseMinMax(vmin,vmax,spec,1))
     256           0 :         throw(AipsError(""));
     257           0 :       addClipInfo(expr, vmin, vmax, clip, ca);
     258           0 :     }
     259             : // Syntax two: we have a record of { expr1=[min,max],expr2=[min,max],.. }
     260             :     else
     261             :     {
     262           0 :       for( uInt i=0; i<spec.nfields(); i++ )
     263             :       {
     264           0 :         Vector<String> expr(1,spec.name(i));
     265           0 :         Float vmin=-C::flt_max,vmax=C::flt_max;
     266           0 :         if( spec.dataType(i) == TpRecord )
     267             :         {
     268           0 :           uInt f0=0;
     269           0 :           if( spec.asRecord(i).name(0) == RF_EXPR )
     270             :           {
     271           0 :             expr = spec.asRecord(i).asArrayString(0);
     272           0 :             f0++;
     273             :           }
     274           0 :           if( !parseMinMax(vmin,vmax,spec.asRecord(i),f0))
     275           0 :             throw(AipsError(""));
     276             :         } 
     277             :         else 
     278             :         {
     279           0 :           if( isArray( spec.type(i)))
     280             :           {
     281           0 :             Vector<Double> vec = spec.toArrayDouble(i);
     282           0 :             if( vec.nelements() == 1 )
     283           0 :               vmax=vec(0);
     284           0 :             else if( vec.nelements() == 2 )
     285           0 :               { vmin=vec(0); vmax=vec(1); }
     286             :             else
     287           0 :               throw(AipsError(""));
     288           0 :           }
     289             :           else
     290             :           {
     291           0 :             vmax = spec.asFloat(i);
     292             :           }
     293             :         }
     294           0 :         addClipInfo(expr,vmin,vmax,clip, ca);
     295           0 :       }
     296             :     }
     297             :   }
     298           0 :   catch( AipsError x ) {
     299           0 :       os<<"Illegal \""<<(clip?RF_CLIP:RF_FLAGRANGE) <<
     300             :           "\" record: " << x.what() << "\n" <<
     301           0 :           LogIO::EXCEPTION;
     302           0 :   }
     303           0 : }
     304             : 
     305           0 : void RFASelector::fortestingonly_parseClipField( const RecordInterface &spec,Bool clip )
     306             : {
     307           0 :     parseClipField(spec, clip);
     308           0 : }
     309             : 
     310           0 : void RFASelector::addClipInfoDesc ( const Block<ClipInfo> &clip)
     311             : {
     312           0 :   for( uInt i=0; i<clip.nelements(); i++ )
     313             :   {
     314           0 :     String ss;
     315           0 :     char s1[32]="",s2[32]="";
     316             : 
     317           0 :     if (clip[i].channel_average) {
     318           0 :       ss = "average=1 ";
     319             :     }
     320             :     else {
     321           0 :       ss = "average=0 ";
     322             :     }
     323             : 
     324           0 :     if( clip[i].vmin != -C::flt_max )
     325           0 :       sprintf(s1,"%g",clip[i].vmin + clip[i].offset);
     326             : 
     327           0 :     if( clip[i].vmax != C::flt_max )
     328           0 :       sprintf(s2,"%g",clip[i].vmax + clip[i].offset);
     329             : 
     330           0 :     if( clip[i].clip )
     331             :     {
     332           0 :       ss += clip[i].mapper->description();
     333           0 :       if( s1[0] )
     334             :       { 
     335           0 :         ss += String("<") +s1;
     336           0 :         if( s2[0] ) ss += ",";
     337             :       }
     338           0 :       if( s2[0] )
     339           0 :         ss += String(">")+s2;
     340             :     }
     341             :     else
     342             :     {
     343           0 :       if( s1[0] )
     344           0 :         ss += String(s1)+"<=";
     345           0 :       ss += clip[i].mapper->description();
     346           0 :       if( s2[0] )
     347           0 :         ss += String("<=")+s2;
     348             :     }
     349             : 
     350           0 :     addString(desc_str,ss);
     351           0 :   }
     352           0 : }
     353             : 
     354             : // -----------------------------------------------------------------------
     355             : // RFASelector constructor
     356             : // -----------------------------------------------------------------------
     357           0 : RFASelector::RFASelector ( RFChunkStats &ch,const RecordInterface &parm) : 
     358           0 :   RFAFlagCubeBase(ch,parm)
     359             : {
     360           0 :   if ( chunk.measSet().isNull() ) {
     361           0 :     throw AipsError("Received chunk referring to NULL MS!");
     362             :   }
     363             : 
     364             :   char s[256];
     365             : 
     366           0 :   if( fieldType(parm,RF_FREQS,TpArrayString)) // frequency range[s], as measures
     367             :   {
     368           0 :     Matrix<String> sfq;
     369           0 :     parseRange(sfq,parm,RF_FREQS);
     370           0 :     sel_freq.resize( sfq.shape()) ;
     371             :     // parse array of String frequency quanta
     372           0 :     for( uInt i=0; i<sfq.nrow(); i++)  
     373           0 :       for( uInt j=0; i<sfq.ncolumn(); j++)  
     374             :       {
     375             :         Float q; char unit[32];
     376           0 :         if( sscanf(sfq(i,j).chars(),"%f%s",&q,unit)<2) 
     377           0 :           os<<"Illegal \""<<RF_FREQS<<"\" array\n"<<LogIO::EXCEPTION;
     378           0 :         Quantity qq(q,unit);
     379           0 :         sel_freq(i,j) = qq.getValue("Hz");
     380           0 :       }
     381           0 :   } 
     382             :   else // freq. specified as MHz
     383             :   {
     384           0 :     parseRange(sel_freq,parm,RF_FREQS);
     385           0 :     sel_freq *= 1e+6;
     386             :   }
     387           0 :   if( sel_freq.nelements()) 
     388             :   {
     389           0 :     String fq;
     390           0 :     for( uInt i=0; i<sel_freq.ncolumn(); i++) 
     391             :     {
     392           0 :       sprintf(s,"%.2f-%.2f",sel_freq(0,i)*1e-6,sel_freq(1,i)*1e-6);
     393           0 :       addString(fq,s,",");
     394             :     }
     395           0 :     addString(desc_str,String(RF_FREQS)+"="+fq+"MHz");
     396           0 :   }
     397             : 
     398             :   // parse input arguments: channels
     399           0 :   if( parseRange(sel_chan,parm,RF_CHANS)) 
     400             :   {
     401           0 :     String sch;
     402           0 :     for( uInt i=0; i<sel_chan.ncolumn(); i++) 
     403             :     {
     404           0 :       sprintf(s,"%d:%d",sel_chan(0,i),sel_chan(1,i));
     405           0 :       addString(sch,s,",");
     406             :     }
     407           0 :     addString(desc_str,String(RF_CHANS)+"="+sch);
     408           0 :     sel_chan(sel_chan>=0) += -(Int)indexingBase();
     409           0 :   }
     410             :   
     411             :   // parse input arguments: correlations
     412           0 :   if( fieldType(parm,RF_CORR,TpString,TpArrayString))
     413             :   {
     414           0 :     String ss;
     415           0 :     Vector<String> scorr( parm.asArrayString(RF_CORR)) ;
     416           0 :     sel_corr.resize( scorr.nelements()) ;
     417           0 :     for( uInt i=0; i<scorr.nelements(); i++) 
     418             :     {
     419           0 :       sel_corr(i) = Stokes::type( scorr(i)) ;
     420           0 :       if( sel_corr(i) == Stokes::Undefined) 
     421           0 :         os<<"Illegal correlation "<<scorr(i)<<endl<<LogIO::EXCEPTION;
     422           0 :       addString(ss,scorr(i),",");
     423             :     }
     424           0 :     addString(desc_str,String(RF_CORR)+"="+ss);
     425           0 :   }
     426             :   // read clip column
     427           0 :   if( fieldType(parm,RF_COLUMN,TpString)) 
     428             :   {
     429           0 :     parm.get(RF_COLUMN,sel_column);
     430           0 :     addString(desc_str, String(RF_COLUMN)+"="+sel_column);
     431             :   }
     432             :   
     433             :   // parse input arguments: Spw ID(s)
     434           0 :   if( fieldType(parm,RF_SPWID,TpInt,TpArrayInt)) 
     435             :   {
     436           0 :     parm.get(RF_SPWID,sel_spwid);
     437           0 :     String ss;
     438           0 :     for( uInt i=0; i<sel_spwid.nelements(); i++) 
     439           0 :       addString(ss,String::toString(sel_spwid(i)),",");
     440           0 :     addString(desc_str,String(RF_SPWID)+"="+ss);
     441           0 :     sel_spwid -= (Int)indexingBase();
     442           0 :   }
     443             : 
     444             :   // parse input arguments: Field names or ID(s)
     445           0 :   if( fieldType(parm,RF_FIELD,TpString,TpArrayString)) 
     446             :   {
     447           0 :     parm.get(RF_FIELD,sel_fieldnames);
     448           0 :     sel_fieldnames.apply(stringUpper);
     449           0 :     String ss;
     450           0 :     for( uInt i=0; i<sel_fieldnames.nelements(); i++) 
     451           0 :       addString(ss,sel_fieldnames(i),",");
     452           0 :     addString(desc_str,String(RF_FIELD)+"="+ss);
     453           0 :   }
     454           0 :   else if( fieldType(parm,RF_FIELD,TpInt,TpArrayInt)) 
     455             :   {
     456           0 :     parm.get(RF_FIELD,sel_fieldid);
     457           0 :     String ss;
     458           0 :     for( uInt i=0; i<sel_fieldid.nelements(); i++) 
     459           0 :       addString(ss,String::toString(sel_fieldid(i)),",");
     460           0 :     addString(desc_str,String(RF_FIELD)+"="+ss);
     461           0 :     sel_fieldid -= (Int)indexingBase();
     462           0 :   }
     463             : // parse input arguments: Scan Number(s)
     464           0 :   if( fieldType(parm,RF_SCAN,TpInt,TpArrayInt)) 
     465             :   {
     466           0 :     parm.get(RF_SCAN,sel_scannumber);
     467           0 :     String ss;
     468           0 :     for( uInt i=0; i<sel_scannumber.nelements(); i++) 
     469           0 :       addString(ss,String::toString(sel_scannumber(i)),",");
     470           0 :     addString(desc_str,String(RF_SCAN)+"="+ss);
     471           0 :     sel_scannumber -= (Int)indexingBase();
     472           0 :   }
     473             : // parse input arguments: Scan intent
     474           0 :   if ( fieldType(parm,RF_INTENT,TpInt,TpArrayInt))
     475             :   {  
     476           0 :     parm.get(RF_INTENT,sel_stateid);
     477           0 :     String ss;
     478           0 :     for( uInt i=0; i<sel_stateid.nelements(); i++) 
     479           0 :       addString(ss,String::toString(sel_stateid(i)),",");
     480           0 :     addString(desc_str,String(RF_INTENT)+"="+ss);
     481           0 :     sel_stateid -= (Int)indexingBase();
     482           0 :   }
     483             : // parse input arguments: Array ID(s)
     484           0 :   if( fieldType(parm,RF_ARRAY,TpInt,TpArrayInt)) 
     485             :   {
     486           0 :     parm.get(RF_ARRAY,sel_arrayid);
     487           0 :     String ss;
     488           0 :     for( uInt i=0; i<sel_arrayid.nelements(); i++) 
     489           0 :       addString(ss,String::toString(sel_arrayid(i)),",");
     490           0 :     addString(desc_str,String(RF_ARRAY)+"="+ss);
     491           0 :     sel_arrayid -= (Int)indexingBase();
     492           0 :   }
     493             :   // parse input arguments: Observation ID(s)
     494           0 :     if( fieldType(parm,RF_OBSERVATION,TpInt,TpArrayInt))
     495             :     {
     496           0 :       parm.get(RF_OBSERVATION,sel_observation);
     497           0 :       String ss;
     498           0 :       for( uInt i=0; i<sel_observation.nelements(); i++)
     499           0 :         addString(ss,String::toString(sel_observation(i)),",");
     500           0 :       addString(desc_str,String(RF_OBSERVATION)+"="+ss);
     501           0 :       sel_observation -= (Int)indexingBase();
     502           0 :     }
     503             : // parse input: specific time ranges 
     504           0 :   Array<Double> rng;
     505           0 :   Matrix<Double> timerng;
     506           0 :   if( parseTimes(rng,parm,RF_TIMERANGE)) 
     507             :   {
     508           0 :       if( !reformRange(timerng,rng)) 
     509           0 :           os << "Illegal \"" << RF_TIMERANGE << "\" array\n" << LogIO::EXCEPTION;
     510           0 :       sel_timerng = timerng*(Double)(24*3600);
     511             : 
     512           0 :       String s(String(RF_TIMERANGE) + "("); // + String::toString(timerng.ncolumn()));
     513             : 
     514             :       Bool del;
     515           0 :       Double *ptimes = rng.getStorage(del);
     516           0 :       for (unsigned i = 0; i < rng.nelements(); i++) {
     517           0 :           s += String::toString(ptimes[i]);
     518           0 :           if (i < rng.nelements()-1) {
     519           0 :               s += ' ';
     520             :           }
     521             :       }
     522           0 :       rng.putStorage(ptimes, del);
     523           0 :       s += ")";
     524             : 
     525           0 :       addString(desc_str, s);
     526           0 :   }
     527             : 
     528             :   // parse input: specific UV ranges 
     529           0 :   Array<Double> uvrng;
     530           0 :   Matrix<Double> uvrange;
     531           0 :   if( parseTimes(uvrng,parm,RF_UVRANGE)) 
     532             :   {
     533           0 :     if( !reformRange(uvrange,uvrng)) 
     534           0 :       os<<"Illegal \""<<RF_UVRANGE<<"\" array\n"<<LogIO::EXCEPTION;
     535           0 :     sel_uvrange = uvrange;
     536           0 :     addString(desc_str,String(RF_UVRANGE)+"("+String::toString(uvrange.ncolumn())+")");
     537             :   }
     538             : 
     539             : // parse input arguments: ANT specified by string ID
     540           0 :   LogicalVector sel_ant(num(ANT),false); 
     541           0 :   if( fieldType(parm,RF_ANT,TpString,TpArrayString)) 
     542             :   {
     543           0 :     Vector<String> sant( parm.asArrayString(RF_ANT)) ;
     544           0 :     sant.apply(stringUpper);
     545           0 :     const Vector<String> &names( chunk.antNames()) ;
     546           0 :     for( uInt i=0; i<sant.nelements(); i++) 
     547             :     {
     548             :       uInt iant;
     549           0 :       if( !find( iant,sant(i),names)) 
     550           0 :         os<<"Illegal antenna ID "<<sant(i)<<endl<<LogIO::EXCEPTION;
     551           0 :       sel_ant(iant)=true;
     552             :     }
     553           0 :   }
     554             : // else ANT specified directly by indexes
     555           0 :   else if( fieldType(parm,RF_ANT,TpInt,TpArrayInt)) 
     556             :   {
     557           0 :     Vector<Int> sant = parm.asArrayInt(RF_ANT);
     558           0 :     for( uInt i=0; i<sant.nelements(); i++) 
     559           0 :       sel_ant( sant(i) - (Int)indexingBase())  = true;
     560           0 :   }
     561           0 :   if( sum(sel_ant)) 
     562             :   {
     563           0 :     String sant;
     564           0 :     for( uInt i=0; i<num(ANT); i++) 
     565           0 :       if( sel_ant(i)) 
     566           0 :         addString(sant, chunk.antNames()(i),",");
     567           0 :     addString(desc_str, String(RF_ANT)+"="+sant);
     568           0 :   }
     569             : 
     570             : // parse input: baselines as "X-Y"
     571           0 :   sel_ifr = LogicalVector(num(IFR),false);
     572           0 :   String ifrdesc;
     573           0 :   const Vector<String> &names( chunk.antNames()) ;
     574           0 :   if( fieldType(parm, RF_BASELINE, TpString, TpArrayString)) 
     575             :   {
     576           0 :     Vector<String> ss(parm.asArrayString(RF_BASELINE));
     577           0 :     ss.apply(stringUpper);
     578           0 :     for( uInt i=0; i<ss.nelements(); i++) 
     579             :     {
     580             :       uInt ant1,ant2;
     581           0 :       String ants[2];
     582           0 :       Int res = split(ss(i),ants,2,"-");
     583           0 :       Bool wild1 = (ants[0]=="*" || ants[0]=="") ;  // is it a wildcard instead of ID?
     584           0 :       Bool wild2 = (ants[1]=="*" || ants[1]=="") ;
     585           0 :       if( res<2 || ( wild1 && wild2)) 
     586           0 :         os<<"Illegal baseline specification "<<ss(i)<<endl<<LogIO::EXCEPTION;
     587           0 :       Bool val1 = wild1 || find(ant1,ants[0],names);
     588           0 :       Bool val2 = wild2 || find(ant2,ants[1],names);
     589             :       // if both antenna IDs are valid, use them
     590           0 :       if( val1 && val2) 
     591             :       {
     592           0 :         if( wild1) 
     593             :         {
     594           0 :           addString(ifrdesc,ants[1]+"-*",",");
     595           0 :           for( uInt a=0; a<num(ANT); a++)  
     596           0 :             sel_ifr( chunk.antToIfr(a,ant2))  = true;
     597             :         }
     598           0 :         else if( wild2) 
     599             :         {
     600           0 :           addString(ifrdesc,ants[0]+"-*",",");
     601           0 :           for( uInt a=0; a<num(ANT); a++)  
     602           0 :             sel_ifr( chunk.antToIfr(ant1,a))  = true;
     603             :         }
     604             :         else
     605             :         {
     606           0 :           addString(ifrdesc,ants[0]+"-"+ants[1],",");
     607           0 :           sel_ifr( chunk.antToIfr(ant1,ant2))  = true;
     608             :         }
     609           0 :       }
     610             :       else // try to interpret them as numbers instead
     611             :       {
     612           0 :         if( sscanf(ss(i).chars(),"%d-%d",&ant1,&ant2)<2 ||
     613           0 :             ant1>=num(ANT) || ant2>=num(ANT)) 
     614           0 :           os<<"Illegal baseline specification "<<ss(i)<<endl<<LogIO::EXCEPTION;
     615           0 :         sel_ifr( chunk.antToIfr(ant1-(Int)indexingBase(),ant2-(Int)indexingBase()))  = true;
     616           0 :         addString(ifrdesc,ss(i),",");
     617             :       }
     618           0 :     }
     619           0 :   }
     620             : // parse input: baselines as [[x1,y1],[x2,y2],... etc.
     621           0 :   else if( fieldType(parm,RF_BASELINE,TpInt,TpArrayInt)) 
     622             :   {
     623           0 :     Matrix<Int> ant;
     624           0 :     if( parseRange(ant,parm,RF_BASELINE))
     625             :     {
     626           0 :       ant -= (Int)indexingBase();
     627           0 :       for( uInt i=0; i<ant.ncolumn(); i++)
     628             :       {
     629           0 :         if( ant(0,i)==-1)
     630             :         {
     631           0 :           if( ant(1,i)==-1)
     632           0 :             os<<"Illegal baseline specification [-1,-1]"<<LogIO::EXCEPTION<<endl;
     633           0 :           for( uInt a=0; a<num(ANT); a++) 
     634           0 :             sel_ifr( chunk.antToIfr(a,ant(1,i))) = true;
     635           0 :           addString(ifrdesc,names(ant(1,i))+"-*",",");
     636             :         }
     637           0 :         else if( ant(1,i)==-1)
     638             :         {
     639           0 :           for( uInt a=0; a<num(ANT); a++) 
     640           0 :             sel_ifr( chunk.antToIfr(ant(0,i),a)) = true;
     641           0 :           addString(ifrdesc,names(ant(0,i))+"-*",",");
     642             :         }
     643             :         else
     644             :         {
     645           0 :           unsigned indx = chunk.antToIfr(ant(0,i),ant(1,i));
     646             : 
     647           0 :           assert( indx < sel_ifr.nelements() );
     648             : 
     649           0 :           sel_ifr(indx) = true;
     650           0 :           addString(ifrdesc,names(ant(0,i))+"-"+names(ant(1,i)),",");
     651             :         }
     652             :       }
     653             :     }
     654           0 :   }
     655             : 
     656           0 :   if( sum(sel_ifr))
     657             :   {
     658           0 :     String ss;
     659           0 :     addString(desc_str,String(RF_BASELINE)+"="+ifrdesc);
     660           0 :   }
     661             :   else // no IFRs were specified
     662             :   {
     663           0 :     if( sum(sel_ant)) // antennas specified? flag only their baselines
     664             :     {
     665           0 :       for( uInt a1=0; a1<num(ANT); a1++)
     666           0 :         if( sel_ant(a1))
     667           0 :           for( uInt a2=0; a2<num(ANT); a2++)
     668           0 :             sel_ifr(chunk.antToIfr(a1,a2)) = true;
     669             :     }
     670             :     else // no antennas either? flag everything
     671           0 :       sel_ifr.resize();
     672             :   }
     673             : 
     674             :   // parse input: feeds as [[x1,y1],[x2,y2],... etc.
     675           0 :   if( fieldType(parm,RF_FEED,TpInt,TpArrayInt)) 
     676             :   {
     677           0 :     sel_feed = LogicalVector(num(FEEDCORR),false);
     678           0 :     String feeddesc;
     679           0 :     Matrix<Int> feed;
     680           0 :     if( parseRange(feed,parm,RF_FEED))
     681             :     {
     682           0 :       feed -= (Int)indexingBase();
     683           0 :       for( uInt i=0; i<feed.ncolumn(); i++)
     684             :       {
     685           0 :         if( feed(0,i)==-1)
     686             :         {
     687           0 :           if( feed(1,i)==-1)
     688           0 :             os<<"Illegal feed specification [-1,-1]"<<LogIO::EXCEPTION<<endl;
     689           0 :           for( uInt a=0; a<num(FEED); a++) 
     690           0 :             sel_feed( chunk.antToIfr(a,feed(1,i))) = true;
     691           0 :           addString(feeddesc,names(feed(1,i))+"-*",",");
     692             :         }
     693           0 :         else if( feed(1,i)==-1)
     694             :         {
     695           0 :           for( uInt a=0; a<num(FEED); a++) 
     696           0 :             sel_feed( chunk.antToIfr(feed(0,i),a)) = true;
     697           0 :           addString(feeddesc,names(feed(0,i))+"-*",",");
     698             :         }
     699             :         else
     700             :         {
     701           0 :           sel_feed(chunk.antToIfr(feed(0,i),feed(1,i))) = true;
     702           0 :           addString(feeddesc,names(feed(0,i))+"-"+names(feed(1,i)),",");
     703             :         }
     704             :       }
     705             :     }
     706           0 :   }
     707             : 
     708             : // now, all selection-related arguments are accounted for.
     709             : // set flag if some subset has been selected
     710           0 :   Bool have_subset = ( desc_str.length());
     711             : 
     712           0 :   if (have_subset)
     713           0 :     desc_str+=";";
     714             : // unflag specified?
     715           0 :   unflag =  (fieldType(parm, RF_UNFLAG,TpBool) && parm.asBool(RF_UNFLAG));
     716             :   //addString(desc_str,unflag?RF_UNFLAG:"flag");
     717             : 
     718           0 :   ac = new MSAntennaColumns(chunk.measSet().antenna());
     719           0 :   diameters = ac->dishDiameter().getColumn();
     720             :   
     721           0 :   shadow = fieldType(parm, RF_SHADOW, TpBool) && parm.asBool(RF_SHADOW);
     722           0 :   if (shadow) {
     723           0 :     diameter = parm.asDouble(RF_DIAMETER);
     724             :   }
     725             : 
     726           0 :   elevation = fieldType(parm, RF_ELEVATION, TpBool) && parm.asBool(RF_ELEVATION);
     727           0 :   if (elevation) {
     728           0 :     lowerlimit = parm.asDouble(RF_LOWERLIMIT);
     729           0 :     upperlimit = parm.asDouble(RF_UPPERLIMIT);
     730             :   }
     731             :  
     732             : // now, scan arguments for what to flag within the selection
     733             : // specific times (specified by center times)
     734           0 :   Vector<Double> ctimes;
     735           0 :   Double timedelta = 10;
     736           0 :   if (parseTimes(ctimes,parm,RF_CENTERTIME))
     737             :   {
     738           0 :     ctimes *= (Double)(24*3600);
     739           0 :     String ss (String(RF_CENTERTIME)+"("+String::toString(ctimes.nelements())+")");
     740           0 :     Vector<Double> dt;
     741           0 :     if (parseTimes(dt,parm,RF_TIMEDELTA,true))
     742             :     {
     743           0 :       timedelta = dt(0);
     744           0 :       sprintf(s,",dtime=%.1fs",timedelta);
     745           0 :       ss += s;
     746             :     }
     747           0 :     addString(desc_str,ss);
     748           0 :     uInt n = ctimes.nelements();
     749           0 :     sel_time.resize(2,n);
     750           0 :     sel_time.row(0) = ctimes - timedelta;
     751           0 :     sel_time.row(1) = ctimes + timedelta;
     752           0 :   }
     753             : 
     754             : // flag autocorrelations too?
     755           0 :   sel_autocorr =  (fieldType(parm,RF_AUTOCORR,TpBool) && parm.asBool(RF_AUTOCORR));
     756           0 :   if (sel_autocorr)
     757           0 :     addString(desc_str,RF_AUTOCORR);
     758             : 
     759             :   // parse input: quack mode (for VLA)
     760           0 :   if (isFieldSet(parm, RF_QUACK)) {
     761             :     
     762             :       //quack_si = 30.0; // scan interval
     763           0 :       quack_dt = 10.0; // dt to flag at start of scan
     764             :  
     765             :       // are specific values given? 
     766           0 :       Vector<Double> qt;
     767           0 :       if (parseTimes(qt, parm, RF_QUACK, true)) {
     768             : 
     769           0 :           if (qt.nelements() > 3) {
     770           0 :               os << RF_QUACK << " must be specified as T, <scaninterval> or [scaninterval,dt]"
     771           0 :                  << endl << LogIO::EXCEPTION;
     772             :           }
     773             :           
     774           0 :           quack_si = qt(0);
     775           0 :           if (qt.nelements() > 2) {
     776           0 :               quack_dt = qt(1);
     777             :           }
     778             : 
     779           0 :           assert(parm.isDefined(RF_QUACKMODE));
     780           0 :           assert(parm.isDefined(RF_QUACKINC));
     781             : 
     782           0 :           quack_mode = parm.asString(RF_QUACKMODE);
     783           0 :           quack_increment = parm.asBool(RF_QUACKINC);
     784             :           
     785             :       }
     786           0 :       sprintf(s, "%s=%ds", // %s=%s; %s=%s", 
     787           0 :               RF_QUACK, (Int)quack_si);
     788             :               //RF_QUACKMODE, quack_mode,
     789             :               //RF_QUACKINC, quack_increment ? "true" : "false");
     790           0 :       addString(desc_str, s);
     791             :       //    quack_si /= (24*3600);
     792             :       //    quack_dt /= (24*3600);
     793           0 :   }
     794             :   else {
     795           0 :     quack_si = 0;
     796             :   }
     797             : 
     798             :   // flag a specific range or clip outside of range?
     799             : 
     800           0 :   if (isValidRecord(parm,RF_CLIP)) {
     801           0 :     parseClipField(parm.asRecord(RF_CLIP),true);
     802             :   }
     803             : 
     804           0 :   if (isValidRecord(parm,RF_FLAGRANGE))
     805           0 :     parseClipField(parm.asRecord(RF_FLAGRANGE),false);
     806             : 
     807             :   // add to description strings, if something was parsed
     808           0 :   if (sel_clip.nelements())
     809             :   {
     810           0 :     addClipInfoDesc(sel_clip);
     811           0 :     sel_clip_active.resize(sel_clip.nelements());
     812             :   }
     813           0 :   if (sel_clip_row.nelements())
     814           0 :     addClipInfoDesc(sel_clip_row);
     815             : 
     816             : // if nothing has been specified to flag, flag everything within selection
     817           0 :   flag_everything = 
     818           0 :     (quack_si == 0 && 
     819           0 :      !sel_time.nelements() && 
     820           0 :      !sel_autocorr && 
     821           0 :      !sel_clip.nelements() && 
     822           0 :      !sel_clip_row.nelements() && 
     823           0 :      !shadow && 
     824           0 :      !elevation &&
     825           0 :      !sel_stateid.nelements());
     826             :      //!elevation);
     827             :   /*
     828             :   if (flag_everything)
     829             :   {
     830             :     if (!have_subset && !unflag)
     831             :       os<<"FLAG ALL requested, but no MS subset specified.\n"
     832             :           "Refusing to flag the whole measurement set!\n"<<LogIO::EXCEPTION;
     833             : //    addString(desc_str,"all");
     834             :   }
     835             :   */
     836             : //  cout<<"Selector: "<<desc_str<<endl;
     837             : 
     838           0 : }
     839             : 
     840             : 
     841           0 : RFASelector::~RFASelector ()
     842             : {
     843           0 :   delete ac;
     844             : 
     845           0 :   for( uInt i=0; i<sel_clip.nelements(); i++ )
     846           0 :     if( sel_clip[i].mapper )
     847           0 :       delete sel_clip[i].mapper;
     848           0 : }
     849             : 
     850           0 : void RFASelector::startData(bool verbose)
     851             : {
     852           0 :     RFAFlagCubeBase::startData(verbose);
     853             :   
     854           0 :     String flagstring = unflag?String("unflag"):String("flag");
     855             : 
     856           0 :     os << LogIO::DEBUGGING << "Data flagged/unflagged : " << desc_str << " " << flagstring;
     857           0 :     if (flag_everything) os << " all" ;
     858           0 :     os << LogIO::POST;
     859             :     
     860           0 :     Bool have_subset = ( desc_str.length() );
     861             :     
     862           0 :     if( flag_everything && !shadow)
     863             :         {
     864             :           /* jmlarsen: This does not seem useful nor necessary */
     865             :           
     866             :             if (false) if( !have_subset && !unflag)
     867             :                 os<<"FLAG ALL requested, but no MS subset specified.\n"
     868             :                     "Refusing to flag the whole measurement set!\n"<<LogIO::EXCEPTION;
     869             :         }
     870             :     
     871           0 :     return;
     872           0 : }
     873             : 
     874             : // -----------------------------------------------------------------------
     875             : // newChunk
     876             : // At each new chunk, figure out what goes where 
     877             : // -----------------------------------------------------------------------
     878           0 : Bool RFASelector::newChunk (Int &maxmem)
     879             : {
     880             : // check correlations and figure out the active correlations mask
     881           0 :   Vector<Int> corrtype;
     882           0 :   chunk.visIter().corrType(corrtype);
     883           0 :   corrmask = 0;
     884           0 :   if( sel_corr.nelements() )
     885             :   {
     886           0 :     corrmask = chunk.getCorrMask(sel_corr);
     887           0 :     if( !corrmask )
     888             :     {
     889           0 :       if(verbose2) os<<"No matching correlations in this chunk\n"<<LogIO::POST;
     890           0 :       return active=false;
     891             :     }
     892             :   }
     893             :   else // no correlations specified so flag everything
     894           0 :     corrmask = chunk.fullCorrMask();
     895             :   
     896             : // check field IDs and spectral window IDs
     897             :   uInt dum;
     898           0 :   if( sel_spwid.nelements() && !find(dum,chunk.visBuf().spectralWindow(),sel_spwid) )
     899             :   {
     900           0 :     if(verbose2) os<<"Spectral window does not match in this chunk\n"<<LogIO::POST;
     901           0 :     return active=false;
     902             :   }
     903           0 :   if( sel_fieldid.nelements() && !find(dum,chunk.visIter().fieldId(),sel_fieldid) )
     904             :   {
     905           0 :     if(verbose2) os<<"Field ID does not match in this chunk\n"<<LogIO::POST;
     906           0 :     return active=false;
     907             :   }
     908           0 :   if( sel_fieldnames.nelements() && !find(dum,chunk.visIter().fieldName(),sel_fieldnames) )
     909             :   {
     910           0 :     if(verbose2) os<<"Field name does not match in this chunk\n"<<LogIO::POST;
     911           0 :     return active=false;
     912             :   }
     913           0 :   if( sel_arrayid.nelements() && !find(dum,chunk.visIter().arrayId(),sel_arrayid) )
     914             :   {
     915           0 :     if(verbose2) os<<"Array ID does not match in this chunk\n"<<LogIO::POST;
     916           0 :     return active=false;
     917             :   }
     918           0 :   if( sel_observation.nelements() && !find(dum,chunk.visBuf().observationId()[0],sel_observation) )
     919             :   {
     920           0 :     if(verbose2) os<<"Observation ID does not match in this chunk\n"<<LogIO::POST;
     921           0 :     return active=false;
     922             :   }
     923             :   //Vector<Int> tempstateid(0);
     924             :   //tempstateid = chunk.visIter().stateId(tempstateid);
     925             :   //if( tempstateid.nelements() && sel_stateid.nelements() && !find(dum,tempstateid[0],sel_stateid) )
     926             :   //{
     927             :   //  if(verbose2) os<<"State ID does not match in this chunk\n"<<LogIO::POST;
     928             :   //  return active=false;
     929             :   //}  
     930             :   //
     931             :   /*
     932             :   Vector<Int> temp(0);
     933             :   temp = chunk.visIter().scan(temp);
     934             :   if( temp.nelements() &&  sel_scannumber.nelements() && !find(dum,temp[0],sel_scannumber) )
     935             :   {
     936             :     os<<"Scan Number does not match the FIRST scan number in this chunk\n"<<LogIO::POST;
     937             :     return active=false;
     938             :   }
     939             :   */
     940             :   
     941             :   // Get the times at the beginning and end of this scan.
     942             :   
     943           0 :   const Vector<Int> &scans(chunk.visBuf().scan());
     944             : 
     945           0 :   Int s0 = scans(0);
     946             : 
     947           0 :   if (!allEQ(scans, s0) && quack_si > 0) {
     948           0 :       os << "RFASelector: VisBuffer has given us different scans (in this chunk)." 
     949           0 :          << LogIO::EXCEPTION;
     950             :   }
     951             :   
     952             : 
     953             :   //cout << "scan range is = " <<
     954             :   //MVTime( scan_start/C::day).string( MVTime::DMY,7) << " - " << 
     955             :   //MVTime( scan_end  /C::day).string( MVTime::DMY,7) << endl;
     956             : 
     957             : 
     958             : // figure out active channels (i.e. within specified segments)
     959           0 :   flagchan.resize();
     960           0 :   if( sel_freq.ncolumn() || sel_chan.ncolumn() )
     961             :   {
     962           0 :     flagchan = LogicalVector(num(CHAN),false);
     963           0 :     const Vector<Double> & fq( chunk.frequency() );
     964           0 :     for( uInt i=0; i<sel_freq.ncolumn(); i++ )
     965           0 :       flagchan = flagchan || ( fq >= sel_freq(0,i) && fq <= sel_freq(1,i) );
     966           0 :     Vector<Int> ch( num(CHAN) );
     967           0 :     indgen(ch);
     968           0 :     Matrix<Int> schan = sel_chan;
     969           0 :     schan( sel_chan<0 ) += (Int)num(CHAN);
     970           0 :     for( uInt i=0; i<sel_chan.ncolumn(); i++ )
     971             :     {
     972           0 :       flagchan = flagchan || ( ch >= schan(0,i) && ch <= schan(1,i) );
     973             :     }
     974           0 :     if( !sum(flagchan) )
     975             :     {
     976           0 :      if(verbose2)  os<<"No matching frequencies/channels in this chunk\n"<<LogIO::POST;
     977           0 :       return active=false;
     978             :     }
     979           0 :     if( allEQ(flagchan,true) )
     980           0 :       flagchan.resize(); // null array = all true
     981           0 :   }
     982             : // init all clipping mappers, and check their correlation masks
     983           0 :   if( sel_clip.nelements() )
     984             :   {
     985             :     // see which mappers are active for this chunk, and accumulate their
     986             :     // masks in clip_corrmask
     987           0 :     RFlagWord clip_corrmask=0;
     988           0 :     for( uInt i=0; i<sel_clip.nelements(); i++ ) 
     989             :     {
     990           0 :       RFlagWord mask = sel_clip[i].mapper->corrMask(chunk.visIter());
     991           0 :       sel_clip_active(i) = (mask!=0);
     992           0 :       clip_corrmask |= mask;
     993             :     }
     994           0 :     sum_sel_clip_active = sum(sel_clip_active);
     995             :     // If no explicit correlations were selected by the user,  
     996             :     // then use clip_corrmask as the overall mask
     997           0 :     if( !sel_corr.nelements() )
     998             :     {
     999           0 :       corrmask = clip_corrmask;
    1000           0 :       if( !corrmask )
    1001             :       {
    1002           0 :         if (verbose2) {
    1003           0 :           os << "No matching correlations in this chunk\n" << LogIO::POST;
    1004             :         }
    1005           0 :         return active=false;
    1006             :       }
    1007             :     }
    1008             :   }
    1009             : // reserve a minimum of memory for ourselves
    1010           0 :   maxmem -= 1;
    1011             : // init flagging cube and off we go...
    1012           0 :   RFAFlagCubeBase::newChunk(maxmem);
    1013             : // see if full row is being flagged, i.e. no subset of channels was selected,
    1014             : // and no explicit correlations (or all correlations).
    1015           0 :   select_fullrow = (!flagchan.nelements() && 
    1016           0 :     (!sel_corr.nelements() || corrmask==chunk.fullCorrMask()) );
    1017           0 :   return active=true;
    1018           0 : }
    1019             : 
    1020             : // -----------------------------------------------------------------------
    1021             : // processRow
    1022             : // Raises/clears flags for a single row, depending on current selection
    1023             : // -----------------------------------------------------------------------
    1024           0 : void RFASelector::processRow(uInt ifr,uInt it)
    1025             : {
    1026           0 :    if(dbg2)   cout << ifr << ",";
    1027             :    // does the selection include whole rows?
    1028           0 :    if (select_fullrow) {
    1029             :        
    1030           0 :        unflag ? flag.clearRowFlag(ifr,it) : flag.setRowFlag(ifr,it);
    1031             :        // apply this to the entire row...
    1032           0 :        for( uInt ich=0; ich<num(CHAN); ich++ )
    1033           0 :            unflag ? flag.clearFlag(ich,ifr) : flag.setFlag(ich,ifr);
    1034             :        
    1035             :    }
    1036             :    else {
    1037             :        // else apply data flags to selection
    1038           0 :        for( uInt ich=0; ich<num(CHAN); ich++ )
    1039           0 :            if( !flagchan.nelements() || flagchan(ich) )
    1040           0 :                unflag ? flag.clearFlag(ich,ifr) : flag.setFlag(ich,ifr);
    1041             :    }
    1042           0 : }
    1043             : 
    1044             : // -----------------------------------------------------------------------
    1045             : // Processes 1 time slot in the MS
    1046             : // There is one MS row per baseline
    1047             : //  
    1048             : // -----------------------------------------------------------------------
    1049           0 : RFA::IterMode RFASelector::iterTime (uInt it)
    1050             : {
    1051           0 :   RFAFlagCubeBase::iterTime(it);
    1052             : 
    1053             :   // setup each correlation clip mapper
    1054           0 :   for (uInt i=0; i<sel_clip.nelements(); i++) 
    1055           0 :       if (sel_clip_active(i))
    1056           0 :           sel_clip[i].mapper->setVisBuffer(chunk.visBuf());
    1057             :   
    1058             :   // extract time
    1059           0 :   const Vector<Double> &times( chunk.visBuf().time() );
    1060           0 :   const Vector<Double> &dtimes( chunk.visBuf().timeInterval() );
    1061           0 :   Double t0 = times(0);
    1062           0 :   Double dt0 = dtimes(0);
    1063           0 :   if( !allEQ(times,t0) )
    1064           0 :     os << "RFASelector: VisBuffer has given us different times." << LogIO::EXCEPTION;
    1065             :   
    1066             :   // extract scan number
    1067           0 :   const Vector<Int> &scans( chunk.visBuf().scan() );
    1068             : 
    1069           0 :   Int s0 = scans(0);
    1070             : 
    1071           0 :   if (!allEQ(scans,s0) && quack_si > 0) {
    1072           0 :       os << "RFASelector: crash&burn, VisBuffer's given us different scans."
    1073           0 :          << LogIO::EXCEPTION;
    1074             :   }
    1075             : 
    1076             :   // is current scan number within selected list of scan numbers?
    1077           0 :   bool scanselect = true;
    1078           0 :   if (sel_scannumber.nelements()) {
    1079           0 :       bool sel = false;
    1080           0 :       for (uInt i = 0;
    1081           0 :            i < sel_scannumber.nelements();
    1082             :            i++) {
    1083           0 :           if( sel_scannumber(i) == s0 ) {
    1084           0 :               sel = true;
    1085             :           }
    1086             :       }
    1087             :     
    1088           0 :       if( ! sel ) scanselect = false;
    1089             :       //if( ! sel )  return RFA::CONT;
    1090             :   }
    1091             : 
    1092             :   // flag if within specific timeslots
    1093           0 :   bool timeselect = true;
    1094           0 :   if (sel_timerng.ncolumn()) {
    1095           0 :       timeselect = false;
    1096           0 :       if( anyEQ(sel_timerng.row(0) <= t0 && sel_timerng.row(1) >= t0,
    1097           0 :                 true) ) {
    1098           0 :           timeselect = true;
    1099             :       }
    1100             :   }
    1101             :   
    1102           0 :   if ( ! (timeselect && scanselect) ) {       
    1103           0 :       return RFA::CONT;
    1104             :   }
    1105             :   
    1106           0 :   const Vector<Int> &ifrs( chunk.ifrNums() );
    1107           0 :   const Vector<Int> &feeds( chunk.feedNums() );
    1108           0 :   const Vector<casacore::RigidVector<casacore::Double, 3> >&uvw( chunk.visBuf().uvw() );
    1109             :   // Vector<Vector<Double> > &uvw=NULL;//( chunk.visIter.uvw(uvw) );
    1110             :   //chunk.visIter().uvw(uvw);
    1111           0 :   Double uvdist=0.0;
    1112             : 
    1113           0 :   if( ifrs.nelements() != feeds.nelements() || 
    1114           0 :       ifrs.nelements() != uvw.nelements() ) 
    1115           0 :           cout << "RFASelector::iterTime ->  nelements mismatch " << endl;
    1116             : 
    1117             : // do we flag the whole selection?  
    1118           0 :   bool flagall = flag_everything;
    1119             : 
    1120           0 :   if (!flagall) {
    1121             : 
    1122           0 :       if (elevation) {
    1123           0 :           const Vector<MDirection> &azimuth_elevation = chunk.visIter().azel(t0);
    1124             : 
    1125           0 :           for (uInt i = 0; i < ifrs.nelements(); i++) {
    1126             :               
    1127             :               unsigned a1, a2;
    1128           0 :               chunk.ifrToAnt(a1, a2, chunk.ifrNum(i));
    1129             : 
    1130           0 :               Bool inrange = false;
    1131           0 :               uvdist = sqrt( uvw(i)(0)*uvw(i)(0) + uvw(i)(1)*uvw(i)(1) );
    1132           0 :               for (uInt j = 0; j < sel_uvrange.ncolumn(); j++)
    1133           0 :                   if (uvdist >= sel_uvrange(0, j) && uvdist <= sel_uvrange(1, j))
    1134           0 :                       inrange |= true;
    1135             :               
    1136           0 :               if( (!sel_ifr.nelements() || sel_ifr(ifrs(i))) && 
    1137           0 :                   (!sel_feed.nelements() || sel_feed(feeds(i))) &&
    1138           0 :                   (!sel_uvrange.nelements() || inrange ) ) {
    1139             :                   
    1140             :                   //                  double antenna_elevation = azimuth_elevation[i].getAngle("deg").getValue()[1];
    1141           0 :                   double antenna1_elevation = azimuth_elevation[a1].getAngle("deg").getValue()[1];
    1142           0 :                   double antenna2_elevation = azimuth_elevation[a2].getAngle("deg").getValue()[1];
    1143             : 
    1144           0 :                   if ( antenna1_elevation < lowerlimit ||
    1145           0 :                        antenna2_elevation < lowerlimit ||
    1146           0 :                        antenna1_elevation > upperlimit ||
    1147           0 :                        antenna2_elevation > upperlimit ) {
    1148           0 :                       processRow(ifrs(i), it);
    1149             :                   }
    1150             :               }
    1151             :           }
    1152             : 
    1153           0 :       }
    1154             : 
    1155           0 :       if (shadow) {
    1156             :           
    1157             :           /*
    1158             :             1st loop: Figure out which antennas are shadowed
    1159             :             2nd loop: Flag all data (incl self correlations)
    1160             :                       involving shadowed antennas
    1161             :            */
    1162             :            
    1163           0 :           std::vector<bool> shadowed(diameters.nelements(), false);
    1164             : 
    1165           0 :           for (uInt i = 0; i < ifrs.nelements(); i++) {
    1166             :               
    1167             :               unsigned a1, a2;
    1168           0 :               chunk.ifrToAnt(a1, a2, chunk.ifrNum(i));
    1169             : 
    1170           0 :               if (a1 != a2) {  /* Antennas don't shadow themselves. */
    1171             :                   double d1, d2;
    1172           0 :                   if (diameter < 0) {
    1173           0 :                     d1 = diameters(a1);
    1174           0 :                     d2 = diameters(a2);
    1175             :                   }
    1176             :                   else {
    1177           0 :                     d1 = diameter;
    1178           0 :                     d2 = diameter;
    1179             :                   }
    1180             :                   
    1181             :                   Double uvdist2 = 
    1182           0 :                       uvw(i)(0) * uvw(i)(0) + 
    1183           0 :                       uvw(i)(1) * uvw(i)(1);
    1184             :                   
    1185             :                   /* The relevant threshold distance for shadowing is
    1186             :                      (d1+d2)/2  */
    1187           0 :                   if (uvdist2 < (d1+d2)*(d1+d2)/4.0) {
    1188             :                       
    1189             :                       if (0) cerr << "antenna is shadowed " << a1 << "-" << a2 << ": " <<
    1190             :                                  "(u, v, w) = (" << 
    1191             :                                  uvw(i)(0) << ", " <<
    1192             :                                  uvw(i)(1) << ", " <<
    1193             :                                  uvw(i)(2) << ")" << endl;
    1194             :                       
    1195           0 :                       if (uvw(i)(2) > 0) {
    1196           0 :                           shadowed[a1] = true;
    1197             :                       }
    1198             :                       else {
    1199           0 :                           shadowed[a2] = true;
    1200             :                       }
    1201             :                   }
    1202             :               }
    1203             :           }
    1204             : 
    1205             :           if (0) {
    1206             :               std::copy(shadowed.begin(),
    1207             :                         shadowed.end(),
    1208             :                         std::ostream_iterator<bool>(std::cout, "] [" ));
    1209             :               cout << endl;
    1210             :           }
    1211             : 
    1212           0 :           for (uInt i = 0; i < ifrs.nelements(); i++) {
    1213             :               
    1214             :               unsigned a1, a2;
    1215           0 :               chunk.ifrToAnt(a1, a2, chunk.ifrNum(i));
    1216             : 
    1217           0 :               Bool inrange = false;
    1218           0 :               uvdist = sqrt( uvw(i)(0)*uvw(i)(0) + uvw(i)(1)*uvw(i)(1) );
    1219           0 :               for (uInt j = 0; j < sel_uvrange.ncolumn(); j++)
    1220           0 :                   if (uvdist >= sel_uvrange(0, j) && uvdist <= sel_uvrange(1, j))
    1221           0 :                       inrange |= true;
    1222             :               
    1223           0 :               if( (!sel_ifr.nelements() || sel_ifr(ifrs(i))) && 
    1224           0 :                   (!sel_feed.nelements() || sel_feed(feeds(i))) &&
    1225           0 :                   (!sel_uvrange.nelements() || inrange ) ) {
    1226             :                   
    1227           0 :                   if (shadowed[a1] || shadowed[a2]) {
    1228           0 :                       processRow(ifrs(i),it);
    1229             :                   }
    1230             :               }
    1231             :           }
    1232           0 :       } /* end if shadow */
    1233             :       
    1234             :       // flag autocorrelations
    1235           0 :       if (sel_autocorr) { 
    1236           0 :           for (uInt i=0; i < ifrs.nelements(); i++) {
    1237           0 :               Bool inrange=false;
    1238           0 :               uvdist = sqrt( uvw(i)(0)*uvw(i)(0) + uvw(i)(1)*uvw(i)(1) );
    1239           0 :               for( uInt j=0; j<sel_uvrange.ncolumn(); j++)
    1240           0 :                   if( uvdist >= sel_uvrange(0,j) && uvdist <= sel_uvrange(1,j) ) inrange |= true;
    1241             :               //    if( inrange ) cout << "x selected : " << i << " : " << uvdist << endl;
    1242           0 :               if ((!sel_ifr.nelements() || sel_ifr(ifrs(i))) && 
    1243           0 :                   (!sel_feed.nelements() || sel_feed(feeds(i))) &&
    1244           0 :                   (!sel_uvrange.nelements() || inrange ))
    1245             :                   {
    1246             :                       uInt a1,a2;
    1247           0 :                       chunk.ifrToAnt(a1,a2,ifrs(i));
    1248           0 :                       if( a1==a2 )
    1249           0 :                           processRow(ifrs(i),it);
    1250             :                   }
    1251             :           }
    1252             :       }
    1253             : 
    1254             :       // flag if quacked
    1255           0 :       if (quack_si > 0) {
    1256             :         
    1257             :         double scan_start;
    1258             :         double scan_end; 
    1259             : 
    1260           0 :         if (quack_increment) {
    1261           0 :           scan_start = chunk.get_scan_start_unflagged(s0);
    1262           0 :           scan_end   = chunk.get_scan_end_unflagged(s0);
    1263             :           // returns negative if there's no unflagged data
    1264             :         }
    1265             :         else {
    1266           0 :           scan_start = chunk.get_scan_start(s0);
    1267           0 :           scan_end   = chunk.get_scan_end(s0);
    1268             :         }
    1269             :           //cout << "Start time for scan  : " << MVTime( scan_start/C::day).string( MVTime::DMY,7) ;
    1270             :           //cout << "   :::  iterTime for " << MVTime( t0/C::day).string( MVTime::DMY,7) << " and scan " << s0;
    1271             : 
    1272           0 :         if (quack_mode == "beg") {
    1273           0 :           if (scan_start > 0 &&
    1274           0 :               t0 <= (scan_start + quack_si)) flagall = true;
    1275             :         }
    1276           0 :         else if (quack_mode == "endb") {
    1277           0 :           if (scan_end > 0 &&
    1278           0 :               t0 >= (scan_end - quack_si)) flagall = true;
    1279             :         }
    1280           0 :         else if (quack_mode == "end") {
    1281           0 :           if (scan_end > 0 &&
    1282           0 :               t0 < (scan_end - quack_si)) flagall = true;
    1283             :         }
    1284           0 :         else if (quack_mode == "tail") {
    1285           0 :           if (scan_start > 0 &&
    1286           0 :               t0 > (scan_start + quack_si)) flagall = true;
    1287             :         }
    1288             :         else {
    1289           0 :           throw(AipsError("Illegal quack mode '" + quack_mode + "'"));
    1290             :         }
    1291             :           
    1292             :       }
    1293             : 
    1294             :       // flag for specific row-based clipping expressions
    1295           0 :       if (sel_clip_row.nelements()) {
    1296             : 
    1297           0 :         for( uInt i=0; i < ifrs.nelements(); i++ ) {// loop over rows
    1298           0 :           for( uInt j=0; j < sel_clip_row.nelements(); j++ ) {
    1299             : 
    1300           0 :               Float vmin = sel_clip_row[j].vmin;
    1301           0 :               Float vmax = sel_clip_row[j].vmax;
    1302           0 :               Float val  = sel_clip_row[j].mapper->mapValue(i) - sel_clip_row[j].offset;
    1303           0 :               if( (sel_clip_row[j].clip  && ( val<vmin || val>vmax ) ) ||
    1304           0 :                   (!sel_clip_row[j].clip && val>=vmin && val<=vmax ) )
    1305           0 :                 processRow(ifrs(i),it);
    1306             :           }
    1307             :         }
    1308             :       }
    1309             : 
    1310           0 :       bool clip_based_on_tsys = false;
    1311           0 :       if (clip_based_on_tsys) {
    1312             :           /*
    1313             :             for each row:
    1314             :             
    1315             :             find antenna1 and antenna2
    1316             :             lookup temperature for 
    1317             :             (antenna1,spwid,time) and
    1318             :             (antenna2,spwid,time) in the SYSCAL subtable
    1319             :             
    1320             :           */
    1321           0 :           cout << "Get sysCal table" << endl;
    1322             :           // note, this is an optional subtable
    1323             : 
    1324           0 :           const MSSysCal syscal(chunk.measSet().sysCal());
    1325             : 
    1326           0 :           ScalarColumn<uInt> sc_antenna_id(syscal, "ANTENNA_ID");
    1327           0 :           ScalarColumn<uInt> sc_spwid     (syscal, "SPECTRAL_WINDOW_ID");
    1328           0 :           ScalarColumn<Double> sc_time   (syscal, "TIME");
    1329           0 :           ArrayColumn<Float> sc_tsys     (syscal, "TSYS");
    1330             :                     
    1331           0 :           unsigned spwid = chunk.visBuf().spectralWindow();
    1332             :           
    1333           0 :           for (uInt i = 0; i < ifrs.nelements(); i++) {
    1334             :           
    1335             :               unsigned a1, a2;
    1336           0 :               chunk.ifrToAnt(a1, a2, chunk.ifrNum(i));
    1337             :               
    1338             :               //for each SYSCAL table row
    1339             :               // if antenna1 matches or antenna2 matches and
    1340             :               //    spwid matches and time matches
    1341             :               //     if (tsys out of allowed range)
    1342             :               //             flag
    1343             : 
    1344           0 :               unsigned nrows_syscal = sc_antenna_id.getColumn().nelements();
    1345           0 :               cout << nrows_syscal << " rows in SYSCAL table" << endl;
    1346           0 :               for (unsigned row = 0; row < nrows_syscal; row++) {
    1347           0 :                   cout << "a1, a2 = " << a1 << ", " << a2 << " ?= " << sc_antenna_id(row) << endl;
    1348           0 :                   cout << "time   = " << t0 << " ?= " << sc_time(row) << endl;
    1349           0 :                   cout << "spwid  = " << spwid << " ?= " << sc_spwid(row) << endl;
    1350           0 :                   cout << "tsys   = " << sc_tsys(row) << endl;
    1351             : 
    1352           0 :                   if ((a1 == sc_antenna_id(row) || a2 == sc_antenna_id(row)) &&
    1353           0 :                       spwid == sc_spwid(row) &&
    1354           0 :                       t0-dt0/2 < sc_time(row) && sc_time(row) < t0+dt0/2) {
    1355           0 :                     cout << "                         MATCH!" << endl;
    1356             :                   }
    1357             :               }
    1358             :           }
    1359           0 :       }
    1360             :       // scan intent based flagging (check match per antenna/baseline) 
    1361           0 :       if(sel_stateid.nelements()) {
    1362           0 :           const Vector<Int> &stateids( chunk.visBuf().stateId() );
    1363             :           //for (uInt i = 0; i < ifrs.nelements(); i++) {
    1364             :           //    for (uInt j = 0; j < sel_stateid.nelements(); j++) {
    1365             :           //        if( sel_stateid(j) == stateid0 )
    1366           0 :           for (uInt i = 0; i < stateids.nelements(); i++) {
    1367             : 
    1368           0 :               Bool inrange=false;
    1369           0 :               uvdist = sqrt( uvw(i)(0)*uvw(i)(0) + uvw(i)(1)*uvw(i)(1) );
    1370           0 :               for( uInt j=0; j<sel_uvrange.ncolumn(); j++) 
    1371           0 :                    if( uvdist >= sel_uvrange(0,j) && uvdist <= sel_uvrange(1,j) ) inrange |= true;
    1372             : 
    1373           0 :               for (uInt j = 0; j < sel_stateid.nelements(); j++) {
    1374           0 :                   if( stateids(i) == sel_stateid(j) && 
    1375           0 :                       ifrs.nelements()==stateids.nelements() &&
    1376           0 :                       (!sel_ifr.nelements()||sel_ifr(ifrs(i))) &&
    1377           0 :                       (!sel_feed.nelements() || sel_feed(feeds(i))) &&
    1378           0 :                       (!sel_uvrange.nelements() || inrange ) )
    1379           0 :                       processRow(ifrs(i),it);
    1380             :               }
    1381             :           }
    1382             :       }
    1383             :   }
    1384             : 
    1385             :   // flag whole selection, if still needed
    1386           0 :   if (flagall)
    1387             :   {
    1388           0 :     for (uInt i=0; i<ifrs.nelements(); i++) // loop over rows
    1389             :     {
    1390           0 :         Bool inrange=false;
    1391           0 :         uvdist = sqrt( uvw(i)(0)*uvw(i)(0) + uvw(i)(1)*uvw(i)(1) );
    1392           0 :         for( uInt j=0; j<sel_uvrange.ncolumn(); j++)
    1393           0 :                 if( uvdist >= sel_uvrange(0,j) && uvdist <= sel_uvrange(1,j) ) inrange |= true;
    1394           0 :         if( (!sel_ifr.nelements() || sel_ifr(ifrs(i))) && 
    1395           0 :             (!sel_feed.nelements() || sel_feed(feeds(i))) &&
    1396           0 :             (!sel_uvrange.nelements() || inrange ) )
    1397           0 :                 processRow(ifrs(i),it);
    1398             :     }
    1399             :   }
    1400             :   
    1401           0 :   return RFA::CONT;
    1402             : }
    1403             : 
    1404             : // -----------------------------------------------------------------------
    1405             : // iterRow
    1406             : // -----------------------------------------------------------------------
    1407           0 : RFA::IterMode RFASelector::iterRow (uInt ir)
    1408             : {
    1409           0 :   uInt ifr = chunk.ifrNum(ir);
    1410             : 
    1411           0 :   if( sel_clip.nelements() && sum_sel_clip_active )
    1412             :   {
    1413             :       // apply data flags
    1414           0 :       for( uInt j=0; j<sel_clip.nelements(); j++ ) {
    1415             :       
    1416           0 :           if (sel_clip[j].channel_average) {
    1417             :               // Compute average
    1418           0 :               Float average = 0;
    1419           0 :               unsigned n_unflagged = 0;
    1420             : 
    1421           0 :               for (uInt ich=0; ich < num(CHAN); ich++ ) {
    1422             :                 
    1423             :                   // if active channel, and not flagged...
    1424           0 :                   if ((!flagchan.nelements() || flagchan(ich))
    1425           0 :                       &&
    1426           0 :                       !flag.preFlagged(ich, ifr)) {
    1427             :                     
    1428             :                     
    1429           0 :                       average += sel_clip[j].mapper->mapValue(ich, ir);
    1430           0 :                       n_unflagged += 1;
    1431             :                   }
    1432             :               }
    1433             :           
    1434             : 
    1435             :               // Decide whether to flag row (or active channels), based on average
    1436             :               //cout << "number of unflagged channels = " << n_unflagged << endl;
    1437           0 :               if (n_unflagged > 0) {
    1438           0 :                   average = average / n_unflagged;
    1439             :                 
    1440             :                   //cout << " average = " << average << endl;
    1441             :                   
    1442           0 :                   Float vmin = sel_clip[j].vmin;
    1443           0 :                   Float vmax = sel_clip[j].vmax;
    1444           0 :                   Float val = average;
    1445             : 
    1446           0 :                   if( ( sel_clip[j].clip && ( val <  vmin || val > vmax ) ) ||
    1447           0 :                       (!sel_clip[j].clip &&   vmin <= val && val <= vmax   ) )
    1448             : 
    1449             :                       /* No channel selections, flag all channels.
    1450             :                          
    1451             :                       jmlarsen: Unfortunately, clearRowFlag and setRowFlag
    1452             :                       don't seem to work, therefore don't do like this.
    1453             :                       (This could probably be brought to work by
    1454             :                       fixing RFFlagCube::setMSFlags() to use the flagrow.)
    1455             :                       
    1456             :                       cout << " flag entire row " << endl;
    1457             :                       unflag ? 
    1458             :                       flag.clearRowFlag(ifr, it) :
    1459             :                       flag.setRowFlag(ifr, it);
    1460             :                       */
    1461             :                       
    1462           0 :                       for (uInt ich = 0; ich < num(CHAN); ich++) {
    1463           0 :                         if (!flagchan.nelements() || flagchan(ich)) {
    1464           0 :                             unflag ?
    1465           0 :                               flag.clearFlag(ich, ifr) :
    1466           0 :                               flag.setFlag(ich, ifr);
    1467             :                         }
    1468             :                     }
    1469             :               }
    1470             :               else {
    1471             :               /* If all channels were already flagged, don't flag/unflag anything. */
    1472             :               }
    1473             :           }
    1474             :           else {
    1475             :             /* No averaging */
    1476           0 :             for( uInt ich=0; ich<num(CHAN); ich++ ) {
    1477           0 :               if( !flagchan.nelements() || flagchan(ich) ) {
    1478           0 :                 Float vmin = sel_clip[j].vmin;
    1479           0 :                 Float vmax = sel_clip[j].vmax;
    1480           0 :                 Float val  = sel_clip[j].mapper->mapValue(ich,ir);
    1481             : 
    1482             :                 // jagonzal: Added ISO isnan check to catch extremely large values (CAS-3355)
    1483           0 :                 if( ( sel_clip[j].clip && (val<vmin || val>vmax || std::isnan(val)) ) ||
    1484           0 :                     (!sel_clip[j].clip && val>=vmin && val<=vmax   ) )
    1485           0 :                   unflag ? flag.clearFlag(ich,ifr) : flag.setFlag(ich,ifr);
    1486             :               }
    1487             :             }
    1488             :           }
    1489             :       }
    1490             :   }
    1491             : 
    1492           0 :   return RFA::CONT;
    1493             : }
    1494             : 
    1495             : /* Flush flags after each time stamp, if in kiss mode */
    1496           0 : void RFASelector::endRows(uInt it)
    1497             : {
    1498           0 :     if (only_selector) {
    1499           0 :         flag.advance(it);
    1500           0 :         flag.setMSFlags(it);
    1501             :     }
    1502           0 : }
    1503             :     
    1504           0 : void RFASelector::iterFlag(uInt it)
    1505             : {
    1506           0 :     if (!only_selector) {
    1507           0 :         RFAFlagCubeBase::iterFlag(it);
    1508             :     }
    1509           0 : }
    1510             : 
    1511           0 : String RFASelector::getDesc ()
    1512             : {
    1513           0 :   return desc_str+" "+RFAFlagCubeBase::getDesc();
    1514             : }
    1515             : 
    1516           0 : const RecordInterface & RFASelector::getDefaults ()
    1517             : {
    1518           0 :   static Record rec;
    1519             : // create record description on first entry
    1520           0 :   if( !rec.nfields() )
    1521             :   {
    1522           0 :     rec = RFAFlagCubeBase::getDefaults();
    1523           0 :     rec.removeField(RF_FIGNORE); // fignore is meaningless
    1524           0 :     rec.define(RF_NAME,"Selector");
    1525           0 :     rec.define(RF_SPWID,false);
    1526           0 :     rec.define(RF_FIELD,false);
    1527           0 :     rec.define(RF_FREQS,false);
    1528           0 :     rec.define(RF_CHANS,false);
    1529           0 :     rec.define(RF_CORR,false);
    1530           0 :     rec.define(RF_ANT,false);
    1531           0 :     rec.define(RF_BASELINE,false);
    1532           0 :     rec.define(RF_TIMERANGE,false);
    1533           0 :     rec.define(RF_AUTOCORR,false);
    1534           0 :     rec.define(RF_CENTERTIME,false);
    1535           0 :     rec.define(RF_TIMEDELTA,10.0);
    1536           0 :     rec.define(RF_QUACK,false);
    1537           0 :     rec.define(RF_CLIP,false);
    1538           0 :     rec.define(RF_CHANAVG, false);
    1539           0 :     rec.define(RF_FLAGRANGE,false);
    1540           0 :     rec.define(RF_UNFLAG,false);
    1541           0 :     rec.define(RF_SHADOW,false);
    1542           0 :     rec.define(RF_ELEVATION, false);
    1543           0 :     rec.define(RF_SCAN,false);
    1544           0 :     rec.define(RF_INTENT,false);
    1545           0 :     rec.define(RF_ARRAY,false);
    1546           0 :     rec.define(RF_FEED,false);
    1547           0 :     rec.define(RF_UVRANGE,false);
    1548           0 :     rec.define(RF_COLUMN,false);
    1549           0 :     rec.define(RF_DIAMETER, false);
    1550           0 :     rec.define(RF_LOWERLIMIT, false);
    1551           0 :     rec.define(RF_UPPERLIMIT, false);
    1552             :     
    1553           0 :     rec.setComment(RF_SPWID,"Restrict flagging to specific spectral windows (integers)");
    1554           0 :     rec.setComment(RF_FIELD,"Restrict flagging to specific field IDs or field names (integers/strings)");
    1555           0 :     rec.setComment(RF_FREQS,"Restrict flagging to specific frequency ranges (2,N array of doubles:MHz)");
    1556           0 :     rec.setComment(RF_CHANS,"Restrict flagging to specific channels (2,N array of integers)");
    1557           0 :     rec.setComment(RF_CORR,"Restrict flagging to specific correlations (array of strings)");
    1558           0 :     rec.setComment(RF_ANT,"Restrict flagging to specific antennas (array of strings/integers)");
    1559           0 :     rec.setComment(RF_BASELINE,"Restrict flagging to specific baselines (array of strings, e.g., 'A1-A2','A1-*', or 2,N array of integers [[A1,A2],[B1,B2],...])");
    1560           0 :     rec.setComment(RF_TIMERANGE,"Restrict flagging to specific time ranges (2,N array of strings or MJDs");
    1561           0 :     rec.setComment(RF_AUTOCORR,"Flag autocorrelations (F/T)");
    1562           0 :     rec.setComment(RF_CENTERTIME,"Flag specific timeslots (array of strings or MJDs)");
    1563           0 :     rec.setComment(RF_TIMEDELTA,String("Time delta for ")+RF_CENTERTIME+", in seconds");
    1564           0 :     rec.setComment(RF_QUACK,"Use [SI,DT] for VLA quack-flagging");
    1565           0 :     rec.setComment(RF_CLIP,"Flag outside a specific range of values");
    1566           0 :     rec.setComment(RF_CHANAVG, "Flag based on channel average");
    1567           0 :     rec.setComment(RF_FLAGRANGE,"Flag inside a specific range of values");
    1568           0 :     rec.setComment(RF_UNFLAG,"If T, specified flags are CLEARED");
    1569           0 :     rec.setComment(RF_SHADOW, "If T, flag shadowed antennas");
    1570           0 :     rec.setComment(RF_ELEVATION, "If T, flag based on elevation");
    1571           0 :     rec.setComment(RF_SCAN,"Restrict flagging to specific scans (integers)");
    1572           0 :     rec.setComment(RF_INTENT,"Restrict flagging to specific scan intent -corresponding state IDs (integers)");
    1573           0 :     rec.setComment(RF_ARRAY,"Restrict flagging to specific array ids (integers)");
    1574           0 :     rec.setComment(RF_FEED,"Restrict flagging to specific feeds (2,N array of integers)");
    1575           0 :     rec.setComment(RF_UVRANGE,"Restrict flagging to specific uv-distance ranges in meters (2,N array of doubles )");
    1576           0 :     rec.setComment(RF_COLUMN,"Data column to clip on.");
    1577           0 :     rec.setComment(RF_DIAMETER, "Effective diameter to use. If negative, the true antenna diameters are used");
    1578           0 :     rec.setComment(RF_LOWERLIMIT, "Limiting elevation");
    1579           0 :     rec.setComment(RF_UPPERLIMIT, "Limiting elevation");
    1580             :   }
    1581           0 :   return rec;
    1582             : }
    1583             : 
    1584             : } //# NAMESPACE CASA - END
    1585             : 

Generated by: LCOV version 1.16