LCOV - code coverage report
Current view: top level - atnf/atca - ATCAFiller.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 1605 0.0 %
Date: 2024-10-04 18:58:15 Functions: 0 40 0.0 %

          Line data    Source code
       1             : //# ATCAFiller.cc: ATCA filler - reads rpfits, creates MeasurementSet
       2             : //# Copyright (C) 2004
       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: casa-feedback@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             : 
      27             : 
      28             : #include <atnf/atca/ATCAFiller.h>
      29             : #include <atnf/atca/ATAtmosphere.h>
      30             : #include <casacore/casa/Arrays/Cube.h>
      31             : #include <casacore/casa/Utilities/GenSort.h>
      32             : #include <casacore/scimath/Mathematics/FFTServer.h>
      33             : #include <casacore/casa/OS/DirectoryIterator.h>
      34             : #include <casacore/casa/OS/RegularFile.h>
      35             : #include <casacore/tables/Tables.h>
      36             : #include <atnf/rpfits/RPFITS.h>
      37             : #include <casacore/ms/MeasurementSets/MSTileLayout.h>
      38             : 
      39             : using namespace casacore;
      40             : namespace casa {
      41             : 
      42           0 : Int myround(Double x) { return Int(floor(x+0.5));}
      43             : 
      44           0 : ATCAFiller::ATCAFiller():
      45           0 : appendMode_p(false),
      46           0 : storedHeader_p(false),
      47           0 : skipScan_p(false),
      48           0 : skipData_p(false),
      49           0 : firstHeader_p(false),
      50           0 : listHeader_p(false),
      51           0 : fileSize_p(0),
      52           0 : birdie_p(false),
      53           0 : reweight_p(false),
      54           0 : noxycorr_p(false),
      55           0 : obsType_p(0),
      56           0 : hires_p(false),
      57           0 : init_p(false),
      58           0 : lastUT_p(0),
      59           0 : bandWidth1_p(0),
      60           0 : numChan1_p(0),
      61           0 : shadow_p(0),
      62           0 : autoFlag_p(true),
      63           0 : flagScanType_p(false),
      64           0 : flagCount_p(NFLAG,0)
      65           0 : {}
      66             : 
      67           0 : ATCAFiller::~ATCAFiller() 
      68           0 : {}
      69             : 
      70           0 : Bool ATCAFiller::open(const String& msName, const Vector<String>& rpfitsFiles,
      71             :                       const Vector<String>& options, Int opcor)
      72             : 
      73             : {
      74             :   Int opt;
      75             : 
      76           0 :   LogOrigin orig("ATCAFiller", "open()", WHERE);
      77           0 :   os_p = LogIO(orig);  
      78           0 :   rpfitsFiles_p = Directory::shellExpand(rpfitsFiles, false);
      79           0 :   GenSort<String>::sort(rpfitsFiles_p);
      80           0 :   if (rpfitsFiles_p.nelements() > 0) {
      81           0 :      os_p << LogIO::NORMAL << "Expanded file names are : " << endl;
      82           0 :      for (uInt i=0; i<rpfitsFiles_p.nelements(); i++) {
      83           0 :        if (rpfitsFiles_p(i).empty()) {
      84           0 :           os_p << "Input file number " << i+1 << " is empty" << LogIO::EXCEPTION;
      85             :        }
      86           0 :        os_p << rpfitsFiles_p(i) << endl;
      87             :      }
      88             :   } else {
      89           0 :      os_p << "Input file names vector is empty" << LogIO::EXCEPTION;
      90             :   }
      91           0 :   Vector<String> opts;
      92           0 :   if (options.nelements()==1) {
      93           0 :     opts=stringToVector(options(0),std::regex(" |,"));
      94             :   } else {
      95           0 :     opts=options;
      96             :   }
      97           0 :   opcor_p=opcor;
      98             :   
      99           0 :   Bool compress=false;
     100             :   // cerr<<"options="<<opts<<endl;
     101           0 :   for (opt=0; opt<Int(opts.nelements()); opt++) {
     102           0 :     if (downcase(opts(opt)) == "birdie") {
     103           0 :       birdie_p = true;
     104             :     }
     105           0 :     if (downcase(opts(opt)) == "reweight") {
     106           0 :       reweight_p = true;
     107             :     }
     108           0 :     if (downcase(opts(opt)) == "noxycorr") {
     109           0 :       noxycorr_p = true;
     110             :     }
     111           0 :     if (downcase(opts(opt)) == "compress") {
     112           0 :       compress = true;
     113             :     }
     114           0 :     if (downcase(opts(opt)) == "fastmosaic") {
     115           0 :       obsType_p=1;
     116             :     }
     117           0 :     if (downcase(opts(opt)) == "noautoflag") {
     118           0 :       autoFlag_p=false;
     119             :     }
     120           0 :     if (downcase(opts(opt)) == "hires") {
     121           0 :       hires_p=true;
     122             :     }
     123           0 :     if (downcase(opts(opt)) == "noac") {
     124           0 :       noac_p = true;
     125             :     }
     126             :   }
     127             :   // Check if this is CABB data or old ATCA data by checking the 
     128             :   // INSTRUMENT keyword (ATCA, ATCABB)
     129           0 :   cabb_p = checkCABB(rpfitsFiles_p(0));
     130           0 :   reweight_p = reweight_p && !cabb_p;
     131           0 :   atms_p = makeTable(msName,compress,cabb_p);
     132           0 :   msc_p = new MSColumns(atms_p);
     133           0 :   msScanInfo_p = atms_p.keywordSet().asTable("ATCA_SCAN_INFO");
     134             : 
     135           0 :   String comp;
     136           0 :   if (compress) comp="Comp";
     137           0 :   dataAccessor_p = TiledDataStManAccessor(atms_p,"TiledData"+comp);
     138           0 :   sigmaAccessor_p = TiledDataStManAccessor(atms_p,"TiledSigma");
     139           0 :   flagAccessor_p = TiledDataStManAccessor(atms_p,"TiledFlag");
     140           0 :   flagCatAccessor_p = TiledDataStManAccessor(atms_p,"TiledFlagCategory");
     141             : 
     142           0 :   prev_fieldId_p = -1;
     143           0 :   lastWeatherUT_p=0;
     144           0 :   errCount_p=0;
     145           0 :   init();
     146           0 :   init_p=true;
     147           0 :   return true;
     148           0 : }
     149             : 
     150             : 
     151           0 : TableDesc ATCAFiller::atcaTableDesc(Bool compress)
     152             : {
     153           0 :   TableDesc td = MS::requiredTableDesc();
     154             :   // add the data column
     155           0 :   MS::addColumnToDesc(td,MS::DATA,2);
     156             :   // and its unit
     157           0 :   td.rwColumnDesc(MS::columnName(MS::DATA)).rwKeywordSet().define("UNIT","Jy");
     158           0 :   if (compress) {
     159           0 :     String col = MS::columnName(MS::DATA);
     160           0 :     td.addColumn(ArrayColumnDesc<Int>(col+"_COMPRESSED",
     161             :           "observed data compressed",2));
     162           0 :     td.addColumn(ScalarColumnDesc<Float>(col+"_SCALE"));
     163           0 :     td.addColumn(ScalarColumnDesc<Float>(col+"_OFFSET"));
     164           0 :   }
     165             :       
     166             :   // add ATCA specific columns here..
     167           0 :   MS::addColumnToDesc(td,MS::PULSAR_BIN);
     168             : 
     169           0 :   td.addColumn(ScalarColumnDesc<Int>("ATCA_SYSCAL_ID_ANT1",
     170             :                                      "Index into SysCal table for Antenna1"));
     171           0 :   td.addColumn(ScalarColumnDesc<Int>("ATCA_SYSCAL_ID_ANT2",
     172             :                                      "Index into SysCal table for Antenna2"));
     173             :   // the tiled column indices
     174           0 :   td.addColumn(ScalarColumnDesc<Int>("DATA_HYPERCUBE_ID",
     175             :                                      "Index for Data Tiling"));
     176           0 :   td.addColumn(ScalarColumnDesc<Int>("SIGMA_HYPERCUBE_ID",
     177             :                                      "Index for Sigma Tiling"));
     178           0 :   td.addColumn(ScalarColumnDesc<Int>("FLAG_HYPERCUBE_ID",
     179             :                                      "Index for Flag Tiling"));
     180           0 :   td.addColumn(ScalarColumnDesc<Int>("FLAG_CATEGORY_HYPERCUBE_ID",
     181             :                                      "Index for Flag Category Tiling"));
     182             : 
     183           0 :   return td;
     184           0 : }
     185             : 
     186           0 : MeasurementSet ATCAFiller::makeTable(const String& tableName, Bool compress, 
     187             :     Bool cabb)
     188             : {
     189             :   // make the MeasurementSet Table
     190           0 :   TableDesc atDesc = atcaTableDesc(compress);
     191             : 
     192           0 :   String colData = MS::columnName(MS::DATA);
     193           0 :   String comp1,comp2;
     194           0 :   if (compress) { comp1="Comp"; comp2="_COMPRESSED";}
     195             :   
     196             :   // define tiled hypercube for the data 
     197           0 :   Vector<String> coordColNames(0); //# don't use coord columns
     198           0 :   atDesc.defineHypercolumn("TiledData"+comp1,3,
     199           0 :                            stringToVector(colData+comp2),
     200             :                            coordColNames,
     201           0 :                            stringToVector("DATA_HYPERCUBE_ID"));
     202           0 :   atDesc.defineHypercolumn("TiledSigma",2,
     203           0 :                            stringToVector(MS::columnName(MS::SIGMA)),
     204             :                            coordColNames,
     205           0 :                            stringToVector("SIGMA_HYPERCUBE_ID"));
     206           0 :   atDesc.defineHypercolumn("TiledFlag",3,
     207           0 :                            stringToVector(MS::columnName(MS::FLAG)),
     208             :                            coordColNames,
     209           0 :                            stringToVector("FLAG_HYPERCUBE_ID"));
     210           0 :   atDesc.defineHypercolumn("TiledFlagCategory",4,
     211           0 :                            stringToVector(MS::columnName(MS::FLAG_CATEGORY)),
     212             :                            coordColNames,
     213           0 :                            stringToVector("FLAG_CATEGORY_HYPERCUBE_ID"));
     214             :   
     215           0 :   SetupNewTable newtab(tableName, atDesc, Table::New);  
     216             :   
     217             :   // Set the default Storage Manager to be the incremental one
     218           0 :   IncrementalStMan incrStMan ("IncrementalData");
     219           0 :   newtab.bindAll(incrStMan, true);
     220             :   // Make an exception for fast varying data
     221           0 :   StandardStMan stStMan ("StandardData");
     222           0 :   newtab.bindColumn(MS::columnName(MS::UVW),stStMan);
     223           0 :   newtab.bindColumn(MS::columnName(MS::ANTENNA2),stStMan);
     224           0 :   newtab.bindColumn("ATCA_SYSCAL_ID_ANT2",stStMan);
     225           0 :   if (compress) {
     226           0 :     newtab.bindColumn(colData+"_SCALE",stStMan);
     227           0 :     newtab.bindColumn(colData+"_OFFSET",stStMan);
     228             :   }
     229             :   
     230             :     
     231           0 :   TiledDataStMan tiledStMan1("TiledData"+comp1);
     232             :   // Bind the DATA & FLAG column to the tiled stman
     233           0 :   newtab.bindColumn(MS::columnName(MS::DATA)+comp2,tiledStMan1);
     234           0 :   newtab.bindColumn("DATA_HYPERCUBE_ID",tiledStMan1);
     235           0 :   if (compress) {;
     236           0 :     CompressComplex ccData(colData,colData+"_COMPRESSED",
     237           0 :       colData+"_SCALE",colData+"_OFFSET", true);
     238           0 :     newtab.bindColumn(MS::columnName(MS::DATA),ccData);
     239           0 :   }
     240             :   
     241           0 :   TiledDataStMan tiledStMan2("TiledSigma");
     242             :   // Bind the SIGMA column to its own tiled stman
     243           0 :   newtab.bindColumn(MS::columnName(MS::SIGMA),tiledStMan2);
     244           0 :   newtab.bindColumn("SIGMA_HYPERCUBE_ID",tiledStMan2);
     245             : 
     246           0 :   TiledDataStMan tiledStMan3("TiledFlag");
     247             :   // Bind the FLAG column to its own tiled stman
     248           0 :   newtab.bindColumn(MS::columnName(MS::FLAG),tiledStMan3);
     249           0 :   newtab.bindColumn("FLAG_HYPERCUBE_ID",tiledStMan3);
     250             : 
     251           0 :   TiledDataStMan tiledStMan3c("TiledFlagCategory");
     252             :   // Bind the FLAG_CATEGORY column to its own tiled stman
     253           0 :   newtab.bindColumn(MS::columnName(MS::FLAG_CATEGORY),tiledStMan3c);
     254           0 :   newtab.bindColumn("FLAG_CATEGORY_HYPERCUBE_ID",tiledStMan3c);
     255             : 
     256             : 
     257             :   // create the table (with 0 rows)
     258           0 :   MeasurementSet ms(newtab, 0);
     259             :   // create the subtables
     260           0 :   makeSubTables(ms, Table::New, cabb);
     261             :   
     262           0 :   return ms;
     263           0 : }
     264             : 
     265           0 : void ATCAFiller::makeSubTables(MS& ms, Table::TableOption option, Bool cabb)
     266             : {
     267             :   // This routine is modeled after MS::makeDummySubtables
     268             :   // we make new tables with 0 rows
     269           0 :   Int nrow=0;
     270             : 
     271             :   // Set up the subtables for the ATCA MS
     272             : 
     273             :   // Antenna
     274           0 :   TableDesc antTD=MSAntenna::requiredTableDesc();
     275           0 :   MSAntenna::addColumnToDesc(antTD, MSAntenna::PHASED_ARRAY_ID);
     276           0 :   MSAntenna::addColumnToDesc(antTD, MSAntenna::ORBIT_ID);
     277           0 :   SetupNewTable antennaSetup(ms.antennaTableName(),antTD,option);
     278           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::ANTENNA), 
     279           0 :                                 Table(antennaSetup,nrow));
     280             : 
     281             :   // Data descr
     282           0 :   TableDesc datadescTD=MSDataDescription::requiredTableDesc();
     283           0 :   SetupNewTable datadescSetup(ms.dataDescriptionTableName(),datadescTD,option);
     284           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::DATA_DESCRIPTION), 
     285           0 :                                 Table(datadescSetup,nrow));
     286             : 
     287             :   // Feed
     288           0 :   TableDesc feedTD=MSFeed::requiredTableDesc();
     289           0 :   MSFeed::addColumnToDesc(feedTD, MSFeed::PHASED_FEED_ID);
     290           0 :   SetupNewTable feedSetup(ms.feedTableName(),feedTD,option);
     291           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::FEED), 
     292           0 :                                 Table(feedSetup,nrow));
     293             : 
     294             :   // Field
     295           0 :   TableDesc fieldTD=MSField::requiredTableDesc();
     296           0 :   SetupNewTable fieldSetup(ms.fieldTableName(),fieldTD,option);
     297           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::FIELD), 
     298           0 :                                 Table(fieldSetup,nrow));
     299             : 
     300             :   // Flag_cmd
     301           0 :   TableDesc flagcmdTD=MSFlagCmd::requiredTableDesc();
     302           0 :   SetupNewTable flagcmdSetup(ms.flagCmdTableName(),flagcmdTD,option);
     303           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::FLAG_CMD), 
     304           0 :                                 Table(flagcmdSetup,nrow));
     305             : 
     306             : 
     307             :   // Observation
     308           0 :   TableDesc obsTD=MSObservation::requiredTableDesc();
     309           0 :   SetupNewTable observationSetup(ms.observationTableName(),obsTD,option);
     310           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::OBSERVATION), 
     311           0 :                                 Table(observationSetup,nrow));
     312             : 
     313             :   // History
     314           0 :   TableDesc historyTD=MSHistory::requiredTableDesc();
     315           0 :   SetupNewTable historySetup(ms.historyTableName(),historyTD,option);
     316           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::HISTORY), 
     317           0 :                                 Table(historySetup,nrow));
     318             : 
     319             :   // Pointing
     320           0 :   TableDesc pointingTD=MSPointing::requiredTableDesc();
     321           0 :   MSPointing::addColumnToDesc(pointingTD, MSPointing::POINTING_OFFSET);
     322           0 :   SetupNewTable pointingSetup(ms.pointingTableName(),pointingTD,option);
     323             :   // Pointing table can be large, set some sensible defaults for storageMgrs
     324           0 :   IncrementalStMan ismPointing ("ISMPointing");
     325           0 :   StandardStMan ssmPointing("SSMPointing",32768);
     326           0 :   pointingSetup.bindAll(ismPointing,true);
     327           0 :   pointingSetup.bindColumn(MSPointing::columnName(MSPointing::ANTENNA_ID),
     328             :                            ssmPointing);
     329           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::POINTING), 
     330           0 :                                 Table(pointingSetup,nrow));
     331             : 
     332             :   // Polarization
     333           0 :   TableDesc polTD=MSPolarization::requiredTableDesc();
     334           0 :   SetupNewTable polSetup(ms.polarizationTableName(),polTD,option);
     335           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::POLARIZATION), 
     336           0 :                                 Table(polSetup,nrow));
     337             : 
     338             :   // Processor
     339           0 :   TableDesc processorTD=MSProcessor::requiredTableDesc();
     340           0 :   SetupNewTable processorSetup(ms.processorTableName(),processorTD,option);
     341           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::PROCESSOR), 
     342           0 :                                 Table(processorSetup,nrow));
     343             : 
     344             :   // Source
     345           0 :   TableDesc sourceTD=MSSource::requiredTableDesc();
     346           0 :   MSSource::addColumnToDesc(sourceTD, MSSource::SYSVEL);
     347           0 :   MSSource::addColumnToDesc(sourceTD, MSSource::NUM_LINES);
     348           0 :   MSSource::addColumnToDesc(sourceTD, MSSource::TRANSITION);
     349           0 :   MSSource::addColumnToDesc(sourceTD, MSSource::REST_FREQUENCY);
     350             :   
     351           0 :   SetupNewTable sourceSetup(ms.sourceTableName(),sourceTD,option);
     352           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::SOURCE),
     353           0 :                                 Table(sourceSetup,nrow));
     354             :   
     355             : 
     356             :   // SpectralWindow
     357           0 :   TableDesc spwTD=MSSpectralWindow::requiredTableDesc();
     358           0 :   if (!cabb) spwTD.addColumn(ScalarColumnDesc<Int>("ATCA_SAMPLER_BITS",
     359             :                                         "Number of bits used for sampling"));
     360           0 :   SetupNewTable spectralWindowSetup(ms.spectralWindowTableName(),spwTD,option);
     361           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::SPECTRAL_WINDOW),  
     362           0 :                                 Table(spectralWindowSetup,nrow));
     363             : 
     364             :   // State
     365           0 :   TableDesc stateTD=MSState::requiredTableDesc();
     366           0 :   SetupNewTable stateSetup(ms.stateTableName(),stateTD,option);
     367           0 :   ms.rwKeywordSet().defineTable(MS::keywordName(MS::STATE),
     368           0 :                                 Table(stateSetup,nrow));
     369             : 
     370             :   // SysCal
     371           0 :   TableDesc sysCalTD=MSSysCal::requiredTableDesc();
     372           0 :   Vector<String> cols(4);
     373           0 :   if (!cabb) {
     374           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     375             :                        ("ATCA_SAMP_STATS_NEG",
     376             :                         "Sampler statistics, negative level",
     377           0 :                         IPosition(1,2),ColumnDesc::Direct));
     378           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     379             :                        ("ATCA_SAMP_STATS_ZERO",
     380             :                         "Sampler statistics, zero level",
     381           0 :                         IPosition(1,2),ColumnDesc::Direct));
     382           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     383             :                        ("ATCA_SAMP_STATS_POS",
     384             :                         "Sampler statistics, positive level",
     385           0 :                         IPosition(1,2),ColumnDesc::Direct));
     386           0 :     cols(1)="ATCA_SAMP_STATS_NEG";
     387           0 :     cols(2)="ATCA_SAMP_STATS_ZERO";
     388           0 :     cols(3)="ATCA_SAMP_STATS_POS";
     389             :   } else {
     390           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     391             :                        ("ATCA_GTP",
     392             :                         "Noise Cal On+Off Autocorrelation",
     393           0 :                         IPosition(1,2),ColumnDesc::Direct));
     394           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     395             :                        ("ATCA_SDO",
     396             :                         "Noise Cal On-Off Autocorrelation",
     397           0 :                         IPosition(1,2),ColumnDesc::Direct));
     398           0 :     sysCalTD.addColumn(ArrayColumnDesc<Float>
     399             :                        ("ATCA_CALJY",
     400             :                         "Calibration factor",
     401           0 :                         IPosition(1,2),ColumnDesc::Direct));
     402             :   
     403           0 :     cols(1)="ATCA_GTP";
     404           0 :     cols(2)="ATCA_SDO";
     405           0 :     cols(3)="ATCA_CALJY";
     406             :   }
     407           0 :   sysCalTD.addColumn(ScalarColumnDesc<Float>
     408             :                      ("ATCA_XY_AMPLITUDE",
     409             :                       "Noise source cross correlation amplitude"));
     410           0 :   sysCalTD.addColumn(ScalarColumnDesc<Float>
     411             :                      ("ATCA_TRACK_ERR_MAX",
     412             :                       "Max tracking error over non blanked cycle"));
     413           0 :   TableQuantumDesc tqd1(sysCalTD,"ATCA_TRACK_ERR_MAX",Unit("arcsec"));
     414           0 :   tqd1.write(sysCalTD);
     415           0 :   sysCalTD.addColumn(ScalarColumnDesc<Float>
     416             :                      ("ATCA_TRACK_ERR_RMS",
     417             :                       "RMS tracking error over non blanked cycle"));
     418           0 :   TableQuantumDesc tqd2(sysCalTD,"ATCA_TRACK_ERR_RMS",Unit("arcsec"));
     419           0 :   tqd2.write(sysCalTD);
     420             :  
     421           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TSYS,
     422           0 :                                IPosition(1, 2), ColumnDesc::Direct);
     423           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TCAL,
     424           0 :                                IPosition(1, 2), ColumnDesc::Direct);
     425           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TRX,
     426           0 :                                IPosition(1, 2),ColumnDesc::Direct);
     427           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TSYS_FLAG);
     428           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::PHASE_DIFF);
     429           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::PHASE_DIFF_FLAG);
     430           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TCAL_FLAG);
     431           0 :   MSSysCal::addColumnToDesc(sysCalTD, MSSysCal::TRX_FLAG);
     432           0 :   cols(0) = MSSysCal::columnName(MSSysCal::TSYS);
     433           0 :   sysCalTD.defineHypercolumn("TiledSysCal",2,cols);
     434           0 :   SetupNewTable sysCalSetup(ms.sysCalTableName(),sysCalTD,option);
     435           0 :   IncrementalStMan incStMan;
     436           0 :   sysCalSetup.bindAll(incStMan);
     437           0 :   TiledColumnStMan tiledStManSysCal("TiledSysCal",IPosition(2,2,1024));
     438             :   
     439           0 :   for (uInt i=0; i<cols.nelements(); i++) {
     440           0 :     sysCalSetup.bindColumn(cols(i),tiledStManSysCal);
     441             :   }
     442           0 :   ms.rwKeywordSet().defineTable(ms.keywordName(MS::SYSCAL), 
     443           0 :                                 Table(sysCalSetup,nrow));
     444             : 
     445             :   // Weather
     446           0 :   TableDesc weatherTD=MSWeather::requiredTableDesc();
     447           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::PRESSURE);
     448           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::REL_HUMIDITY);
     449           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::TEMPERATURE);
     450           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::WIND_DIRECTION);
     451           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::WIND_SPEED);
     452           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::PRESSURE_FLAG);
     453           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::REL_HUMIDITY_FLAG);
     454           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::TEMPERATURE_FLAG);
     455           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::WIND_DIRECTION_FLAG);
     456           0 :   MSWeather::addColumnToDesc(weatherTD,MSWeather::WIND_SPEED_FLAG);
     457           0 :   weatherTD.addColumn(ScalarColumnDesc<Float>
     458             :                      ("ATCA_RAIN_GAUGE",
     459             :                       "Rain since 10am local time"));
     460           0 :   TableQuantumDesc tqds0(weatherTD,"ATCA_RAIN_GAUGE",Unit("mm"));
     461           0 :   tqds0.write(weatherTD);
     462           0 :   weatherTD.addColumn(ScalarColumnDesc<Float>
     463             :                      ("ATCA_SEEMON_PHASE",
     464             :                       "Seeing monitor raw phase at 22GHz"));
     465           0 :   TableQuantumDesc tqds1(weatherTD,"ATCA_SEEMON_PHASE",Unit("rad"));
     466           0 :   tqds1.write(weatherTD);
     467           0 :   weatherTD.addColumn(ScalarColumnDesc<Float>
     468             :                      ("ATCA_SEEMON_RMS",
     469             :                       "Seeing monitor RMS phase"));
     470           0 :   TableQuantumDesc tqds2(weatherTD,"ATCA_SEEMON_RMS",Unit("mm"));
     471           0 :   tqds2.write(weatherTD);
     472           0 :   weatherTD.addColumn(ScalarColumnDesc<Bool>
     473             :                      ("ATCA_SEEMON_FLAG",
     474             :                       "Seeing monitor flag"));
     475           0 :   SetupNewTable weatherSetup(ms.weatherTableName(),weatherTD,option);
     476           0 :   ms.rwKeywordSet().defineTable(ms.keywordName(MS::WEATHER), 
     477           0 :                                 Table(weatherSetup,nrow));
     478             : 
     479             :   // ATCA_SCAN_INFO
     480           0 :   TableDesc atsiTD;
     481           0 :   atsiTD.addColumn(ScalarColumnDesc<Int>("ANTENNA_ID",
     482             :                                          "Antenna Id"));
     483           0 :   atsiTD.addColumn(ScalarColumnDesc<Int>("SCAN_ID",
     484             :                                          "Scan number from main table"));
     485           0 :   atsiTD.addColumn(ScalarColumnDesc<Int>("SPECTRAL_WINDOW_ID",
     486             :                                          "Spectral window Id"));
     487           0 :   atsiTD.addColumn(ArrayColumnDesc<Int>("FINE_ATTENUATOR",
     488             :                                         "Fine Attenuator setting A,B",
     489           0 :                                          IPosition(1,2),ColumnDesc::Direct));
     490           0 :   atsiTD.addColumn(ArrayColumnDesc<Int>("COARSE_ATTENUATOR",
     491             :                                         "COARSE Attenuator setting A,B",
     492           0 :                                          IPosition(1,2),ColumnDesc::Direct));
     493           0 :   atsiTD.addColumn(ArrayColumnDesc<Int>("MM_ATTENUATOR",
     494             :                                         "mm Attenuator setting A,B",
     495           0 :                                          IPosition(1,2),ColumnDesc::Direct));
     496           0 :   atsiTD.addColumn(ArrayColumnDesc<Float>("SUBREFLECTOR",
     497             :                                   "Subreflector position(center,edge/tilt)",
     498           0 :                                          IPosition(1,2),ColumnDesc::Direct));
     499           0 :   TableQuantumDesc tqd3(atsiTD,"SUBREFLECTOR",Unit("m"));
     500           0 :   tqd3.write(atsiTD);
     501           0 :   atsiTD.addColumn(ScalarColumnDesc<String>("CORR_CONFIG",
     502             :                                             "Correlator configuration"));
     503           0 :   atsiTD.addColumn(ScalarColumnDesc<String>("SCAN_TYPE",
     504             :                                             "Scan type"));
     505           0 :   atsiTD.addColumn(ScalarColumnDesc<String>("COORD_TYPE",
     506             :                                             "CAOBS Coordinate type"));
     507           0 :   atsiTD.addColumn(ScalarColumnDesc<String>("POINTING_INFO",
     508             :                                             "Pointing info - details of last point scan"));
     509           0 :   atsiTD.addColumn(ScalarColumnDesc<Bool>("LINE_MODE",
     510             :                                          "Line Mode: true=spectrum, false=mfs"));
     511           0 :   atsiTD.addColumn(ScalarColumnDesc<Int>("CACAL_CNT",
     512             :                                          "Online calibration counter"));
     513             :   
     514           0 :   SetupNewTable scanInfoSetup(ms.tableName()+"/ATCA_SCAN_INFO",atsiTD,option);
     515           0 :   IncrementalStMan incSIStMan("ISMScanInfo");
     516           0 :   StandardStMan stdSIStMan("SSMScanInfo",32768);
     517           0 :   scanInfoSetup.bindAll(incSIStMan);
     518           0 :   scanInfoSetup.bindColumn("ANTENNA_ID",stdSIStMan);
     519           0 :   ms.rwKeywordSet().defineTable("ATCA_SCAN_INFO",  
     520           0 :                                 Table(scanInfoSetup,nrow));
     521             : 
     522             :   // update the references to the subtable keywords
     523           0 :   ms.initRefs();
     524           0 : }
     525             : 
     526             : 
     527           0 : void ATCAFiller::init()
     528             : {
     529             :   //Initialize selection
     530           0 :   scanRange(0, 0);
     531           0 :   freqRange(0.0,1.e30);
     532           0 :   Vector<String> fieldNames(0);
     533           0 :   fields(fieldNames);
     534             :   
     535             :   // extra ID columns in main table
     536           0 :   colSysCalIdAnt1.attach(atms_p,"ATCA_SYSCAL_ID_ANT1");
     537           0 :   colSysCalIdAnt2.attach(atms_p,"ATCA_SYSCAL_ID_ANT2");
     538             : 
     539             :   // extra spectralWindow table columns
     540           0 :   if (!cabb_p) colSamplerBits.attach(atms_p.spectralWindow(),"ATCA_SAMPLER_BITS");
     541             : 
     542             :   // extra syscal table columns
     543           0 :   if (cabb_p) {
     544           0 :     colGTP.attach(atms_p.sysCal(),"ATCA_GTP");
     545           0 :     colSDO.attach(atms_p.sysCal(),"ATCA_SDO");
     546           0 :     colCalJy.attach(atms_p.sysCal(),"ATCA_CALJY");
     547             :   } else {
     548           0 :     colSamplerStatsNeg.attach(atms_p.sysCal(),"ATCA_SAMP_STATS_NEG");
     549           0 :     colSamplerStatsZero.attach(atms_p.sysCal(),"ATCA_SAMP_STATS_ZERO");
     550           0 :     colSamplerStatsPos.attach(atms_p.sysCal(),"ATCA_SAMP_STATS_POS");
     551             :   }
     552             :   // cParAngle.attach(sysCalTable,"ParalAngle");
     553           0 :   colXYAmplitude.attach(atms_p.sysCal(),"ATCA_XY_AMPLITUDE");
     554           0 :   colTrackErrMax.attach(atms_p.sysCal(),"ATCA_TRACK_ERR_MAX");
     555           0 :   colTrackErrRMS.attach(atms_p.sysCal(),"ATCA_TRACK_ERR_RMS");
     556             :   
     557             :   // ScanInfo table columns
     558           0 :   Table sit(atms_p.keywordSet().asTable("ATCA_SCAN_INFO"));
     559           0 :   colScanInfoAntId.attach(sit,"ANTENNA_ID");
     560           0 :   colScanInfoScanId.attach(sit,"SCAN_ID");
     561           0 :   colScanInfoSpWId.attach(sit,"SPECTRAL_WINDOW_ID");
     562           0 :   colScanInfoCacal.attach(sit,"CACAL_CNT");
     563           0 :   colScanInfoFine.attach(sit,"FINE_ATTENUATOR");
     564           0 :   colScanInfoCoarse.attach(sit,"COARSE_ATTENUATOR");
     565           0 :   colScanInfommAtt.attach(sit,"MM_ATTENUATOR");
     566           0 :   colScanInfoSubreflector.attach(sit,"SUBREFLECTOR");
     567           0 :   colScanInfoCorrConfig.attach(sit,"CORR_CONFIG");
     568           0 :   colScanInfoScanType.attach(sit,"SCAN_TYPE");
     569           0 :   colScanInfoCoordType.attach(sit,"COORD_TYPE");
     570           0 :   colScanInfoPointInfo.attach(sit,"POINTING_INFO");
     571           0 :   colScanInfoLineMode.attach(sit,"LINE_MODE");
     572             : 
     573             :   // Extra weather table columns
     574           0 :   colWeatherRainGauge.attach(atms_p.weather(),"ATCA_RAIN_GAUGE");
     575           0 :   colWeatherSeeMonPhase.attach(atms_p.weather(),"ATCA_SEEMON_PHASE");
     576           0 :   colWeatherSeeMonRMS.attach(atms_p.weather(),"ATCA_SEEMON_RMS");
     577           0 :   colWeatherSeeMonFlag.attach(atms_p.weather(),"ATCA_SEEMON_FLAG");
     578             :  
     579           0 :   nScan_p=nSpW_p=nField_p=scanNo_p=0;
     580           0 :   gotAN_p=false;
     581           0 : }
     582             : 
     583             : // list the current scan and return the current day in mjd
     584           0 : void ATCAFiller::listScan(Double & mjd, Int scan, Double ut)
     585             : {
     586             :   // Convert observation date to mjd 
     587             :     Int day,month,year;
     588           0 :     sscanf(names_.datobs,"%4d-%2d-%2d",&year,&month,&day);
     589           0 :     MVTime mjd_date(year,month,(Double)day);
     590           0 :     mjd=mjd_date.second();
     591           0 :     mjd_date=MVTime((mjd_date.second()+ut)/C::day);
     592           0 :     os_p << LogIO::NORMAL << "Scan #   : "<< scan << endl;
     593           0 :     os_p << LogIO::NORMAL << "Object   : "<< String(names_.object,16) << endl;
     594           0 :     os_p << LogIO::NORMAL << "Date     : "<< mjd_date.string(MVTime::YMD) 
     595           0 :          << LogIO::POST;
     596           0 : }
     597             : 
     598             : 
     599           0 : Bool ATCAFiller::fill() {
     600           0 :   if (!init_p) return false;
     601           0 :   if (!appendMode_p) {
     602           0 :     firstHeader_p = true;
     603           0 :     skipScan_p=false;
     604           0 :     skipData_p=false;
     605             : 
     606           0 :     nScan_p=1; // we've seen the 1st header
     607           0 :     scanNo_p=-1; // make zero based for storage in MS
     608             : 
     609             :     Int fileno;
     610           0 :     Int offset=0;
     611             : 
     612           0 :     for (fileno=0; fileno<Int(rpfitsFiles_p.nelements())-offset; fileno++) {
     613           0 :       listHeader_p = true;
     614           0 :       currentFile_p = rpfitsFiles_p(fileno);
     615           0 :       fill1(currentFile_p);
     616             :     }
     617             : 
     618           0 :     os_p << LogIO::DEBUGGING << "FillFeed" << LogIO::POST;
     619           0 :     fillFeedTable();
     620             : 
     621           0 :     fillObservationTable();
     622             : 
     623           0 :     fillMeasureReferences();
     624           0 :     os_p << LogIO::DEBUGGING << "#spectral windows " << nSpW_p << LogIO::POST;
     625             : 
     626             : 
     627             :   } else { // appendMode
     628           0 :     if (!eof_p) { 
     629           0 :       fill1(currentFile_p);
     630             :     } else {
     631             : 
     632           0 :       RegularFile rFile(currentFile_p);
     633           0 :       uInt newSize = rFile.size();
     634           0 :       os_p << LogIO::NORMAL << "new file size " << newSize << LogIO::POST;
     635             :       
     636           0 :       if ( newSize != fileSize_p) {
     637           0 :               fill1(currentFile_p);
     638             :       } else {
     639             :               
     640           0 :         Int jstat=1; // close file
     641           0 :         rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, 
     642             :                   &flg, &bin, &if_no, &sourceno);  
     643             :         
     644           0 :         os_p << LogIO::NORMAL << "Look for next file ..." << LogIO::POST;
     645             :         
     646           0 :         Vector<String> elts=stringToVector(currentFile_p,std::regex("/"));
     647           0 :         String rpfitsDir_p = "";
     648           0 :         if (elts.nelements()>1) {
     649           0 :           Int m = elts.nelements() - 1;
     650           0 :           for (Int n=0; n < m; n++) {
     651           0 :             rpfitsDir_p = rpfitsDir_p + elts(n) + "/";
     652             :           }
     653             :         }
     654           0 :         os_p << LogIO::DEBUGGING << "RPFITSDIR : " << rpfitsDir_p << LogIO::POST;
     655             : 
     656           0 :         Directory dir(rpfitsDir_p);
     657           0 :         Regex regexp(".*\\.[cxv]+[0-9]+");
     658             :         
     659           0 :         DirectoryIterator dirIter(dir, regexp);
     660             :         
     661           0 :         String entry;
     662           0 :         Bool found = false;
     663           0 :         while (!dirIter.pastEnd()) {
     664           0 :           entry = rpfitsDir_p+dirIter.name();
     665           0 :           os_p << LogIO::DEBUGGING << " file: "<< entry << LogIO::POST;
     666           0 :           if (found) break;
     667           0 :           if (entry == currentFile_p) found = true;
     668           0 :           dirIter++;
     669             :         }
     670             :         
     671           0 :         os_p << LogIO::NORMAL << " new file: "<< entry << LogIO::POST;
     672             :         
     673           0 :         if (entry == currentFile_p) {
     674           0 :           os_p << LogIO::NORMAL << " No new file..."<< LogIO::POST;
     675             :         } else {
     676           0 :           String oldstr = String(currentFile_p.at(1, currentFile_p.length()));
     677           0 :           os_p << LogIO::DEBUGGING << " oldstr... "<< oldstr << LogIO::POST;
     678           0 :           String newstr = String(entry.at(1, entry.length()));
     679           0 :           os_p << LogIO::DEBUGGING << " newstr... "<< newstr << LogIO::POST;
     680             :           
     681           0 :           if (oldstr.after(Regex(".*\\.")) != newstr.after(Regex(".*\\."))) {
     682           0 :             os_p << LogIO::NORMAL << " Project changed..."<< LogIO::POST;
     683             :           } else {
     684           0 :             currentFile_p = entry;
     685           0 :             listHeader_p = true;
     686           0 :             fill1(currentFile_p);
     687             :           }
     688           0 :         }
     689           0 :       }
     690           0 :     }
     691             :   }
     692             :   // flag the last integration for shadowing
     693           0 :   if (shadow_p>0) shadow(0,true);
     694             : 
     695             :   // flush the table and unlock it
     696             :   // NOTE: this still keeps a reference to the table which causes problems
     697             :   // when the ms do calls close (it wants to write to the table)
     698           0 :   flush();
     699           0 :   unlock();
     700             : 
     701           0 :   return true;
     702             : }
     703             : 
     704           0 : Bool ATCAFiller::checkCABB(const String& rpfitsFile)
     705             : { 
     706             :   Int jstat;  
     707           0 :   Regex trailing(" *$"); // trailing blanks
     708             : 
     709           0 :   String file = rpfitsFile;
     710           0 :   os_p << LogIO::NORMAL <<"Checking header of file "<<file<< LogIO::POST;
     711           0 :   strcpy(names_.file,file.chars());
     712           0 :   jstat=-2; // open rpfits file and read first header
     713           0 :   param_.ncard=-1; // collect cards into card array
     714           0 :   rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, &flg, &bin,
     715             :             &if_no, &sourceno);  
     716           0 :   if (jstat==-1) {
     717           0 :     os_p << LogIO::SEVERE << " Error opening RPFits file: "<<file
     718           0 :          << LogIO::POST;
     719           0 :     return false;
     720             :   }
     721             :   // read INSTRUMENT keyword
     722           0 :   String instrument = String(names_.instrument,16).before(trailing);
     723             :   // close the file
     724           0 :   jstat=1;
     725           0 :   rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, &flg, &bin,
     726             :             &if_no, &sourceno); 
     727           0 :   if (instrument=="ATCABB") {
     728           0 :     os_p<< LogIO::NORMAL<<"CABB data detected"<<LogIO::POST;
     729           0 :     return true;
     730             :   }
     731           0 :   else return false;  
     732           0 : }
     733             : 
     734           0 : Bool ATCAFiller::fill1(const String& rpfitsFile)
     735             : { 
     736             :   Int jstat;  
     737           0 :   Regex trailing(" *$"); // trailing blanks
     738             : 
     739           0 :   String file = rpfitsFile;
     740           0 :   if (listHeader_p == true) {
     741           0 :     os_p << LogIO::NORMAL <<"Reading file "<<file<< LogIO::POST;
     742           0 :     strcpy(names_.file,file.chars());
     743           0 :     jstat=-2; // open rpfits file and read first header
     744           0 :     param_.ncard=-1; // collect cards into card array
     745           0 :     rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, &flg, &bin,
     746             :               &if_no, &sourceno);  
     747           0 :     if (jstat==-1) {
     748           0 :       os_p << LogIO::SEVERE << " Error opening RPFits file: "<<file
     749           0 :            << LogIO::POST;
     750           0 :       return false;
     751             :     }
     752             :   }
     753             :   // Otherwise we enter fill1 for the second time with the same file name
     754             : 
     755             :   // prepare to read data blocks, rpfitsin will tell us if
     756             :   // there is a header to be read instead
     757           0 :   jstat=0; 
     758             :   
     759           0 :   Double lastUT=0,lastUT2=0;
     760           0 :   Int lastScanNo=-1,lastIF=-1;
     761           0 :   flagCount_p=0;
     762           0 :   while (jstat==0) {
     763           0 :     rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, &flg, &bin,
     764             :                     &if_no, &sourceno);
     765             : 
     766           0 :     switch(jstat) {
     767           0 :     case -1: // read failed
     768           0 :       os_p << LogIO::WARN << 
     769           0 :         "rpfitsin: read failed, retrying"<< LogIO::POST;
     770           0 :       jstat=0;
     771           0 :       break;
     772           0 :     case 0: // found data: store header (incl Tables) and data
     773           0 :       if (listHeader_p) { listScan(mjd0_p,nScan_p,ut); listHeader_p=false;}
     774             : 
     775             :       // do we want this scan?
     776           0 :       if (skipScan_p ||  nScan_p<firstScan_p || 
     777           0 :           (lastScan_p>0 && nScan_p>lastScan_p)) {
     778             :           //if (!skipScan_p) cerr<<"ss1=T"<<endl;
     779           0 :         skipScan_p=true;
     780             :       } else {
     781             :         // if_no and sourceno are not (always) set properly
     782             :         //   for syscal records
     783           0 :         if (baseline==-1) {if_no=1; sourceno=1;} 
     784             : 
     785             :         // check if if_no valid
     786           0 :         if (!if_.if_found|| if_no>if_.n_if) {
     787             :           //if (!skipScan_p)cerr<<"ss2=T"<<endl; 
     788           0 :           skipScan_p=true; 
     789             :           // assume not wanted or ^  garbled data
     790             :         } else {
     791             :           // check if we want this field
     792           0 :           if (lastUT!=ut) {
     793           0 :             String field=String(names_.object,16).before(trailing);
     794           0 :             if (fieldSelection_p.nelements()>0 && fieldSelection_p(0).length()>0 &&
     795           0 :                 !(anyEQ(fieldSelection_p,field))) {
     796             :                 //cerr<< "Field:"<<field<<"-"<<fieldSelection_p.nelements()<<endl;
     797             :                 //if (!skipScan_p) cerr<<"ss3=T"<<endl;
     798           0 :                 skipScan_p=true; 
     799             :             }
     800           0 :           }
     801           0 :           if (!skipScan_p) {
     802           0 :             if_no--; // go from 1-based to 0-based indexing (f2c)
     803           0 :             sourceno--; // same here
     804             :             // skip unselected or garbled data
     805           0 :             skipData_p=Bool(if_no<0 || !selected(if_no) || sourceno<0);
     806             :             // reject auto correlations?
     807           0 :             if (noac_p) skipData_p |= (Int(baseline)%257==0);
     808             :             //cerr<<"SkipData="<<skipData_p<< " ifno="<<if_no<< " sourceno="<<sourceno<<endl;
     809             :           }
     810             :         }
     811             :       }
     812           0 :       if (!skipScan_p && !skipData_p && firstHeader_p && anten_.nant>0) {
     813           0 :         nAnt_p=anten_.nant;
     814           0 :         Int NChan=if_.if_nfreq[if_no];
     815           0 :         Int NPol=if_.if_nstok[if_no];
     816           0 :         firstHeader_p=false;
     817           0 :         os_p << LogIO::NORMAL << " First data/header has NAnt="<<nAnt_p<<
     818           0 :           ", NChan="<<NChan<<", NPol="<<NPol<< LogIO::POST;
     819             :       } 
     820           0 :       if (!skipScan_p && !skipData_p) {
     821           0 :         if (anten_.nant>0 && anten_.nant!=nAnt_p) {
     822           0 :           os_p << LogIO::WARN << "#antennas changed from "<< nAnt_p <<
     823           0 :             " to "<<anten_.nant<<", skipping scan"<< LogIO::POST;
     824             :           //if (!skipScan_p)cerr<<"ss4=T"<<endl;
     825           0 :           skipScan_p=true; 
     826             :         }
     827             :       }
     828           0 :       if (!skipScan_p && !skipData_p && !storedHeader_p) {
     829           0 :         storeHeader();
     830           0 :         scanNo_p++; 
     831           0 :         storedHeader_p=true;
     832             :       }
     833           0 :       if (!skipScan_p) {
     834           0 :         if (baseline==-1) {
     835             :           // we want at least some of the syscal data for this scan
     836           0 :           storeSysCal();
     837             :         }
     838           0 :         else if (!skipData_p) {
     839           0 :           if (lastUT2!=ut || lastIF!=if_no){
     840           0 :             checkSpW(if_no); // we need to check these every integration to
     841           0 :             if (lastUT2!=ut) checkField();// cope with freq. switching and mosaicing
     842           0 :             lastUT2=ut;
     843           0 :             lastIF=if_no;
     844             :           }          
     845           0 :           storeData();
     846             :         }
     847             :       }
     848           0 :       skipData_p=false;
     849           0 :       break;
     850           0 :     case 1:
     851           0 :       if (skipScan_p || scanNo_p==lastScanNo) {
     852             :         //cerr<<"ScanNo_p="<<scanNo_p<<" lastScanNo="<<lastScanNo<<" skipScan_p="<<skipScan_p<<endl;
     853           0 :         os_p << LogIO::NORMAL << "Scan "<<nScan_p <<" skipped"<<LogIO::POST;
     854             :       } else {
     855           0 :         os_p << LogIO::NORMAL << "Scan "<<nScan_p <<" stored"<< LogIO::POST;
     856             :       }
     857           0 :       lastScanNo=scanNo_p;
     858           0 :       nScan_p++;
     859           0 :       errCount_p=0;
     860           0 :       os_p << LogIO::DEBUGGING << "Read new header "<< LogIO::POST;
     861           0 :       jstat=-1;
     862           0 :       param_.ncard=-1;
     863           0 :       rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, 
     864             :                 &flg, &bin, &if_no, &sourceno);  
     865           0 :       jstat=0;
     866             :         
     867           0 :       listScan(mjd0_p,nScan_p,ut);
     868           0 :       storedHeader_p=false;
     869           0 :       skipScan_p=false; //cerr<<"ss=F"<<endl;
     870           0 :       eof_p = false;
     871           0 :       if (!appendMode_p) break;
     872             :         // suppress this break to return after each end of scan
     873             :         // (actually each beginning of a new scan) in on line mode
     874             : 
     875             :     case 3:
     876           0 :       if (jstat == 3) {  // because of the break suppression in case 1
     877           0 :         if (!skipScan_p && !skipData_p && !storedHeader_p) {
     878           0 :           storeHeader(True); // store sole header at end of file
     879           0 :           scanNo_p++;    // to capture last commands & log messages
     880           0 :           storedHeader_p=true;
     881             :         }
     882           0 :         os_p << LogIO::NORMAL << "End of File" << LogIO::POST;
     883           0 :         eof_p = true;
     884           0 :         nScan_p++; // increment for next scan
     885             :         // print flagging stats for last scan
     886           0 :         if (flagCount_p(COUNT)>0) {
     887           0 :           Vector<Float> perc(NFLAG);
     888           0 :           for (Int i=0; i<NFLAG; i++) perc(i)=0.1*((1000*flagCount_p(i))/flagCount_p(COUNT));
     889           0 :           os_p<< LogIO::NORMAL <<"Number of rows selected  : "<<flagCount_p(COUNT)<<endl; 
     890           0 :           os_p<< LogIO::NORMAL <<"Flagged                  : "<<perc(FLAG)<<"%"<<endl; 
     891           0 :           os_p<< LogIO::NORMAL <<"  Antenna off source     : "<<perc(ONLINE)<<"%"<<endl; 
     892           0 :           os_p<< LogIO::NORMAL <<"  ScanType (Point/Paddle): "<<perc(SCANTYPE)<<"%"<<endl; 
     893           0 :           if (!cabb_p) os_p<< LogIO::NORMAL <<"  Bad Sampler stats      : "<<perc(SYSCAL)<<"%"<<endl; 
     894           0 :           if (shadow_p>0) os_p<< LogIO::NORMAL <<"  Antenna shadowed       : "<<perc(SHADOW)<<"%"<<LogIO::POST; 
     895           0 :         }
     896             :       }
     897             :       
     898           0 :       if (appendMode_p) {
     899             :         // after bumping one time at the end of the file or after the
     900             :         // first scan
     901             : 
     902           0 :         RegularFile rFile(file);
     903           0 :         fileSize_p = rFile.size();
     904             : 
     905           0 :         os_p << LogIO::NORMAL << "old file size " << fileSize_p 
     906           0 :              << " Waiting ..." << LogIO::POST;
     907             : 
     908           0 :         flush();
     909           0 :         unlock();
     910             : 
     911           0 :       } else {
     912           0 :         jstat=1; // close file
     913           0 :         rpfitsin_(&jstat, vis, weight, &baseline, &ut, &u, &v, &w, 
     914             :                   &flg, &bin, &if_no, &sourceno);  
     915             :       }
     916           0 :       jstat=1; // exit loop
     917           0 :       break;
     918           0 :     case 4:
     919           0 :       os_p << LogIO::WARN 
     920             :            << "rpfitsin: found FG Table, ignoring it"
     921           0 :            << LogIO::POST;
     922           0 :       jstat=0;
     923           0 :       break;
     924           0 :     case 5:
     925             :       // jstat == 5 is usually record padding at the end of an integration.
     926             :       // just continue on loading..
     927           0 :       jstat=0;
     928           0 :       break;
     929           0 :     default:
     930           0 :       os_p << LogIO::WARN << "unknown rpfitsin return value: "
     931           0 :            <<jstat<< LogIO::POST;
     932           0 :       jstat=0;
     933             :     }
     934           0 :     lastUT=ut;
     935             :   }
     936             : 
     937             :   // uncomment this if things take unexpectedly long
     938             :   // dataAccessor_p.showCacheStatistics(cout);
     939             :   // sigmaAccessor_p.showCacheStatistics(cout);
     940           0 :   return true;
     941           0 : }
     942             : 
     943             : 
     944             : 
     945             : 
     946           0 : void ATCAFiller::fillMeasureReferences() 
     947             : {
     948           0 :   String key("MEASURE_REFERENCE");
     949           0 :   msc_p->time().rwKeywordSet().define(key,"UTC");
     950           0 :   msc_p->uvw().rwKeywordSet().define(key,"J2000");
     951           0 :   msc_p->antenna().position().rwKeywordSet().define(key,"ITRF");
     952           0 :   msc_p->feed().time().rwKeywordSet().define(key,"UTC");
     953           0 :   msc_p->field().time().rwKeywordSet().define(key,"UTC");
     954           0 :   msc_p->field().delayDir().rwKeywordSet().define(key,"J2000");
     955           0 :   msc_p->field().phaseDir().rwKeywordSet().define(key,"J2000");
     956           0 :   msc_p->field().referenceDir().rwKeywordSet().define(key,"J2000");
     957           0 :   msc_p->source().time().rwKeywordSet().define(key,"UTC");
     958           0 :   msc_p->source().direction().rwKeywordSet().define(key,"J2000");
     959           0 :   msc_p->history().time().rwKeywordSet().define(key,"UTC");
     960           0 :   msc_p->spectralWindow().chanFreq().rwKeywordSet().define(key,"TOPO");
     961           0 :   msc_p->spectralWindow().refFrequency().rwKeywordSet().define(key,"TOPO");
     962             :   
     963             :   MFrequency::Types tp;
     964           0 :   MFrequency::getType(tp, msc_p->spectralWindow().refFrequency().keywordSet().asString("MEASURE_REFERENCE"));
     965           0 :   Int meas_freq_ref = tp;
     966           0 :   msc_p->spectralWindow().measFreqRef().fillColumn(meas_freq_ref);
     967           0 :   msc_p->sysCal().time().rwKeywordSet().define(key,"UTC");
     968           0 :   msc_p->weather().time().rwKeywordSet().define(key,"UTC");
     969           0 :   msc_p->pointing().direction().rwKeywordSet().define(key,"J2000");
     970           0 :   msc_p->pointing().pointingOffset().rwKeywordSet().define(key,"AZEL");
     971           0 : }
     972             : 
     973           0 : ATCAFiller & ATCAFiller::scanRange(Int first, Int last)
     974             : {
     975           0 :   firstScan_p=first; 
     976           0 :   lastScan_p=max(0,last);
     977           0 :   return *this;
     978             : }
     979             : 
     980           0 : ATCAFiller & ATCAFiller::freqRange(Double low, Double high)
     981             : { 
     982           0 :   lowFreq_p=low;
     983           0 :   highFreq_p=high;
     984           0 :   return *this;
     985             : }
     986             : 
     987           0 : ATCAFiller & ATCAFiller::freqSel(const Vector<Int>& spws)
     988             : { 
     989           0 :   spws_p=spws;
     990           0 :   return *this;
     991             : }
     992             : 
     993           0 : ATCAFiller & ATCAFiller::fields(const Vector<String>& fieldList)
     994             : {
     995           0 :   fieldSelection_p=fieldList;
     996           0 :   return *this;
     997             : }
     998             : 
     999           0 : ATCAFiller & ATCAFiller::bandwidth1(Int bandwidth1)
    1000             : { 
    1001           0 :   bandWidth1_p=0;
    1002           0 :   for (Int bw=2; bw<=256; bw*=2) {
    1003           0 :     if(bw==bandwidth1) {
    1004           0 :       bandWidth1_p=bw;
    1005           0 :       break;
    1006             :     }
    1007             :   }
    1008           0 :   return *this;
    1009             : }
    1010             : 
    1011           0 : ATCAFiller & ATCAFiller::numChan1(Int numchan1)
    1012             : { 
    1013           0 :   numChan1_p=0;
    1014           0 :   for (Int nchan=32; nchan<=16384; nchan*=2) {
    1015           0 :     if((numchan1==nchan) || (numchan1==(nchan+1))) {
    1016           0 :       numChan1_p=nchan+1;
    1017           0 :       break;
    1018             :     }
    1019             :   }  
    1020           0 :   return *this;
    1021             : }
    1022             : 
    1023           0 : ATCAFiller & ATCAFiller::shadow(Float diam)
    1024             : { 
    1025           0 :   shadow_p=0;
    1026           0 :   if (diam>0) shadow_p=diam;
    1027           0 :   return *this;
    1028             : }
    1029             : 
    1030           0 : ATCAFiller & ATCAFiller::edge(float edge)
    1031             : { 
    1032           0 :   edge_p=edge;
    1033           0 :   return *this;
    1034             : }
    1035             : 
    1036           0 : void ATCAFiller::storeHeader(bool last) {
    1037             :   //  Bool skip=false;
    1038           0 :   Regex trailing(" *$"); // trailing blanks
    1039             : 
    1040             :   // First check antenna Table and store any new stations encountered
    1041           0 :   if (!gotAN_p && anten_.nant>0) {
    1042           0 :     if (anten_.an_found) {
    1043           0 :       gotAN_p=true;
    1044             :       
    1045           0 :       for (Int i=0; i<nAnt_p; i++) {
    1046           0 :         Int ant=Int(anten_.ant_num[i]); // 1-based !
    1047           0 :         if (ant!=i+1) { 
    1048           0 :           os_p << LogIO::SEVERE 
    1049             :                << "AN table corrupt, will try next one " << ant <<":"<<i<<":"<<nAnt_p
    1050           0 :                << LogIO::POST;
    1051           0 :           gotAN_p=false;
    1052           0 :           break;
    1053             :         }
    1054           0 :         atms_p.antenna().addRow();
    1055           0 :         Int n=atms_p.antenna().nrow()-1;
    1056             : 
    1057           0 :         String instrument = String(names_.instrument,16).before(trailing);
    1058           0 :         String station(&names_.sta[i*8],8);
    1059           0 :         os_p << LogIO::NORMAL <<"Antenna  : "<< station << " ";
    1060           0 :         Vector<Double> xyz(3); 
    1061           0 :         xyz(0)=doubles_.x[i];xyz(1)=doubles_.y[i];xyz(2)=doubles_.z[i];
    1062           0 :         os_p << " position:"<<xyz << endl;
    1063           0 :         if (instrument=="ATCA" || cabb_p) {
    1064           0 :           String antName;
    1065             :           // construct antenna name
    1066           0 :           ostringstream ostr; ostr << "CA0" <<i+1;
    1067           0 :           String str = ostr.str();
    1068           0 :           msc_p->antenna().name().put(n,str);
    1069           0 :             msc_p->antenna().station().put(n,atcaPosToStation(xyz));         
    1070           0 :         } else {
    1071           0 :             msc_p->antenna().station().put(n,station.before(trailing));
    1072           0 :             msc_p->antenna().name().put(n,station.before(trailing));
    1073             :         }  
    1074           0 :         msc_p->antenna().orbitId().put(n,-1);
    1075           0 :         msc_p->antenna().phasedArrayId().put(n,-1);
    1076           0 :         msc_p->antenna().dishDiameter().put(n,22.0);
    1077           0 :         msc_p->antenna().type().put(n, "GROUND-BASED");
    1078             : 
    1079           0 :         if (anten_.ant_mount[i]==0) {
    1080           0 :           msc_p->antenna().mount().put(n,"alt-az");
    1081             :         }
    1082             :         else {
    1083           0 :           msc_p->antenna().mount().put(n,"bizarre");
    1084             :         }
    1085           0 :         msc_p->antenna().position().put(n,xyz);
    1086           0 :         Vector<Double> offset(3); offset=0.; 
    1087             :         // todo: figure out coordinate system of offset
    1088           0 :         offset(0)=doubles_.axis_offset[i];
    1089           0 :         msc_p->antenna().offset().put(n,offset);
    1090             :         // todo: values below may have to be stored elsewhere
    1091             :         //Vector<String> ft(2);
    1092             :         //ft(0)=String(&names_.feed_type[i*4],2);
    1093             :         //ft(1)=String(&names_.feed_type[i*4+2],2);
    1094             :         //                cFeedType.put(n,ft);
    1095             :         //Vector<Double> pa(2);
    1096             :         //pa(0)=doubles_.feed_pa[i*2];pa(1)=doubles_.feed_pa[i*2+1];
    1097             :         // cFeedPA.put(n,pa);
    1098             :         //Matrix<Double> feedcal(1,1);//feedcal :split out on if and pol?
    1099             :         //feedcal(0,0)=0.0;
    1100             :         // cFeedCal.put(n,feedcal);
    1101           0 :       }
    1102           0 :       os_p.post();
    1103             :     } else {
    1104           0 :        os_p << LogIO::SEVERE << 
    1105           0 :          "No AN Table found before start of data!"<< LogIO::POST;
    1106             :     }
    1107             :   }
    1108             : 
    1109             :   // Check if current if_no already in SpW Table, add it if not.
    1110           0 :   if (!last) checkSpW(if_no);
    1111             :   
    1112             :   // Check if current Observation info already stored, add it if not
    1113           0 :   checkObservation();
    1114             :   
    1115             :   // Store the ATCA header cards
    1116           0 :   storeATCAHeader(last);
    1117             : 
    1118             :   // Check if we've seen current source before, if not add to table
    1119           0 :   if (!last) checkField();
    1120           0 : }
    1121             : 
    1122           0 : void ATCAFiller::storeATCAHeader(Bool last) {
    1123           0 :   uInt ncard = abs(param_.ncard);
    1124             :   //cout<<" #cards = "<<ncard<<endl;
    1125           0 :   String cards = String(names_.card,ncard*80);
    1126           0 :   const Int nTypes = 10;
    1127           0 :   Block<String> types(nTypes);
    1128           0 :   types[0]=  "OBSLOG";
    1129           0 :   types[1] = "ATTEN";
    1130           0 :   types[2] = "SUBREFL";
    1131           0 :   types[3] = "CORR_CFG";
    1132           0 :   types[4] = "SCANTYPE";
    1133           0 :   types[5] = "COORDTYP";
    1134           0 :   types[6] = "LINEMODE";
    1135           0 :   types[7] = "CACALCNT";
    1136           0 :   types[8] = "POINTCOR";
    1137           0 :   types[9] = "POINTINF";
    1138           0 :   String obsLog = "";
    1139           0 :   String config = "none";
    1140           0 :   const Int nIF = if_.n_if;
    1141           0 :   const Int nAnt = anten_.nant;
    1142           0 :   Cube<Int> fine(2,nIF,nAnt,0),coarse(2,nIF,6,0);
    1143           0 :   Matrix<Int> mmAtt(nIF,nAnt,0);
    1144           0 :   Vector<Float> subrPos(nAnt,0),subrTilt(nAnt,0);
    1145           0 :   Matrix<Float> pointCorr(2,nAnt,0);
    1146           0 :   newPointingCorr_p=false;
    1147           0 :   flagScanType_p=false;
    1148           0 :   String scanType,coordType,pointInfo;
    1149           0 :   Vector<Bool> lineMode(nIF);
    1150           0 :   Int cacalCnt=0;
    1151           0 :   const Regex trailing(" *$"); // trailing blanks
    1152           0 :   Bool foundAny = false;
    1153           0 :   String::size_type pos=cards.find("EPHEM12"); // last 'standard' card
    1154             :   //cout << "pos="<<pos<<" String::npos=="<<String::npos<<endl;
    1155           0 :   if (pos==String::npos) return;
    1156           0 :   uInt iFirst=pos/80+1;
    1157           0 :   for (uInt i=iFirst; i<ncard; i++) {
    1158             :     // extract card
    1159           0 :     String card = cards.substr(i*80,80);
    1160             :     //cout << "card = "<< card<<endl;
    1161             :     // read antenna number (if present)
    1162           0 :     Int ant = 0;
    1163           0 :     pos=card.find("CA0");
    1164           0 :     if (pos!=String::npos) istringstream(card.substr(pos+2,2))>> ant;
    1165           0 :     ant-=1; // zero based indexing
    1166           0 :     if (ant>=nAnt) ant = -1;
    1167           0 :     for (Int j=0; j<nTypes; j++) {
    1168           0 :       if (card.find(types[j])==0) {
    1169           0 :         foundAny=true;
    1170             :         //cout << "Found card :"<<types[j]<<", ant="<<ant<<endl;
    1171           0 :         switch (j) {
    1172           0 :         case 0: obsLog+=card.substr(8,72).before(trailing);
    1173           0 :                 obsLog+="\n";
    1174           0 :                 break;
    1175           0 :         case 1: { //ATTEN
    1176           0 :                   String::size_type pos=card.find("FINE=");
    1177           0 :                   if (pos!=String::npos && ant>=0) {
    1178           0 :                     for (Int k=0; k<nIF; k++) {
    1179           0 :                       istringstream(card.substr(pos+5+k*2,1))>>fine(0,k,ant);
    1180           0 :                       istringstream(card.substr(pos+6+k*2,1))>>fine(1,k,ant);
    1181             :                     }
    1182             :                   }
    1183           0 :                   pos=card.find("COARSE=");
    1184           0 :                   if (pos!=String::npos && ant>=0) {
    1185           0 :                     for (Int k=0; k<nIF; k++) {
    1186           0 :                      istringstream(card.substr(pos+7+k*2,1))>>coarse(0,k,ant);
    1187           0 :                       istringstream(card.substr(pos+8+k*2,1))>>coarse(1,k,ant);
    1188             :                     }
    1189             :                   }
    1190           0 :                   pos=card.find("MM=");
    1191           0 :                   if (pos!=String::npos && ant>=0) {
    1192           0 :                     istringstream(card.substr(pos+3,2))>>mmAtt(0,ant);
    1193           0 :                     istringstream(card.substr(pos+6,2))>>mmAtt(1,ant);
    1194             :                   }
    1195             :                 }
    1196           0 :                 break;
    1197           0 :         case 2: { //SUBREFL
    1198           0 :                   String::size_type pos=card.find("POS=");
    1199           0 :                   if (pos!=String::npos && ant>=0) {
    1200           0 :                     istringstream(card.substr(pos+4,6))>>subrPos(ant);
    1201             :                   }
    1202           0 :                   pos=card.find("TILT=");
    1203           0 :                   if (pos!=String::npos && ant>=0) {
    1204           0 :                     istringstream(card.substr(pos+5,6))>>subrTilt(ant);
    1205             :                   }
    1206             :                 }
    1207           0 :                 break;
    1208           0 :         case 3: {// CORR_CFG
    1209           0 :                   String::size_type pos=card.find("=");
    1210           0 :                   if (pos!=String::npos) {
    1211           0 :                     config=card.substr(pos+3,80-pos-3).before(trailing);
    1212             :                   }
    1213             :                 }
    1214           0 :                 break;
    1215           0 :         case 4: {// SCANTYPE
    1216           0 :                    String::size_type pos=card.find("=");
    1217           0 :                    if (pos!=String::npos) {
    1218           0 :                      scanType=card.substr(pos+2,80-pos-3).before(trailing);
    1219             :                    }
    1220           0 :                    if (scanType=="PADDLE"||scanType=="POINT"||scanType=="XPOINT"
    1221           0 :                        ||scanType=="EARLY") {
    1222           0 :                      flagScanType_p=true;
    1223             :                    }
    1224             :                 }
    1225           0 :                 break;
    1226           0 :         case 5: {// COORDTYP
    1227           0 :                   String::size_type pos=card.find("=");
    1228           0 :                   if (pos!=String::npos) {
    1229           0 :                     coordType=card.substr(pos+2,80-pos-3).before(trailing);
    1230             :                   }
    1231             :                 }
    1232           0 :                 break;
    1233           0 :         case 6: {// LINEMODE
    1234           0 :                   String::size_type pos=card.find("=");
    1235           0 :                   if (pos!=String::npos) {
    1236           0 :                     lineMode(0)=(card[pos+2]=='T');
    1237           0 :                     if (nIF>1) lineMode(1)=(card[pos+4]=='T');
    1238             :                   }
    1239             :                 }
    1240           0 :                 break;
    1241           0 :         case 7: {// CACALCNT
    1242           0 :                   String::size_type pos=card.find("=");
    1243           0 :                   if (pos!=String::npos) {
    1244           0 :                     istringstream(card.substr(pos+1,7))>>cacalCnt;
    1245             :                   }
    1246             :                 }
    1247           0 :                 break;
    1248           0 :         case 8: {// POINTCOR
    1249           0 :                   String::size_type pos=card.find("Az=");
    1250           0 :                   if (pos!=String::npos && ant>=0) {
    1251           0 :                     istringstream(card.substr(pos+3,6))>>pointCorr(0,ant);
    1252           0 :                     newPointingCorr_p=true;
    1253             :                   }
    1254           0 :                   pos=card.find("El=");
    1255           0 :                   if (pos!=String::npos && ant>=0) {
    1256           0 :                     istringstream(card.substr(pos+3,6))>>pointCorr(1,ant);
    1257           0 :                     newPointingCorr_p=true;
    1258             :                   }
    1259             :                 }
    1260           0 :                 break;
    1261           0 :         case 9: {// POINTINF
    1262           0 :                   pointInfo = card.substr(9).before(trailing);
    1263             :                 }
    1264           0 :                 break;
    1265           0 :         default:
    1266           0 :                 cerr << "Missing SCAN_INFO card type in switch statement"<<endl;
    1267             :         }
    1268             :         //cout <<" Match: cardname = "<<types[j]<<" : "<<card<<endl;
    1269             :       }
    1270             :     }
    1271           0 :   }
    1272           0 :   if (!foundAny) return;
    1273           0 :   Vector<String> tmp;
    1274           0 :   if (msc_p->observation().log().isDefined(obsId_p)) {
    1275           0 :     tmp=msc_p->observation().log()(obsId_p);
    1276             :   }
    1277           0 :   if (tmp.nelements()==0) tmp.resize(1);
    1278           0 :   Int index=tmp.nelements()-1;
    1279           0 :   tmp(index)+=obsLog;
    1280           0 :   msc_p->observation().log().put(obsId_p,tmp);
    1281           0 :   if ((nAnt*nIF)==0 || last) return;
    1282             : 
    1283             :   // find out spectral window index of IFs
    1284           0 :   Vector<Int> spwId(nIF,-1);
    1285           0 :   if (if_no>=0) spwId(if_no)=spWId_p;
    1286           0 :   if (nIF>1) {
    1287           0 :     for (Int ifNum=0; ifNum<nIF; ifNum++) {
    1288           0 :       if (ifNum!=if_no) {
    1289           0 :         if (selected(ifNum)) spwId(ifNum)=checkSpW(ifNum);
    1290             :       }
    1291             :     }
    1292             :   }
    1293             :   // reset to original spW
    1294           0 :   if (if_no>0) checkSpW(if_no);
    1295             :   
    1296           0 :   Int row=msScanInfo_p.nrow();
    1297           0 :   msScanInfo_p.addRow(nAnt*nIF);
    1298           0 :   colScanInfoScanId.put(row,scanNo_p+1);
    1299           0 :   colScanInfoCacal.put(row,cacalCnt);
    1300           0 :   colScanInfoCorrConfig.put(row,config);
    1301           0 :   colScanInfoScanType.put(row,scanType);
    1302           0 :   colScanInfoCoordType.put(row,coordType);
    1303           0 :   colScanInfoPointInfo.put(row,pointInfo);
    1304           0 :   if (newPointingCorr_p) { 
    1305           0 :     pointingCorr_p.reference(pointCorr);
    1306             :   } else {
    1307           0 :     pointingCorr_p.resize(0,0);
    1308             :   }
    1309             :      
    1310           0 :   Vector<Int> f(2),c(2),m(2);
    1311           0 :   Vector<Float> sr(2);
    1312           0 :   for (Int i=0; i<nIF; i++) {
    1313           0 :     colScanInfoSpWId.put(row,spwId(i));
    1314           0 :     colScanInfoLineMode.put(row,lineMode(i));
    1315           0 :     for (Int ant=0; ant<nAnt; ant++) {
    1316           0 :       colScanInfoAntId.put(row,ant);
    1317           0 :       if (!cabb_p) {
    1318           0 :         f(0)=fine(0,i,ant); f(1)=fine(1,i,ant);
    1319           0 :         c(0)=coarse(0,i,ant); c(1)=coarse(1,i,ant);
    1320           0 :         colScanInfoFine.put(row,f);
    1321           0 :         colScanInfoCoarse.put(row,c);
    1322             :       }
    1323           0 :       m(0)=mmAtt(0,ant); m(1)=mmAtt(1,ant);
    1324           0 :       colScanInfommAtt.put(row,m);
    1325           0 :       sr(0)=subrPos(ant)/1000.0; sr(1)=subrTilt(ant)/1000.; // convert to meter
    1326           0 :       colScanInfoSubreflector.put(row,sr);
    1327           0 :       row++;
    1328             :     }
    1329             :   }
    1330           0 : }
    1331             : 
    1332           0 : String ATCAFiller::atcaPosToStation(Vector<Double>& xyz) {
    1333           0 :   String station("NONE");
    1334             :   // determine station from xyz position
    1335             :   // Use W106 as reference
    1336           0 :   Double x106 = -4751615.0l;
    1337           0 :   Double y106 = 2791719.246l;
    1338           0 :   Double z106 = -3200483.747l;
    1339           0 :   Double incr = 6000.0l/392;
    1340           0 :   Bool north = (xyz(2)-z106)>1.0;
    1341           0 :   Bool east = (xyz(0)-x106)<1.0;
    1342           0 :   Int n = Int(floor(0.5l+
    1343           0 :                     sqrt((xyz(0)-x106)*(xyz(0)-x106)+
    1344           0 :                          (xyz(1)-y106)*(xyz(1)-y106)+
    1345           0 :                          (xyz(2)-z106)*(xyz(2)-z106))/incr));
    1346           0 :   Bool invalid = (n>392);
    1347           0 :   if (!invalid) {
    1348           0 :     if (north) {
    1349           0 :       ostringstream ostr; ostr << "N"<<n;
    1350           0 :       station = ostr.str();
    1351           0 :     } else {
    1352           0 :       if (east) n = 106 -n; else n += 106;
    1353           0 :       ostringstream ostr; ostr << "W"<<n;
    1354           0 :       station = ostr.str();  
    1355           0 :     }
    1356             :   }   
    1357           0 :   return station;
    1358           0 : }
    1359             : 
    1360           0 : Int ATCAFiller::checkSpW(Int ifNumber,Bool log) {
    1361             :   // Check if current if_no already in SpW Table
    1362             :   // Add it if not, set SpWId_p index for our SpW Table
    1363             :   // NOTE we should use ddId instead of SpWid everywhere, for now
    1364             :   // we create one SpWId per ddId so they always match, this may result
    1365             :   // in duplicate spw rows if only the pol info changed..
    1366           0 :   Regex trailing(" *$"); // trailing blanks
    1367           0 :   if (if_.if_found) {
    1368           0 :     spWId_p=-1;
    1369           0 :     for (Int i=0; i<nSpW_p; i++) {
    1370           0 :       Double freq = msc_p->spectralWindow().refFrequency()(i);
    1371           0 :       Double bw = msc_p->spectralWindow().totalBandwidth()(i);
    1372           0 :       Int nchan = msc_p->spectralWindow().numChan()(i);
    1373           0 :       Int polId = msc_p->dataDescription().polarizationId()(i);
    1374           0 :       Int npol = msc_p->polarization().numCorr()(polId);
    1375             :       // compare freq and bw, cope with case where birdie option has reduced bw
    1376           0 :       if (doubles_.if_freq[ifNumber]==freq &&
    1377           0 :                 doubles_.if_bw[ifNumber]>=bw && doubles_.if_bw[ifNumber]<2*bw &&
    1378           0 :                 (if_.if_nfreq[ifNumber] == nchan || (nchan<33 &&
    1379           0 :                  if_.if_nfreq[ifNumber]==33)) && 
    1380           0 :                 if_.if_nstok[ifNumber]==npol) {
    1381           0 :               spWId_p=i; 
    1382           0 :               break;
    1383             :       }
    1384             :     }
    1385           0 :     if (spWId_p<0) { // i.e. not found
    1386           0 :       spWId_p=nSpW_p++;
    1387           0 :       atms_p.spectralWindow().addRow();
    1388           0 :       Int n=atms_p.spectralWindow().nrow()-1;
    1389           0 :       Double refFreq=doubles_.if_freq[ifNumber];
    1390           0 :       msc_p->spectralWindow().refFrequency().put(n,refFreq);
    1391             :       // no doppler tracking
    1392           0 :       Int nchan = if_.if_nfreq[ifNumber];
    1393           0 :       Int npol =if_.if_nstok[ifNumber];
    1394             : 
    1395           0 :       if (log) os_p << LogIO::NORMAL<< 
    1396             :               "IF "<< ifNumber+1 << 
    1397             :               "     : Frequency = "<< refFreq/1.e6 << " MHz" <<
    1398           0 :               ", bandwidth = " << doubles_.if_bw[ifNumber]/1.e6 << "MHz" << 
    1399           0 :               ", #channels = "<< nchan << LogIO::POST;
    1400             : 
    1401           0 :       Double refChan=doubles_.if_ref[ifNumber]-1; // make zero based
    1402           0 :       Double chanSpac = doubles_.if_bw[ifNumber]/max(1,nchan-1);
    1403           0 :       Int inversion=if_.if_invert[ifNumber];
    1404           0 :       msc_p->spectralWindow().netSideband().put(n,inversion);
    1405           0 :       chanSpac*=inversion;
    1406           0 :       Double chanBW = abs(chanSpac);
    1407           0 :       if (!cabb_p && nchan==33) chanBW=chanBW*1.6;  // roughly
    1408           0 :       if (!cabb_p && nchan==65) chanBW=chanBW*1.3;  // guess
    1409             :           
    1410             :       // do birdie check here - reduce number of channels we will store
    1411             :       // for 33 channel data (drop half the channels + edge) and fix
    1412             :       // spw description  
    1413           0 :       if (birdie_p && nchan == 33 && !cabb_p) {
    1414           0 :          Int bchan = birdChan(refFreq/1.e9, (Int)refChan, chanSpac/1.e9);
    1415           0 :          Int edge = 3 + (bchan+1)%2;
    1416           0 :          nchan = (nchan - 2*edge + 1)/2;
    1417           0 :          chanSpac*=2;
    1418           0 :          refChan = (refChan - edge)/2;
    1419             :       }    
    1420           0 :       Vector<Double> chanFreq(nchan), resolution(nchan),width(nchan);
    1421           0 :       for (Int ichan=0; ichan<nchan; ichan++)
    1422           0 :         chanFreq(ichan)=refFreq+(ichan-refChan)*chanSpac;
    1423           0 :       msc_p->spectralWindow().chanFreq().put(n,chanFreq);
    1424           0 :       resolution=chanBW;
    1425           0 :       width=chanSpac;
    1426           0 :       msc_p->spectralWindow().resolution().put(n,resolution);
    1427           0 :       msc_p->spectralWindow().chanWidth().put(n, width);
    1428           0 :       msc_p->spectralWindow().effectiveBW().put(n, resolution);
    1429           0 :       msc_p->spectralWindow().totalBandwidth().put(n,
    1430           0 :           (nchan<33 ? abs(nchan*chanSpac) : doubles_.if_bw[ifNumber]));
    1431           0 :       msc_p->spectralWindow().numChan().put(n,nchan);
    1432             : 
    1433           0 :       Vector<Int> corrType(npol);
    1434           0 :       Matrix<Int> corrProduct(2,npol); corrProduct=0;
    1435           0 :       if (log) os_p << LogIO::NORMAL << "         : Polarizations ";
    1436           0 :       for (Int i=0; i<npol; i++) {
    1437           0 :           corrType(i) = Stokes::type
    1438           0 :             (String(&names_.if_cstok[2*(i+ifNumber*MaxNPol)],2).before(trailing));
    1439             :       }
    1440           0 :       Vector<Int> tmp(npol); tmp=corrType;
    1441             :       // Sort the polarizations to standard order
    1442           0 :       GenSort<Int>::sort(corrType);
    1443           0 :       if (corrIndex_p.nrow()==0) {
    1444           0 :         corrIndex_p.resize(64,4);
    1445             :       }
    1446           0 :       if (Int(corrIndex_p.nrow())<=spWId_p) {
    1447           0 :         corrIndex_p.resize(nSpW_p,4,true);
    1448             :       }
    1449             :       // Get the sort indices to rearrange the data to standard order
    1450           0 :       for (Int i=0;i<npol;i++) {
    1451           0 :         for (Int j=0;j<npol;j++) {
    1452           0 :           if (corrType(j)==tmp(i)) corrIndex_p(spWId_p,i)=j;
    1453             :         }
    1454             :       }
    1455             : 
    1456             :       // Figure out the correlation products from the polarizations
    1457           0 :       corrProduct.resize(2,npol); corrProduct=0;
    1458           0 :       for (Int i=0; i<npol; i++) {
    1459           0 :         Stokes::StokesTypes s=Stokes::type(corrType(i));
    1460           0 :         Fallible<Int> receptor=Stokes::receptor1(s);
    1461           0 :         if (receptor.isValid()) corrProduct(0,i)=receptor;
    1462           0 :         receptor=Stokes::receptor2(s);
    1463           0 :         if (receptor.isValid()) corrProduct(1,i)=receptor;
    1464           0 :         if (i>0 && log) os_p << " , ";
    1465           0 :         if (log) os_p << Stokes::name(s)<< " - " << corrType(i);
    1466           0 :       } 
    1467           0 :       if (log) os_p << LogIO::POST;
    1468             : 
    1469             :       // try to find matching pol row
    1470           0 :       Int nPolRow = atms_p.polarization().nrow();
    1471           0 :       Int polRow = -1;
    1472           0 :       for (Int i = 0; i< nPolRow; i++) {
    1473           0 :         if (msc_p->polarization().numCorr()(i)== Int(if_.if_nstok[ifNumber])) {
    1474           0 :           if (allEQ(msc_p->polarization().corrType()(i),corrType)) {
    1475           0 :             polRow=i;
    1476           0 :             break;
    1477             :           }
    1478             :         }
    1479             :       }
    1480             :       // add new pol id if needed
    1481           0 :       if (polRow==-1) {
    1482           0 :         atms_p.polarization().addRow();
    1483           0 :         polRow = nPolRow;
    1484           0 :         msc_p->polarization().numCorr().put(polRow,Int(if_.if_nstok[ifNumber]));
    1485           0 :         msc_p->polarization().corrType().put(polRow,corrType);
    1486           0 :         msc_p->polarization().corrProduct().put(polRow,corrProduct);
    1487           0 :         msc_p->polarization().flagRow().put(polRow, false);
    1488             :       }         
    1489           0 :       atms_p.dataDescription().addRow();
    1490           0 :       msc_p->dataDescription().spectralWindowId().put(n, spWId_p);
    1491           0 :       msc_p->dataDescription().polarizationId().put(n, polRow);
    1492           0 :       msc_p->dataDescription().flagRow().put(n, false);
    1493             : 
    1494           0 :       msc_p->spectralWindow().ifConvChain().put(n,Int(if_.if_chain[ifNumber])-1);
    1495           0 :       if (!cabb_p) colSamplerBits.put(n,Int(if_.if_sampl[ifNumber]));
    1496             : 
    1497             :       // set up the TiledStorageManagers
    1498           0 :       Record values1, values2, values3, values3c;
    1499           0 :       values1.define("DATA_HYPERCUBE_ID",spWId_p);
    1500           0 :       values2.define("SIGMA_HYPERCUBE_ID",spWId_p);
    1501           0 :       values3.define("FLAG_HYPERCUBE_ID",spWId_p);
    1502           0 :       values3c.define("FLAG_CATEGORY_HYPERCUBE_ID",spWId_p);
    1503             : 
    1504           0 :       Record values4; values4.define("MODEL_HYPERCUBE_ID",spWId_p);
    1505           0 :       Record values5; values5.define("CORRECTED_HYPERCUBE_ID",spWId_p);
    1506             :       //Record values6; values6.define("IMAGING_WT_HYPERCUBE_ID",spWId_p);
    1507             : 
    1508           0 :       Int nChan=msc_p->spectralWindow().numChan()(spWId_p);
    1509           0 :       Int nCorr=msc_p->polarization().numCorr()(polRow);
    1510           0 :       Int nCat=3;
    1511             : 
    1512             :       // Choose an appropriate tileshape
    1513           0 :       IPosition dataShape(2,nCorr,nChan);
    1514           0 :       IPosition tileShape = MSTileLayout::tileShape(dataShape,obsType_p,"ATCA");
    1515           0 :       dataAccessor_p.addHypercube(IPosition(3,nCorr,nChan,0),
    1516             :                                  tileShape,values1);
    1517           0 :       sigmaAccessor_p.addHypercube(IPosition(2,nCorr,0),
    1518           0 :                                    IPosition(2,tileShape(0),tileShape(2)),
    1519             :                                    values2);
    1520           0 :       flagAccessor_p.addHypercube(IPosition(3,nCorr,nChan,0),
    1521             :                                   tileShape,values3);
    1522           0 :       flagCatAccessor_p.addHypercube(IPosition(4,nCorr,nChan,nCat,0),
    1523           0 :                                      IPosition(4,tileShape(0),tileShape(1),
    1524           0 :                                                1,tileShape(2)),values3c);
    1525             : 
    1526           0 :     }
    1527             :   }
    1528           0 :   return spWId_p;
    1529           0 : }
    1530             : 
    1531             : 
    1532           0 : void ATCAFiller::checkObservation() {
    1533           0 :   const Regex trailing(" *$"); // trailing blanks
    1534             :   // Check if current observer already in OBSERVATION table
    1535           0 :   String observer;
    1536           0 :   obsId_p=-1;
    1537           0 :   for (uInt i=0; i<atms_p.observation().nrow(); i++) {
    1538           0 :     msc_p->observation().observer().get(i,observer);
    1539           0 :     if (String(names_.rp_observer,16).before(trailing)==observer) {
    1540           0 :       obsId_p=i;
    1541           0 :       break;
    1542             :     }
    1543             :   }
    1544           0 :   if (obsId_p<0) {
    1545             :     // not found, so add it
    1546           0 :     atms_p.observation().addRow();
    1547           0 :     obsId_p=atms_p.observation().nrow()-1;
    1548           0 :     msc_p->observation().observer().put(obsId_p,
    1549           0 :                                      String(names_.rp_observer,16).before(trailing));
    1550             :     // decode project from rpfits file name..
    1551           0 :     String project=rpfitsFiles_p(0).after(Regex(".*\\."));
    1552           0 :     if (project.contains(";")) project=project.before(";");
    1553           0 :     msc_p->observation().project().put(obsId_p,project);
    1554           0 :   }
    1555           0 : }
    1556             : 
    1557           0 : void ATCAFiller::checkField() {
    1558             :   // Check if current source already in Field Table
    1559             :   // Add it if not, set fieldId_p index for our Field Table
    1560             :   // For now, we have 1 source per field, we may handle mosaicing differently
    1561             :   // at some point.
    1562           0 :   const Regex trailing(" *$"); // trailing blanks
    1563             :   //0.1 arcsec tolerance for positional coincidence
    1564           0 :   const Double PosTol=0.1*C::arcsec; 
    1565             : 
    1566           0 :   if (su_.su_found) {
    1567           0 :     fieldId_p=-1;
    1568           0 :     Bool seenSource = false;
    1569             :     Int numPol;
    1570           0 :     String name;
    1571           0 :     String su_name=String(&names_.su_name[sourceno*16],16).before(trailing);
    1572           0 :     for (Int i=0; i<nField_p; i++) {
    1573           0 :       msc_p->field().name().get(i,name);
    1574           0 :       msc_p->field().numPoly().get(i,numPol);
    1575             : 
    1576           0 :       if (su_name==name) {
    1577           0 :               IPosition shape(2, 2, numPol+1);
    1578           0 :               Matrix<Double> phaseDir(shape);
    1579           0 :               msc_p->field().phaseDir().get(i,phaseDir);
    1580           0 :               if (abs(phaseDir(0, 0)-doubles_.su_ra[sourceno])<PosTol) { 
    1581           0 :                 if (abs(phaseDir(1, 0)-doubles_.su_dec[sourceno])<PosTol) {
    1582           0 :                   fieldId_p=i; // found it!
    1583             :                   // now check if we've seen this field for this spectral window
    1584           0 :                   Vector<Int> sourceIdCol = msc_p->source().sourceId().getColumn();
    1585           0 :                   Vector<Int> spwIdCol = msc_p->source().spectralWindowId().getColumn();
    1586           0 :                   Vector<Int> spwids = spwIdCol(sourceIdCol==i).getCompressedArray();
    1587           0 :                   seenSource = (spwids.nelements()>0) && anyEQ(spwids,spWId_p);
    1588           0 :                   break;
    1589           0 :                 }
    1590             :               }
    1591           0 :       }
    1592             :     }
    1593             :         
    1594           0 :     if (fieldId_p<0 || !seenSource) { // i.e. not found, or not at this spwid
    1595           0 :       String src = String(&names_.su_name[sourceno*16],16);
    1596             : 
    1597           0 :       nsources_p++;
    1598           0 :       sources_p = src;
    1599             : 
    1600           0 :       Double epoch=mjd0_p+Double(proper_.pm_epoch);
    1601           0 :       Int numPol = 0;
    1602           0 :       if (abs(proper_.pm_ra)+abs(proper_.pm_dec) > 0) {
    1603           0 :         numPol = 1;
    1604             :       }
    1605           0 :       IPosition shape(2, 2, numPol+1);
    1606           0 :       Matrix<Double> dir(shape);
    1607             :       // convert proper motions from s & " per year to rad/s
    1608           0 :       const Double arcsecPerYear=C::arcsec/(365.25*C::day);
    1609           0 :       dir(0, 0)=doubles_.su_ra[sourceno]; 
    1610           0 :       dir(1, 0)=doubles_.su_dec[sourceno];
    1611           0 :       if (numPol>0) {
    1612           0 :         dir(0, 1)=proper_.pm_ra*15.*arcsecPerYear; // (15"/s)
    1613           0 :         dir(1, 1)=proper_.pm_dec*arcsecPerYear;
    1614             :       } 
    1615             : 
    1616           0 :       if (fieldId_p<0) {
    1617           0 :         os_p << LogIO::DEBUGGING << "Found field:" << src << LogIO::POST;
    1618           0 :         if (numPol>0) os_p << LogIO::DEBUGGING << "Field:" << src << " has proper motion parameters"<<LogIO::POST;
    1619           0 :         fieldId_p=nField_p++;
    1620           0 :         atms_p.field().addRow();
    1621           0 :         Int nf=atms_p.field().nrow()-1;
    1622             :         // for now we have 1 field/source
    1623           0 :         msc_p->field().sourceId().put(nf,fieldId_p); 
    1624           0 :         msc_p->field().name().put(nf,src.before(trailing));
    1625             : 
    1626           0 :         msc_p->field().phaseDir().put(nf,dir);
    1627           0 :         msc_p->field().delayDir().put(nf,dir);
    1628           0 :         msc_p->field().referenceDir().put(nf, dir);
    1629           0 :         msc_p->field().numPoly().put(nf, numPol);
    1630           0 :         msc_p->field().time().put(nf,epoch);
    1631           0 :         msc_p->field().code().put(nf,String(&names_.su_cal[sourceno*16],
    1632           0 :                                       16).before(trailing));
    1633             :       }
    1634           0 :       dir(0, 0)=doubles_.su_pra[sourceno]; 
    1635           0 :       dir(1, 0)=doubles_.su_pdec[sourceno];
    1636           0 :       Vector<Double> srcdir(2);
    1637           0 :       srcdir(0)=doubles_.su_ra[sourceno]; 
    1638           0 :       srcdir(1)=doubles_.su_dec[sourceno];
    1639           0 :       atms_p.source().addRow();
    1640           0 :       Int ns=atms_p.source().nrow()-1;
    1641           0 :       msc_p->source().sourceId().put(ns,fieldId_p);
    1642           0 :       msc_p->source().name().put(ns,src.before(trailing));
    1643           0 :       msc_p->source().direction().put(ns,srcdir);
    1644           0 :       Vector<Double> rate(2);
    1645           0 :       rate(0)=proper_.pm_ra*15.*arcsecPerYear; // (15"/s)
    1646           0 :       rate(1)=proper_.pm_dec*arcsecPerYear;
    1647           0 :       msc_p->source().properMotion().put(ns,rate);
    1648           0 :       msc_p->source().time().put(ns,epoch);
    1649           0 :       msc_p->source().interval().put(ns,DBL_MAX);
    1650             :       // assume source is at infinity, specify as zero
    1651             :       //Vector<Double> pos(3); pos=0.;
    1652             :       //msc_p->source().position().put(ns,pos);
    1653             :       
    1654             :       //suRow["VelRefFrame"].put(Int(spect_.ivelref));
    1655             :       // need to specify reference frame for velocity as well
    1656             :       // vel1 may be velocity at channel 1 instead of ref freq..
    1657             :       
    1658           0 :       msc_p->source().spectralWindowId().put(ns,spWId_p);
    1659           0 :       Vector<Double> sysv(1),restFreq(1);
    1660           0 :       Vector<String> transition(1);
    1661           0 :       sysv = Double(doubles_.vel1);
    1662           0 :       msc_p->source().sysvel().put(ns, sysv);
    1663           0 :       msc_p->source().numLines().put(ns,1);
    1664           0 :       restFreq(0) = Double(doubles_.rfreq);
    1665           0 :       if (restFreq(0)<1.0) {
    1666             :         // fill in an appropriate default
    1667           0 :         Double freq = msc_p->spectralWindow().refFrequency()(spWId_p);
    1668           0 :         Double bw = msc_p->spectralWindow().totalBandwidth()(spWId_p);
    1669           0 :         if ( freq>1200.e6 && freq< 1450.e6 && bw <64.e6) {
    1670           0 :           restFreq(0)= 1420.4e6;
    1671           0 :           transition(0)="HI";
    1672             :         } else {
    1673           0 :           restFreq(0) = freq;
    1674           0 :           transition(0) = "";
    1675             :         }            
    1676             :       }
    1677           0 :       msc_p->source().transition().put(ns,transition);
    1678           0 :       msc_p->source().restFrequency().put(ns,restFreq);
    1679             :       
    1680             :       // dummy fill 
    1681           0 :       msc_p->source().calibrationGroup().put(ns,-1);
    1682           0 :     }
    1683             : 
    1684           0 :     Bool fillPointingTable=False; //Imaging fails with pointing table filled
    1685           0 :     if (fillPointingTable && 
    1686           0 :         (fieldId_p != prev_fieldId_p || newPointingCorr_p)) {
    1687           0 :       prev_fieldId_p = fieldId_p;
    1688           0 :       Double epoch=mjd0_p+Double(proper_.pm_epoch);
    1689           0 :       Int np=atms_p.pointing().nrow();
    1690           0 :       IPosition shape(2, 2, 1);
    1691           0 :       Matrix<Double> pointingDir(shape,0.0);
    1692           0 :       pointingDir(0, 0)=doubles_.su_pra[sourceno]; 
    1693           0 :       pointingDir(1, 0)=doubles_.su_pdec[sourceno];
    1694           0 :       Matrix<Double> pointingOffset(shape,0.0);
    1695           0 :       for (Int i=0; i<nAnt_p; i++) {
    1696           0 :               atms_p.pointing().addRow();
    1697           0 :               msc_p->pointing().antennaId().put(np+i, i+1);
    1698           0 :         if (newPointingCorr_p) {
    1699           0 :           pointingOffset(0, 0)=pointingCorr_p(0,i)*C::arcsec;
    1700           0 :           pointingOffset(1, 0)=pointingCorr_p(0,i)*C::arcsec;
    1701             :         }    
    1702           0 :         if (i==0) { // ISM storage
    1703           0 :           msc_p->pointing().time().put(np,epoch);
    1704           0 :           msc_p->pointing().interval().put(np,DBL_MAX);
    1705           0 :           msc_p->pointing().numPoly().put(np, 0);
    1706           0 :           msc_p->pointing().direction().put(np,pointingDir);
    1707           0 :           msc_p->pointing().pointingOffset().put(np,pointingOffset);
    1708           0 :           msc_p->pointing().tracking().put(np,True);
    1709             :         } else {
    1710           0 :           if (newPointingCorr_p) {
    1711           0 :             msc_p->pointing().pointingOffset().put(np,pointingOffset);
    1712             :           }           
    1713             :         }
    1714             :       }
    1715           0 :     }
    1716           0 :   }
    1717           0 : }
    1718             : 
    1719             : 
    1720           0 : void ATCAFiller::storeSysCal() 
    1721             : {
    1722             :   // Conversion factor for atmospheric pressure
    1723           0 :   Vector<String> const pressure_unit = msc_p->weather().pressure().keywordSet().asArrayString("QuantumUnits");
    1724           0 :   auto const pressure_conversion = Quantum<Double>(1.0, Unit("mbar")).getValue(Unit(pressure_unit[0]));
    1725             : 
    1726             :   // RPFITS SysCal table layout:
    1727             :   // sc_.sc_ant = 7 (1-6 is antenna 1-6 syscal data, 7th has ant=0 weather data)
    1728             :   // sc_cal(q,if,ant) (in practice sc_.sc_if is always 1 since ~1999)
    1729             :   // q=0 : ant
    1730             :   //   1 : if
    1731             :   //   2 : XYPhase (deg)
    1732             :   //   3 : tsysX (sqrt(tsys*10))
    1733             :   //   4 : tsysY
    1734             :   //  5-7: samp-stats X
    1735             :   //  8-10:samp-stats Y
    1736             :   //  11 : Parallactic Angle (deg)
    1737             :   //  12 : Flag
    1738             :   //  13 : XYAmp (Jy)
    1739             :   //  15: Tracking error Max (arcsec)
    1740             :   //  16: Tracking error RMS (arcsec)
    1741           0 :   Int last_if_no=-2; // if_no can come out to be -1 if syscal rec is blank
    1742           0 :   Bool skip=false;
    1743           0 :   sourceno=sc_.sc_srcno-1; // 0-based source number for this syscal record
    1744           0 :   Int scq=sc_.sc_q, scif=sc_.sc_if;
    1745           0 :   for (Int i=0; i<scif; i++) {
    1746           0 :     for (Int ant=0; ant<sc_.sc_ant; ant++) {
    1747           0 :       if (Int(sc_.sc_cal[scq*(i+scif*ant)+0])==0) {
    1748             :         // special syscal record with antenna==0
    1749             :         // field 7-12 contain weather data
    1750           0 :         if (sc_.sc_ut!=lastWeatherUT_p) {
    1751           0 :           lastWeatherUT_p = sc_.sc_ut;
    1752           0 :           Int nAnt = max(1,sc_.sc_ant-1);
    1753           0 :           Int row=atms_p.weather().nrow();
    1754           0 :           atms_p.weather().addRow(nAnt);
    1755           0 :           Double time=mjd0_p+Double(sc_.sc_ut);
    1756           0 :           for (Int iAnt=0; iAnt<nAnt; iAnt++,row++) {
    1757           0 :             msc_p->weather().antennaId().put(row,iAnt);
    1758           0 :             msc_p->weather().time().put(row,time);
    1759           0 :             msc_p->weather().interval().put(row,Double(param_.intbase));
    1760           0 :             msc_p->weather().temperature().put(row,  
    1761           0 :                 Double(sc_.sc_cal[scq*(i+scif*ant)+1])+273.15); // C to K
    1762           0 :             msc_p->weather().pressure().put(row,    
    1763           0 :                 Double(sc_.sc_cal[scq*(i+scif*ant)+2])*pressure_conversion); // mBar to Pa/hPa
    1764           0 :             msc_p->weather().relHumidity().put(row,  
    1765           0 :                 Double(sc_.sc_cal[scq*(i+scif*ant)+3]));
    1766           0 :             msc_p->weather().windSpeed().put(row,   
    1767           0 :                 Double(sc_.sc_cal[scq*(i+scif*ant)+4])/3.6); // km/s to m/s
    1768           0 :             msc_p->weather().windDirection().put(row,
    1769           0 :                 Double(sc_.sc_cal[scq*(i+scif*ant)+5])*C::pi/180.0); // deg to rad
    1770           0 :             msc_p->weather().temperatureFlag().put(row,  Bool(sc_.sc_cal[scq*(i+scif*ant)+6]));
    1771           0 :             msc_p->weather().pressureFlag().put(row,     Bool(sc_.sc_cal[scq*(i+scif*ant)+6]));
    1772           0 :             msc_p->weather().relHumidityFlag().put(row,  Bool(sc_.sc_cal[scq*(i+scif*ant)+6]));
    1773           0 :             msc_p->weather().windSpeedFlag().put(row,    Bool(sc_.sc_cal[scq*(i+scif*ant)+6]));
    1774           0 :             msc_p->weather().windDirectionFlag().put(row,Bool(sc_.sc_cal[scq*(i+scif*ant)+6]));
    1775           0 :             colWeatherRainGauge.put(row,  Float(sc_.sc_cal[scq*(i+scif*ant)+7]));
    1776           0 :             colWeatherSeeMonPhase.put(row,  Float(sc_.sc_cal[scq*(i+scif*ant)+8]));
    1777           0 :             colWeatherSeeMonRMS.put(row,  Float(sc_.sc_cal[scq*(i+scif*ant)+9])/1000);
    1778           0 :             colWeatherSeeMonFlag.put(row,  Bool(sc_.sc_cal[scq*(i+scif*ant)+10]));
    1779             :           }
    1780             :         }
    1781           0 :         continue;
    1782           0 :       }
    1783           0 :       if_no=Int(sc_.sc_cal[scq*(i+scif*ant)+1])-1; // make 0-based
    1784           0 :       if (if_no!=last_if_no) { // check if we want this one
    1785           0 :           last_if_no=if_no; 
    1786           0 :           skip=Bool(if_no<0 || if_no>=if_.n_if || !selected(if_no));
    1787           0 :           if (!skip) {
    1788           0 :               checkSpW(if_no); // sets spWId_p corresponding to this if_no
    1789           0 :               checkField(); // sets fieldId_p
    1790             :           }
    1791             :       }
    1792           0 :       if (!skip) {
    1793           0 :               atms_p.sysCal().addRow();
    1794           0 :               Int n=atms_p.sysCal().nrow()-1;
    1795           0 :               Double time=mjd0_p+Double(sc_.sc_ut);
    1796           0 :               msc_p->sysCal().time().put(n,time);
    1797           0 :               msc_p->sysCal().antennaId()
    1798           0 :                 .put(n,Int(sc_.sc_cal[scq*(i+scif*ant)+0]-1)); // make 0-based
    1799           0 :               msc_p->sysCal().feedId().put(n,0);
    1800           0 :               msc_p->sysCal().interval().put(n,Double(param_.intbase));
    1801           0 :               msc_p->sysCal().spectralWindowId().put(n,spWId_p);
    1802             : 
    1803           0 :               msc_p->sysCal().phaseDiff().put(n,sc_.sc_cal[scq*(i+scif*ant)+2]);
    1804             : 
    1805           0 :               Vector<Float> tSys(2);
    1806             :               // convert from sqrt(tsys*10) to true tsys
    1807           0 :               tSys(0)=square(sc_.sc_cal[scq*(i+scif*ant)+3])/10.;
    1808           0 :               tSys(1)=square(sc_.sc_cal[scq*(i+scif*ant)+4])/10.;
    1809             : 
    1810           0 :               msc_p->sysCal().tsys().put(n,tSys);
    1811             : 
    1812           0 :               Vector<Float> a(2),b(2),c(2);
    1813           0 :               for (Int j=0; j<2; j++) {
    1814           0 :                 a(j)=sc_.sc_cal[scq*(i+scif*ant)+5+j*3];
    1815           0 :                 b(j)=sc_.sc_cal[scq*(i+scif*ant)+6+j*3];
    1816           0 :                 c(j)=sc_.sc_cal[scq*(i+scif*ant)+7+j*3];
    1817             :               }
    1818           0 :               if (cabb_p) {
    1819           0 :                 colGTP.put(n,a);
    1820           0 :                 colSDO.put(n,b);
    1821           0 :                 colCalJy.put(n,c);
    1822             :               } else {
    1823           0 :                 colSamplerStatsNeg.put(n,a);
    1824           0 :                 colSamplerStatsZero.put(n,b);
    1825           0 :                 colSamplerStatsPos.put(n,c);
    1826             :               } 
    1827             :               //cParAngle.put(n,sc_.sc_cal[scq*(i+scif*ant)+11]);
    1828           0 :               msc_p->sysCal().phaseDiffFlag().
    1829           0 :                 put(n,(sc_.sc_cal[scq*(i+scif*ant)+12]!=0));
    1830           0 :               msc_p->sysCal().tsysFlag().
    1831           0 :                 put(n,(sc_.sc_cal[scq*(i+scif*ant)+12]!=0));
    1832           0 :               colXYAmplitude.put(n,sc_.sc_cal[scq*(i+scif*ant)+13]);
    1833           0 :               msc_p->sysCal().tcalFlag().put(n,true);
    1834           0 :               msc_p->sysCal().trxFlag().put(n,true);
    1835           0 :              colTrackErrMax.put(n,Float(sc_.sc_cal[scq*(i+scif*ant)+14]));
    1836           0 :              colTrackErrRMS.put(n,Float(sc_.sc_cal[scq*(i+scif*ant)+15]));
    1837           0 :       }
    1838             :     }
    1839             :   }
    1840           0 : }
    1841             : 
    1842             : 
    1843           0 : void ATCAFiller::reweight()
    1844             : {
    1845           0 :   Int npol =if_.if_nstok[if_no];
    1846           0 :   Int nfreq=33;
    1847           0 :   Int n=2*nfreq-2;
    1848           0 :   FFTServer<Float, Complex> server;
    1849             : 
    1850           0 :   Vector<Complex> cscr(33);
    1851           0 :   Vector<Float>   rscr(64);
    1852             : 
    1853             :   static Float wts[64]={ 1.000000,    
    1854             :    1.028847, 1.0526778, 1.0711329, 1.083963, 1.0909837, 1.0921189,    
    1855             :    1.0873495, 1.0767593, 1.0605253, 1.0389025, 1.0122122,
    1856             :    0.9808576, 0.9453095, 0.9060848, 0.8637353, 0.8188493,    
    1857             :    0.7720414, 0.7239398, 0.6751758, 0.6263670, 0.5781130,    
    1858             :    0.5310048, 0.4856412, 0.4426092, 0.4025391, 0.3661798,    
    1859             :    0.3346139, 0.3096083, 0.2951138, 0.3024814, 0.6209788, 1.000000,    
    1860             :    0.6209788, 0.3024814, 0.2951138, 0.3096083, 0.3346139,    
    1861             :    0.3661798, 0.4025391, 0.4426092, 0.4856412, 0.5310048,    
    1862             :    0.5781130, 0.6263670, 0.6751758, 0.7239398, 0.7720414,    
    1863             :    0.8188493, 0.8637353, 0.9060848, 0.9453095, 0.9808576,    
    1864             :    1.0122122, 1.0389025, 1.0605253, 1.0767593, 1.0873495, 1.0921189,    
    1865             :    1.0909837, 1.083963, 1.0711329, 1.0526778, 1.028847 };
    1866             : 
    1867           0 :   for (Int p=0; p<npol; p++) {
    1868           0 :     for (Int i=0; i<nfreq; i++)
    1869           0 :       cscr(i) = Complex(vis[0+2*(p+i*npol)],vis[1+2*(p+i*npol)]);
    1870           0 :     server.fft0(rscr, cscr);
    1871           0 :     for (Int i=0; i<n; i++) rscr(i) = rscr(i)*wts[i];
    1872           0 :     server.fft0(cscr, rscr);
    1873           0 :     for (Int i=0; i<nfreq; i++) {
    1874           0 :       vis[0+2*(p+i*npol)] = real(cscr(i));
    1875           0 :       vis[1+2*(p+i*npol)] = imag(cscr(i));
    1876             :     }
    1877             :   }
    1878           0 : }
    1879             : 
    1880           0 : Int ATCAFiller::birdChan(Double refFreq, Int refChan, Double chanSpac)
    1881             : {
    1882           0 :   Double flo = 0.128* myround(refFreq/0.128);
    1883           0 :   Int chan = refChan + myround((flo - refFreq)/chanSpac);
    1884           0 :   if(chan <= 0) {
    1885             :     //    os_p << LogIO::NORMAL << "CHAN " << chan << "  ";
    1886           0 :     chan = chan + myround(0.128/fabs(chanSpac));
    1887             :   }
    1888             :   //os_p << LogIO::NORMAL << "birdie channel = " << chan << " refFreq="<<refFreq << " flo="<<flo <<"\n";
    1889           0 :   return chan;
    1890             : }
    1891             : 
    1892           0 : void ATCAFiller::storeData()
    1893             : {
    1894           0 :   const double MJD01Jul2004 = 2453187.5; // 12mm receiver xy inversion end
    1895           0 :   const double MJD18Oct2007 = 2454390.5; // 3mm CA02 xyphase valid
    1896             :   
    1897           0 :   atms_p.addRow();
    1898             :   
    1899           0 :   const RecordFieldId rfid1("DATA_HYPERCUBE_ID");
    1900           0 :   const RecordFieldId rfid2("SIGMA_HYPERCUBE_ID");
    1901           0 :   const RecordFieldId rfid3("FLAG_HYPERCUBE_ID");
    1902           0 :   const RecordFieldId rfid3c("FLAG_CATEGORY_HYPERCUBE_ID");
    1903           0 :   Record values1, values2, values3, values3c;
    1904           0 :   values1.define(rfid1,spWId_p);
    1905           0 :   values2.define(rfid2,spWId_p);
    1906           0 :   values3.define(rfid3,spWId_p);
    1907           0 :   values3c.define(rfid3c,spWId_p);
    1908             : 
    1909           0 :   dataAccessor_p.extendHypercube(1,values1);
    1910           0 :   sigmaAccessor_p.extendHypercube(1,values2);
    1911           0 :   flagAccessor_p.extendHypercube(1,values3);
    1912           0 :   flagCatAccessor_p.extendHypercube(1,values3c);
    1913             : 
    1914           0 :   Record values4, values5, values6; 
    1915             : 
    1916           0 :   Int n=atms_p.nrow()-1;
    1917           0 :   if (n==0) gotSysCalId_p=false;
    1918             :     
    1919           0 :   Int npol =if_.if_nstok[if_no];
    1920           0 :   Int nfreq=if_.if_nfreq[if_no];
    1921           0 :   Regex trailing(" *$"); // trailing blanks
    1922           0 :   String instrument = String(names_.instrument,16).before(trailing);
    1923           0 :   Bool atca = (instrument=="ATCA");
    1924           0 :   Bool atlba = (instrument=="ATLBA");
    1925             :   
    1926             :   // fill in the easy items
    1927             :   // make antenna numbers 0-based
    1928           0 :   Int ant1=Int(baseline)/256-1, ant2=Int(baseline)%256-1;
    1929           0 :   msc_p->antenna1().put(n,ant1);  
    1930           0 :   msc_p->antenna2().put(n,ant2);
    1931           0 :   Bool flagData=flg;
    1932           0 :   if (flagData) { flagCount_p(ONLINE)++;}
    1933           0 :   if (autoFlag_p && flagScanType_p) { flagData=true; flagCount_p(SCANTYPE)++;}
    1934           0 :   Double exposure=Double(param_.intbase);
    1935             :   // averaging = number of integration periods averaged by correlator: 1,2 or 3
    1936           0 :   Int averaging = 1;
    1937           0 :   if (param_.intime>0) averaging = Int(exposure/param_.intime)+1; 
    1938           0 :   Double interval = averaging*Double(param_.intime);
    1939             :   // check for old data with intbase set to zero
    1940           0 :   Double blank=51.e-3; // standard 51 ms blank time at end of integration
    1941           0 :   if (exposure<0.001) exposure = interval-blank;
    1942           0 :   if (interval==0.0) interval = exposure;
    1943             :   
    1944             :   // Is binning mode active?
    1945           0 :   Int nBin = Int(floor(param_.intime/exposure+0.01));
    1946           0 :   if (nBin<4) nBin=1; // short exposure due to long hold period.. 
    1947           0 :   msc_p->dataDescId().put(n, spWId_p);
    1948           0 :   if (ut!=lastUT_p) { // the ISM columns that don't change within integration
    1949           0 :     msc_p->arrayId().put(n,0);
    1950           0 :     msc_p->exposure().put(n,exposure);
    1951           0 :     msc_p->feed1().put(n,0);
    1952           0 :     msc_p->feed2().put(n,0);
    1953           0 :     msc_p->fieldId().put(n,fieldId_p);
    1954           0 :     msc_p->interval().put(n,interval);
    1955           0 :     msc_p->observationId().put(n,obsId_p);
    1956           0 :     msc_p->processorId().put(n,-1);
    1957           0 :     msc_p->scanNumber().put(n,scanNo_p);
    1958           0 :     msc_p->stateId().put(n,-1);
    1959           0 :     Double mjd=mjd0_p+ut;
    1960             :     // try to figure out what the midpoint of the integration interval was
    1961           0 :     if (nBin>1 || !atca) {
    1962           0 :       msc_p->time().put(n,mjd);
    1963             :     } else {
    1964           0 :       msc_p->time().put(n,floor((mjd+exposure/2+blank*(averaging+1)/2
    1965           0 :                               -interval/2)*1000+0.5)/1000);
    1966             :     }    
    1967             :     // time centroid is the centroid of the exposure window
    1968             :     // it is the time used for the uvw & phase calculation 
    1969             :     // [note that cacor corrects uvw for change in centroid from caobs value
    1970             :     // due to blank, hold and averaging, but not binning]
    1971           0 :     msc_p->timeCentroid().put(n,mjd);
    1972             :   } 
    1973           0 :   Int pulsarBin = max(0,bin-1);// make zero-based (but catch unset value) 
    1974           0 :   msc_p->pulsarBin().put(n,pulsarBin); 
    1975           0 :   if (hires_p && nBin>1) {
    1976             :     // in hires mode we adjust timeCentroid to match the bin centers, but
    1977             :     // uvw's still refer to center of interval (now given by time column)
    1978             :     // Time column will still be in time order, but TimeCentroid is not.
    1979           0 :     Double midTime = msc_p->time()(n);
    1980           0 :     msc_p->timeCentroid().put(n,midTime+(pulsarBin-nBin/2+0.5)*exposure/averaging);
    1981             :   }
    1982           0 :   Vector<Double> uvw(3); uvw(0)=u; uvw(1)=v; uvw(2)=w;
    1983           0 :   msc_p->uvw().put(n,uvw);
    1984             : 
    1985             :   // use exposure time as weight
    1986           0 :   Vector<Float> Weight(npol); Weight=exposure;
    1987           0 :   msc_p->weight().put(n,Weight); 
    1988             :   //#  Vector<Float> weightSpectrum(nfreq); weightSpectrum=exposure;
    1989             :   //#  msc_p->weightSpectrum().put(n,weightSpectrum);
    1990             :   
    1991             :   // Find the indices into the sysCal table for this row
    1992           0 :   if (!gotSysCalId_p || ut!=lastUT_p || spWId_p!=lastSpWId_p) {
    1993           0 :     lastUT_p=ut;
    1994           0 :     lastSpWId_p=spWId_p;
    1995             :     // we need to get the new syscal info
    1996             :     // search backwards from last syscal row
    1997           0 :     Bool done=false;
    1998           0 :     Int nsc=atms_p.sysCal().nrow();
    1999             :     //# os_p << LogIO::NORMAL << " Current number of syscal rows="<<nsc<<LogIO::POST;
    2000           0 :     sysCalId_p.resize(nAnt_p); sysCalId_p=-1;
    2001             :     // search backwards, as it should be a recent entry
    2002           0 :     for (Int i=nsc-1; (i>=0 && !done); i--) {
    2003           0 :       if (nearAbs(msc_p->sysCal().time()(i),mjd0_p+ut,0.5) && 
    2004           0 :           msc_p->sysCal().spectralWindowId()(i)==spWId_p) {
    2005           0 :         Int ant=msc_p->sysCal().antennaId()(i);
    2006           0 :         if (ant>=0 && ant<nAnt_p) { //valid antenna
    2007           0 :           sysCalId_p(ant)=i;
    2008           0 :           done=(!(anyEQ(sysCalId_p,-1)));
    2009             :         }
    2010             :       }
    2011             :     }
    2012           0 :     if (!done && atca) {
    2013           0 :       errCount_p++;
    2014           0 :       if (errCount_p<3) os_p << LogIO::WARN <<"Warning: some syscal info is missing"<< LogIO::POST;
    2015             :     }
    2016             :   }
    2017             :   // set a sysCalId in the main table to point to
    2018             :   // the sysCal subtable row - missing points get a -1
    2019           0 :   colSysCalIdAnt1.put(n,sysCalId_p(ant1));
    2020           0 :   colSysCalIdAnt2.put(n,sysCalId_p(ant2));
    2021             :   
    2022             :   // Check for bad sampler stats now that we've found the syscal data
    2023           0 :   if (!flagData && autoFlag_p && (!atlba && !cabb_p && samplerFlag(n))) {
    2024           0 :     flagData=true; flagCount_p(SYSCAL)++;
    2025             :   }
    2026           0 :   flagCount_p(COUNT)++;
    2027           0 :   if (flagData) flagCount_p(FLAG)++;
    2028           0 :   msc_p->flagRow().put(n,flagData);
    2029             :     
    2030             : 
    2031             :   // flags and data
    2032           0 :   const Int nCat = 3; // three initial categories
    2033             :   // define the categories
    2034           0 :   Vector<String> cat(nCat);
    2035           0 :   cat(0)="FLAG_CMD";
    2036           0 :   cat(1)="ORIGINAL"; 
    2037           0 :   cat(2)="USER"; 
    2038           0 :   msc_p->flagCategory().rwKeywordSet().define("CATEGORY",cat);
    2039             : 
    2040             :   // Gibbs reweighting
    2041           0 :   if (nfreq == 33) {
    2042           0 :     if (reweight_p) reweight();
    2043             :   }
    2044             : 
    2045             :   // do birdie check here - reduce number of channels we will store
    2046             :   // for 33 channel data (drop half the channels + edge) 
    2047           0 :   Double refFreq=doubles_.if_freq[if_no];
    2048           0 :   Double refChan=doubles_.if_ref[if_no]-1; // make zero based
    2049           0 :   Double chanSpac = doubles_.if_bw[if_no]/max(1,nfreq-1);
    2050           0 :   Int inversion=if_.if_invert[if_no];
    2051           0 :   chanSpac*=inversion;
    2052           0 :   Int bchan = -1;
    2053           0 :   Int edge = 0;
    2054           0 :   if (birdie_p && atca) {
    2055           0 :     bchan = birdChan(refFreq/1.e9, (Int)refChan, chanSpac/1.e9);
    2056           0 :     if (nfreq == 33) {  // ATCA continuum mode - flag edge + every other channel
    2057           0 :      edge = 3 + (bchan+1)%2;
    2058           0 :      nfreq = (nfreq - 2*edge + 1)/2;
    2059           0 :      chanSpac*=2;
    2060           0 :      refChan = (refChan - edge)/2;
    2061           0 :      bchan = (bchan -edge)/2;
    2062             :     } 
    2063             :   }
    2064           0 :   Bool band12mm = (refFreq>13.e9 && refFreq<28.e9);
    2065           0 :   Bool band3mm  = (refFreq>75.e9);
    2066             :       
    2067           0 :   Matrix<Complex> VIS(npol,nfreq);
    2068           0 :   Cube<Bool> flagCat(npol,nfreq,nCat,false);  
    2069           0 :   Matrix<Bool> flags= flagCat.xyPlane(1); // references flagCat's storage
    2070             :   
    2071             :   
    2072           0 :   if (birdie_p) {
    2073           0 :     if (bchan >= 0 && bchan < nfreq) {
    2074           0 :       for (Int i=0; i<npol; i++) {
    2075           0 :         flags(i, bchan) = true;       
    2076             :       }
    2077             :     }
    2078             :   }
    2079             :     
    2080             :   // Some corrections as specified by Bob Sault(2000/09/07):
    2081             :   //Conjugate all data if the IF_INVERT switch is negative
    2082             :   //Negate the XY and YX correlations (both real and imag parts) for all
    2083             :   // except 12mm observations.
    2084             :   //The xyphase measurement should also be multiplied by the IF_INVERT switch
    2085             :   //sign. The xyphase measurement is the phase of a correlation. So to
    2086             :   //correct the data with the xyphase measurement, you will want to multiply
    2087             :   //by gains whose phase has the opposite sign to the measurements.
    2088             :   //Note any Gibbs reweighting needs to be done before any xyphase correction
    2089             :   //is done.
    2090             : 
    2091             :  
    2092             :   // correct for inversion - conjugate data; skip birdie channels
    2093             :   // resort pols
    2094           0 :   for (Int j=0; j<nfreq; j++) {
    2095           0 :     Int k = (edge>0 ? (2*j+edge) : j);
    2096           0 :     for (Int i=0; i<npol; i++) {
    2097           0 :       Int ipol = corrIndex_p(spWId_p,i);
    2098           0 :       VIS(ipol,j)=Complex(vis[0+2*(i+k*npol)],inversion*vis[1+2*(i+k*npol)]);
    2099             :     }
    2100             :   }
    2101             :   // Flag NaNs
    2102           0 :   Matrix<Bool> nanFlags = isNaN(real(VIS));
    2103           0 :   nanFlags |= isNaN(imag(VIS));
    2104           0 :   flags |= nanFlags;
    2105             : 
    2106             :   // Flag CABB birdies and RFI
    2107           0 :   if (cabb_p) rfiFlag(flags);
    2108             :     
    2109             :   // correct for xy phase - multiply y correlation with opposite of xyphase
    2110           0 :   Int id1 = sysCalId_p(ant1);
    2111           0 :   Complex gain1 = (id1!=-1 && !msc_p->sysCal().phaseDiffFlag()(id1) ?
    2112           0 :                    exp(Complex(0,1)*msc_p->sysCal().phaseDiff()(id1)*inversion):
    2113           0 :                    Complex(1,0));
    2114             :   // negate xyphase for second antenna since the correlation product uses conjugate for ant2
    2115           0 :   Int id2 = sysCalId_p(ant2);
    2116           0 :   Complex gain2 = (id2!=-1 && !msc_p->sysCal().phaseDiffFlag()(id2) ?
    2117           0 :                    exp(-Complex(0,1)*msc_p->sysCal().phaseDiff()(id2)*inversion):
    2118           0 :                    Complex(1,0));
    2119           0 :   Int polId = msc_p->dataDescription().polarizationId()(spWId_p);
    2120           0 :   Vector<Int> corrType = msc_p->polarization().corrType()(polId);
    2121             :   // 3mm receiver on CA02 got valid xyphase on 18Oct2007
    2122           0 :   if (noxycorr_p || (band3mm && mjd0_p<MJD18Oct2007)) { gain1=gain2=1; }
    2123           0 :   if (band3mm && mjd0_p>=MJD18Oct2007) {
    2124           0 :     if (ant1!=1) gain1 = 1;
    2125           0 :     if (ant2!=1) gain2 = 1;
    2126             :   }
    2127             :   // "-" because XY and YX corr need to be negated, except for 12mm until 2004
    2128           0 :   if (!band12mm || mjd0_p>MJD01Jul2004) { gain1=-gain1; gain2=-gain2;}
    2129           0 :   for (Int i=0; i<npol; i++) {
    2130           0 :     switch (corrType(i)) {
    2131           0 :     case Stokes::XX :
    2132           0 :       break;
    2133           0 :     case Stokes::XY : 
    2134             :       {
    2135           0 :         Vector<Complex> tmp(VIS.row(i));
    2136           0 :         tmp*=gain2; 
    2137           0 :       }
    2138           0 :     break;
    2139           0 :     case Stokes::YX :
    2140             :       {
    2141           0 :         Vector<Complex> tmp(VIS.row(i));
    2142           0 :         tmp*=gain1;
    2143           0 :       }
    2144           0 :     break;
    2145           0 :     case Stokes::YY :
    2146             :       {
    2147           0 :         Vector<Complex> tmp(VIS.row(i));
    2148           0 :         tmp*=(gain1*gain2);
    2149           0 :       }
    2150           0 :     break;
    2151           0 :     default:
    2152           0 :       break;
    2153             :     }
    2154             :   }
    2155             : 
    2156           0 :   msc_p->data().put(n,VIS);
    2157             :   // CASA wants all flags set if flagRow is set
    2158           0 :   if (flagData) flags=flagData;
    2159           0 :   msc_p->flag().put(n,flags);
    2160           0 :   msc_p->flagCategory().put(n,flagCat);
    2161             :   
    2162             :   // now calculate the sigma for this row
    2163             :   //
    2164           0 :   Vector<Double> chnbw;  
    2165           0 :   msc_p->spectralWindow().resolution().get(spWId_p,chnbw);
    2166           0 :   Vector<Float> tsys1,tsys2;
    2167             :   //#  os_p << LogIO::NORMAL << "Looking up syscal info at rows: "<<sysCalId_p(ant1)<<" and "<<
    2168             :   //#  sysCalId_p(ant2)<< LogIO::POST;
    2169             : 
    2170           0 :   if (sysCalId_p(ant1)!=-1 && !msc_p->sysCal().tsysFlag()(sysCalId_p(ant1))) 
    2171           0 :     msc_p->sysCal().tsys().get(sysCalId_p(ant1),tsys1);
    2172           0 :   else { tsys1.resize(nAnt_p); tsys1=50.;}
    2173           0 :   if (sysCalId_p(ant2)!=-1 && !msc_p->sysCal().tsysFlag()(sysCalId_p(ant2)))
    2174           0 :     msc_p->sysCal().tsys().get(sysCalId_p(ant2),tsys2);
    2175           0 :   else { tsys2.resize(nAnt_p); tsys2=50.;}
    2176           0 :   Vector<Float> sigma(npol); sigma=0.;
    2177           0 :   Matrix<Int> corrProduct(2,npol);
    2178           0 :   msc_p->polarization().corrProduct().get(polId,corrProduct);
    2179             : 
    2180             :   // sigma=sqrt(Tx1*Tx2)/sqrt(chnbw*intTime)*JyPerK;
    2181           0 :   Float JyPerK=13.; // guess for ATCA dishes at 3-20cm
    2182           0 :   Float factor=sqrt(chnbw(0)*exposure)/JyPerK;
    2183           0 :   for (Int pol=0; pol<npol; pol++) {
    2184           0 :     Float tsysAv=tsys1(corrProduct(0,pol))*tsys2(corrProduct(1,pol));
    2185           0 :     if (tsysAv>=0 && factor>0 ) sigma(pol)=sqrt(tsysAv)/factor;
    2186             :   }
    2187           0 :   msc_p->sigma().put(n,sigma);
    2188             : 
    2189             :   // determine shadowing & flag data with shadowed antennas
    2190           0 :   if (shadow_p>0) shadow(n);
    2191             :   
    2192           0 : }
    2193             : 
    2194           0 : void ATCAFiller::rfiFlag(Matrix<Bool> & flags) {
    2195             :   // CABB birdies
    2196             :   // 1 MHz mode
    2197           0 :   const int nb1=11;
    2198             :   static const int b1[nb1] = {640,256,768,1408,1280,1920,1792,1176,156,128,1152};
    2199             :   // 64 MHz mode
    2200           0 :   const int nb2=3;
    2201             :   static const int b2[nb2] = {8,16,24};
    2202             :   
    2203             :   // Get details of spectrum
    2204           0 :   Int nfreq=if_.if_nfreq[if_no];
    2205           0 :   Double bw=doubles_.if_bw[if_no];
    2206           0 :   Int chn=0;
    2207             :   // Flag birdies and edge channels
    2208           0 :   if (bw>2.e9) {
    2209           0 :     chn = nfreq*edge_p/200;
    2210           0 :     if (nfreq==2049) {
    2211             :       // CABB 2049 chan * 1 MHz continuum mode
    2212           0 :       for (Int i=0; i<nb1; i++) {
    2213           0 :         flags.column(b1[i])=true;
    2214             :       }
    2215           0 :     } else if (nfreq==33) {
    2216             :       // CABB 33 chan * 64 MHz continuum mode
    2217           0 :       for (Int i=0; i<nb2; i++) {
    2218           0 :          flags.column(b2[i])=true;
    2219             :       }
    2220             :     }
    2221           0 :   } else if (bw<1.e9 && nfreq>=2049) {
    2222             :     // CABB zoom mode, 2049 or more channels (combined zooms)
    2223           0 :     chn = 2049*edge_p/200;
    2224             :   }  
    2225           0 :   for (Int i=0; i<chn; i++) flags.column(i)=true;
    2226           0 :   for (Int i=nfreq-chn; i<nfreq; i++) flags.column(i)=true;  
    2227           0 : }
    2228             : 
    2229           0 : void ATCAFiller::fillFeedTable() {
    2230             :   // At present there is always only a single feed per antenna (at any
    2231             :   // given spectralwindow).
    2232           0 :   Int nAnt=atms_p.antenna().nrow();
    2233             :   //  Int nSpW=atms_p.spectralWindow().nrow();
    2234             :   // Only X and Y receptors available
    2235           0 :   Vector<String> rec_type(2); rec_type(0)="X"; rec_type(1)="Y";
    2236           0 :   Matrix<Complex> polResponse(2,2); 
    2237           0 :   polResponse=0.; polResponse(0,0)=polResponse(1,1)=1.;
    2238           0 :   Matrix<Double> offset(2,2); offset=0.;
    2239           0 :   Vector<Double> position(3); position=0.;
    2240             :   // X feed is at 45 degrees, Y at 135 degrees for all except 7mm
    2241           0 :   Vector<Double> receptorAngle(2); 
    2242           0 :   receptorAngle(0)=45*C::degree;
    2243           0 :   receptorAngle(1)=135*C::degree;
    2244             :   // Single entry, so we use the first spectral window
    2245           0 :   Double f = msc_p->spectralWindow().refFrequency()(0);
    2246           0 :   if (f>30e9 && f<50e9) receptorAngle+=90*C::degree;
    2247             : 
    2248             :   // fill the feed table
    2249           0 :   Int row=-1;
    2250             :   // in principle we should have a separate entry for each SpectralWindow
    2251             :   // but at present all this is 'dummy' filled
    2252             :   //  for (Int spw=0; spw<nSpW; spw++) {
    2253           0 :   for (Int ant=0; ant<nAnt; ant++) {
    2254           0 :     atms_p.feed().addRow(); row++;
    2255           0 :     msc_p->feed().antennaId().put(row,ant);
    2256           0 :     msc_p->feed().beamId().put(row,-1);
    2257           0 :     msc_p->feed().feedId().put(row,0);
    2258           0 :     msc_p->feed().interval().put(row,DBL_MAX);
    2259           0 :     msc_p->feed().phasedFeedId().put(row,-1);
    2260           0 :     msc_p->feed().spectralWindowId().put(row,-1);  //spw);
    2261           0 :     msc_p->feed().time().put(row,0.);
    2262           0 :     msc_p->feed().numReceptors().put(row,2);
    2263           0 :     msc_p->feed().beamOffset().put(row,offset);
    2264           0 :     msc_p->feed().polarizationType().put(row,rec_type);
    2265           0 :     msc_p->feed().polResponse().put(row,polResponse);
    2266           0 :     msc_p->feed().position().put(row,position);
    2267           0 :     msc_p->feed().receptorAngle().put(row,receptorAngle);
    2268             :   }
    2269           0 : }
    2270             :  
    2271           0 : void ATCAFiller::fillObservationTable() 
    2272             : {
    2273           0 :   Vector<Double> tim = msc_p->time().getColumn();
    2274           0 :   Vector<Int> obsid = msc_p->observationId().getColumn();
    2275             :   Int startInd;
    2276             :   Int endInd;
    2277             : 
    2278           0 :   Int nObs=atms_p.observation().nrow();
    2279           0 :   Vector<Double> vt(2);
    2280           0 :   for (Int obs=0; obs<nObs; obs++) {
    2281             :     // fill time range
    2282           0 :     startInd = 0;
    2283           0 :     endInd = atms_p.nrow()-1;
    2284           0 :     for (uInt i=0; i<atms_p.nrow(); i++) {
    2285           0 :       if (obsid(i) == obs) { startInd = i; break; }
    2286             :     }
    2287           0 :     for (uInt i=startInd; i<atms_p.nrow(); i++) {
    2288           0 :       if (obsid(i) > obs) { endInd = i-1; break; }
    2289             :     }
    2290           0 :     vt(0) = tim(startInd);
    2291           0 :     vt(1) = tim(endInd);
    2292           0 :     msc_p->observation().timeRange().put(obs, vt);
    2293           0 :     msc_p->observation().releaseDate().put(obs,vt(1)+18*30.5*86400);
    2294             :     // telescope name
    2295           0 :     msc_p->observation().telescopeName().put(obs, "ATCA");
    2296             :   }
    2297           0 : }
    2298             : 
    2299           0 : void ATCAFiller::flush()
    2300             : {
    2301           0 :   atms_p.flush();
    2302           0 :   atms_p.antenna().flush();
    2303           0 :   atms_p.dataDescription().flush();
    2304           0 :   atms_p.feed().flush();
    2305           0 :   atms_p.field().flush();
    2306           0 :   atms_p.observation().flush();
    2307           0 :   atms_p.history().flush();
    2308           0 :   atms_p.pointing().flush();
    2309           0 :   atms_p.polarization().flush();
    2310           0 :   atms_p.source().flush();
    2311           0 :   atms_p.spectralWindow().flush();
    2312           0 :   atms_p.sysCal().flush();
    2313           0 :   atms_p.weather().flush();
    2314           0 : }
    2315             : 
    2316           0 : void ATCAFiller::unlock()
    2317             : {
    2318           0 :   atms_p.unlock();
    2319           0 :   atms_p.antenna().unlock();
    2320           0 :   atms_p.dataDescription().unlock();
    2321           0 :   atms_p.feed().unlock();
    2322           0 :   atms_p.field().unlock();
    2323           0 :   atms_p.observation().unlock();
    2324           0 :   atms_p.history().unlock();
    2325           0 :   atms_p.pointing().unlock();
    2326           0 :   atms_p.polarization().unlock();
    2327           0 :   atms_p.source().unlock();
    2328           0 :   atms_p.spectralWindow().unlock();
    2329           0 :   atms_p.sysCal().unlock();
    2330           0 :   atms_p.weather().unlock();
    2331           0 : }
    2332             : 
    2333           0 : Bool ATCAFiller::selected(Int ifNum)
    2334             : {
    2335           0 :   Bool select=true;
    2336             :   //Check for rotten eggs
    2337           0 :   if (if_.if_nfreq[ifNum]==0) 
    2338           0 :     select=false;
    2339             :   // check if we want this frequency 
    2340           0 :   if (spws_p.nelements()>0 && spws_p(0)>=0 && !anyEQ(spws_p,ifNum)) {
    2341           0 :     select=false;
    2342             :   } else {
    2343             :     // check if we want this frequency
    2344           0 :     if (lowFreq_p>0 && (doubles_.if_freq[ifNum]-lowFreq_p)<0) 
    2345           0 :       select=false;
    2346             :     else {
    2347           0 :       if (highFreq_p>0 && (highFreq_p-doubles_.if_freq[ifNum])<0) 
    2348           0 :         select=false;
    2349             :       else {
    2350             :         // check if we want this bandwidth on the first IF
    2351           0 :         if (bandWidth1_p>0 && 
    2352           0 :         (bandWidth1_p != myround(doubles_.if_bw[ifNum]/1.e6))) 
    2353           0 :           select=false;
    2354             :         else {
    2355             :           // check if we want this number of channels on the first IF
    2356           0 :           if (numChan1_p>0 && numChan1_p != if_.if_nfreq[ifNum])
    2357           0 :             select=false;
    2358             :         }
    2359             :       }
    2360             :     }
    2361             :   }
    2362           0 :   return select;
    2363             : }
    2364             : 
    2365           0 : void ATCAFiller::shadow(Int row, Bool last)
    2366             : {
    2367             :   // 1. collect together all rows with the same time
    2368             :   // 2. determine which antennas are shadowed
    2369             :   // 3. flag all baselines involving a shadowed antenna 
    2370             : 
    2371           0 :   if (last || msc_p->time()(row)!=prevTime_p) {
    2372             :     // flag previous rows if needed
    2373           0 :     if (nRowCache_p>0) {
    2374           0 :       Vector<Bool> flag(nAnt_p); flag=false;
    2375           0 :       Vector<Double> uvw;
    2376           0 :       for (Int i=0; i< nRowCache_p; i++) {
    2377           0 :         Int k=rowCache_p[i];
    2378             :         // check for shadowing: projected baseline < shadow diameter
    2379           0 :         uvw = msc_p->uvw()(k);
    2380           0 :         double uvd2=uvw(0)*uvw(0)+uvw(1)*uvw(1);
    2381           0 :         if (uvd2>0) {
    2382           0 :           Bool shadowed = (uvd2<shadow_p*shadow_p);
    2383           0 :           if (shadowed) {
    2384             :             // w term decides which antenna is being shadowed
    2385           0 :             if (uvw(2)>0) {
    2386           0 :               flag(msc_p->antenna2()(k))=true;
    2387             :               //            cout << " Shadowed: antenna2="<<msc_p->antenna2()(k)<<" for row "
    2388             :               //                 <<k<<" time="<< msc_p->timeMeas()(k) <<endl;
    2389             :             } else {
    2390           0 :               flag(msc_p->antenna1()(k))=true;
    2391             :               //            cout << " Shadowed: antenna1="<<msc_p->antenna1()(k)<<" for row "
    2392             :               //                 <<k<<" time="<<msc_p->timeMeas()(k) <<endl;
    2393             :             }
    2394             :           }
    2395             :         }
    2396             :       }
    2397             :       // now flag rows with shadowed antennas
    2398           0 :       for (Int i=0; i< nRowCache_p; i++) {
    2399           0 :         Int k=rowCache_p[i];
    2400           0 :         Int ant1 = msc_p->antenna1()(k);
    2401           0 :         Int ant2 = msc_p->antenna2()(k);
    2402           0 :         if (flag(ant1) || flag(ant2)) {
    2403           0 :           flagCount_p(SHADOW)++;
    2404           0 :           msc_p->flagRow().put(k,true);
    2405             :         }
    2406             :       }
    2407           0 :     }
    2408             :     // reinitialize
    2409           0 :     if (!last) {
    2410           0 :       nRowCache_p=0;
    2411           0 :       prevTime_p=msc_p->time()(row);
    2412             :     }
    2413             :   }
    2414           0 :   if (!last) {
    2415           0 :     if (Int(rowCache_p.nelements())<=nRowCache_p) {
    2416           0 :       rowCache_p.resize(2*(nRowCache_p+1),true);
    2417             :     }
    2418           0 :     rowCache_p[nRowCache_p++]=row;
    2419             :   }
    2420           0 : }
    2421             : 
    2422           0 : Bool ATCAFiller::samplerFlag(Int row, Double posNegTolerance, 
    2423             :                              Double zeroTolerance) {
    2424             :   // check the sampler stats for the current row, return false if data needs to
    2425             :   // be flagged
    2426             : 
    2427           0 :   const Float posNegRef = 17.3;
    2428           0 :   const Float zeroRef =50.0;
    2429           0 :   Vector<Int> rows(2);
    2430           0 :   rows(0) = colSysCalIdAnt1(row);
    2431           0 :   rows(1) = colSysCalIdAnt2(row);
    2432           0 :   Bool flag = rows(0)<0 || rows(1)<0;
    2433           0 :   for (Int i=0; (!flag && i<2); i++) {
    2434           0 :     Vector<Float> neg = colSamplerStatsNeg(rows(i));
    2435           0 :     Vector<Float> pos = colSamplerStatsPos(rows(i));
    2436           0 :     Vector<Float> zero = colSamplerStatsZero(rows(i));
    2437           0 :     flag |=(abs(neg(0)-posNegRef)>posNegTolerance) ||
    2438           0 :            (abs(neg(1)-posNegRef)>posNegTolerance) ||
    2439           0 :            (abs(pos(0)-posNegRef)>posNegTolerance) ||
    2440           0 :            (abs(pos(1)-posNegRef)>posNegTolerance) ||
    2441           0 :            (abs(zero(0)-zeroRef)>zeroTolerance) ||
    2442           0 :            (abs(zero(1)-zeroRef)>zeroTolerance);
    2443           0 :   }
    2444           0 :   return flag;
    2445           0 : }
    2446             : 
    2447           0 : Vector<Double> ATCAFiller::opacities(Vector<Double> fGHz, Float tempK,Float humi,Float press,
    2448             :                                      Float height) {
    2449             :   // use (former) ASAP/Miriad code to calculate zenith opacities at a range of frequencies
    2450             :   // given the surface weather conditions
    2451             :   
    2452           0 :   ATAtmosphere atm = ATAtmosphere(tempK,press*100.,humi/100.);
    2453           0 :   atm.setObservatoryElevation(height);
    2454           0 :   return atm.zenithOpacities(fGHz*1e9);
    2455           0 : }
    2456             : 
    2457             : } //# end casa namespace

Generated by: LCOV version 1.16