LCOV - code coverage report
Current view: top level - alma/MS2ASDM - MS2ASDM.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 2806 0.0 %
Date: 2024-10-04 18:58:15 Functions: 0 42 0.0 %

          Line data    Source code
       1             : //# MS2ASDM.cc 
       2             : //#
       3             : //#  ALMA - Atacama Large Millimeter Array
       4             : //#  (c) European Southern Observatory, 2002
       5             : //#  (c) Associated Universities Inc., 2002
       6             : //#  Copyright by ESO (in the framework of the ALMA collaboration),
       7             : //#  Copyright by AUI (in the framework of the ALMA collaboration),
       8             : //#  All rights reserved.
       9             : //#  
      10             : //#  This library is free software; you can redistribute it and/or
      11             : //#  modify it under the terms of the GNU Lesser General Public
      12             : //#  License as published by the Free software Foundation; either
      13             : //#  version 2.1 of the License, or (at your option) any later version.
      14             : //#  
      15             : //#  This library is distributed in the hope that it will be useful,
      16             : //#  but WITHOUT ANY WARRANTY, without even the implied warranty of
      17             : //#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             : //#  Lesser General Public License for more details.
      19             : //#  
      20             : //#  You should have received a copy of the GNU Lesser General Public
      21             : //#  License along with this library; if not, write to the Free Software
      22             : //#  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      23             : //#  MA 02111-1307  USA
      24             : //# $Id: $
      25             : #include <casacore/tables/TaQL/ExprNode.h>
      26             : #include <casacore/tables/Tables/RefRows.h>
      27             : #include <casacore/ms/MeasurementSets/MSColumns.h>
      28             : #include <casacore/casa/Quanta/MVBaseline.h>
      29             : #include <casacore/casa/Arrays/Matrix.h>
      30             : #include <casacore/casa/Arrays/Cube.h>
      31             : #include <casacore/casa/Arrays/ArrayMath.h>
      32             : #include <casacore/casa/Arrays/ArrayOpsDiffShapes.h>
      33             : #include <casacore/casa/Arrays/ArrayLogical.h>
      34             : #include <casacore/casa/Arrays/ArrayUtil.h>
      35             : #include <casacore/casa/Arrays/IPosition.h>
      36             : #include <casacore/casa/Arrays/Slice.h>
      37             : #include <casacore/casa/Logging/LogIO.h>
      38             : #include <casacore/casa/OS/File.h>
      39             : #include <casacore/casa/OS/HostInfo.h>
      40             : #include <casacore/casa/Containers/Record.h>
      41             : #include <casacore/casa/BasicMath/Math.h>
      42             : #include <casacore/casa/BasicSL/String.h>
      43             : #include <casacore/casa/Utilities/Assert.h>
      44             : #include <casacore/casa/Utilities/GenSort.h>
      45             : #include <casacore/casa/System/AppInfo.h>
      46             : #include <casacore/tables/DataMan/IncrementalStMan.h>
      47             : #include <casacore/tables/Tables/ScalarColumn.h>
      48             : #include <casacore/tables/Tables/ScaColDesc.h>
      49             : #include <casacore/tables/Tables/SetupNewTab.h>
      50             : #include <casacore/tables/DataMan/StandardStMan.h>
      51             : #include <casacore/tables/Tables/Table.h>
      52             : #include <casacore/tables/Tables/TableDesc.h>
      53             : #include <casacore/tables/Tables/TableInfo.h>
      54             : #include <casacore/tables/Tables/TableLock.h>
      55             : #include <casacore/tables/Tables/TableRecord.h>
      56             : #include <casacore/tables/Tables/TableCopy.h>
      57             : #include <casacore/tables/Tables/TableRow.h>
      58             : #include <casacore/tables/DataMan/TiledColumnStMan.h>
      59             : #include <casacore/tables/DataMan/TiledShapeStMan.h>
      60             : #include <casacore/tables/DataMan/TiledDataStMan.h>
      61             : #include <casacore/tables/DataMan/TiledStManAccessor.h>
      62             : #include <casacore/measures/Measures/MeasTable.h>
      63             : #include <sstream>
      64             : #include <iomanip>
      65             : 
      66             : #include <algorithm>
      67             : #include <casacore/casa/OS/Directory.h>
      68             : #include <alma/ASDM/ASDMAll.h>
      69             : #include <alma/ASDMBinaries/SDMDataObjectWriter.h>
      70             : #include <alma/ASDMBinaries/SDMDataObject.h>
      71             : 
      72             : #include <alma/MS2ASDM/MS2ASDM.h>
      73             : 
      74             : using asdm::ASDM;
      75             : using asdm::TagType;
      76             : using namespace asdm;
      77             : using namespace asdmbinaries;
      78             : 
      79             : using namespace casacore;
      80             : namespace casa {
      81             : 
      82             :   using casacore::Double;
      83             :   using casacore::Complex;
      84             :   using casacore::Float;
      85             :   
      86           0 :   MS2ASDM::MS2ASDM(MeasurementSet& ms) :
      87             :     MSColumns(ms),
      88           0 :     ms_p(ms),
      89           0 :     baseUid_p("uid://X0/X0/X"),
      90           0 :     runningId_p(0),
      91           0 :     currentUid_p("uid://X0/X0/X0"),
      92           0 :     telName_p(""),
      93             :     // the maps with defaults
      94           0 :     asdmFeedId_p(-1),
      95           0 :     asdmSourceId_p(-1),
      96           0 :     asdmPointingModelId_p(-1)
      97             :   {
      98           0 :     ASDM_p = new ASDM();
      99           0 :     asdmVersion_p = String((ASDM_p->getEntity()).getEntityVersion());
     100           0 :     setSBDuration(); // set to default values
     101           0 :     setSubScanDuration(); 
     102           0 :     setDataAPCorrected();
     103           0 :     setVerbosity();
     104           0 :   }
     105             :   
     106           0 :   MS2ASDM::~MS2ASDM()
     107             :   {
     108           0 :     delete ASDM_p;
     109           0 :   }
     110             :   
     111           0 :   const String& MS2ASDM::showversion()
     112             :   {
     113             : 
     114           0 :     static String rstr = String(asdmVersion_p);
     115           0 :     if(rstr==""){
     116           0 :       ASDM* myASDM = new ASDM();
     117           0 :       rstr = String((myASDM->getEntity()).getEntityVersion());
     118           0 :       delete myASDM;
     119             :     }
     120           0 :     return rstr;
     121             :   }
     122             :   
     123           0 :   void MS2ASDM::setBaseUid(const String& baseuid){ baseUid_p = baseuid; }
     124             : 
     125           0 :   const String& MS2ASDM::getBaseUid(){ return baseUid_p; }
     126             : 
     127           0 :   const std::string& MS2ASDM::getCurrentUid(){ 
     128           0 :     static std::string str;
     129           0 :     str = string(currentUid_p.c_str());
     130           0 :     return str; 
     131             :   }
     132             : 
     133           0 :   const std::string& MS2ASDM::getCurrentUidAsFileName(){ 
     134           0 :     static std::string str;
     135           0 :     str = string(currentUid_p.c_str());
     136           0 :     std::replace( str.begin(), str.end(), ':', '_' );
     137           0 :     std::replace( str.begin(), str.end(), '/', '_' );
     138             : 
     139           0 :     return str; 
     140             :   }
     141             : 
     142           0 :   Bool MS2ASDM::incrementUid()
     143             :   {
     144             :     static char cstr[20];
     145           0 :     runningId_p++;
     146           0 :     if(sprintf(cstr,"%x", runningId_p) > 0){
     147           0 :       currentUid_p = baseUid_p + String(cstr);
     148           0 :       return true;
     149             :     }
     150             :     else{
     151           0 :       runningId_p--;
     152           0 :       return false;
     153             :     }
     154             :   }
     155             : 
     156           0 :   Bool MS2ASDM::writeASDM(const String& asdmfile, const String& datacolumn, 
     157             :                           const String& archiveid, const String& rangeid, Bool verbose,
     158             :                           const casacore::Double subscanDuration, const casacore::Double schedBlockDuration,
     159             :                           const Bool msDataIsAPCorrected)
     160             :   {
     161             : 
     162           0 :     LogIO os(LogOrigin("MS2ASDM", "writeASDM()"));
     163             : 
     164           0 :     setBaseUid("uid://"+archiveid+"/"+rangeid+"/X");
     165             : 
     166           0 :     if(!incrementUid()){// need to increment before first use
     167             :       os << LogIO::SEVERE << "Error generating UID"
     168           0 :          << LogIO::POST;      
     169           0 :       return false;
     170             :     }
     171             : 
     172             :     // set the container UID of all tables == the UID of the ASDM
     173           0 :     asdmUID_p = getCurrentUid().c_str();
     174           0 :     Entity myEntity;
     175           0 :     myEntity.setEntityId(EntityId(asdmUID_p));
     176           0 :     myEntity.setEntityIdEncrypted("na");
     177           0 :     myEntity.setEntityTypeName("ASDM");
     178           0 :     myEntity.setEntityVersion(asdmVersion_p);
     179           0 :     myEntity.setInstanceVersion("1"); 
     180           0 :     ASDM_p->setEntity(myEntity);
     181             :       
     182           0 :     incrementUid();
     183             : 
     184             :     // initialize observatory name
     185           0 :     if(observation().nrow()==0){
     186           0 :       os << LogIO::SEVERE << "MS Observation table is empty." << LogIO::POST;
     187           0 :       return false;
     188             :     }
     189             : 
     190           0 :     setObservatoryName(observation().telescopeName()(0)); // get name of observatory from first row of observation table
     191             : 
     192           0 :     if(subscanDuration<1.){
     193             :       os << LogIO::SEVERE << "Input error: Unreasonably short sub scan duration limit: " << subscanDuration  
     194           0 :          << " seconds." << LogIO::POST;
     195           0 :       return false;
     196             :     }
     197             :      
     198           0 :     if(schedBlockDuration<60.){
     199             :       os << LogIO::SEVERE << "Input error: Unreasonably short scheduling block duration limit: " << schedBlockDuration  
     200           0 :          << " seconds. (Should be >= 60 s)" << LogIO::POST;
     201           0 :       return false;
     202             :     }
     203             :      
     204           0 :     setSubScanDuration(subscanDuration);
     205             : 
     206           0 :     setSBDuration(schedBlockDuration);
     207             : 
     208           0 :     setDataAPCorrected(msDataIsAPCorrected);
     209             : 
     210           0 :     if(verbose){
     211           0 :       setVerbosity(1); // set to 1 before releasing
     212             :     }
     213             :     else{
     214           0 :       setVerbosity(0);
     215             :     }
     216             : 
     217           0 :     if(verbosity_p>0){
     218             :       os << LogIO::NORMAL << "Converting " << ms_p.tableName() << " to ASDM " << asdmfile << endl
     219           0 :          << "UID base is " << getBaseUid() << ", ASDM UID is " << asdmUID_p
     220           0 :          << LogIO::POST;
     221             :     }
     222             : 
     223             :     // write the ASDM tables
     224             : 
     225           0 :     if(!writeStation()){
     226           0 :       return false;
     227             :     }
     228             : 
     229           0 :     if(!writeAntenna()){
     230           0 :       return false;
     231             :     }
     232             : 
     233           0 :     if(!writeSpectralWindow()){
     234           0 :       return false;
     235             :     }
     236             : 
     237           0 :     if(!writeSource()){
     238           0 :       return false;
     239             :     }
     240             : 
     241           0 :     if(!writePolarization()){
     242           0 :       return false;
     243             :     }
     244             : 
     245           0 :     if(!writeProcessor()){
     246           0 :       return false;
     247             :     }
     248             : 
     249           0 :     if(!writeField()){
     250           0 :       return false;
     251             :     }
     252             : 
     253           0 :     if(!writeReceiver()){
     254           0 :       return false;
     255             :     }
     256             : 
     257           0 :     if(!writeFeed()){
     258           0 :       return false;
     259             :     }
     260             : 
     261           0 :     if(!writeDataDescription()){
     262           0 :       return false;
     263             :     }
     264             : 
     265           0 :     if(!writeSwitchCycle()){
     266           0 :       return false;
     267             :     }
     268             : 
     269           0 :     if(!writeState()){
     270           0 :       return false;
     271             :     }
     272             : 
     273           0 :     if(!writeSysCal()){
     274           0 :       return false;
     275             :     }
     276             : 
     277           0 :     if(!writeConfigDescription()){
     278           0 :       return false;
     279             :     }
     280             : 
     281           0 :     if(!writeSBSummaryAndExecBlockStubs()){ 
     282           0 :       return false;
     283             :     }
     284             : 
     285             :     // prepare the writing of binary data
     286           0 :     if(!setDirectory(asdmfile)){
     287           0 :        return false;
     288             :     }
     289             : 
     290           0 :     if(!writeMainAndScanAndSubScan(datacolumn)){ 
     291           0 :       return false;
     292             :     }
     293             : 
     294           0 :     if(!writePointingModel()){
     295           0 :       return false;
     296             :     }
     297             : 
     298           0 :     if(!writePointing()){
     299           0 :       return false;
     300             :     }
     301             : 
     302             :     // finish writing the ASDM non-binary data
     303             :     try{
     304           0 :       ASDM_p->toFile(asdmfile);
     305             :     }
     306           0 :     catch(ConversionException x){
     307           0 :       os << LogIO::SEVERE << "Error writing ASDM non-binary data:" << x.getMessage()
     308           0 :          << LogIO::POST;      
     309           0 :       return false;
     310           0 :     }     
     311             : 
     312           0 :     return true;
     313             : 
     314           0 :   }
     315             : 
     316           0 :   Bool MS2ASDM::setDirectory(const String& asdmfile){
     317             : 
     318           0 :     LogIO os(LogOrigin("MS2ASDM", "setDirectory()"));
     319             : 
     320             :     // create ASDM output directories
     321           0 :     Directory asdmDir(asdmfile);
     322             :     // create if it doesn't exist
     323             :     try{
     324           0 :       asdmDir.isEmpty(); // throws if dir doesn't exist
     325             :     }
     326           0 :     catch(AipsError x){
     327             :       try{
     328           0 :         asdmDir.create(false); // do not overwrite
     329             :       }
     330           0 :       catch(AipsError y){
     331             :         os << LogIO::SEVERE << "Error creating ASDM top directory: " << y.getMesg()
     332           0 :            << LogIO::POST;      
     333           0 :         return false;
     334           0 :       }
     335           0 :     }
     336             :     // create ASDM binary output directory
     337           0 :     Directory asdmDir2(asdmfile+"/ASDMBinary");
     338             :     try{
     339           0 :       asdmDir2.create(false); // do not overwrite
     340             :     }
     341           0 :     catch(AipsError x){
     342             :       os << LogIO::SEVERE << "Error creating ASDMBinary directory: " << x.getMesg()
     343           0 :          << LogIO::POST;      
     344           0 :       return false;
     345           0 :     }
     346           0 :     asdmDir_p = asdmfile;
     347           0 :     return true;
     348           0 :   }
     349             : 
     350             : 
     351           0 :   Int MS2ASDM::writeMainBinSubScanForOneDDIdFIdPair(const Int theDDId, const Int theFieldId, 
     352             :                                                     const String& datacolumn, 
     353             :                                                     const uInt theScan, const uInt theSubScan,
     354             :                                                     const uInt startRow, const uInt endRow,
     355             :                                                     const Tag eBlockId,
     356             :                                                     int& datasize, asdm::EntityRef& dataOid, 
     357             :                                                     vector< asdm::Tag >& stateIdV){
     358             : 
     359           0 :     LogIO os(LogOrigin("MS2ASDM", "writeMainBinForOneDDIdAndSubScan()"));
     360             : 
     361             :     // return values
     362           0 :     Int numIntegrations = 0;
     363           0 :     datasize = 0;
     364           0 :     dataOid = EntityRef();
     365           0 :     stateIdV.resize(0);
     366             : 
     367           0 :     asdm::ExecBlockRow* eBlockRow = (ASDM_p->getExecBlock()).getRowByKey(eBlockId);
     368           0 :     string eBlockUID = eBlockRow->getExecBlockUID().getEntityId ().toString();
     369           0 :     int eBlockNum = eBlockRow->getExecBlockNum();
     370             : 
     371           0 :     Bool warned=false; // use later to avoid repetitive warnings
     372           0 :     Bool warned2=false; // use later to avoid repetitive warnings
     373             : 
     374             :     try{
     375             : 
     376           0 :       uInt nMainTabRows = ms_p.nrow();
     377             : 
     378           0 :       unsigned int subscanNum = theSubScan;
     379             : 
     380           0 :       if(startRow>=nMainTabRows){
     381             :         os << LogIO::SEVERE << "Internal error: startRow " << startRow << " exceeds end of MS."
     382           0 :            << LogIO::POST;
     383           0 :         return -1;
     384             :       }
     385             : 
     386           0 :       if(endRow>=nMainTabRows){
     387             :         os << LogIO::SEVERE << "Internal error: endRow " << endRow << " exceeds end of MS."
     388           0 :            << LogIO::POST;
     389           0 :         return -1;
     390             :       }
     391             : 
     392           0 :       Int DDId = dataDescId()(startRow);
     393           0 :       if(DDId != theDDId){ // check Data Description Id
     394             :         os << LogIO::SEVERE << "Internal error: input parameters to this routine are inconsistent.\n"
     395           0 :            << " DDId in start row should be as given in input parameters ==" << theDDId << LogIO::POST;
     396           0 :         return -1;
     397             :       }
     398             :       
     399           0 :       Int FId = fieldId()(startRow);
     400           0 :       if(FId != theFieldId){ // check Field Id
     401             :         os << LogIO::SEVERE << "Internal error: input parameters to this routine are inconsistent.\n"
     402           0 :            << " FieldId in start row should be as given in input parameters ==" << theFieldId << LogIO::POST;
     403           0 :         return -1;
     404             :       }
     405             : 
     406           0 :       if(verbosity_p>1){
     407             :         os << LogIO::NORMAL << "Writing Main table entries for DataDescId " << DDId 
     408             :            << ", Field Id " << FId << ", ExecBlock " << eBlockNum << ", Scan number " << theScan
     409           0 :            << ", SubScan number " << theSubScan << LogIO::POST;
     410             :       }
     411             : 
     412             :       //////////////////////
     413             :       // Construct subscan == SDMDataObject
     414             :       
     415             :       // Assume MS main table is sorted in time. 
     416             :       
     417             :       // Get first timestamp.
     418           0 :       Double subScanStartTime = time()(startRow);
     419           0 :       Double subScanEndTime = time()(endRow); 
     420             :       
     421             :       // determine number of different timestamps in this subscan 
     422           0 :       unsigned int numTimestampsCorr = 0;
     423           0 :       unsigned int numTimestampsAuto = 0;
     424           0 :       for(uInt i=startRow; i<=endRow; i++){
     425             : 
     426           0 :         DDId = dataDescId()(i);
     427           0 :         if(DDId != theDDId){ // skip all other Data Description Ids
     428           0 :           continue;
     429             :         }
     430           0 :         FId = fieldId()(i);
     431           0 :         if(FId != theFieldId){ // skip all other Field Ids
     432           0 :           continue;
     433             :         }
     434             :         
     435           0 :         if(antenna1()(i)==antenna2()(i)){
     436           0 :           numTimestampsAuto++;
     437             :         }
     438             :         else{
     439           0 :           numTimestampsCorr++;
     440             :         }
     441             :       } // end for i
     442             : 
     443           0 :       if(verbosity_p>1){
     444           0 :         cout << " subscan number is " << subscanNum << endl;
     445           0 :         cout << " DDId " << theDDId << " FId " << theFieldId << endl;
     446           0 :         cout << " start row " << startRow << " end row " << endRow << endl;
     447           0 :         cout << "  subscan number of timestamps with crosscorrelations is " << numTimestampsCorr << endl;
     448           0 :         cout << "  subscan number of timestamps with autocorrelations is " << numTimestampsAuto << endl;
     449           0 :         cout << "  subscan end time is " << subScanEndTime << endl;
     450             :       }
     451             :       
     452             :       // open disk file for subscan
     453           0 :       String subscanFileName = asdmDir_p+"/ASDMBinary/"+String(getCurrentUidAsFileName());
     454           0 :       if(verbosity_p>1){
     455           0 :         cout << "  subscan filename is " << subscanFileName << endl;
     456             :       }
     457             :       try{
     458           0 :         dataOid = EntityRef(getCurrentUid(),"","ASDM",asdmVersion_p); 
     459             :       }
     460           0 :       catch(asdm::InvalidArgumentException x){
     461             :         os << LogIO::SEVERE << "Error creating ASDM:  UID \"" << getCurrentUid() 
     462           0 :            << "\" (intended for a BLOB) is not a valid Entity reference: " <<  x.getMessage()
     463           0 :            << LogIO::POST;      
     464           0 :         return -1;
     465           0 :       }
     466             :         
     467             :       // make sure that this file doesn't exist yet
     468           0 :       ofstream ofs(subscanFileName.c_str());
     469             :       
     470             :       // set up SDMDataObjectWriter
     471             :       
     472           0 :       SDMDataObjectWriter sdmdow(&ofs, getCurrentUid()); // use default title
     473             :       
     474           0 :       uint64_t startTime = (uint64_t) floor(subScanStartTime);
     475           0 :       unsigned int execBlockNum = eBlockNum; // constant for all scans
     476           0 :       unsigned int scanNum = theScan; // ASDM scan numbering starts at 1
     477           0 :       if(scanNum == 0 && !warned){
     478           0 :         os << LogIO::WARN << "Scan Number is 0. Note that by convention scan numbers in ASDMs should start at 1." << LogIO::POST;
     479           0 :         warned = true;
     480             :       }
     481             : 
     482             :       // find the first occurence of the timestamp which has the most baselines
     483           0 :       uInt theSampleStartRow = 0;
     484             :       {
     485           0 :         uInt maxNRows = 0;
     486             :         
     487           0 :         uInt mainTabRowX=startRow; 
     488             : 
     489           0 :         while(mainTabRowX <= endRow){
     490             :         
     491           0 :           DDId = dataDescId()(mainTabRowX);
     492           0 :           if(DDId != theDDId){ // skip all other Data Description Ids
     493           0 :             mainTabRowX++;
     494           0 :             continue;
     495             :           }
     496           0 :           FId = fieldId()(mainTabRowX);
     497           0 :           if(FId != theFieldId){ // skip all other Field Ids
     498           0 :             mainTabRowX++;
     499           0 :             continue;
     500             :           }
     501             :           
     502           0 :           Double theTStamp = time()(mainTabRowX);
     503           0 :           uInt sRow = mainTabRowX;
     504           0 :           uInt nRows = 0;
     505           0 :           while(mainTabRowX < nMainTabRows 
     506           0 :                 && time()(mainTabRowX)==theTStamp){
     507           0 :             DDId = dataDescId()(mainTabRowX);
     508           0 :             if(DDId != theDDId){ // skip all other Data Description Ids
     509           0 :               mainTabRowX++;
     510           0 :               continue;
     511             :             }
     512           0 :             FId = fieldId()(mainTabRowX);
     513           0 :             if(FId != theFieldId){ // skip all other Field Ids
     514           0 :               mainTabRowX++;
     515           0 :               continue;
     516             :             }
     517           0 :             nRows++;
     518           0 :             mainTabRowX++;
     519             :           }
     520           0 :           if(nRows>maxNRows){
     521           0 :             maxNRows = nRows;
     522           0 :             theSampleStartRow = sRow;
     523             :           }
     524             :         } // end while
     525             :       }
     526             : 
     527             :       // determine actual number of baselines and antennas
     528             :       // (at the same time also fill the stateId vector)
     529           0 :       unsigned int numAutoCorrs = 0;
     530           0 :       unsigned int numBaselines = 0;
     531           0 :       unsigned int numAntennas = 0;
     532           0 :       vector<Int> ant;
     533             :       {
     534           0 :         uInt i = theSampleStartRow;
     535           0 :         Double thisTStamp = time()(i); 
     536           0 :         while(i<nMainTabRows && time()(i)== thisTStamp){
     537             :           
     538           0 :           DDId = dataDescId()(i);
     539           0 :           if(DDId != theDDId){ // skip all other Data Description Ids
     540           0 :             i++;
     541           0 :             continue;
     542             :           }
     543           0 :           FId = fieldId()(i);
     544           0 :           if(FId != theFieldId){ // skip all other Field Ids
     545           0 :             i++;
     546           0 :             continue;
     547             :           }
     548             :           
     549           0 :           if(antenna1()(i) == antenna2()(i)){
     550           0 :             numAutoCorrs++;
     551             :           }
     552             :           else{
     553           0 :             numBaselines++;
     554             :           }
     555             :           
     556           0 :           Bool found = false;
     557           0 :           for(uInt j=0;j<ant.size();j++){
     558           0 :             if(antenna1()(i) == ant[j]){
     559           0 :               found = true;
     560           0 :               break;
     561             :             }
     562             :           }
     563           0 :           if(!found){
     564           0 :             ant.push_back(antenna1()(i));
     565           0 :             stateIdV.push_back( asdmStateId_p[stateId()(i)] );
     566             :           }
     567           0 :           found = false;
     568           0 :           for(uInt j=0;j<ant.size();j++){
     569           0 :             if(antenna2()(i) == ant[j]){
     570           0 :               found = true;
     571           0 :               break;
     572             :             }
     573             :           }
     574           0 :           if(!found){
     575           0 :             ant.push_back(antenna2()(i));
     576           0 :             stateIdV.push_back( asdmStateId_p[stateId()(i)] );
     577             :           }
     578           0 :           i++;
     579             :         }
     580             :       }
     581           0 :       numAntennas = ant.size();
     582             :       
     583             :       CorrelationModeMod::CorrelationMode correlationMode;
     584           0 :       if(numAutoCorrs==0){
     585           0 :         correlationMode = CorrelationModeMod::CROSS_ONLY;
     586             :       }
     587           0 :       else if(numBaselines>0){
     588           0 :         correlationMode = CorrelationModeMod::CROSS_AND_AUTO;
     589             :       }
     590             :       else{
     591           0 :         correlationMode = CorrelationModeMod::AUTO_ONLY;
     592             :       }
     593             :       // if datacolumn is FLOAT_DATA make correlation mode == AUTO as well!
     594             :       
     595             :       
     596           0 :       vector< AtmPhaseCorrectionMod::AtmPhaseCorrection >  apc;
     597           0 :       if(dataIsAPCorrected()){
     598           0 :         apc.push_back(AtmPhaseCorrectionMod::AP_CORRECTED); 
     599             :       }
     600             :       else{
     601           0 :         apc.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED); 
     602             :       }     
     603           0 :       vector< SDMDataObject::Baseband > basebands; // ???
     604             :       
     605             :       // construct spectral window and basedband vectors
     606             :       
     607           0 :       vector<SDMDataObject::SpectralWindow> spectralWindows;
     608             :       
     609             :       // for creating a Spectral Window
     610           0 :       uInt PolId = dataDescription().polarizationId()(theDDId);
     611           0 :       uInt numStokesMS = polarization().numCorr()(PolId);
     612             : 
     613           0 :       asdm::PolarizationRow* PR = (ASDM_p->getPolarization()).getRowByKey(asdmPolarizationId_p[PolId]);
     614           0 :       uInt numStokes = PR->getNumCorr();
     615           0 :       Array<Int> corrT = polarization().corrType()(PolId);
     616           0 :       vector<StokesParameterMod::StokesParameter> crossPolProducts = PR->getCorrType();
     617             : 
     618           0 :       vector<StokesParameterMod::StokesParameter> sdPolProduct;
     619           0 :       float scaleFactor = 1.;
     620           0 :       uInt spwId = dataDescription().spectralWindowId()(theDDId);
     621           0 :       unsigned int numSpectralPoint = spectralWindow().numChan()(spwId);
     622             : 
     623           0 :       OptionalSpectralResolutionType spectralResolution = SpectralResolutionTypeMod::FULL_RESOLUTION; 
     624           0 :       if(numSpectralPoint<5){
     625             :         //      spectralResolution = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
     626           0 :         if(!warned2 && verbosity_p>1){
     627             :           //      os << LogIO::NORMAL << "    Less than 5 channels. Assuming data is of spectral resolution type \"CHANNEL_AVERAGE\"." << LogIO::POST;      
     628             :           //    }
     629             :           os << LogIO::NORMAL << " DDId " << theDDId << ": Less than 5 channels. Probably should use spectral resolution type \"CHANNEL_AVERAGE\"." 
     630           0 :              << endl << "    But this is not yet implemented. Assuming FULL_RESOLUTION." << LogIO::POST;      
     631           0 :           warned2 = true;
     632             :         }
     633             :       } 
     634             : 
     635           0 :       unsigned int numBin = 1; // number of switch cycles
     636           0 :       NetSidebandMod::NetSideband sideband = CNetSideband::from_int(spectralWindow().netSideband()(spwId));
     637             :       
     638             :       SDMDataObject::SpectralWindow spw(crossPolProducts,
     639             :                                         sdPolProduct,
     640             :                                         scaleFactor,
     641             :                                         numSpectralPoint,
     642             :                                         numBin,
     643           0 :                                         sideband);
     644             :       
     645           0 :       spectralWindows.push_back(spw);
     646             :       
     647             :       
     648           0 :       SDMDataObject::Baseband bband(BasebandNameMod::NOBB, spectralWindows); // how to select name ???? -> Francois
     649             :       // note: for ALMA only four basebands exist, not easy to find baseband for a given SPW
     650             :       
     651           0 :       basebands.push_back(bband);
     652             :       
     653             :       // construct binary parts for dataStruct
     654           0 :       unsigned int bpFlagsSize = numSpectralPoint * numStokes * (numBaselines+numAutoCorrs);
     655             : 
     656           0 :       vector<AxisNameMod::AxisName> bpFlagsAxes;
     657           0 :       bpFlagsAxes.push_back(AxisNameMod::TIM); // order: inner part of loop should be last!!!!!!
     658           0 :       bpFlagsAxes.push_back(AxisNameMod::SPP); 
     659           0 :       bpFlagsAxes.push_back(AxisNameMod::POL);
     660           0 :       SDMDataObject::BinaryPart bpFlags(bpFlagsSize, bpFlagsAxes);
     661           0 :       if(verbosity_p>1){
     662           0 :         cout << "FlagsSize " << bpFlagsSize << " numStokes " << numStokes << endl;
     663             :       }
     664             :       
     665           0 :       unsigned int bpTimesSize = 0; // only needed for data blanking
     666             :       //unsigned int bpTimesSize = numTimestampsCorr+numTimestampsAuto; 
     667           0 :       vector<AxisNameMod::AxisName> bpTimesAxes;
     668             : //      bpTimesAxes.push_back(AxisNameMod::TIM);
     669           0 :       SDMDataObject::BinaryPart bpActualTimes(bpTimesSize, bpTimesAxes);
     670             :       //      cout << "TimesSize " << bpTimesSize << endl;
     671             :       
     672           0 :       unsigned int bpDurSize = 0; // only needed for data blanking
     673             :       //        unsigned int bpDurSize = numTimestampsCorr+numTimestampsAuto;
     674           0 :       vector<AxisNameMod::AxisName> bpDurAxes;
     675             : //      bpDurAxes.push_back(AxisNameMod::TIM);
     676           0 :       SDMDataObject::BinaryPart bpActualDurations(bpDurSize, bpDurAxes);
     677             :       //      cout << "DurSize " << bpDurSize << endl;
     678             :       
     679           0 :       unsigned int bpLagsSize = 0; // not filled for the moment (only useful if LAG_DATA column present) -> Francois 
     680           0 :       vector<AxisNameMod::AxisName> bpLagsAxes;
     681           0 :       bpLagsAxes.push_back(AxisNameMod::SPP); // ******
     682           0 :       SDMDataObject::ZeroLagsBinaryPart bpZeroLags(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FXF); // ALMA default
     683           0 :       if(telName_p != "ALMA" && telName_p != "OSF"){
     684           0 :         if(telName_p == "ACA" || telName_p == "VLBA" || telName_p == "EVLA"){
     685           0 :           bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::FX);          
     686             :         }
     687             :         else{
     688           0 :           bpZeroLags = SDMDataObject::ZeroLagsBinaryPart(bpLagsSize, bpLagsAxes, CorrelatorTypeMod::XF);
     689             :         }
     690             :       }
     691             :       //      cout << "LagsSize " << bpLagsSize << endl;
     692             :       
     693           0 :       unsigned int bpCrossSize = numSpectralPoint * numStokes * numBaselines * 2; // real + imag
     694           0 :       vector<AxisNameMod::AxisName> bpCrossAxes;
     695             :       //      bpCrossAxes.push_back(AxisNameMod::TIM);
     696           0 :       bpCrossAxes.push_back(AxisNameMod::BAL);
     697           0 :       bpCrossAxes.push_back(AxisNameMod::SPP); 
     698           0 :       bpCrossAxes.push_back(AxisNameMod::POL);
     699           0 :       SDMDataObject::BinaryPart bpCrossData(bpCrossSize, bpCrossAxes);
     700             :       //      cout << "CrossSize " << bpCrossSize << endl;
     701             :       
     702           0 :       unsigned int bpAutoSize = numSpectralPoint * numStokes * numAutoCorrs;
     703           0 :       vector<AxisNameMod::AxisName> bpAutoAxes;
     704             :       //      bpAutoAxes.push_back(AxisNameMod::TIM);
     705           0 :       bpAutoAxes.push_back(AxisNameMod::ANT);
     706           0 :       bpAutoAxes.push_back(AxisNameMod::SPP); 
     707           0 :       bpAutoAxes.push_back(AxisNameMod::POL);
     708           0 :       SDMDataObject::AutoDataBinaryPart bpAutoData(bpAutoSize, bpAutoAxes, false); // not normalised
     709             :       //      cout << "AutoSize " << bpAutoSize << endl;
     710             :       
     711             :       SDMDataObject::DataStruct dataStruct( apc, basebands, bpFlags, bpActualTimes, bpActualDurations, 
     712           0 :                                             bpZeroLags, bpCrossData, bpAutoData);        
     713             :       
     714             :       // Parameters of dataStruct:
     715             :       //        apc             a vector of AtmPhaseCorrection. If apc is not relevant pass an empty vector.
     716             :       //        basebands       a vector of Baseband.
     717             :       //        flags           a BinaryPart object describing the flags. If flags is not relevant pass an 
     718             :       //                      empty BinaryPart object.
     719             :       //        actualTimes     a BinaryPart object describing the actual times. If actualTimes is not 
     720             :       //                      relevant pass an empty BinaryPart object.
     721             :       //        actualDurations a BinaryPart object describing the actual durations. If actualDurations is 
     722             :       //                      not relevant pass an empty BinaryPart object.
     723             :       //        zeroLags        a ZeroLagsBinaryPart object describing the zero lags. If zeroLags is not 
     724             :       //                      relevant pass an empty ZeroLagsBinaryPart object.
     725             :       //        crossData       a BinaryPart object describing the cross data. If crossData is not relevant 
     726             :       //                      pass an empty BinaryPart object.
     727             :       //        autoData        an AutoDataBinaryPart object describing the auto data. If autoData is not 
     728             :       //                      relevant pass an empty AutoDataBinaryPart object. 
     729             :       
     730             :       
     731             :       // Write the global header.
     732           0 :       sdmdow.corrDataHeader(startTime,
     733             :                             eBlockUID,
     734             :                             execBlockNum,
     735             :                             scanNum,
     736             :                             subscanNum,
     737             :                             numAntennas,        
     738             :                             correlationMode,    // the correlation mode.
     739             :                             spectralResolution, // the spectral resolution.
     740             :                             dataStruct);        // the description of the structure of the binary data.
     741             :       
     742             :       //////////////////////////////////////////////////////
     743             :       // write the integrations until timestamp exceeds limit
     744           0 :       unsigned int integrationNum = 1;
     745           0 :       uInt mainTabRow=startRow; 
     746             : 
     747           0 :       while(mainTabRow <= endRow){
     748             :         
     749           0 :         DDId = dataDescId()(mainTabRow);
     750           0 :         if(DDId != theDDId){ // skip all other Data Description Ids
     751           0 :           mainTabRow++;
     752           0 :           continue;
     753             :         }
     754           0 :         FId = fieldId()(mainTabRow);
     755           0 :         if(FId != theFieldId){ // skip all other Field Ids
     756           0 :           mainTabRow++;
     757           0 :           continue;
     758             :         }
     759             :         
     760           0 :         uint64_t timev = (uint64_t) floor((time()(mainTabRow))*1E9); // what units? nanoseconds
     761           0 :         uint64_t intervalv = (uint64_t) floor(interval()(mainTabRow)*1E9);
     762           0 :         vector< unsigned int > flags;
     763           0 :         vector< int64_t > actualTimes;
     764           0 :         vector< int64_t > actualDurations;
     765           0 :         vector< float > zeroLags; // LAG_DATA, optional column, not used for the moment
     766           0 :         vector< float > crossData;
     767             :         // vector< short > crossData;
     768             :         // vector< int > crossData; // standard case for ALMA
     769           0 :         vector< float > autoData;  
     770             :         
     771             :         ////////////////////////////////////////////////////////
     772             :         // fill data, time, and flag vectors for this timestamp
     773           0 :         Double theTStamp = time()(mainTabRow);
     774             :         
     775             :         // SORT the data by baseline and antenna resp.!!!!!!!!!!!!
     776             : 
     777             :         // create a list of the row numbers in this timestamp sorted by baseline in BDF style,
     778             :         // i.e., e.g., for antennas (1,2,3,4): ['(1,1)', '(1,2)', '(2,2)', '(1,3)', '(2,3)', '(3,3)', '(1,4)', 
     779             :         //                             '(2,4)', '(3,4)', '(4,4)', '(1,5)', '(2,5)', '(3,5)', '(4,5)', '(5,5)']
     780           0 :         vector< uInt > rowsSorted;
     781             :         {
     782           0 :           vector< uInt > rows;
     783           0 :           while(mainTabRow < nMainTabRows 
     784           0 :                 && time()(mainTabRow)==theTStamp){
     785           0 :             DDId = dataDescId()(mainTabRow);
     786           0 :             if(DDId != theDDId){ // skip all other Data Description Ids
     787           0 :               mainTabRow++;
     788           0 :               continue;
     789             :             }
     790           0 :             FId = fieldId()(mainTabRow);
     791           0 :             if(FId != theFieldId){ // skip all other Field Ids
     792           0 :               mainTabRow++;
     793           0 :               continue;
     794             :             }
     795           0 :             rows.push_back(mainTabRow);
     796           0 :             mainTabRow++;
     797             :           }
     798             : 
     799           0 :           uInt nRows = rows.size();
     800           0 :           vector<Int> bLine(nRows);
     801           0 :           uInt maxAnt = 0;
     802           0 :           for(uInt i=0; i<nRows; i++){
     803           0 :             uInt a2 = antenna2()(rows[i]);
     804           0 :             bLine[i] = antenna1()(rows[i])*1000 + a2;
     805           0 :             if(maxAnt<a2){
     806           0 :               maxAnt=a2;
     807             :             }
     808             :           }     
     809             : 
     810           0 :           rowsSorted.resize(nRows);
     811           0 :           uInt expNRows = maxAnt*(maxAnt+1)/2; // (zero-based counting)
     812           0 :           uInt expNRowsWAuto = maxAnt*(maxAnt+1)/2 + maxAnt+1; // (zero-based counting)
     813           0 :           Bool haveAuto = false;
     814           0 :           if(nRows==expNRowsWAuto){
     815           0 :             haveAuto=true;
     816             :           }
     817           0 :           else if(nRows!=expNRows){ 
     818           0 :             ostringstream oss;
     819           0 :             oss << "Expected " << expNRows << " rows in integration but found " << nRows << endl;
     820           0 :             throw(asdmbinaries::SDMDataObjectWriterException(oss.str()));
     821           0 :           }
     822           0 :           uInt count=0;
     823           0 :           for(uInt i= (haveAuto ? 0 : 1) ; i<maxAnt+1; i++){
     824           0 :             for(uInt j=0; j< (haveAuto ? i+1 : i); j++){
     825           0 :               Int myBLine = j*1000 + i;
     826           0 :               for(uInt ii=0; ii<nRows; ii++){
     827           0 :                 if(bLine[ii]==myBLine){
     828           0 :                   rowsSorted[count] = rows[ii];
     829           0 :                   break;
     830             :                 }
     831           0 :                 if(ii==nRows-1){ // not found
     832           0 :                   ostringstream oss;
     833           0 :                   oss << "Baseline " << myBLine << " not found." << endl;
     834           0 :                   throw(asdmbinaries::SDMDataObjectWriterException(oss.str()));
     835           0 :                 }
     836             :               }
     837           0 :               count++;
     838             :             }
     839             :           }
     840             : 
     841           0 :         }
     842             :         
     843           0 :         for(uInt ii=0; ii<rowsSorted.size(); ii++){
     844             :           
     845           0 :           uInt iRow = rowsSorted[ii];
     846             : 
     847           0 :           DDId = dataDescId()(iRow);
     848           0 :           FId = fieldId()(iRow);
     849             :           
     850           0 :           Matrix<casacore::Complex> dat;
     851           0 :           Matrix<Bool> flagsm;
     852           0 :           String dataColumn(datacolumn);
     853           0 :           dataColumn.upcase();
     854           0 :           if(dataColumn == "MODEL"){
     855           0 :             dat.reference(modelData()(iRow));
     856             :           }
     857           0 :           else if(dataColumn == "CORRECTED"){
     858           0 :             dat.reference(correctedData()(iRow));
     859             :           }
     860             :           else{
     861           0 :             dat.reference(data()(iRow));
     862             :           }
     863           0 :           flagsm.reference(flag()(iRow));
     864             :           
     865             :           //cout << " ii row a1 a2 " << ii << " " << iRow << " " << antenna1()(iRow) << " " << antenna2()(iRow) << endl;
     866             : 
     867           0 :           Bool haveAuto = (antenna1()(iRow) == antenna2()(iRow));
     868             : 
     869           0 :           if(haveAuto){
     870           0 :             Complex x;  
     871             :             float a;
     872           0 :             for(uInt i=0; i<numSpectralPoint; i++){
     873           0 :               for(uInt j=0; j<numStokesMS; j++){
     874           0 :                 if(skipCorr_p[PolId][j]){
     875           0 :                   continue;
     876             :                 }
     877             :                 else{
     878           0 :                   x = dat(j,i);
     879           0 :                   a = x.real();
     880           0 :                   autoData.push_back( a );
     881             :                 }
     882             :               }
     883             :             }
     884             :           }
     885             :           else{
     886           0 :             casacore::Complex x;
     887             :             float a,b;
     888             :             // int a,b;
     889           0 :             for(uInt i=0; i<numSpectralPoint; i++){
     890           0 :               for(uInt j=0; j<numStokesMS; j++){
     891           0 :                 x = dat(j,i);
     892           0 :                 a = x.real();
     893           0 :                 b = x.imag();
     894           0 :                 crossData.push_back( a );
     895           0 :                 crossData.push_back( b );
     896             :               }
     897             :             }
     898             :           }
     899             : 
     900             :           unsigned int ul;
     901           0 :           for(uInt i=0; i<numSpectralPoint; i++){
     902           0 :             for(uInt j=0; j<numStokesMS; j++){
     903           0 :               if(haveAuto && skipCorr_p[PolId][j]){
     904           0 :                 continue;
     905             :               }
     906             :               else{
     907           0 :                 if(flagRow()(iRow)){
     908           0 :                   ul = 1;
     909             :                 }
     910             :                 else{
     911           0 :                   ul = flagsm(j,i);
     912             :                 }
     913           0 :                 flags.push_back( ul );
     914             :               }
     915             :             }
     916             :           }
     917             :           // the following two lines only needed for data blanking
     918             :           //        actualTimes.push_back((int64_t)floor(time()(iRow))*1000.);
     919             :           //        actualDurations.push_back((int64_t)floor(interval()(iRow))*1000.);
     920           0 :         }// end loop over rows in this timestamp sorted by baseline
     921             :         
     922             : 
     923             :         // fill with flagged entries in case there are missing baselines in the MS
     924           0 :         uInt nToAdd1 = 0;
     925           0 :         uInt nToAdd2 = 0;
     926           0 :         uInt nToAdd3 = 0;
     927           0 :         uInt nToAdd4 = 0;
     928           0 :         uInt nToAdd5 = 0;
     929           0 :         uInt nToAdd6 = 0;
     930             : 
     931           0 :         if(flags.size()<bpFlagsSize){
     932           0 :           nToAdd1 = bpFlagsSize - flags.size();
     933           0 :           for(uInt i=0; i<nToAdd1; i++){
     934           0 :             flags.push_back(1);
     935             :           }
     936             :         }       
     937           0 :         if(actualTimes.size()<bpTimesSize){
     938           0 :           nToAdd2 = bpTimesSize-actualTimes.size();
     939           0 :           for(uInt i=0; i<nToAdd2; i++){
     940           0 :             actualTimes.push_back(0);
     941             :           }
     942             :         }
     943           0 :         if(actualDurations.size()<bpDurSize){
     944           0 :           nToAdd3 = bpDurSize-actualDurations.size();
     945           0 :           for(uInt i=0; i<nToAdd3; i++){
     946           0 :             actualDurations.push_back(0);
     947             :           }
     948             :         }
     949           0 :         if(zeroLags.size()<bpLagsSize){
     950           0 :           nToAdd4 = bpLagsSize-zeroLags.size();
     951           0 :           for(uInt i=0; i<nToAdd4; i++){
     952           0 :             zeroLags.push_back(0.);
     953             :           }
     954             :         }
     955           0 :         if(crossData.size()<bpCrossSize){
     956           0 :           nToAdd5 = bpCrossSize-crossData.size();
     957           0 :           for(uInt i=0; i<nToAdd5; i++){
     958           0 :             crossData.push_back(0.);
     959             :           }
     960             :         }
     961           0 :         if(autoData.size()<bpAutoSize){
     962           0 :           nToAdd6 = bpAutoSize-autoData.size();
     963           0 :           for(uInt i=0; i<nToAdd6; i++){
     964           0 :             autoData.push_back(0.);
     965             :           }
     966             :         }
     967             : 
     968           0 :         if(nToAdd1+nToAdd2+nToAdd3+nToAdd4+nToAdd5+nToAdd6>0){
     969             :           os << LogIO::WARN << "Encountered missing integrations for some baselines in MS."
     970             :              << " Will fill with flagged entries (" << nToAdd1 << ", " << nToAdd2 << ", " << nToAdd3 
     971           0 :              << ", "<< nToAdd4 << ", "<< nToAdd5 << ", "<< nToAdd6 << ")" << LogIO::POST; 
     972             :         }
     973             :         
     974             :         // finally write the integration
     975             :           
     976           0 :         if(verbosity_p>1){
     977           0 :           cout << "Sizes: " << endl;
     978           0 :           cout << "   flags " << flags.size() << endl;
     979           0 :           cout << "   actualTimes " << actualTimes.size() << endl;
     980           0 :           cout << "   actualDurations " << actualDurations.size() << endl;
     981           0 :           cout << "   zeroLags " << zeroLags.size() << endl;
     982           0 :           cout << "   crossData " << crossData.size() << endl;
     983           0 :           cout << "   autoData " << autoData.size() << endl;
     984             :         }
     985             : 
     986             :         try{
     987             : 
     988           0 :           sdmdow.addIntegration(integrationNum,    // integration's index.
     989             :                                 timev,             // midpoint
     990             :                                 intervalv,         // time interval
     991             :                                 flags,             // flags binary data 
     992             :                                 actualTimes,       // actual times binary data      
     993             :                                 actualDurations,   // actual durations binary data          
     994             :                                 zeroLags,          // zero lags binary data                 
     995             :                                 crossData,    // cross data (can be short or int)  
     996             :                                 autoData);         // single dish data.  
     997             : 
     998           0 :           integrationNum++;
     999           0 :           datasize += flags.size() * sizeof(unsigned int)
    1000           0 :             + actualTimes.size() * sizeof( int64_t )
    1001           0 :             + actualDurations.size() * sizeof( int64_t )
    1002           0 :             + zeroLags.size() * sizeof( float )
    1003           0 :             + crossData.size() * sizeof( float )
    1004           0 :             + autoData.size() * sizeof( float );
    1005           0 :           numIntegrations++;
    1006             : 
    1007             :         }
    1008           0 :         catch(asdmbinaries::SDMDataObjectWriterException x){
    1009           0 :           os << LogIO::WARN << "Error writing ASDM:" << x.getMessage() << endl
    1010             :              << "Will try to continue ..."
    1011           0 :              << LogIO::POST; 
    1012           0 :         }
    1013             :         // (Note: subintegrations are used only for channel averaging to gain time res. by sacrificing spec. res.)
    1014             :         
    1015           0 :       } // end while 
    1016             :       
    1017           0 :       sdmdow.done();
    1018             :       
    1019           0 :       ofs.close();
    1020             :       
    1021             :       // end write subscan
    1022             :       
    1023           0 :       incrementUid();
    1024             :             
    1025           0 :     }
    1026           0 :     catch(asdmbinaries::SDMDataObjectWriterException x){
    1027           0 :       os << LogIO::SEVERE << "Error creating ASDM: " << x.getMessage()
    1028           0 :          << LogIO::POST;      
    1029           0 :       return -1;
    1030           0 :     }
    1031           0 :     catch(asdmbinaries::SDMDataObjectException x){
    1032           0 :       os << LogIO::SEVERE << "Error creating ASDM: " << x.getMessage()
    1033           0 :          << LogIO::POST;      
    1034           0 :       return -1;
    1035           0 :     }
    1036           0 :     catch(AipsError y){
    1037             :       os << LogIO::SEVERE << "Error creating ASDM: " << y.getMesg()
    1038           0 :          << LogIO::POST;      
    1039           0 :       return -1;
    1040           0 :     }      
    1041           0 :     catch(std::string z){
    1042             :       os << LogIO::SEVERE << "Error creating ASDM: " << z
    1043           0 :          << LogIO::POST;      
    1044           0 :       return -1;
    1045           0 :     }      
    1046           0 :     catch(std::exception zz){
    1047             :       os << LogIO::SEVERE << "Error creating ASDM: " << zz.what()
    1048           0 :          << LogIO::POST;      
    1049           0 :       return -1;
    1050           0 :     }      
    1051             :     
    1052           0 :     return numIntegrations;
    1053             : 
    1054           0 :   } // end writeMainBinForOneDDIdAndSubScan
    1055             : 
    1056             : 
    1057             :   /////////////////////////////////////
    1058             :   //   // Pattern for wrting a non-binary table:
    1059             :   //   Bool MS2ASDM::writeAntenna(){ // create asdm antenna table and fill antenna id map
    1060             :   //     LogIO os(LogOrigin("MS2ASDM", "writeAntenna()"));
    1061             :   
    1062             :   //     Bool rstat = true;
    1063             :   
    1064             :   //     asdm::AntennaTable& tT = ASDM_p->getAntenna();
    1065             :   
    1066             :   //     asdm::AntennaRow* tR = 0;
    1067             :   
    1068             :   //     //    tR = tT.newRow();
    1069             :   
    1070             :   //     tT.add(tR);
    1071             :   
    1072             :   //     EntityId theUid(getCurrentUid());
    1073             :   //     Entity ent = tT.getEntity();
    1074             :   //     ent.setEntityId(theUid);
    1075             :   //     tT.setEntity(ent);
    1076             :   //     if(verbosity_p>0){
    1077             :   //       os << LogIO::NORMAL << "Filled Antenna table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1078             :   //     }
    1079             :   //     incrementUid();
    1080             :   
    1081             :   //     return rstat;
    1082             :   //   }
    1083             : 
    1084           0 :   Bool MS2ASDM::writeStation(){ // create asdm station table and fill station id map
    1085           0 :     LogIO os(LogOrigin("MS2ASDM", "writeStation()"));
    1086             : 
    1087           0 :     Bool rstat = true;
    1088             : 
    1089           0 :     asdm::StationTable& tT = ASDM_p->getStation();
    1090             : 
    1091           0 :     asdm::StationRow* tR = 0;
    1092             : 
    1093             :     // MS has no station table; get information from the antenna table
    1094             : 
    1095           0 :     for(uInt irow=0; irow<antenna().nrow(); irow++){
    1096             : 
    1097             :       // parameters for the new station row
    1098           0 :       StationTypeMod::StationType type = StationTypeMod::ANTENNA_PAD; 
    1099             :       // (alternatives are MAINTENANCE_PAD and WEATHER_STATION)
    1100             : 
    1101             :       // parameters of the new row
    1102           0 :       string name = antenna().station()(irow).c_str();
    1103             : 
    1104           0 :       vector<Length > position; // take the antenna position (!), (later set the ASDM antenna postion to 0,0,0)
    1105           0 :       Vector<Double > v; // aux. vector
    1106           0 :       v.reference(antenna().position()(irow));
    1107           0 :       for(uInt i=0; i<v.size(); i++){
    1108           0 :         position.push_back(Length(v[i]));
    1109             :       }
    1110             : 
    1111           0 :       Tag stationId;
    1112           0 :       String sId = antenna().station()(irow);
    1113           0 :       tR = tT.newRow(name, position, type);
    1114             :       
    1115           0 :       asdm::StationRow* tR2 = 0;
    1116             : 
    1117           0 :       tR2 = tT.add(tR);
    1118           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    1119             :         // enter tag into the map
    1120           0 :           asdmStationId_p[String(name)] = tR->getStationId();
    1121             :       }
    1122             :       else{
    1123           0 :         os << LogIO::SEVERE << "Duplicate station in MS Antenna table: " << irow << LogIO::POST;
    1124           0 :         return false;
    1125             :       }
    1126             : 
    1127           0 :     } // end for irow
    1128             : 
    1129           0 :     EntityId theUid(getCurrentUid());
    1130           0 :     Entity ent = tT.getEntity();
    1131           0 :     ent.setEntityId(theUid);
    1132           0 :     tT.setEntity(ent);
    1133           0 :     if(verbosity_p>0){
    1134           0 :       os << LogIO::NORMAL << "Filled Station table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1135             :     }
    1136           0 :     incrementUid();
    1137             : 
    1138           0 :     return rstat;
    1139           0 :   }
    1140             : 
    1141           0 :   Bool MS2ASDM::writeAntenna(){ // create asdm antenna table and fill antenna id map
    1142           0 :     LogIO os(LogOrigin("MS2ASDM", "writeAntenna()"));
    1143             : 
    1144           0 :     Bool rstat = true;
    1145             : 
    1146           0 :     asdm::AntennaTable& tT = ASDM_p->getAntenna();
    1147             : 
    1148           0 :     asdm::AntennaRow* tR = 0;
    1149             : 
    1150           0 :     for(uInt irow=0; irow<antenna().nrow(); irow++){
    1151             : 
    1152             :       // parameters of the new row
    1153           0 :       string name = antenna().name()(irow).c_str();
    1154           0 :       AntennaMakeMod::AntennaMake antennaMake = AntennaMakeMod::UNDEFINED; // no info in MS (presently)
    1155           0 :       AntennaTypeMod::AntennaType antennaType = ASDMAntennaType( antenna().type()(irow) );
    1156           0 :       Length dishDiameter = Length( antenna().dishDiameter()(irow) );
    1157             : 
    1158           0 :       vector<Length > position;
    1159           0 :       for(uInt i=0; i<3; i++){
    1160           0 :         position.push_back(Length(0.)); // the antenna position in the ASDM is the sum of station pos and antenna pos.
    1161             :       }
    1162             : 
    1163           0 :       vector<Length > offset;
    1164           0 :       Vector<Double > v; // aux. vector
    1165           0 :       v.reference(antenna().offset()(irow));
    1166           0 :       for(uInt i=0; i<v.size(); i++){
    1167           0 :         offset.push_back(Length(v[i]));
    1168             :       }
    1169             : 
    1170           0 :       ArrayTime atime = ASDMArrayTime(time()(0)); // use start time of MS 
    1171             : 
    1172           0 :       Tag stationId;
    1173           0 :       String sId = antenna().station()(irow); // the station name
    1174           0 :       if(asdmStationId_p.find(sId) != asdmStationId_p.end( )){
    1175           0 :           stationId = asdmStationId_p[sId];
    1176             :       }
    1177             :       else{
    1178           0 :         os << LogIO::SEVERE << "Internal error: No station ID defined for station name " << sId << LogIO::POST;
    1179           0 :         return false;
    1180             :       }
    1181             :       
    1182           0 :       tR = tT.newRow(name, antennaMake, antennaType, dishDiameter, position, offset, atime, stationId);
    1183             :       
    1184           0 :       asdm::AntennaRow* tR2 = 0;
    1185             : 
    1186           0 :       tR2 = tT.add(tR);
    1187           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    1188             :         // enter tag into the map
    1189           0 :           asdmAntennaId_p[irow] = tR->getAntennaId();
    1190             :       }
    1191             :       else{
    1192           0 :         os << LogIO::WARN << "Duplicate row in MS Antenna table :" << irow << LogIO::POST;
    1193             :       }
    1194           0 :     }
    1195             : 
    1196           0 :     EntityId theUid(getCurrentUid());
    1197           0 :     Entity ent = tT.getEntity();
    1198           0 :     ent.setEntityId(theUid);
    1199           0 :     tT.setEntity(ent);
    1200           0 :     if(verbosity_p>0){
    1201           0 :       os << LogIO::NORMAL << "Filled Antenna table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1202             :     }
    1203           0 :     incrementUid();
    1204             : 
    1205           0 :     return rstat;
    1206           0 :   }
    1207             : 
    1208           0 :   Bool MS2ASDM::writeSpectralWindow(){
    1209           0 :     LogIO os(LogOrigin("MS2ASDM", "writeSpectralWindow()"));
    1210             : 
    1211           0 :     Bool rstat = true;
    1212             : 
    1213           0 :     asdm::SpectralWindowTable& tT = ASDM_p->getSpectralWindow();
    1214             : 
    1215           0 :     asdm::SpectralWindowRow* tR = 0;
    1216             : 
    1217           0 :     for(uInt irow=0; irow<spectralWindow().nrow(); irow++){
    1218             : 
    1219             :       // parameters of the new row
    1220           0 :       BasebandNameMod::BasebandName basebandName = BasebandNameMod::NOBB;
    1221           0 :       if(!spectralWindow().bbcNo().isNull()){ // BBC_NO is an optional MS column
    1222           0 :         basebandName = ASDMBBName( spectralWindow().bbcNo()(irow) );
    1223             :       }
    1224           0 :       NetSidebandMod::NetSideband netSideband = ASDMNetSideBand( spectralWindow().netSideband()(irow) );
    1225           0 :       int numChan = spectralWindow().numChan()(irow);
    1226             : 
    1227           0 :       Frequency refFreq  = Frequency( spectralWindow().refFrequencyQuant()(irow).getValue(unitASDMFreq()) );
    1228           0 :       SidebandProcessingModeMod::SidebandProcessingMode sidebandProcessingMode = SidebandProcessingModeMod::NONE;
    1229           0 :       Frequency totBandwidth = Frequency( spectralWindow().totalBandwidthQuant()(irow).getValue(unitASDMFreq()) );
    1230           0 :       WindowFunctionMod::WindowFunction windowFunction = WindowFunctionMod::UNIFORM;
    1231             : 
    1232           0 :       tR = tT.newRow(basebandName, netSideband, numChan, refFreq, sidebandProcessingMode, totBandwidth, windowFunction);
    1233             : 
    1234           0 :       Vector< Quantum<Double> > v;
    1235           0 :       vector< Frequency > chanFreqArray;
    1236           0 :       v.reference( spectralWindow().chanFreqQuant()(irow) );
    1237           0 :       for(uInt i=0; i<v.nelements(); i++){ 
    1238           0 :         chanFreqArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
    1239             :       }
    1240           0 :       tR->setChanFreqArray(chanFreqArray);
    1241             : 
    1242           0 :       vector< Frequency > chanWidthArray;
    1243           0 :       v.reference( spectralWindow().chanWidthQuant()(irow) );
    1244           0 :       for(uInt i=0; i<v.nelements(); i++){ 
    1245           0 :         chanWidthArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
    1246             :       }
    1247           0 :       tR->setChanWidthArray(chanWidthArray);
    1248             : 
    1249           0 :       vector< Frequency > effectiveBwArray;
    1250           0 :       v.reference( spectralWindow().effectiveBWQuant()(irow) );
    1251           0 :       for(uInt i=0; i<v.nelements(); i++){ 
    1252           0 :         effectiveBwArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
    1253             :       }
    1254           0 :       tR->setEffectiveBwArray(effectiveBwArray);
    1255             : 
    1256           0 :       vector< Frequency > resolutionArray;
    1257           0 :       v.reference( spectralWindow().resolutionQuant()(irow) );
    1258           0 :       for(uInt i=0; i<v.nelements(); i++){ 
    1259           0 :         resolutionArray.push_back( Frequency( v[i].getValue(unitASDMFreq()) ) );
    1260             :       }      
    1261           0 :       tR->setResolutionArray( resolutionArray );
    1262             : 
    1263           0 :       MFrequency::Types refFrame = MFrequency::castType(spectralWindow().measFreqRef()(irow));
    1264           0 :       FrequencyReferenceCodeMod::FrequencyReferenceCode measFreqRef = ASDMFreqRefCode( refFrame );
    1265           0 :       tR->setMeasFreqRef( measFreqRef );
    1266             : 
    1267           0 :       tR->setFreqGroup( spectralWindow().freqGroup()(irow) );
    1268             : 
    1269           0 :       tR->setFreqGroupName( string( spectralWindow().freqGroupName()(irow).c_str() ) );      
    1270             : 
    1271           0 :       if(!spectralWindow().dopplerId().isNull()){ // DOPPLER_ID is an optional MS column
    1272           0 :         tR->setDopplerId( spectralWindow().dopplerId()(irow) );
    1273             :       }
    1274             : 
    1275             :       // add the row to the table
    1276           0 :       asdm::SpectralWindowRow* tR2 = 0;
    1277           0 :       tR2 = tT.add(tR);
    1278             : 
    1279           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    1280             :         // enter tag into the map
    1281           0 :           asdmSpectralWindowId_p[irow] = tR->getSpectralWindowId();
    1282             :       }
    1283             :       else{
    1284           0 :         os << LogIO::WARN << "Duplicate row in MS Spectral Window table :" << irow << LogIO::POST;
    1285             :       }
    1286           0 :     } // end loop over MS SPW table
    1287             : 
    1288           0 :     EntityId theUid(getCurrentUid());
    1289           0 :     Entity ent = tT.getEntity();
    1290           0 :     ent.setEntityId(theUid);
    1291           0 :     tT.setEntity(ent);
    1292           0 :     if(verbosity_p>0){
    1293           0 :       os << LogIO::NORMAL << "Filled SpectralWindow table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1294             :     }
    1295           0 :     incrementUid();
    1296             : 
    1297           0 :     return rstat;
    1298           0 :   }
    1299             : 
    1300           0 :   Bool MS2ASDM::writeSource(){ // create asdm source table and fill source id map
    1301           0 :     LogIO os(LogOrigin("MS2ASDM", "writeSource()"));
    1302             :     
    1303           0 :     Bool rstat = true;
    1304             :     
    1305           0 :     asdm::SourceTable& tT = ASDM_p->getSource();
    1306             :     
    1307           0 :     asdm::SourceRow* tR = 0;
    1308             :     
    1309           0 :     if(source().isNull()){// the source table doesn't exist (it is optional)
    1310             :       os << LogIO::WARN << "MS Source table doesn't exist (it is optional). Cannot create ASDM Source table."
    1311           0 :          << LogIO::POST;
    1312           0 :       rstat = true; // not an error
    1313             :     }
    1314             :     else {
    1315           0 :       for(uInt irow=0; irow<source().nrow(); irow++){
    1316             : 
    1317           0 :         Int sId = source().sourceId()(irow);
    1318             : 
    1319             :         // parameters of the new row
    1320             : 
    1321           0 :         ArrayTimeInterval timeInterval( ASDMTimeInterval(source().timeQuant()(irow), source().intervalQuant()(irow)) );
    1322             :         //cout << "in writeSource: timeInterval " << source().time()(irow) << ", " << source().interval()(irow) << endl;
    1323             :         //cout << "                timeInterval " << timeInterval.getStartInNanoSeconds() << ", " << timeInterval.getDurationInNanoSeconds() << endl;
    1324             : 
    1325           0 :         Int spwId = source().spectralWindowId()(irow);
    1326           0 :         Tag spectralWindowId;
    1327           0 :         if( asdmSpectralWindowId_p.find(spwId) == asdmSpectralWindowId_p.end( ) ){
    1328           0 :           os << LogIO::SEVERE << "Undefined SPW id " << spwId << " in MS Source table row "<< irow << LogIO::POST;
    1329           0 :           return false;
    1330             :         } else {
    1331           0 :           spectralWindowId = asdmSpectralWindowId_p[spwId];
    1332             :         }
    1333           0 :         string code = source().code()(irow).c_str();
    1334           0 :         if(code=="" || code==" "){
    1335           0 :           code="-";
    1336             :         }
    1337           0 :         vector< Angle > direction;
    1338           0 :         MDirection theSourceDir = source().directionMeas()(irow);
    1339           0 :         direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(0) ) ); // RA
    1340           0 :         direction.push_back( Angle( theSourceDir.getAngle( unitASDMAngle() ).getValue()(1) ) ); // DEC
    1341             :         
    1342             :         MDirection::Types dirRef;
    1343           0 :         MDirection::getType(dirRef, theSourceDir.getRefString());
    1344             :         DirectionReferenceCodeMod::DirectionReferenceCode directionCode
    1345           0 :           = ASDMDirRefCode(dirRef);
    1346             : 
    1347           0 :         vector< AngularRate > properMotion;
    1348           0 :         if(!source().properMotionQuant().isNull()){
    1349           0 :           Vector< Quantity > pMV;
    1350           0 :           pMV.reference(source().properMotionQuant()(irow));
    1351             :           try{
    1352           0 :             properMotion.push_back( AngularRate( pMV[0].getValue(unitASDMAngularRate()) ) );
    1353           0 :             properMotion.push_back( AngularRate( pMV[1].getValue(unitASDMAngularRate()) ) );
    1354             :           }
    1355           0 :           catch(AipsError x){
    1356             :             os << LogIO::SEVERE << "Error accessing proper motion parameters in MS Source table row " << irow 
    1357           0 :                << ":\n   " << x.getMesg() << LogIO::POST;
    1358           0 :           }
    1359           0 :         }
    1360             :         else{ 
    1361           0 :           properMotion.push_back( AngularRate( 0. ) );
    1362           0 :           properMotion.push_back( AngularRate( 0. ) );
    1363             :         }         
    1364             :         
    1365           0 :         string sourceName = (source().name()(irow)).c_str();
    1366             : 
    1367           0 :         tR = tT.newRow(timeInterval, spectralWindowId, code, direction, properMotion, sourceName);
    1368             :     
    1369           0 :         tR->setDirectionCode(directionCode);
    1370             : 
    1371           0 :         asdm::SourceRow* tR2 = 0;
    1372             :         try{
    1373           0 :           tR2 = tT.add(tR);
    1374             :         }
    1375           0 :         catch(asdm::UniquenessViolationException x){
    1376             :           os << LogIO::WARN << "While creating ASDM:  UID \"" << getCurrentUid() 
    1377           0 :              << "\" Source table: " <<  x.getMessage() << endl
    1378             :              << "Will try to continue."
    1379           0 :              << LogIO::POST;   
    1380           0 :         }
    1381             : 
    1382           0 :         if(tR2 != tR){ // did not lead to the creation of a new tag
    1383           0 :           os << LogIO::WARN << "Duplicate MS Source table row " << irow << ", source id " << sId << LogIO::POST;
    1384             :         }
    1385           0 :         if( asdmSourceId_p.find(sId) == asdmSourceId_p.end( ) ){
    1386           0 :           int souId = tR2->getSourceId();
    1387           0 :           asdmSourceId_p[sId] = souId;
    1388             :         }
    1389           0 :       } // end loop over source table
    1390             :     } // id if source table exists
    1391             : 
    1392           0 :     EntityId theUid(getCurrentUid());
    1393           0 :     Entity ent = tT.getEntity();
    1394           0 :     ent.setEntityId(theUid);
    1395           0 :     tT.setEntity(ent);
    1396           0 :     if(verbosity_p>0){
    1397           0 :       os << LogIO::NORMAL << "Filled Source table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1398             :     }
    1399           0 :     incrementUid();
    1400             :     
    1401           0 :     return rstat;
    1402           0 :   }
    1403             : 
    1404             : 
    1405             : 
    1406           0 :   Bool MS2ASDM::writePolarization(){
    1407           0 :     LogIO os(LogOrigin("MS2ASDM", "writePolarization()"));
    1408             : 
    1409           0 :     Bool rstat = true;
    1410           0 :     asdm::PolarizationTable& tT = ASDM_p->getPolarization();
    1411             : 
    1412           0 :     asdm::PolarizationRow* tR = 0;
    1413             : 
    1414           0 :     skipCorr_p.resize(0); 
    1415             : 
    1416           0 :     for(uInt irow=0; irow<polarization().nrow(); irow++){
    1417             : 
    1418           0 :       if(polarization().flagRow()(irow)){
    1419           0 :         continue;
    1420             :       }
    1421             : 
    1422           0 :       vector< Bool > skipCorr;
    1423             : 
    1424             :       // parameters of the new row
    1425             : 
    1426           0 :       vector< StokesParameterMod::StokesParameter > corrTypeV;
    1427           0 :       vector< vector< PolarizationTypeMod::PolarizationType > > corrProduct;
    1428             :       
    1429           0 :       Vector< Int > v; // aux. vector
    1430           0 :       v.reference( polarization().corrType()(irow) );
    1431           0 :       for(uInt i=0; i<v.nelements(); i++){
    1432           0 :         Bool skip = true;
    1433           0 :         Stokes::StokesTypes st = static_cast<Stokes::StokesTypes>(v[i]);
    1434           0 :         if(st == Stokes::LR){ // only add if RL is not also present
    1435           0 :           if(!stokesTypePresent(v, Stokes::RL)){
    1436           0 :             skip = false;
    1437             :           }
    1438             :         }
    1439           0 :         else if(st == Stokes::YX){ // only add if XY is not also present
    1440           0 :           if(!stokesTypePresent(v, Stokes::XY)){
    1441           0 :             skip = false;
    1442             :           }
    1443             :         }
    1444             :         else{
    1445           0 :           skip = false;
    1446             :         }
    1447           0 :         corrTypeV.push_back( ASDMStokesParameter( st ) );
    1448           0 :         skipCorr.push_back(skip);
    1449             :       }
    1450           0 :       int numCorr = corrTypeV.size(); 
    1451           0 :       skipCorr_p.push_back(skipCorr);
    1452             : 
    1453             :       // now read the just created corrTypeV and write the correlation products accordingly
    1454           0 :       for(uInt i=0; i<corrTypeV.size(); i++){
    1455           0 :         vector< PolarizationTypeMod::PolarizationType > w;
    1456           0 :         switch(corrTypeV[i]){
    1457           0 :         case StokesParameterMod::RR:
    1458           0 :           w.push_back(PolarizationTypeMod::R);
    1459           0 :           w.push_back(PolarizationTypeMod::R);
    1460           0 :           break;
    1461           0 :         case StokesParameterMod::RL:
    1462           0 :           w.push_back(PolarizationTypeMod::R);
    1463           0 :           w.push_back(PolarizationTypeMod::L);
    1464           0 :           break;
    1465           0 :         case StokesParameterMod::LR:
    1466           0 :           w.push_back(PolarizationTypeMod::L);
    1467           0 :           w.push_back(PolarizationTypeMod::R);
    1468           0 :           break;
    1469           0 :         case StokesParameterMod::LL:
    1470           0 :           w.push_back(PolarizationTypeMod::L);
    1471           0 :           w.push_back(PolarizationTypeMod::L);
    1472           0 :           break;
    1473           0 :         case StokesParameterMod::XX:
    1474           0 :           w.push_back(PolarizationTypeMod::X);
    1475           0 :           w.push_back(PolarizationTypeMod::X);
    1476           0 :           break;
    1477           0 :         case StokesParameterMod::XY:
    1478           0 :           w.push_back(PolarizationTypeMod::X);
    1479           0 :           w.push_back(PolarizationTypeMod::Y);
    1480           0 :           break;
    1481           0 :         case StokesParameterMod::YX:
    1482           0 :           w.push_back(PolarizationTypeMod::Y);
    1483           0 :           w.push_back(PolarizationTypeMod::X);
    1484           0 :           break;
    1485           0 :         case StokesParameterMod::YY:
    1486           0 :           w.push_back(PolarizationTypeMod::Y);
    1487           0 :           w.push_back(PolarizationTypeMod::Y);
    1488           0 :           break;
    1489           0 :         case StokesParameterMod::RX:
    1490           0 :           w.push_back(PolarizationTypeMod::R);
    1491           0 :           w.push_back(PolarizationTypeMod::X);
    1492           0 :           break;
    1493           0 :         case StokesParameterMod::RY:
    1494           0 :           w.push_back(PolarizationTypeMod::R);
    1495           0 :           w.push_back(PolarizationTypeMod::Y);
    1496           0 :           break;
    1497           0 :         case StokesParameterMod::LX:
    1498           0 :           w.push_back(PolarizationTypeMod::L);
    1499           0 :           w.push_back(PolarizationTypeMod::X);
    1500           0 :           break;
    1501           0 :         case StokesParameterMod::LY:
    1502           0 :           w.push_back(PolarizationTypeMod::L);
    1503           0 :           w.push_back(PolarizationTypeMod::Y);
    1504           0 :           break;
    1505           0 :         case StokesParameterMod::XR:
    1506           0 :           w.push_back(PolarizationTypeMod::X);
    1507           0 :           w.push_back(PolarizationTypeMod::R);
    1508           0 :           break;
    1509           0 :         case StokesParameterMod::XL:
    1510           0 :           w.push_back(PolarizationTypeMod::X);
    1511           0 :           w.push_back(PolarizationTypeMod::L);
    1512           0 :           break;
    1513           0 :         case StokesParameterMod::YR:
    1514           0 :           w.push_back(PolarizationTypeMod::Y);
    1515           0 :           w.push_back(PolarizationTypeMod::R);
    1516           0 :           break;
    1517           0 :         case StokesParameterMod::YL:
    1518           0 :           w.push_back(PolarizationTypeMod::Y);
    1519           0 :           w.push_back(PolarizationTypeMod::L);
    1520           0 :           break;
    1521           0 :         case StokesParameterMod::I:
    1522           0 :           os << LogIO::NORMAL << "Note: Stokes I (probably WVR data) stored with corr. types XX." << LogIO::POST;
    1523           0 :           w.push_back(PolarizationTypeMod::X);
    1524           0 :           w.push_back(PolarizationTypeMod::X);
    1525           0 :           break;
    1526           0 :         default:
    1527           0 :           os << LogIO::SEVERE << "Cannot store correlation product for stokes parameter " << CStokesParameter::name(corrTypeV[i]) << LogIO::POST;
    1528           0 :           rstat = false;
    1529           0 :           break;
    1530             :         }         
    1531           0 :         corrProduct.push_back(w);
    1532           0 :       } // end loop over corrTypeV
    1533             : 
    1534           0 :       tR = tT.newRow(numCorr, corrTypeV, corrProduct);
    1535             : 
    1536             :       //cout << "ASDM numCorr is " << numCorr << endl;
    1537             : 
    1538             :       ////bool flagRow = polarization().flagRow()(irow);
    1539             :       ////tR->setFlagRow(flagRow);
    1540             : 
    1541             :       // add the row to the table
    1542           0 :       asdm::PolarizationRow* tR2 = 0;
    1543           0 :       tR2 = tT.add(tR);
    1544             : 
    1545           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    1546             :         // enter tag into the map
    1547           0 :           asdmPolarizationId_p[irow] = tR->getPolarizationId();
    1548             :       }
    1549             :       else{
    1550           0 :         os << LogIO::WARN << "Duplicate row in MS Polarization table :" << irow << LogIO::POST;
    1551             :       }
    1552           0 :     } // end loop over MS Pol table
    1553             : 
    1554           0 :     EntityId theUid(getCurrentUid());
    1555           0 :     Entity ent = tT.getEntity();
    1556           0 :     ent.setEntityId(theUid);
    1557           0 :     tT.setEntity(ent);
    1558           0 :     if(verbosity_p>0){
    1559           0 :       os << LogIO::NORMAL << "Filled Polarization table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1560             :     }
    1561           0 :     incrementUid();
    1562             : 
    1563           0 :     return rstat;
    1564           0 :   }
    1565             : 
    1566           0 :   Bool MS2ASDM::writeCorrelatorMode(){
    1567           0 :     LogIO os(LogOrigin("MS2ASDM", "writeCorrelatorMode()"));
    1568             : 
    1569           0 :     Bool rstat = true;
    1570           0 :     asdm::CorrelatorModeTable& tT = ASDM_p->getCorrelatorMode();
    1571             : 
    1572           0 :     asdm::CorrelatorModeRow* tR = 0;
    1573             : 
    1574             :     // create only one row
    1575             : 
    1576           0 :     int numBaseband = 1;
    1577           0 :     vector<BasebandNameMod::BasebandName > basebandNames;
    1578           0 :     basebandNames.push_back(BasebandNameMod::NOBB);
    1579           0 :     vector<int > basebandConfig;
    1580           0 :     basebandConfig.push_back(0);
    1581           0 :     AccumModeMod::AccumMode accumMode = AccumModeMod::NORMAL;
    1582           0 :     int binMode = 1; // standard setting for interferometry
    1583           0 :     int numAxes = 4; // time, antenna, stokes, pol 
    1584           0 :     vector<AxisNameMod::AxisName > axesOrderArray;
    1585           0 :     axesOrderArray.push_back(AxisNameMod::TIM);
    1586           0 :     axesOrderArray.push_back(AxisNameMod::ANT);
    1587           0 :     axesOrderArray.push_back(AxisNameMod::SPP); 
    1588           0 :     axesOrderArray.push_back(AxisNameMod::POL);
    1589           0 :     vector<FilterModeMod::FilterMode > filterMode;
    1590           0 :     filterMode.push_back(FilterModeMod::UNDEFINED);
    1591             : 
    1592           0 :     CorrelatorNameMod::CorrelatorName correlatorName = CorrelatorNameMod::ALMA_BASELINE; // the default
    1593           0 :     if(telName_p == "ALMA" || telName_p == "OSF"){
    1594           0 :       correlatorName = CorrelatorNameMod::ALMA_BASELINE; //???
    1595             :     }
    1596           0 :     else if(telName_p == "ACA"){
    1597           0 :       correlatorName = CorrelatorNameMod::ALMA_ACA; //???
    1598             :     }
    1599           0 :     else if(telName_p == "VLA"){
    1600           0 :       correlatorName = CorrelatorNameMod::NRAO_VLA; //???
    1601             :     }
    1602           0 :     else if(telName_p == "EVLA"){
    1603           0 :       correlatorName = CorrelatorNameMod::NRAO_WIDAR; //???
    1604             :     }
    1605           0 :     else if(telName_p == "PDB"){
    1606           0 :       correlatorName = CorrelatorNameMod::IRAM_PDB; //???
    1607             :     }
    1608             :     else{
    1609           0 :       os << LogIO::WARN << "Unknown telescope name: " << telName_p << ". Assuming ALMA_BASELINE." << LogIO::POST;
    1610             :     }      
    1611             : 
    1612           0 :     tR = tT.newRow(numBaseband, basebandNames, basebandConfig, accumMode, binMode, numAxes, axesOrderArray, filterMode, correlatorName);
    1613             : 
    1614           0 :     tT.add(tR);
    1615             : 
    1616           0 :     EntityId theUid(getCurrentUid());
    1617           0 :     Entity ent = tT.getEntity();
    1618           0 :     ent.setEntityId(theUid);
    1619           0 :     tT.setEntity(ent);
    1620           0 :     if(verbosity_p>0){
    1621           0 :       os << LogIO::NORMAL << "Filled CorrelatorMode table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1622             :     }
    1623           0 :     incrementUid();
    1624             : 
    1625           0 :     return rstat;
    1626           0 :   }
    1627             : 
    1628           0 :   Bool MS2ASDM::writeAlmaRadiometer(){
    1629           0 :     LogIO os(LogOrigin("MS2ASDM", "writeAlmaRadiometer()"));
    1630             : 
    1631           0 :     Bool rstat = true;
    1632           0 :     asdm::AlmaRadiometerTable& tT = ASDM_p->getAlmaRadiometer();
    1633             : 
    1634           0 :     asdm::AlmaRadiometerRow* tR = 0;
    1635             : 
    1636           0 :     tR = tT.newRow();
    1637             : 
    1638           0 :     tT.add(tR);
    1639             : 
    1640           0 :     EntityId theUid(getCurrentUid());
    1641           0 :     Entity ent = tT.getEntity();
    1642           0 :     ent.setEntityId(theUid);
    1643           0 :     tT.setEntity(ent);
    1644           0 :     if(verbosity_p>0){
    1645           0 :       os << LogIO::NORMAL << "Filled AlmaRadiometer table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1646             :     }
    1647           0 :     incrementUid();
    1648             : 
    1649           0 :     return rstat;
    1650           0 :   }
    1651             : 
    1652           0 :   Bool MS2ASDM::writeHolography(){
    1653           0 :     LogIO os(LogOrigin("MS2ASDM", "writeHolography()"));
    1654             : 
    1655           0 :     Bool rstat = true;
    1656           0 :     asdm::HolographyTable& tT = ASDM_p->getHolography();
    1657             : 
    1658           0 :     asdm::HolographyRow* tR = 0;
    1659             : 
    1660             :     //    tR = tT.newRow();
    1661             : 
    1662           0 :     tT.add(tR);
    1663             : 
    1664           0 :     EntityId theUid(getCurrentUid());
    1665           0 :     Entity ent = tT.getEntity();
    1666           0 :     ent.setEntityId(theUid);
    1667           0 :     tT.setEntity(ent);
    1668           0 :     if(verbosity_p>0){
    1669           0 :       os << LogIO::NORMAL << "Filled Holography table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1670             :     }
    1671           0 :     incrementUid();
    1672             : 
    1673           0 :     return rstat;
    1674           0 :   }
    1675             : 
    1676           0 :   Bool MS2ASDM::writeProcessor(){
    1677           0 :     LogIO os(LogOrigin("MS2ASDM", "writeProcessor()"));
    1678             : 
    1679           0 :     Bool rstat = true;
    1680           0 :     asdm::ProcessorTable& tT = ASDM_p->getProcessor();
    1681             : 
    1682           0 :     asdm::ProcessorRow* tR = 0;
    1683             : 
    1684           0 :     uInt nPRows = processor().nrow();
    1685             : 
    1686           0 :     if(nPRows > 0){ // need to test because MS processor table is obligatory but may be empty
    1687           0 :       for(uInt irow=0; irow<nPRows; irow++){
    1688             :         // parameters of the new row
    1689           0 :         Tag modeId;
    1690             :         ProcessorTypeMod::ProcessorType processorType;
    1691             :         ProcessorSubTypeMod::ProcessorSubType processorSubType;
    1692           0 :         if(processor().type()(irow) == "CORRELATOR"){
    1693           0 :           processorType = ProcessorTypeMod::CORRELATOR; 
    1694           0 :           if(processor().subType()(irow) == "ALMA_CORRELATOR_MODE"){
    1695           0 :             processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE; 
    1696             :           }
    1697             :           else{
    1698           0 :             os << LogIO::WARN << "Unsupported processor subType for type CORRELATOR " << processor().subType()(irow)
    1699           0 :                << " assuming ALMA_CORRELATOR" << LogIO::POST;
    1700           0 :             processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE; 
    1701             :           }         
    1702             :         }
    1703           0 :         else if(processor().type()(irow) == "SPECTROMETER"){
    1704           0 :           processorType = ProcessorTypeMod::SPECTROMETER; 
    1705           0 :           if(processor().subType()(irow) == "HOLOGRAPHY"){
    1706           0 :             processorSubType = ProcessorSubTypeMod::HOLOGRAPHY; 
    1707             :           }
    1708             :           else{
    1709           0 :             os << LogIO::WARN << "Unsupported processor subType for type SPECTROMETER " << processor().subType()(irow)
    1710           0 :                << " assuming HOLOGRAPHY" << LogIO::POST;
    1711           0 :             processorSubType = ProcessorSubTypeMod::HOLOGRAPHY; 
    1712             :           }         
    1713             :         }
    1714           0 :         else if(processor().type()(irow) == "RADIOMETER"){
    1715           0 :           processorType = ProcessorTypeMod::RADIOMETER; 
    1716           0 :           if(processor().subType()(irow) == "ALMA_RADIOMETER"){
    1717           0 :             processorSubType = ProcessorSubTypeMod::ALMA_RADIOMETER;
    1718             :           }
    1719             :           else{
    1720           0 :             os << LogIO::WARN << "Unsupported processor type " << processor().subType()(irow)
    1721           0 :                << " assuming ALMA_RADIOMETER" << LogIO::POST;
    1722           0 :             processorSubType = ProcessorSubTypeMod::ALMA_RADIOMETER;
    1723             :           }         
    1724             :         }
    1725             :         else{
    1726           0 :           os << LogIO::WARN << "Unsupported processor type " << processor().type()(irow)
    1727           0 :              << " assuming CORRELATOR" << LogIO::POST;
    1728           0 :           processorType = ProcessorTypeMod::CORRELATOR; 
    1729           0 :           processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE; 
    1730             :         }
    1731             : 
    1732             :         // the following three vectors need to be declared outside the switch statement below;
    1733             :         // otherwise the compiler complains
    1734           0 :         vector< asdm::CorrelatorModeRow* > corrModeRows;
    1735           0 :         vector< asdm::HolographyRow* > holographyRows;
    1736           0 :         vector< asdm::AlmaRadiometerRow* > almaRadiometerRows;
    1737             :           
    1738           0 :         switch(processorSubType){
    1739           0 :         case ProcessorSubTypeMod::ALMA_CORRELATOR_MODE:
    1740           0 :           if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
    1741           0 :             return false;
    1742             :           }
    1743           0 :           corrModeRows = (ASDM_p->getCorrelatorMode()).get();
    1744           0 :           if(corrModeRows.size()==0){
    1745           0 :             os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
    1746           0 :             return false;
    1747             :           }
    1748           0 :           modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ??? 
    1749           0 :           break;
    1750           0 :         case ProcessorSubTypeMod::HOLOGRAPHY:
    1751           0 :           if(!writeHolography()){ // create the optional Holography table
    1752           0 :             return false;
    1753             :           }
    1754           0 :           holographyRows = (ASDM_p->getHolography()).get();
    1755           0 :           if(holographyRows.size()==0){
    1756           0 :             os << LogIO::SEVERE << "Internal error: ASDM Holography table is empty." << LogIO::POST;
    1757           0 :             return false;
    1758             :           }
    1759           0 :           modeId = holographyRows[0]->getHolographyId(); // get tag from first row of Holography table (there is only one) ??? 
    1760           0 :           break;
    1761           0 :         case ProcessorSubTypeMod::ALMA_RADIOMETER:
    1762           0 :           if(!writeAlmaRadiometer()){ // create the optional AlmaRadiometer table
    1763           0 :             return false;
    1764             :           }
    1765           0 :           almaRadiometerRows = (ASDM_p->getAlmaRadiometer()).get();
    1766           0 :           if(almaRadiometerRows.size()==0){
    1767           0 :             os << LogIO::SEVERE << "Internal error: ASDM AlmaRadiometer table is empty." << LogIO::POST;
    1768           0 :             return false;
    1769             :           }
    1770           0 :           modeId = almaRadiometerRows[0]->getAlmaRadiometerId(); // get tag from first row of AlmaRadiometer table (there is only one) ??? 
    1771           0 :           break;
    1772           0 :         default:
    1773             :           os << LogIO::SEVERE << "Internal error: unsupported processor sub type." 
    1774           0 :              << CProcessorSubType::name(processorSubType) << LogIO::POST;
    1775           0 :           return false;
    1776             :         }
    1777             :           
    1778           0 :         tR = tT.newRow(modeId, processorType, processorSubType);
    1779             :         // add the row to the table
    1780           0 :         asdm::ProcessorRow* tR2 = 0;
    1781           0 :         tR2 = tT.add(tR);
    1782             : 
    1783           0 :         if(tR2 == tR){ // adding this row caused a new tag to be defined
    1784             :             // enter tag into the map
    1785           0 :             asdmProcessorId_p[irow] = tR->getProcessorId();
    1786             :         }
    1787             :         else{
    1788           0 :           os << LogIO::WARN << "Duplicate row in MS Processor table :" << irow << LogIO::POST;
    1789             :         }
    1790           0 :       } // end loop over MS processor table
    1791             :     }
    1792             :     else{ // MS processor table is empty
    1793           0 :       os << LogIO::WARN << "MS Processor table is empty. Will try to proceed assuming a standard ALMA Correlator." << LogIO::POST;
    1794           0 :       ProcessorTypeMod::ProcessorType processorType = ProcessorTypeMod::CORRELATOR;
    1795           0 :       ProcessorSubTypeMod::ProcessorSubType processorSubType = ProcessorSubTypeMod::ALMA_CORRELATOR_MODE;
    1796           0 :       if(!writeCorrelatorMode()){ // create the optional CorrelatorMode table
    1797           0 :         return false;
    1798             :       }
    1799           0 :       vector< asdm::CorrelatorModeRow* > corrModeRows = ASDM_p->getCorrelatorMode().get();
    1800           0 :       if(corrModeRows.size()==0){
    1801           0 :         os << LogIO::SEVERE << "Internal error: ASDM CorrelatorMode table is empty." << LogIO::POST;
    1802           0 :         return false;
    1803             :       }
    1804           0 :       Tag modeId = corrModeRows[0]->getCorrelatorModeId(); // get tag from first row of CorrelatorMode table (there is only one) ??? 
    1805           0 :       tR = tT.newRow(modeId, processorType, processorSubType);
    1806           0 :       tT.add(tR);
    1807             :       // enter tag into the map connecting it to "-1"
    1808           0 :       asdmProcessorId_p[-1] = tR->getProcessorId();
    1809           0 :     } // end if
    1810             : 
    1811           0 :     EntityId theUid(getCurrentUid());
    1812           0 :     Entity ent = tT.getEntity();
    1813           0 :     ent.setEntityId(theUid);
    1814           0 :     tT.setEntity(ent);
    1815           0 :     if(verbosity_p>0){
    1816           0 :       os << LogIO::NORMAL << "Filled Processor table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1817             :     }
    1818           0 :     incrementUid();
    1819             : 
    1820           0 :     return rstat;
    1821           0 :   }
    1822             : 
    1823             : 
    1824           0 :   Bool MS2ASDM::writeField(){
    1825           0 :     LogIO os(LogOrigin("MS2ASDM", "writeField()"));
    1826             : 
    1827           0 :     Bool rstat = true;
    1828           0 :     asdm::FieldTable& tT = ASDM_p->getField();
    1829             : 
    1830           0 :     asdm::FieldRow* tR = 0;
    1831             : 
    1832           0 :     for(uInt irow=0; irow<field().nrow(); irow++){
    1833             : 
    1834             :       // parameters of the new row
    1835           0 :       string fieldName = field().name()(irow).c_str();
    1836           0 :       string code = field().code()(irow).c_str();
    1837           0 :       if(code=="" || code==" "){
    1838           0 :        code="-";
    1839             :       }
    1840           0 :       int numPoly = field().numPoly()(irow) + 1; // MS give poly order, ASDM needs number of coefficients
    1841           0 :       if(numPoly>1){
    1842           0 :         os << LogIO::SEVERE << "Internal error: MS Field table with NUM_POLY > 0 not yet supported." << LogIO::POST;
    1843           0 :         return false;
    1844             :       }
    1845           0 :       Int numpol = 0;
    1846             : 
    1847           0 :       String msAngUnit = "rad"; // MS uses radians here
    1848           0 :       Matrix< Double > mdir; // aux. matrix
    1849             : 
    1850             : 
    1851             :       MDirection::Types phaseDirRef;
    1852           0 :       MDirection::getType(phaseDirRef, field().phaseDirMeasCol()(irow)(IPosition(1,0)).getRefString());
    1853             :       MDirection::Types delayDirRef;
    1854           0 :       MDirection::getType(delayDirRef, field().delayDirMeasCol()(irow)(IPosition(1,0)).getRefString());
    1855             :       MDirection::Types refDirRef;
    1856           0 :       MDirection::getType(refDirRef, field().referenceDirMeasCol()(irow)(IPosition(1,0)).getRefString());
    1857           0 :       if((phaseDirRef!=delayDirRef) || phaseDirRef!=refDirRef){
    1858             :         os << LogIO::SEVERE << "Internal error: the reference frames for phase, delay, and reference direction are not identical" 
    1859             :            << "in the MS Field table row " << irow << "." << endl
    1860           0 :            << "Not yet supported case." << LogIO::POST;
    1861           0 :         return false;
    1862             :       }
    1863             :         
    1864             :       DirectionReferenceCodeMod::DirectionReferenceCode directionCode
    1865           0 :         = ASDMDirRefCode(phaseDirRef);
    1866             : 
    1867           0 :       vector< vector< Angle > > delayDirV;
    1868           0 :       mdir.reference(field().delayDir()(irow));
    1869             :       {
    1870           0 :         vector< Angle > dirV;
    1871           0 :         Quantity angle0(mdir(0,numpol), msAngUnit);
    1872           0 :         dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
    1873           0 :         Quantity angle1(mdir(1,numpol), msAngUnit);
    1874           0 :         dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
    1875           0 :         delayDirV.push_back(dirV);
    1876           0 :       }
    1877             : 
    1878           0 :       vector< vector< Angle > > phaseDirV;
    1879           0 :       mdir.reference(field().phaseDir()(irow));
    1880             :       {
    1881           0 :         vector< Angle > dirV;
    1882           0 :         Quantity angle0(mdir(0,numpol), msAngUnit);
    1883           0 :         dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
    1884           0 :         Quantity angle1(mdir(1,numpol), msAngUnit);
    1885           0 :         dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
    1886           0 :         phaseDirV.push_back(dirV);
    1887           0 :       }
    1888             : 
    1889           0 :       vector< vector< Angle > > referenceDirV;
    1890           0 :       mdir.reference(field().referenceDir()(irow));
    1891             :       {
    1892           0 :         vector< Angle > dirV;
    1893           0 :         Quantity angle0(mdir(0,numpol), msAngUnit);
    1894           0 :         dirV.push_back(Angle(angle0.getValue(unitASDMAngle())));
    1895           0 :         Quantity angle1(mdir(1,numpol), msAngUnit);
    1896           0 :         dirV.push_back(Angle(angle1.getValue(unitASDMAngle())));
    1897           0 :         referenceDirV.push_back(dirV);
    1898           0 :       }
    1899             : 
    1900             :       ////tR = tT.newRow(fieldName, code, numPoly, delayDirV, phaseDirV, referenceDirV);
    1901           0 :       tR = tT.newRow(fieldName, numPoly, delayDirV, phaseDirV, referenceDirV);
    1902             :       
    1903           0 :       tR->setCode(code);
    1904           0 :       tR->setDirectionCode(directionCode);
    1905           0 :       tR->setTime(ASDMArrayTime(field().timeQuant()(irow).getValue("s")));
    1906             : 
    1907           0 :       Int sId = field().sourceId()(irow);
    1908           0 :       if ( asdmSourceId_p.find(sId) != asdmSourceId_p.end( ) ) {
    1909           0 :           tR->setSourceId(asdmSourceId_p[sId]);      
    1910             :       }
    1911           0 :       else if(sId!=-1){ // -1 means "no source"
    1912           0 :         os << LogIO::WARN << "Undefined source id " << sId << " in MS field table row " << irow << LogIO::POST;
    1913             :       }
    1914             : 
    1915             :       /*
    1916             :       if(!field().ephemerisId().isNull()){
    1917             :         Int eid = field().ephemerisId()(irow);
    1918             :         if(asdmEphemerisId_p.isDefined(eid)){
    1919             :           tR->setEphemerisId(asdmEphemerisId_p(eid));
    1920             :         }
    1921             :         else{
    1922             :           os << LogIO::WARN << "Undefined ephemeris id " << eid << " in MS field table row " << irow << LogIO::POST;
    1923             :         }
    1924             :       }
    1925             :       */
    1926             :       // add the row to the table
    1927           0 :       asdm::FieldRow* tR2 = 0;
    1928           0 :       tR2 = tT.add(tR);
    1929           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    1930             :         // enter tag into the map
    1931           0 :           asdmFieldId_p[irow] = tR->getFieldId();
    1932             :       }
    1933             :       else{
    1934           0 :         if(sId == tR2->getSourceId()){ // if also the Source ID agrees, we really have a duplication
    1935           0 :           os << LogIO::SEVERE << "Duplicate row in MS Field table :" << irow << LogIO::POST;
    1936           0 :           return false;
    1937             :         }
    1938           0 :         fieldName = fieldName+"_B";
    1939           0 :         tR->setFieldName(fieldName);
    1940           0 :         tR2 = tT.add(tR);
    1941           0 :         if(tR2 == tR){ // adding this row caused a new tag to be defined
    1942             :           os << LogIO::WARN << "Duplicate row in MS Field table :" << irow << endl
    1943           0 :              << "   appended \"_B\" to field name for second occurrence. New field name: " << fieldName << LogIO::POST;
    1944           0 :           asdmFieldId_p[irow] = tR->getFieldId();
    1945             :         }
    1946             :         else{
    1947           0 :           os << LogIO::SEVERE << "Duplicate row in MS Field table :" << irow << LogIO::POST;
    1948           0 :           return false;
    1949             :         } 
    1950             :       }
    1951           0 :     } // end loop over MS field table
    1952             : 
    1953           0 :     EntityId theUid(getCurrentUid());
    1954           0 :     Entity ent = tT.getEntity();
    1955           0 :     ent.setEntityId(theUid);
    1956           0 :     tT.setEntity(ent);
    1957           0 :     if(verbosity_p>0){
    1958           0 :       os << LogIO::NORMAL << "Filled Field table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    1959             :     }
    1960           0 :     incrementUid();
    1961             : 
    1962           0 :     return rstat;
    1963           0 :   }
    1964             : 
    1965             : 
    1966           0 :   Bool MS2ASDM::writeReceiver(){
    1967           0 :     LogIO os(LogOrigin("MS2ASDM", "writeReceiver()"));
    1968             : 
    1969           0 :     Bool rstat = true;
    1970           0 :     asdm::ReceiverTable& tT = ASDM_p->getReceiver();
    1971             : 
    1972           0 :     asdm::ReceiverRow* tR = 0;
    1973             : 
    1974             :     // create one row for each spectral window Id and time interval (i.e. receiverId is always == 0) 
    1975             : 
    1976             :     // loop over ASDM SPW table
    1977           0 :     vector< asdm::SpectralWindowRow* > SPWRows = (ASDM_p->getSpectralWindow()).get();
    1978             : 
    1979           0 :     Bool informed = false;
    1980             : 
    1981           0 :     for(uInt irow=0; irow<SPWRows.size(); irow++){
    1982             :    
    1983             :       // parameters for the new Recevier table row
    1984           0 :       Tag spectralWindowId = SPWRows[irow]->getSpectralWindowId();
    1985           0 :       if(!informed){
    1986           0 :         if(verbosity_p>0){
    1987             :           os << LogIO::NORMAL << "Taking validity time interval for all ASDM Receiver table entries from row 0 of MS Feed table." 
    1988           0 :              << LogIO::POST;
    1989             :         }
    1990           0 :         informed = true;
    1991             :       }
    1992           0 :       asdm::ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(0), feed().intervalQuant()(0)) ); 
    1993           0 :       string name = "unspec. frontend";
    1994             :       ReceiverBandMod::ReceiverBand frequencyBand;
    1995             :       ReceiverSidebandMod::ReceiverSideband receiverSideband;
    1996             :       double dummyF;
    1997           0 :       setRecBands(SPWRows[irow]->getRefFreq(), dummyF, frequencyBand, receiverSideband); 
    1998           0 :       int numLO = 0; // no information in the MS ???
    1999           0 :       vector<Frequency > freqLO;
    2000             :       //freqLO.push_back(Frequency(1.)); // ???
    2001           0 :       vector<NetSidebandMod::NetSideband > sidebandLO;
    2002             :       //sidebandLO.push_back(SPWRows[irow]->getNetSideband()); // ???
    2003             : 
    2004           0 :       tR = tT.newRow(spectralWindowId, timeInterval, name, numLO, frequencyBand, freqLO, receiverSideband, sidebandLO);
    2005             : 
    2006             :       // add the row to the table
    2007           0 :       tT.add(tR);
    2008           0 :     } // end loop over SPW rows
    2009             : 
    2010           0 :     EntityId theUid(getCurrentUid());
    2011           0 :     Entity ent = tT.getEntity();
    2012           0 :     ent.setEntityId(theUid);
    2013           0 :     tT.setEntity(ent);
    2014           0 :     if(verbosity_p>0){
    2015           0 :       os << LogIO::NORMAL << "Filled Receiver table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    2016             :     }
    2017           0 :     incrementUid();
    2018             : 
    2019           0 :     return rstat;
    2020           0 :   }
    2021             : 
    2022           0 :   Bool MS2ASDM::writeFeed(){
    2023           0 :     LogIO os(LogOrigin("MS2ASDM", "writeFeed()"));
    2024             : 
    2025           0 :     Bool rstat = true;
    2026           0 :     asdm::FeedTable& tT = ASDM_p->getFeed();
    2027             : 
    2028           0 :     asdm::FeedRow* tR = 0;
    2029             : 
    2030           0 :     Bool warned = false;
    2031           0 :     Bool warned2 = false;
    2032           0 :     Bool warned3 = false;
    2033             : 
    2034           0 :     for(uInt irow=0; irow<feed().nrow(); irow++){
    2035             : 
    2036             :       // parameters of the new feed row
    2037           0 :       Tag antennaId;
    2038           0 :       Int aid = feed().antennaId()(irow);
    2039           0 :       if( asdmAntennaId_p.find(aid) != asdmAntennaId_p.end( ) ){
    2040           0 :           antennaId = asdmAntennaId_p[aid];
    2041             :       }
    2042             :       else{
    2043           0 :         os << LogIO::SEVERE << "Undefined antenna id " << aid << " in MS feed table row "<< irow << LogIO::POST;
    2044           0 :         return false;
    2045             :       }
    2046           0 :       ArrayTimeInterval timeInterval( ASDMTimeInterval(feed().timeQuant()(irow), feed().intervalQuant()(irow)) );
    2047             :       
    2048           0 :       int numReceptor = feed().numReceptors()(irow);
    2049             : 
    2050           0 :       vector< vector< double > > beamOffsetV;
    2051           0 :       vector< vector< Length > > focusReferenceV;
    2052           0 :       vector< PolarizationTypeMod::PolarizationType > polarizationTypesV;
    2053           0 :       vector< vector< asdm::Complex > > polResponseV;
    2054           0 :       vector< Angle > receptorAngleV;
    2055           0 :       vector< int > receiverIdV;
    2056             : 
    2057           0 :       Matrix< Double > mboffset; // aux. matrix
    2058           0 :       mboffset.reference(feed().beamOffset()(irow));
    2059             : 
    2060           0 :       Vector< String > polT; // aux. vector
    2061           0 :       polT.reference(feed().polarizationType()(irow));
    2062             : 
    2063           0 :       Matrix< Complex > polR;
    2064           0 :       polR.reference(feed().polResponse()(irow));
    2065             : 
    2066           0 :       Vector< Quantity > receptA;
    2067           0 :       receptA.reference(feed().receptorAngleQuant()(irow));
    2068             : 
    2069           0 :       for(uInt rnum=0; rnum<(uInt)numReceptor; rnum++){ // loop over all receptors
    2070           0 :         vector< double > abo;
    2071           0 :         abo.push_back(mboffset(0,rnum));
    2072           0 :         abo.push_back(mboffset(1,rnum));
    2073           0 :         beamOffsetV.push_back(abo);
    2074             : 
    2075           0 :         vector< Length > afr;
    2076           0 :         afr.push_back(0); // x
    2077           0 :         afr.push_back(0); // y
    2078           0 :         if(!feed().focusLength().isNull()){ // the FOCUS_LENGTH column is optional
    2079           0 :           afr.push_back(Length(feed().focusLength()(irow))); // z  ???
    2080             :         }
    2081             :         else{
    2082           0 :           afr.push_back(0); // z
    2083             :         } 
    2084           0 :         focusReferenceV.push_back(afr);
    2085             : 
    2086             :         try{
    2087           0 :           polarizationTypesV.push_back(CPolarizationType::literal(polT[rnum].c_str()));
    2088             :         }
    2089           0 :         catch(std::string z){
    2090           0 :           os << LogIO::SEVERE << "Polarization type " << polT[rnum].c_str() << " for receptor " 
    2091             :              << rnum << " in MS Feed table row  " << irow << " not defined in ASDM: " 
    2092           0 :              << z << LogIO::POST;      
    2093           0 :           return false;
    2094           0 :         }       
    2095             :         
    2096           0 :         vector< asdm::Complex > apr;
    2097           0 :         for(uInt rnum2=0; rnum2<(uInt)numReceptor; rnum2++){
    2098           0 :           apr.push_back( ASDMComplex( polR(rnum,rnum2) ) );
    2099             :         }
    2100           0 :         polResponseV.push_back(apr);
    2101             : 
    2102           0 :         receptorAngleV.push_back( Angle( receptA[rnum].getValue( unitASDMAngle() ) ) );
    2103             : 
    2104           0 :         if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
    2105           0 :           receiverIdV.push_back(0); // always zero for ALMA
    2106             :         }
    2107             :         else{
    2108           0 :           receiverIdV.push_back(0);
    2109           0 :           if(!warned){
    2110           0 :             os << LogIO::WARN << "Setting receiver ID to zero (ALMA convention)." << LogIO::POST;
    2111           0 :             warned = true;
    2112             :           }
    2113             :         }
    2114           0 :       } // end loop over receptors
    2115             : 
    2116             :       // look at SPW Id parameter last!
    2117           0 :       Tag spectralWindowId;
    2118           0 :       vector< Tag > spwIdV; // the spw ids fow which to insert rows for this feed
    2119           0 :       Int spwid = feed().spectralWindowId()(irow);
    2120           0 :       if(spwid == -1){ // this means the MS Feed row is valid for all SPWs => need to insert same row for each SPW!
    2121             :         // loop over all SPWs
    2122           0 :         for(Int ispw=0; ispw<(Int)spectralWindow().nrow(); ispw++){
    2123           0 :           if( asdmSpectralWindowId_p.find(ispw) != asdmSpectralWindowId_p.end( ) ){
    2124           0 :             spectralWindowId = asdmSpectralWindowId_p[ispw];
    2125           0 :             spwIdV.push_back(spectralWindowId); 
    2126             :           }
    2127             :         }  
    2128             :       }
    2129           0 :       else if( asdmSpectralWindowId_p.find(spwid) != asdmSpectralWindowId_p.end( ) ){
    2130           0 :           spectralWindowId = asdmSpectralWindowId_p[spwid];
    2131           0 :           spwIdV.push_back(spectralWindowId); // just one entry
    2132             :       }
    2133             :       else{
    2134           0 :         os << LogIO::SEVERE << "Undefined SPW id " << spwid << " in MS feed table row "<< irow << LogIO::POST;
    2135           0 :         return false;
    2136             :       }
    2137             : 
    2138             :       // create the row for the first of the SPW Ids
    2139           0 :       tR = tT.newRow(antennaId, spwIdV[0], timeInterval, numReceptor, beamOffsetV, focusReferenceV, 
    2140             :                      polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
    2141             : 
    2142           0 :       if(telName_p=="ALMA" || telName_p=="ACA" || telName_p == "OSF"){
    2143           0 :         tR->setFeedNum(1); // always 1 for ALMA
    2144             :       }
    2145             :       else{
    2146           0 :         tR->setFeedNum(1); 
    2147           0 :         if(!warned2){
    2148           0 :           os << LogIO::WARN << "Assuming single-feed receivers. Setting FeedNum to 1 (as for ALMA)." << LogIO::POST;
    2149           0 :           warned2 = true;
    2150             :         }
    2151             :       }
    2152             : 
    2153           0 :       vector< Length > positionV;
    2154           0 :       Vector< Quantity > pos;
    2155           0 :       pos.reference(feed().positionQuant()(irow));
    2156           0 :       for(uInt i=0; i<3; i++){
    2157           0 :         positionV.push_back( Length( pos[0].getValue( unitASDMLength() ) ) );
    2158             :       }
    2159           0 :       tR->setPosition(positionV);
    2160             : 
    2161           0 :       if(feed().beamId()(irow)!=-1 && !warned3){ // there should be a beam table in the MS, but presently it is not implemented!!!
    2162           0 :         os << LogIO::WARN << "MS Feed table contains reference to a Beam table row " << feed().beamId()(irow)
    2163           0 :            << " but a Beam table is not implemented in CASA. Ignoring." << LogIO::POST;
    2164             :       }
    2165             : 
    2166             :       // add the row to the table
    2167           0 :       tT.add(tR);       
    2168             : 
    2169           0 :       int asdmFId = tR->getFeedId(); // the determination of the feed id is done internally by the add() method
    2170           0 :       Int fId = feed().feedId()(irow);
    2171           0 :       if( asdmFeedId_p.find(fId) != asdmFeedId_p.end( ) ){ // there is already a mapping
    2172           0 :         if(asdmFId!=asdmFeedId_p[fId]){ // but it doesn't agree with the newly defined id
    2173             :           os << LogIO::WARN << "Internal problem: field id map inconsistent for MS feed table row:" << irow 
    2174           0 :              << ". MS FId " << fId << " is already mapped to ASDM FId" << asdmFeedId_p[fId]
    2175           0 :              << " but should also be mapped to ASDM FId " << asdmFId << LogIO::POST;
    2176             :         }
    2177             :       }
    2178             :       else{
    2179             :         // enter id into the map
    2180           0 :         asdmFeedId_p[fId] = asdmFId;
    2181             :       }
    2182             : 
    2183             :       // add the same row for the remaining SPW Ids in the vector accumulated above
    2184           0 :       for(uint i=1; i<spwIdV.size(); i++){
    2185           0 :         tR = tT.newRow(antennaId, spwIdV[i], timeInterval, numReceptor, beamOffsetV, focusReferenceV, 
    2186             :                      polarizationTypesV, polResponseV, receptorAngleV, receiverIdV);
    2187           0 :         tT.add(tR);     
    2188             :       } 
    2189             : 
    2190           0 :     } // end loop over MS feed table
    2191             : 
    2192           0 :     EntityId theUid(getCurrentUid());
    2193           0 :     Entity ent = tT.getEntity();
    2194           0 :     ent.setEntityId(theUid);
    2195           0 :     tT.setEntity(ent);
    2196           0 :     if(verbosity_p>0){
    2197           0 :       os << LogIO::NORMAL << "Filled Feed table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    2198             :     }
    2199           0 :     incrementUid();
    2200             : 
    2201           0 :     return rstat;
    2202           0 :   }
    2203             : 
    2204             : 
    2205           0 :   Bool MS2ASDM::writeDataDescription(){
    2206           0 :     LogIO os(LogOrigin("MS2ASDM", "writeDataDescription()"));
    2207             : 
    2208           0 :     Bool rstat = true;
    2209           0 :     asdm::DataDescriptionTable& tT = ASDM_p->getDataDescription();
    2210             : 
    2211           0 :     asdm::DataDescriptionRow* tR = 0;
    2212             : 
    2213             :     // loop over MS data description table
    2214           0 :     for(uInt irow=0; irow<dataDescription().nrow(); irow++){
    2215             :       // parameters for the new row
    2216           0 :       Tag polOrHoloId;
    2217           0 :       Tag spectralWindowId;
    2218           0 :       Int polId = dataDescription().polarizationId()(irow);
    2219           0 :       Int spwId = dataDescription().spectralWindowId()(irow);
    2220           0 :       if( asdmPolarizationId_p.find(polId) != asdmPolarizationId_p.end( ) ){
    2221           0 :         polOrHoloId = asdmPolarizationId_p[polId];
    2222             :       }
    2223             :       else{
    2224             :         os << LogIO::SEVERE << "Inconsistent MS: undefined polarization id " << polId 
    2225           0 :            << " in row " << irow << " of the DataDesc table." << LogIO::POST;
    2226           0 :         return false;
    2227             :       }
    2228           0 :       if( asdmSpectralWindowId_p.find(spwId) != asdmSpectralWindowId_p.end( ) ){
    2229           0 :         spectralWindowId = asdmSpectralWindowId_p[spwId];
    2230             :       }
    2231             :       else{
    2232             :         os << LogIO::SEVERE << "Inconsistent MS: undefined SPW id " << spwId 
    2233           0 :            << " in row " << irow << " of the DataDesc table." << LogIO::POST;
    2234           0 :         return false;
    2235             :       }
    2236             : 
    2237           0 :       tR = tT.newRow(polOrHoloId, spectralWindowId);
    2238             : 
    2239           0 :       asdm::DataDescriptionRow* tR2 = 0;
    2240             : 
    2241           0 :       tR2 = tT.add(tR);
    2242           0 :       if(tR2 == tR){ // adding this row caused a new tag to be defined
    2243             :         // enter tag into the map
    2244           0 :         asdmDataDescriptionId_p[irow] = tR->getDataDescriptionId();
    2245             :       }
    2246             :       else{
    2247           0 :         os << LogIO::WARN << "Duplicate row in MS DataDesc table :" << irow << LogIO::POST;
    2248             :       }
    2249           0 :     } // end loop over MS DD table
    2250             : 
    2251           0 :     EntityId theUid(getCurrentUid());
    2252           0 :     Entity ent = tT.getEntity();
    2253           0 :     ent.setEntityId(theUid);
    2254           0 :     tT.setEntity(ent);
    2255           0 :     if(verbosity_p>0){
    2256           0 :       os << LogIO::NORMAL << "Filled DataDescription table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    2257             :     }
    2258           0 :     incrementUid();
    2259             : 
    2260           0 :     return rstat;
    2261           0 :   }
    2262             : 
    2263           0 :   Bool MS2ASDM::writeSwitchCycle(){ 
    2264           0 :     LogIO os(LogOrigin("MS2ASDM", "writeSwitchCycle()"));
    2265             :     
    2266           0 :     Bool rstat = true;
    2267             :     
    2268           0 :     asdm::SwitchCycleTable& tT = ASDM_p->getSwitchCycle();
    2269             :     
    2270           0 :     asdm::SwitchCycleRow* tR = 0;
    2271             :     
    2272             :     // switch cycle table will only be dummy ? -> Francois
    2273             :     // dummy if PHASE_ID column doesn't exist in MS main
    2274             :     // PHASE_ID identifies bin in switch cycle
    2275             :     //   otherwise, e.g. PHASE_ID = 0 and 1 => numStep == 2
    2276             : 
    2277           0 :     if(phaseId().isNull()){ // phaseId column doesn't exist
    2278             : 
    2279             :       // parameters of the new row
    2280           0 :       int numStep = 1;
    2281           0 :       vector< float > weightArray;
    2282           0 :       weightArray.push_back(1.);
    2283           0 :       vector< vector< Angle > > dirOffsetArray;
    2284           0 :       vector< Angle > aV;
    2285           0 :       aV.push_back(Angle(0.));
    2286           0 :       aV.push_back(Angle(0.));
    2287           0 :       dirOffsetArray.push_back(aV);
    2288           0 :       vector< Frequency > freqOffsetArray;
    2289           0 :       freqOffsetArray.push_back(Frequency(0.));
    2290           0 :       vector< Interval > stepDurationArray;
    2291           0 :       stepDurationArray.push_back(Interval(0)); // set to zero ???
    2292             :       
    2293           0 :       tR = tT.newRow(numStep, weightArray, dirOffsetArray, freqOffsetArray, stepDurationArray);
    2294             :       
    2295           0 :       tT.add(tR);
    2296             :       
    2297           0 :       EntityId theUid(getCurrentUid());
    2298           0 :       Entity ent = tT.getEntity();
    2299           0 :       ent.setEntityId(theUid);
    2300           0 :       tT.setEntity(ent);
    2301           0 :       if(verbosity_p>0){
    2302             :         os << LogIO::NORMAL << "PHASE_ID column doesn't exist in MS Main table.\n Filled ASDM SwitchCycle table " 
    2303           0 :            << getCurrentUid() << " with one dummy entry." << LogIO::POST;
    2304             :       }
    2305           0 :       incrementUid();
    2306           0 :     }
    2307             :     else{ // phaseId column exists
    2308             :       os << LogIO::SEVERE 
    2309             :          << "PHASE_ID column exists in MS Main table but proper creation of ASDM SwitchCycle table not yet implemented." 
    2310           0 :          << LogIO::POST;
    2311           0 :       rstat = false;
    2312             :     }      
    2313             : 
    2314           0 :     return rstat;
    2315           0 :   }
    2316             : 
    2317           0 :   Bool MS2ASDM::writeState(){ 
    2318           0 :     LogIO os(LogOrigin("MS2ASDM", "writeState()"));
    2319             : 
    2320           0 :     Bool rstat = true;
    2321             : 
    2322           0 :     asdm::StateTable& tT = ASDM_p->getState();
    2323             : 
    2324           0 :     asdm::StateRow* tR = 0;
    2325             : 
    2326           0 :     if(state().nrow()<1){ // State table not filled
    2327             : 
    2328             :       os << LogIO::WARN << "MS State table is empty. Creating ASDM State table with one on-source entry." 
    2329           0 :          << LogIO::POST;
    2330             :      
    2331             :       // parameters of the new row
    2332           0 :       bool bSig = true;
    2333           0 :       bool bRef = false;
    2334           0 :       bool bOnSky = true; 
    2335           0 :       CalibrationDeviceMod::CalibrationDevice calDeviceName = CalibrationDeviceMod::NONE;
    2336             : 
    2337           0 :       tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
    2338             :       
    2339           0 :       tR->setWeight(1.); // optional column
    2340             : 
    2341             :       // add the new row to the table
    2342           0 :       tT.add(tR);
    2343             :       // enter tag into the map
    2344           0 :       asdmStateId_p[-1] = tR->getStateId();
    2345             :     }
    2346             :     else{ // MS State table exists
    2347           0 :       for(uInt irow=0; irow<state().nrow(); irow++){
    2348             :         // parameters of the new row
    2349           0 :         bool bSig = state().sig()(irow);
    2350           0 :         bool bRef = state().ref()(irow);
    2351           0 :         Double loadT = state().load()(irow);
    2352           0 :         Double noiseT = state().cal()(irow);
    2353           0 :         bool bOnSky = bSig || bRef; 
    2354             :         CalibrationDeviceMod::CalibrationDevice calDeviceName;
    2355           0 :         if(0.<loadT && loadT<270.){
    2356           0 :           calDeviceName = CalibrationDeviceMod::COLD_LOAD;
    2357             :         }
    2358           0 :         else if(270<=loadT && loadT<303.){
    2359           0 :           calDeviceName = CalibrationDeviceMod::AMBIENT_LOAD;
    2360             :         }
    2361           0 :         else if(303.<=loadT){
    2362           0 :           calDeviceName = CalibrationDeviceMod::HOT_LOAD;
    2363             :         }
    2364           0 :         else if(0.<noiseT){
    2365           0 :           calDeviceName = CalibrationDeviceMod::NOISE_TUBE_LOAD;
    2366             :         }
    2367             :         else{
    2368           0 :           calDeviceName = CalibrationDeviceMod::NONE;
    2369           0 :           if(!bSig){
    2370             :             os << LogIO::WARN << "Trouble determining Cal Device for row " << irow << " in MS State table."
    2371           0 :                << "Assuming NONE." << LogIO::POST;
    2372             :           }
    2373             :         }
    2374             :         
    2375           0 :         tR = tT.newRow(calDeviceName, bSig, bRef, bOnSky);
    2376             :         
    2377           0 :         tR->setWeight(1.); // optional column
    2378             :         
    2379             :         // add the new row to the table
    2380           0 :         asdm::StateRow* tR2 = 0;
    2381             :         
    2382           0 :         tR2 = tT.add(tR);
    2383             :         // enter tag into the map
    2384           0 :         asdmStateId_p[irow] = tR2->getStateId();
    2385           0 :         if(tR2 != tR){ // adding this row did not cause a new tag to be defined
    2386           0 :           os << LogIO::WARN << "Duplicate row in MS State table :" << irow << LogIO::POST;
    2387             :         }
    2388             :       } // end loop over MS state table
    2389             :     } // end else
    2390             : 
    2391           0 :     EntityId theUid(getCurrentUid());
    2392           0 :     Entity ent = tT.getEntity();
    2393           0 :     ent.setEntityId(theUid);
    2394           0 :     tT.setEntity(ent);
    2395           0 :     if(verbosity_p>0){
    2396           0 :       os << LogIO::NORMAL << "Filled State table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    2397             :     }
    2398           0 :     incrementUid();
    2399             : 
    2400           0 :     return rstat;
    2401           0 :   }
    2402             : 
    2403           0 :   Bool MS2ASDM::writeSysCal(){ 
    2404           0 :     LogIO os(LogOrigin("MS2ASDM", "writeSysCal()"));
    2405             : 
    2406           0 :     Bool rstat = true;
    2407             : 
    2408           0 :     asdm::SysCalTable& tT = ASDM_p->getSysCal();
    2409             : 
    2410           0 :     asdm::SysCalRow* tR = 0;
    2411             : 
    2412           0 :     uInt nSysCalRows = sysCal().nrow();
    2413             : 
    2414           0 :     if(nSysCalRows<1){ // SysCal table not filled
    2415             :       os << LogIO::WARN << "MS SysCal table doesn't exist or is empty. Creating ASDM SysCal table with default entries." 
    2416           0 :          << LogIO::POST;
    2417             :     
    2418             :       // loop over the main table
    2419           0 :       uInt nMainTabRows = ms_p.nrow();
    2420           0 :       for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
    2421             : 
    2422             :         // get DDId and feed id
    2423           0 :         Int f1Id = feed1()(mainTabRow);
    2424           0 :         Int f2Id = feed2()(mainTabRow);
    2425           0 :         Int DDId = dataDescId()(mainTabRow);    
    2426             :         // get start time stamp
    2427           0 :         Double startTime = timestampStartSecs(mainTabRow);
    2428             :         // create vectors of info for each antenna
    2429           0 :         vector< Int > aIdV;
    2430           0 :         vector< Int > SPWIdV;
    2431           0 :         vector< Int > feedIdV;
    2432           0 :         vector< int > nRecV;
    2433           0 :         vector< int > nChanV;
    2434           0 :         MapWithDefault<Int, Int> antennaDone(-1);
    2435             : 
    2436           0 :         uInt irow = mainTabRow;
    2437             :         // while ddid and feed id remain the same
    2438           0 :         while(irow<nMainTabRows &&
    2439           0 :               dataDescId()(irow) == DDId &&
    2440           0 :               feed1()(irow) == f1Id &&
    2441           0 :               feed2()(irow) == f2Id
    2442             :               ){
    2443           0 :           Int aId = antenna1()(irow);
    2444             :           //   if info for given antenna not yet filled
    2445           0 :           if( antennaDone.find(aId) == antennaDone.end( ) ){
    2446             :             //       get info for antenna and fill vectors
    2447           0 :             aIdV.push_back(aId);
    2448           0 :             Int spwId = dataDescription().spectralWindowId()(DDId);
    2449           0 :             SPWIdV.push_back(spwId);
    2450           0 :             feedIdV.push_back(f1Id);
    2451           0 :             nRecV.push_back(feed().numReceptors()(f1Id)); 
    2452           0 :             nChanV.push_back(spectralWindow().numChan()(spwId));
    2453           0 :             antennaDone[aId] = f1Id;
    2454             :           }
    2455           0 :           aId = antenna2()(irow);
    2456             :           //   if info for given antenna not yet filled
    2457           0 :           if( antennaDone.find(aId) == antennaDone.end( ) ){
    2458             :             //       get info for antenna and fill vectors
    2459           0 :             aIdV.push_back(aId);
    2460           0 :             Int spwId = dataDescription().spectralWindowId()(DDId);
    2461           0 :             SPWIdV.push_back(spwId);
    2462           0 :             feedIdV.push_back(f2Id);
    2463           0 :             nRecV.push_back(feed().numReceptors()(f2Id)); 
    2464           0 :             nChanV.push_back(spectralWindow().numChan()(spwId));
    2465           0 :             antennaDone[aId] = f2Id;
    2466             :           }
    2467           0 :           irow++;
    2468             :         } // end while
    2469             :         // get end timestamp
    2470           0 :         Double endTime = timestampEndSecs(irow-1);
    2471             :         // create ArrayTimeInterval
    2472           0 :         asdm::ArrayTimeInterval timeInterval( ASDMArrayTime(startTime),
    2473           0 :                                               ASDMInterval(endTime-startTime) );
    2474             :         // create new rows in syscal table based on the vectors
    2475           0 :         for(uInt i=0; i<aIdV.size(); i++){
    2476             :           // parameters of the new SysCal row
    2477           0 :           Tag antennaId = asdmAntennaId_p[aIdV[i]];
    2478           0 :           Tag spectralWindowId = asdmSpectralWindowId_p[SPWIdV[i]];
    2479           0 :           int feedId = asdmFeedId_p[feedIdV[i]];
    2480           0 :           int numReceptor = nRecV[i];
    2481           0 :           int numChan = nChanV[i];
    2482             : 
    2483           0 :           tR = tT.newRow(antennaId, spectralWindowId, timeInterval, feedId, numReceptor, numChan);
    2484             :       
    2485             :           // add the new row to the table
    2486           0 :           tT.add(tR);
    2487           0 :         }
    2488           0 :         mainTabRow = irow;
    2489           0 :       } // end loop over main table
    2490             :     }
    2491             :     else{ // MS SysCal table exists
    2492           0 :       for(uInt irow=0; irow<nSysCalRows; irow++){
    2493             :         // parameters of the new row
    2494           0 :         Tag antennaId = asdmAntennaId_p[ sysCal().antennaId()(irow) ];
    2495           0 :         Int spwId = sysCal().spectralWindowId()(irow);
    2496           0 :         Tag spectralWindowId = asdmSpectralWindowId_p[ spwId ];
    2497           0 :         int feedId = sysCal().feedId()(irow);
    2498           0 :         ArrayTimeInterval timeInterval( ASDMTimeInterval(sysCal().timeQuant()(irow), sysCal().intervalQuant()(irow)) );
    2499             : 
    2500           0 :         uInt numReceptor = feed().numReceptors()(feedId); 
    2501           0 :         uInt nChan = spectralWindow().numChan()(spwId); 
    2502             : 
    2503           0 :         tR = tT.newRow(antennaId, spectralWindowId, timeInterval, feedId, (int)numReceptor, (int)nChan);
    2504             : 
    2505             : 
    2506             :         // now set the optional columns if they exist in the MS
    2507             :         
    2508             :         // Tant 
    2509           0 :         if(!sysCal().tantFlag().isNull()){
    2510           0 :           tR->setTantFlag(sysCal().tantFlag()(irow));
    2511             :         }
    2512           0 :         if(!sysCal().tantSpectrumQuant().isNull()){
    2513           0 :           Matrix< Quantum< Float > > sM;
    2514           0 :           sM.reference(sysCal().tantSpectrumQuant()(irow));
    2515           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2516             :             os << LogIO::SEVERE << "Inconsistent MS: TANT spectrum in syscal table row " << irow
    2517           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2518           0 :             return false;
    2519             :           } 
    2520           0 :           if(sM.shape()(1) != (Int)nChan){
    2521             :             os << LogIO::SEVERE << "Inconsistent MS: TANT spectrum in syscal table row " << irow
    2522           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2523           0 :             return false;
    2524             :           } 
    2525           0 :           vector< vector< float > > fVV; // presently a float but should be a Temperature ???
    2526           0 :           for(uInt i=0; i<numReceptor; i++){
    2527           0 :             vector< float > fV;
    2528           0 :             for(uInt j=0; j<nChan; j++){
    2529           0 :               fV.push_back( sM(i,j).getValue(unitASDMTemp()) ); 
    2530             :             }
    2531           0 :             fVV.push_back(fV);
    2532           0 :           }
    2533           0 :           tR->setTantSpectrum(fVV);
    2534           0 :         }
    2535           0 :         else if(!sysCal().tantQuant().isNull()){
    2536           0 :           Vector< Quantum< Float > > sV;
    2537           0 :           sV.reference(sysCal().tantQuant()(irow));
    2538           0 :           vector< vector< float > > fVV; // presently a float but should be a Temperature ???
    2539           0 :           if(sV.size() != numReceptor){
    2540             :             os << LogIO::SEVERE << "Inconsistent MS: TANT in syscal table row " << irow
    2541           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2542           0 :             return false;
    2543             :           } 
    2544           0 :           for(uInt i=0; i<numReceptor; i++){
    2545           0 :             vector< float > fV;
    2546           0 :             for(uInt j=0; j<nChan; j++){
    2547           0 :               fV.push_back( sV[i].getValue(unitASDMTemp()) );
    2548             :             }
    2549           0 :             fVV.push_back(fV);
    2550           0 :           }
    2551           0 :           tR->setTantSpectrum(fVV);
    2552           0 :         }
    2553             : 
    2554             :         // Tant/Tsys
    2555           0 :         if(!sysCal().tantTsysFlag().isNull()){
    2556           0 :           tR->setTantTsysFlag(sysCal().tantTsysFlag()(irow));
    2557             :         }
    2558           0 :         if(!sysCal().tantTsysSpectrum().isNull()){
    2559           0 :           Matrix< Float > sM;
    2560           0 :           sM.reference(sysCal().tantTsysSpectrum()(irow));
    2561           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2562             :             os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS spectrum in syscal table row " << irow
    2563           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2564           0 :             return false;
    2565             :           } 
    2566           0 :           if(sM.shape()(1) != (Int)nChan){
    2567             :             os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS spectrum in syscal table row " << irow
    2568           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2569           0 :             return false;
    2570             :           } 
    2571           0 :           vector< vector< float > > fVV; 
    2572           0 :           for(uInt i=0; i<numReceptor; i++){
    2573           0 :             vector< float > fV;
    2574           0 :             for(uInt j=0; j<nChan; j++){
    2575           0 :               fV.push_back( sM(i,j) ); 
    2576             :             }
    2577           0 :             fVV.push_back(fV);
    2578           0 :           }
    2579           0 :           tR->setTantTsysSpectrum(fVV);
    2580           0 :         }
    2581           0 :         else if(!sysCal().tantTsys().isNull()){
    2582           0 :           Vector< Float > sV;
    2583           0 :           sV.reference(sysCal().tantTsys()(irow));
    2584           0 :           vector< vector< float > > fVV; 
    2585           0 :           if(sV.size() != numReceptor){
    2586             :             os << LogIO::SEVERE << "Inconsistent MS: TANT_TSYS in syscal table row " << irow
    2587           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2588           0 :             return false;
    2589             :           } 
    2590           0 :           for(uInt i=0; i<numReceptor; i++){
    2591           0 :             vector< float > fV;
    2592           0 :             for(uInt j=0; j<nChan; j++){
    2593           0 :               fV.push_back( sV[i] );
    2594             :             }
    2595           0 :             fVV.push_back(fV);
    2596           0 :           }
    2597           0 :           tR->setTantTsysSpectrum(fVV);
    2598           0 :         }
    2599             : 
    2600             :         // Tcal
    2601           0 :         if(!sysCal().tcalFlag().isNull()){
    2602           0 :           tR->setTcalFlag(sysCal().tcalFlag()(irow));
    2603             :         }
    2604           0 :         if(!sysCal().tcalSpectrumQuant().isNull()){
    2605           0 :           Matrix< Quantum< Float > > sM;
    2606           0 :           sM.reference(sysCal().tcalSpectrumQuant()(irow));
    2607           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2608             :             os << LogIO::SEVERE << "Inconsistent MS: TCAL spectrum in syscal table row " << irow
    2609           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2610           0 :             return false;
    2611             :           } 
    2612           0 :           if(sM.shape()(1) != (Int)nChan){
    2613             :             os << LogIO::SEVERE << "Inconsistent MS: TCAL spectrum in syscal table row " << irow
    2614           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2615           0 :             return false;
    2616             :           } 
    2617           0 :           vector< vector< Temperature > > fVV; 
    2618           0 :           for(uInt i=0; i<numReceptor; i++){
    2619           0 :             vector< Temperature > fV;
    2620           0 :             for(uInt j=0; j<nChan; j++){
    2621           0 :               fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) ); 
    2622             :             }
    2623           0 :             fVV.push_back(fV);
    2624           0 :           }
    2625           0 :           tR->setTcalSpectrum(fVV);
    2626           0 :         }
    2627           0 :         else if(!sysCal().tcalQuant().isNull()){
    2628           0 :           Vector< Quantum< Float > > sV;
    2629           0 :           sV.reference(sysCal().tcalQuant()(irow));
    2630           0 :           vector< vector< Temperature > > fVV; 
    2631           0 :           if(sV.size() != numReceptor){
    2632             :             os << LogIO::SEVERE << "Inconsistent MS: TCAL in syscal table row " << irow
    2633           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2634           0 :             return false;
    2635             :           } 
    2636           0 :           for(uInt i=0; i<numReceptor; i++){
    2637           0 :             vector< Temperature > fV;
    2638           0 :             for(uInt j=0; j<nChan; j++){
    2639           0 :               fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
    2640             :             }
    2641           0 :             fVV.push_back(fV);
    2642           0 :           }
    2643           0 :           tR->setTcalSpectrum(fVV);
    2644           0 :         }
    2645             : 
    2646             :         // Trx
    2647           0 :         if(!sysCal().trxFlag().isNull()){
    2648           0 :           tR->setTrxFlag(sysCal().trxFlag()(irow));
    2649             :         }
    2650           0 :         if(!sysCal().trxSpectrumQuant().isNull()){
    2651           0 :           Matrix< Quantum< Float > > sM;
    2652           0 :           sM.reference(sysCal().trxSpectrumQuant()(irow));
    2653           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2654             :             os << LogIO::SEVERE << "Inconsistent MS: TRX spectrum in syscal table row " << irow
    2655           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2656           0 :             return false;
    2657             :           } 
    2658           0 :           if(sM.shape()(1) != (Int)nChan){
    2659             :             os << LogIO::SEVERE << "Inconsistent MS: TRX spectrum in syscal table row " << irow
    2660           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2661           0 :             return false;
    2662             :           } 
    2663           0 :           vector< vector< Temperature > > fVV; 
    2664           0 :           for(uInt i=0; i<numReceptor; i++){
    2665           0 :             vector< Temperature > fV;
    2666           0 :             for(uInt j=0; j<nChan; j++){
    2667           0 :               fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) ); 
    2668             :             }
    2669           0 :             fVV.push_back(fV);
    2670           0 :           }
    2671           0 :           tR->setTrxSpectrum(fVV);
    2672           0 :         }
    2673           0 :         else if(!sysCal().trxQuant().isNull()){
    2674           0 :           Vector< Quantum< Float > > sV;
    2675           0 :           sV.reference(sysCal().trxQuant()(irow));
    2676           0 :           vector< vector< Temperature > > fVV; 
    2677           0 :           if(sV.size() != numReceptor){
    2678             :             os << LogIO::SEVERE << "Inconsistent MS: TRX in syscal table row " << irow
    2679           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2680           0 :             return false;
    2681             :           } 
    2682           0 :           for(uInt i=0; i<numReceptor; i++){
    2683           0 :             vector< Temperature > fV;
    2684           0 :             for(uInt j=0; j<nChan; j++){
    2685           0 :               fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
    2686             :             }
    2687           0 :             fVV.push_back(fV);
    2688           0 :           }
    2689           0 :           tR->setTrxSpectrum(fVV);
    2690           0 :         }
    2691             : 
    2692             :         // Tsky
    2693           0 :         if(!sysCal().tskyFlag().isNull()){
    2694           0 :           tR->setTskyFlag(sysCal().tskyFlag()(irow));
    2695             :         }
    2696           0 :         if(!sysCal().tskySpectrumQuant().isNull()){
    2697           0 :           Matrix< Quantum< Float > > sM;
    2698           0 :           sM.reference(sysCal().tskySpectrumQuant()(irow));
    2699           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2700             :             os << LogIO::SEVERE << "Inconsistent MS: TSKY spectrum in syscal table row " << irow
    2701           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2702           0 :             return false;
    2703             :           } 
    2704           0 :           if(sM.shape()(1) != (Int)nChan){
    2705             :             os << LogIO::SEVERE << "Inconsistent MS: TSKY spectrum in syscal table row " << irow
    2706           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2707           0 :             return false;
    2708             :           } 
    2709           0 :           vector< vector< Temperature > > fVV; 
    2710           0 :           for(uInt i=0; i<numReceptor; i++){
    2711           0 :             vector< Temperature > fV;
    2712           0 :             for(uInt j=0; j<nChan; j++){
    2713           0 :               fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) ); 
    2714             :             }
    2715           0 :             fVV.push_back(fV);
    2716           0 :           }
    2717           0 :           tR->setTskySpectrum(fVV);
    2718           0 :         }
    2719           0 :         else if(!sysCal().tskyQuant().isNull()){
    2720           0 :           Vector< Quantum< Float > > sV;
    2721           0 :           sV.reference(sysCal().tskyQuant()(irow));
    2722           0 :           vector< vector< Temperature > > fVV; 
    2723           0 :           if(sV.size() != numReceptor){
    2724             :             os << LogIO::SEVERE << "Inconsistent MS: TSKY in syscal table row " << irow
    2725           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2726           0 :             return false;
    2727             :           } 
    2728           0 :           for(uInt i=0; i<numReceptor; i++){
    2729           0 :             vector< Temperature > fV;
    2730           0 :             for(uInt j=0; j<nChan; j++){
    2731           0 :               fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
    2732             :             }
    2733           0 :             fVV.push_back(fV);
    2734           0 :           }
    2735           0 :           tR->setTskySpectrum(fVV);
    2736           0 :         }
    2737             : 
    2738             :         // Tsys
    2739           0 :         if(!sysCal().tsysFlag().isNull()){
    2740           0 :           tR->setTsysFlag(sysCal().tsysFlag()(irow));
    2741             :         }
    2742           0 :         if(!sysCal().tsysSpectrumQuant().isNull()){
    2743           0 :           Matrix< Quantum< Float > > sM;
    2744           0 :           sM.reference(sysCal().tsysSpectrumQuant()(irow));
    2745           0 :           if(sM.shape()(0) != (Int)numReceptor){
    2746             :             os << LogIO::SEVERE << "Inconsistent MS: TSYS spectrum in syscal table row " << irow
    2747           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2748           0 :             return false;
    2749             :           } 
    2750           0 :           if(sM.shape()(1) != (Int)nChan){
    2751             :             os << LogIO::SEVERE << "Inconsistent MS: TSYS spectrum in syscal table row " << irow
    2752           0 :                << " should have second dimension as referenced SPW." << LogIO::POST;
    2753           0 :             return false;
    2754             :           } 
    2755           0 :           vector< vector< Temperature > > fVV; 
    2756           0 :           for(uInt i=0; i<numReceptor; i++){
    2757           0 :             vector< Temperature > fV;
    2758           0 :             for(uInt j=0; j<nChan; j++){
    2759           0 :               fV.push_back( Temperature(sM(i,j).getValue(unitASDMTemp())) ); 
    2760             :             }
    2761           0 :             fVV.push_back(fV);
    2762           0 :           }
    2763           0 :           tR->setTsysSpectrum(fVV);
    2764           0 :         }
    2765           0 :         else if(!sysCal().tsysQuant().isNull()){
    2766           0 :           Vector< Quantum< Float > > sV;
    2767           0 :           sV.reference(sysCal().tsysQuant()(irow));
    2768           0 :           vector< vector< Temperature > > fVV; 
    2769           0 :           if(sV.size() != numReceptor){
    2770             :             os << LogIO::SEVERE << "Inconsistent MS: TSYS in syscal table row " << irow
    2771           0 :                << " should have number of receptors as in Feed table: " << numReceptor << LogIO::POST;
    2772           0 :             return false;
    2773             :           } 
    2774           0 :           for(uInt i=0; i<numReceptor; i++){
    2775           0 :             vector< Temperature > fV;
    2776           0 :             for(uInt j=0; j<nChan; j++){
    2777           0 :               fV.push_back( Temperature(sV[i].getValue(unitASDMTemp())) );
    2778             :             }
    2779           0 :             fVV.push_back(fV);
    2780           0 :           }
    2781           0 :           tR->setTsysSpectrum(fVV);
    2782           0 :         }
    2783             : 
    2784             :         // phase diff
    2785           0 :         if(!sysCal().phaseDiffFlag().isNull()){
    2786           0 :           tR->setPhaseDiffFlag(sysCal().phaseDiffFlag()(irow));
    2787             :         }
    2788           0 :         if(!sysCal().phaseDiffQuant().isNull()){
    2789           0 :           float pD = sysCal().phaseDiffQuant()(irow).getValue(unitASDMAngle());
    2790           0 :           vector< vector< float > > fVV;
    2791           0 :           for(uInt i=0; i<numReceptor; i++){
    2792           0 :             vector< float > fV;
    2793           0 :             for(uInt j=0; j<nChan; j++){
    2794           0 :               fV.push_back(pD); 
    2795             :             }
    2796           0 :             fVV.push_back(fV);
    2797           0 :           }
    2798           0 :           tR->setPhaseDiffSpectrum(fVV);
    2799           0 :         }
    2800             :         
    2801             :         // finally add the completed new row to the table
    2802           0 :         asdm::SysCalRow* tR2 = 0;
    2803           0 :         tR2 = tT.add(tR);
    2804           0 :         if(tR2 != tR){ 
    2805           0 :           os << LogIO::WARN << "Duplicate row in MS SysCal table :" << irow << LogIO::POST;
    2806             :         }       
    2807             : 
    2808           0 :       } // end loop over MS syscal table
    2809             :     } // end else
    2810             : 
    2811           0 :     EntityId theUid(getCurrentUid());
    2812           0 :     Entity ent = tT.getEntity();
    2813           0 :     ent.setEntityId(theUid);
    2814           0 :     tT.setEntity(ent);
    2815           0 :     if(verbosity_p>0){
    2816           0 :       os << LogIO::NORMAL << "Filled SysCal table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    2817             :     }
    2818           0 :     incrementUid();
    2819             : 
    2820           0 :     return rstat;
    2821           0 :   }
    2822             : 
    2823             : 
    2824           0 :   Bool MS2ASDM::writeConfigDescription(){
    2825             : 
    2826           0 :    LogIO os(LogOrigin("MS2ASDM", "writeConfigDesc()"));
    2827             : 
    2828           0 :     Bool rstat = true;
    2829             : 
    2830           0 :     asdm::ConfigDescriptionTable& tT = ASDM_p->getConfigDescription();
    2831             : 
    2832           0 :     asdm::ProcessorTable& procT = ASDM_p->getProcessor();
    2833             : 
    2834           0 :     asdm::SwitchCycleTable& swcT = ASDM_p->getSwitchCycle();
    2835           0 :     vector< asdm::SwitchCycleRow * > swcRV = swcT.get();
    2836           0 :     Tag swcTag = swcRV[0]->getSwitchCycleId(); // preliminary implementation: get tag from first (and only) row
    2837             :     
    2838           0 :     uInt nMainTabRows = ms_p.nrow();    
    2839           0 :     uInt nProcTabRows =  processor().nrow();
    2840           0 :     Int dummyProcId = -1;
    2841           0 :     if(nProcTabRows<1){ // processor table not filled, all data should have proc id == -1
    2842           0 :       os <<  LogIO::WARN << "MS Processor table is empty. Will assume processor type is CORRELATOR." << LogIO::POST;
    2843           0 :       nProcTabRows = 1;
    2844           0 :       if(ms_p.nrow()>0 && processorId()(0)!=dummyProcId){
    2845             :         os <<  LogIO::WARN << "   Still, the MS Main table seems to refer to an existing processor id "
    2846           0 :            << processorId()(0) << ". Will try to proceed ..." << LogIO::POST;
    2847           0 :         dummyProcId = processorId()(0); // accept other proc id (e.g. 0)
    2848             :       }
    2849             :     }
    2850             : 
    2851             :     // temprorarily needed until all processor types are supported
    2852           0 :     vector<Int> goodSpwV;
    2853           0 :     vector<Int> badSpwV;
    2854             : 
    2855             :     // loop over MS processor table (typically, this loop will only be executed once)
    2856           0 :     for(uInt uprocId=0; uprocId<nProcTabRows; uprocId++){
    2857             :       
    2858           0 :       Int procId = uprocId;
    2859             :       
    2860           0 :       if(processor().nrow()<1){
    2861           0 :         procId = dummyProcId;
    2862             :       }
    2863             :       
    2864           0 :       if(verbosity_p>0){
    2865           0 :         os << LogIO::NORMAL << "Processor Id: " << procId << LogIO::POST;
    2866             :       }
    2867             :       
    2868           0 :       asdm::ConfigDescriptionRow* tR = 0;
    2869             :       
    2870           0 :       Tag procIdTag;
    2871           0 :       if(asdmProcessorId_p.find(procId) != asdmProcessorId_p.end()){
    2872           0 :         procIdTag = asdmProcessorId_p[procId];
    2873             :       }
    2874             :       else{
    2875           0 :         if(procId == dummyProcId && asdmProcessorId_p.find(-1) != asdmProcessorId_p.end( )){ // there is no MS Proc table and the main table is
    2876           0 :           procIdTag = asdmProcessorId_p[-1];                          //   using wrong proc ids
    2877             :         }
    2878             :         else{
    2879           0 :           os << LogIO::SEVERE << "Internal error: undefined mapping for processor id " << procId << LogIO::POST;
    2880           0 :           return false;
    2881             :         }
    2882             :       }
    2883             :       
    2884             :       // get processor type from already existing ASDM processor table
    2885           0 :       ProcessorTypeMod::ProcessorType processorType = procT.getRowByKey(procIdTag)->getProcessorType();
    2886             :       
    2887             :       // loop over data description table
    2888           0 :       for(Int iDDId=0; iDDId<(Int)dataDescription().nrow(); iDDId++){
    2889             : 
    2890             :         // find first row in main table with this proc ID and extract spectral type
    2891           0 :         SpectralResolutionTypeMod::SpectralResolutionType spectralType = SpectralResolutionTypeMod::FULL_RESOLUTION;
    2892             :         
    2893           0 :         uInt jrow=0;
    2894           0 :         while(jrow<nMainTabRows){
    2895           0 :           if(processorId()(jrow)==procId && dataDescId()(jrow)==iDDId){
    2896           0 :             break;
    2897             :           }
    2898           0 :           jrow++;
    2899             :         }
    2900           0 :         if(jrow>=nMainTabRows){ // DDId-processor pair not found
    2901           0 :           continue;
    2902             :         }
    2903             :         
    2904             :         // temprorary solution until other processro types are supported
    2905           0 :         if(processorType!=ProcessorTypeMod::CORRELATOR){
    2906           0 :           badSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
    2907             :         }
    2908             :         else{
    2909           0 :           goodSpwV.push_back(dataDescription().spectralWindowId()(iDDId));
    2910             :         }         
    2911             :         ///////////
    2912             : 
    2913           0 :         if(asdmDataDescriptionId_p.find(iDDId) == asdmDataDescriptionId_p.end( )){
    2914             :           os << LogIO::SEVERE << "Internal error: undefined mapping for data desc. id " << iDDId
    2915           0 :              << " in main table row " << jrow << LogIO::POST;
    2916           0 :           return false;
    2917             :         }
    2918             :         
    2919           0 :         uInt spwId = dataDescription().spectralWindowId()(iDDId);
    2920           0 :         if(spectralWindow().numChan()(spwId)<5){
    2921             : //        spectralType = SpectralResolutionTypeMod::CHANNEL_AVERAGE;
    2922           0 :           if(verbosity_p>1){
    2923             : //          os << LogIO::NORMAL << "    Less than 5 channels. Assuming data is of spectral resolution type \"CHANNEL_AVERAGE\"." 
    2924             : //             << LogIO::POST;      
    2925             :             os << LogIO::WARN << "    SPW " << spwId << ": less than 5 channels. Probably should use spectral resolution type \"CHANNEL_AVERAGE\"." 
    2926           0 :                << endl << "    But this is not yet implemented. Assuming FULL_RESOLUTION." << LogIO::POST;      
    2927             :           }
    2928             :         }
    2929             :       
    2930             :         // loop over MS Main table
    2931           0 :         Tag previousTag = Tag();
    2932           0 :         for(uInt mainTabRow=jrow; mainTabRow<nMainTabRows; mainTabRow++){
    2933             : 
    2934           0 :           if(dataDescId()(mainTabRow)!=iDDId || processorId()(mainTabRow)!=procId){
    2935           0 :             continue;
    2936             :           }
    2937             :           
    2938           0 :           if(verbosity_p>2){
    2939           0 :             cout << "proc id " << procId << " used at main table row " << mainTabRow << endl;
    2940             :           } 
    2941             :           
    2942           0 :           vector<Int> msAntennaIdV;
    2943           0 :           vector<Int> msDDIdV;
    2944           0 :           msDDIdV.push_back(iDDId); // always just this one entry
    2945           0 :           vector<Int> msFeedIdV;
    2946           0 :           vector<Int> msFeedKeyV;
    2947             :           
    2948           0 :           vector<Tag> antennaId;
    2949           0 :           vector<Tag> dataDId;
    2950           0 :           vector<int> feedId; 
    2951           0 :           vector<Tag> switchCycleId;
    2952           0 :           vector<AtmPhaseCorrectionMod::AtmPhaseCorrection> atmPhaseCorrection;
    2953           0 :           int numAntenna = 0;
    2954           0 :           int numDD = 0;
    2955           0 :           int numFeed = 0;
    2956             :           CorrelationModeMod::CorrelationMode correlationMode;
    2957             :           
    2958             :           // loop over MS main table and find for this proc id, DDId, and timestamp
    2959             :           //  a) all used antennas
    2960             :           //  b) all used feed IDs
    2961           0 :           uInt numAutoCorrs = 0;
    2962           0 :           uInt numBaselines = 0;
    2963             :           
    2964           0 :           uInt irow = mainTabRow;
    2965           0 :           Double thisTStamp = time()(irow); 
    2966             :           
    2967           0 :           while(irow<nMainTabRows && time()(irow)==thisTStamp){
    2968             :             
    2969           0 :             if(dataDescId()(irow)!=iDDId || processorId()(irow)!=procId){
    2970           0 :               irow++;
    2971           0 :               continue;
    2972             :             }
    2973             :             
    2974             :             // for the later determination of the correlation mode
    2975           0 :             if(antenna1()(irow) == antenna2()(irow)){
    2976           0 :               numAutoCorrs++;
    2977             :             }
    2978             :             else{
    2979           0 :               numBaselines++;
    2980             :             }
    2981             :             
    2982             :             // antenna ids
    2983             :             
    2984           0 :             Int aId = antenna1()(irow); 
    2985           0 :             Bool found = false;
    2986           0 :             for(uInt j=0; j<msAntennaIdV.size(); j++){
    2987           0 :               if(aId == msAntennaIdV[j]){
    2988           0 :                 found = true;
    2989           0 :                 break;
    2990             :               }
    2991             :             }
    2992           0 :             if(!found){
    2993           0 :               msAntennaIdV.push_back(aId);
    2994           0 :               if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
    2995             :                 os << LogIO::SEVERE << "Internal error: undefined mapping for antenna1 id " << aId 
    2996           0 :                    << " in main table row " << irow << LogIO::POST;
    2997           0 :                 return false;
    2998             :               }
    2999             :             }
    3000           0 :             aId = antenna2()(irow); 
    3001           0 :             found = false;
    3002           0 :             for(uInt j=0; j<msAntennaIdV.size(); j++){
    3003           0 :               if(aId == msAntennaIdV[j]){
    3004           0 :                 found = true;
    3005           0 :                 break;
    3006             :               }
    3007             :             }
    3008           0 :             if(!found){
    3009           0 :               msAntennaIdV.push_back(aId);
    3010           0 :               if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
    3011             :                 os << LogIO::SEVERE << "Internal error: undefined mapping for antenna2 id " << aId 
    3012           0 :                    << " in main table row " << irow << LogIO::POST;
    3013           0 :                 return false;
    3014             :               }
    3015             :             }
    3016             :             
    3017             :             
    3018             :             // feed ids
    3019           0 :             Int fIdi = feed1()(irow);
    3020           0 :             Int fKeyi = fIdi + 10000*antenna1()(irow);
    3021           0 :             found = false;            
    3022           0 :             for(uInt j=0;j<msFeedKeyV.size();j++){
    3023           0 :               if(fKeyi == msFeedKeyV[j]){
    3024           0 :                 found = true;
    3025           0 :                 break;
    3026             :               }
    3027             :             }
    3028           0 :             if(!found){
    3029           0 :               msFeedKeyV.push_back(fKeyi);
    3030           0 :               msFeedIdV.push_back(fIdi);
    3031           0 :               if(asdmFeedId_p.find(fIdi) == asdmFeedId_p.end( )){
    3032             :                 os << LogIO::SEVERE << "Internal error: undefined mapping for feed1 id " << fIdi
    3033           0 :                    << " in main table row " << irow << LogIO::POST;
    3034           0 :                 return false;
    3035             :               }
    3036             :             }
    3037           0 :             fIdi = feed2()(irow);
    3038           0 :             fKeyi = fIdi + 10000*antenna2()(irow);
    3039           0 :             found = false;            
    3040           0 :             for(uInt j=0;j<msFeedKeyV.size();j++){
    3041           0 :               if(fKeyi == msFeedKeyV[j]){
    3042           0 :                 found = true;
    3043           0 :                 break;
    3044             :               }
    3045             :             }
    3046           0 :             if(!found){
    3047           0 :               msFeedKeyV.push_back(fKeyi);
    3048           0 :               msFeedIdV.push_back(fIdi);
    3049           0 :               if(asdmFeedId_p.find(fIdi) == asdmFeedId_p.end( )){
    3050             :                 os << LogIO::SEVERE << "Internal error: undefined mapping for feed2 id " << fIdi
    3051           0 :                    << " in main table row " << irow << LogIO::POST;
    3052           0 :                 return false;
    3053             :               }
    3054             :             }
    3055             :             
    3056           0 :             irow++;
    3057             :           } // end while
    3058             :           
    3059             :             // sort the  antenna ids before entering them into the ConfigDescription table
    3060           0 :           std::sort(msAntennaIdV.begin(), msAntennaIdV.end());
    3061           0 :           for(uInt i=0; i<msAntennaIdV.size(); i++){
    3062           0 :               antennaId.push_back(asdmAntennaId_p[msAntennaIdV[i]]);
    3063             :           }
    3064           0 :           numAntenna = antennaId.size();
    3065             :           
    3066             :           // (there is just one DDId per config description in this scheme)
    3067           0 :           dataDId.push_back(asdmDataDescriptionId_p[msDDIdV[0]]);
    3068           0 :           numDD = 1;
    3069             :           
    3070             :           // sort the feed ids before entering them into the ConfigDescription table
    3071           0 :           std::sort(msFeedIdV.begin(), msFeedIdV.end());
    3072           0 :           for(uInt i=0; i<msFeedIdV.size(); i++){
    3073           0 :             feedId.push_back(asdmFeedId_p[msFeedIdV[i]]);
    3074             :           }
    3075           0 :           numFeed = feedId.size();
    3076           0 :           if(numAntenna>1){
    3077           0 :             numFeed = numFeed/numAntenna;
    3078             :           }
    3079             :           
    3080           0 :           if(numAutoCorrs==0){
    3081           0 :             correlationMode = CorrelationModeMod::CROSS_ONLY;
    3082             :           }
    3083           0 :           else if(numBaselines>0){
    3084           0 :             correlationMode = CorrelationModeMod::CROSS_AND_AUTO;
    3085             :           }
    3086             :           else{
    3087           0 :             correlationMode = CorrelationModeMod::AUTO_ONLY;
    3088             :           }
    3089             :           
    3090           0 :           switchCycleId.push_back(swcTag); // switch cycle table will only be dummy ? -> Francois
    3091             :           // dummy if PHASE_ID column doesn't exist in MS main
    3092             :           // PHASE_ID identifies bin in switch cycle
    3093             :           //   otherwise, e.g. PHASE_ID = 0 and 1 => numStep == 2
    3094             :           
    3095           0 :           if(dataIsAPCorrected()){
    3096           0 :             atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_CORRECTED); 
    3097             :           }
    3098             :           else{
    3099           0 :             atmPhaseCorrection.push_back(AtmPhaseCorrectionMod::AP_UNCORRECTED); 
    3100             :           }         
    3101             :           
    3102             :           // create a new row with its mandatory attributes.
    3103           0 :           tR = tT.newRow (numAntenna,
    3104             :                           numDD,
    3105             :                           numFeed,
    3106             :                           correlationMode, 
    3107           0 :                           atmPhaseCorrection.size(),
    3108             :                           atmPhaseCorrection, 
    3109             :                           processorType, 
    3110             :                           spectralType, 
    3111             :                           antennaId, 
    3112             :                           feedId, 
    3113             :                           switchCycleId, 
    3114             :                           dataDId, 
    3115             :                           procIdTag);
    3116             :           
    3117             :           // optional attributes.
    3118             :           //vector<Tag> assocConfigDescriptionId(1);
    3119             :           //assocConfigDescriptionId[0] = Tag(1, TagType::ConfigDescription);
    3120             :           //vector<int> phasedArrayList(2);
    3121             :           //phasedArrayList[0] = 0;
    3122             :           //phasedArrayList[1] = 1;
    3123             :           //vector<bool> flagAnt(2, false);
    3124             :           //      vector<SpectralResolutionTypeMod::SpectralResolutionType> assocNature(1);
    3125             :           //assocNature[0] = SpectralResolutionTypeMod::FULL_RESOLUTION;
    3126             :           //tR->setAssocConfigDescriptionId(assocConfigDescriptionId);
    3127             :           //tR->setPhasedArrayList(phasedArrayList);
    3128             :           //tR->setFlagAnt(flagAnt);
    3129             :           //tR->setAssocNature(assocNature);   
    3130             :           
    3131             :           // add this row to to the config description table.
    3132             :           //  note that this will check for uniqueness
    3133           0 :           asdm::ConfigDescriptionRow* tR2 = 0;
    3134             :           
    3135           0 :           tR2 = tT.add(tR);
    3136           0 :           Tag newTag = tR2->getConfigDescriptionId();
    3137           0 :           asdmConfigDescriptionId_p[mainTabRow] = newTag;
    3138           0 :           if(verbosity_p>1){
    3139           0 :             cout << "Defined conf desc id for main table row " << mainTabRow << endl;
    3140             :           }
    3141             : 
    3142           0 :           mainTabRow = irow-1;
    3143             :           
    3144           0 :         } // end loop over remainder of timestamp in MS main table 
    3145             : 
    3146           0 :       } // end loop over MS DD table
    3147             : 
    3148           0 :     } // end loop over MS processor table
    3149             : 
    3150             :     // temporarily needed until all processor types are supported
    3151           0 :     if(badSpwV.size() > 0){
    3152             :       os << LogIO::SEVERE << "Input MS contains data which is not of processor type CORRELATOR.\n" 
    3153             :          << "Writing this data to an ASDM is not yet properly supported by exportasdm.\n"
    3154           0 :          << "As a temporary solution please create an input MS containing only the following SPWs" << LogIO::POST;
    3155           0 :       for(uInt ii=0; ii<goodSpwV.size(); ii++){
    3156           0 :         os <<  LogIO::SEVERE <<  "    " << goodSpwV[ii] << "  " << LogIO::POST;
    3157             :       }
    3158           0 :       os <<  LogIO::SEVERE << "using task \"split\"." << LogIO::POST;
    3159           0 :       return false;
    3160             :     }
    3161             : 
    3162           0 :     EntityId theUid(getCurrentUid());
    3163           0 :     Entity ent = tT.getEntity();
    3164           0 :     ent.setEntityId(theUid);
    3165           0 :     tT.setEntity(ent);
    3166           0 :     if(verbosity_p>0){
    3167           0 :       os << LogIO::NORMAL << "Filled ConfigDescription table " << getCurrentUid() << " with " << tT.size() << " rows ... " << LogIO::POST;
    3168             :     }
    3169           0 :     incrementUid();
    3170             : 
    3171           0 :     return rstat;
    3172             : 
    3173           0 :   }
    3174             : 
    3175           0 :   Bool MS2ASDM::writeSBSummaryAndExecBlockStubs(){
    3176           0 :     LogIO os(LogOrigin("MS2ASDM", "writeSBSummaryAndExecBlockStubs()"));
    3177             :     
    3178           0 :     Bool rstat = true;
    3179             :     
    3180           0 :     asdm::SBSummaryTable& tT = ASDM_p->getSBSummary();
    3181             :     
    3182           0 :     asdm::SBSummaryRow* tR = 0;
    3183             : 
    3184           0 :     asdm::ExecBlockTable& tET = ASDM_p->getExecBlock();
    3185             :     
    3186           0 :     asdm::ExecBlockRow* tER = 0;
    3187             : 
    3188           0 :     MapWithDefault <asdm::Tag, Double> execBlockStartTime(-1.); // map from SBSummaryID to current execblock start time
    3189           0 :     MapWithDefault <asdm::Tag, Double> execBlockEndTime(-1.); // map from SBSummaryID to current execblock end time
    3190           0 :     MapWithDefault <asdm::Tag, asdm::ConfigDescriptionRow*> correspConfigDescRow(0); // map from SBSummaryID to the 
    3191             :                                                                              // ConfigDescription row of current exec block
    3192           0 :     MapWithDefault <asdm::Tag, Int> execBlockNumber(0); // map from SBSummaryID to current execblock number
    3193           0 :     MapWithDefault <asdm::Tag, Int> obsIdFromSBSum(-1); // map from SBSummaryID to current obs ID
    3194           0 :     MapWithDefault <asdm::Tag, Double> minBaseline(0.); // map from SBSummaryID to minimum baseline of current exec block
    3195           0 :     MapWithDefault <asdm::Tag, Double> maxBaseline(0.); // map from SBSummaryID to maximum baseline of current exec block
    3196             : 
    3197           0 :     MapWithDefault <Int, Int> firstFieldIdFromObsId(-1); // map from obsId to first field id (for the representative direction)
    3198             : 
    3199             :     // unfortunately, we have to loop over the main table to get the information
    3200             : 
    3201             :     // but beforehand we calculate the position of the array center for later reference
    3202             : 
    3203           0 :     MPosition pos;
    3204             :     {
    3205           0 :       MPosition Xpos;
    3206           0 :       String Xobservatory;
    3207           0 :       if (observation().nrow() > 0) {
    3208           0 :         Xobservatory = observation().telescopeName()(observationId()(0));
    3209             :       }
    3210           0 :       if (Xobservatory.length() == 0 || 
    3211           0 :           !MeasTable::Observatory(Xpos,Xobservatory)) {
    3212             :         // unknown observatory
    3213             :         os << LogIO::WARN << "Unknown observatory: \"" << Xobservatory 
    3214           0 :            << "\". Determining observatory position from antenna 0." << LogIO::POST;
    3215           0 :         Xpos=MPosition::Convert(antenna().positionMeas()(0), MPosition::WGS84)();
    3216             :       }
    3217             :       else{
    3218             :         os << LogIO::NORMAL << "Using tabulated observatory position for " << Xobservatory << ":"
    3219           0 :            << LogIO::POST;
    3220           0 :         Xpos=MPosition::Convert(Xpos, MPosition::WGS84)();
    3221             :       }
    3222           0 :       pos = Xpos;
    3223           0 :       ostringstream oss;
    3224           0 :       oss <<  "   " << pos << " (WGS84)";
    3225           0 :       os << LogIO::NORMAL << oss.str() << LogIO::POST;
    3226           0 :     }
    3227             : 
    3228             :     ////MVPosition mObsPos = pos.getValue();
    3229             :     ////Vector<Double> hlonlat = mObsPos.get(); // get three-vector of height, lon, lat  in m, rad, rad
    3230             :     ////Length siteAltitude = Length(hlonlat(0));
    3231             :     ////Angle siteLongitude = Angle(hlonlat(1));
    3232             :     ////Angle siteLatitude = Angle(hlonlat(2));
    3233             : 
    3234             :     // loop over main table
    3235           0 :     Bool warned = false; // aux. var. to avoid warning repetition  
    3236           0 :     uInt nMainTabRows = ms_p.nrow();
    3237             : 
    3238           0 :     Int prevSBKey = -1;
    3239           0 :     double prevReprFreq = (163.+211.)/2.*1E9;
    3240           0 :     ReceiverBandMod::ReceiverBand prevFrequencyBand = ReceiverBandMod::ALMA_RB_05; 
    3241           0 :     ReceiverSidebandMod::ReceiverSideband prevRSB = ReceiverSidebandMod::TSB;
    3242           0 :     Int nProcTabRows =  processor().nrow();
    3243             : 
    3244           0 :     for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
    3245             : 
    3246             :       // Step 1: determine SBSummary ID and fill SBSummary table row
    3247             :       // (duplicate rows will automatically be taken care of by the row adding method)
    3248             : 
    3249           0 :       Int obsId = observationId()(mainTabRow);
    3250             : 
    3251             :       // parameters of the new SBSummary row
    3252           0 :       Int ddId = dataDescId()(mainTabRow);
    3253           0 :       Int spwId = dataDescription().spectralWindowId()(ddId);
    3254           0 :       Int procId = processorId()(mainTabRow);
    3255             : 
    3256           0 :       Bool isWVR = false;
    3257           0 :       if(procId>=0 && nProcTabRows>0 && procId < nProcTabRows){
    3258           0 :         if(processor().type()(procId) == "RADIOMETER"){
    3259             :           //cout << "Found WVR data" << endl;
    3260           0 :           isWVR = true;
    3261             :         }
    3262             :       }
    3263             : 
    3264           0 :       double frequency = (spectralWindow().refFrequencyQuant()(spwId)).getValue(unitASDMFreq()); 
    3265             :       //cout << "Freq " << frequency << endl;
    3266             : 
    3267             :       ReceiverBandMod::ReceiverBand frequencyBand; // get from frequency
    3268             :       ReceiverSidebandMod::ReceiverSideband rSB;
    3269           0 :       double reprFreq = 0.;
    3270           0 :       Int bandNum = setRecBands(Frequency(frequency), reprFreq, frequencyBand, rSB); 
    3271             :       //cout << "Band " << bandNum << endl;
    3272             : 
    3273           0 :       Int sbKey = obsId;
    3274             :       
    3275           0 :       if(bandNum >= 0){
    3276           0 :         if(isWVR){// special case: WVR data is observed in a (potentially) different band but no separate SB is created for it
    3277           0 :           if(prevSBKey>=0){ // other data was encountered beforehand, there is already a proper SBKey from it
    3278           0 :             sbKey = prevSBKey;
    3279           0 :             reprFreq = prevReprFreq;
    3280           0 :             frequencyBand = prevFrequencyBand;
    3281           0 :             rSB = prevRSB;
    3282             :           }
    3283             :           else{ // we need to peek forward until non-WVR data is found
    3284           0 :             Bool foundNonWVR = false;
    3285           0 :             uInt mainTabRowB = 0;
    3286           0 :             for(mainTabRowB=mainTabRow+1; mainTabRowB<nMainTabRows; mainTabRowB++){
    3287           0 :               Int procIdB = processorId()(mainTabRowB);
    3288           0 :               if(procIdB>=0 && nProcTabRows>0 && procIdB < nProcTabRows){
    3289           0 :                 if(processor().type()(procIdB) == "RADIOMETER"){
    3290             :                   //cout << "Found WVR data again" << endl;
    3291           0 :                   continue;
    3292             :                 }
    3293           0 :                 foundNonWVR=true;
    3294           0 :                 break;
    3295             :                 
    3296             :               }
    3297           0 :               foundNonWVR=true;
    3298           0 :               break;
    3299             :             }// end for
    3300           0 :             if(foundNonWVR){
    3301           0 :               obsId = observationId()(mainTabRowB);
    3302           0 :               ddId = dataDescId()(mainTabRowB);
    3303           0 :               spwId = dataDescription().spectralWindowId()(ddId);
    3304           0 :               frequency = (spectralWindow().refFrequencyQuant()(spwId)).getValue(unitASDMFreq());
    3305           0 :               bandNum = setRecBands(Frequency(frequency), reprFreq, frequencyBand, rSB);
    3306           0 :               sbKey = obsId+10000*bandNum;
    3307             :             }
    3308             :             else{ // there is only WVR data
    3309           0 :               sbKey = obsId+10000*bandNum;
    3310             :             }
    3311             :           }
    3312             :         }
    3313             :         else{ // this is normal non-WVR data
    3314           0 :           sbKey = obsId+10000*bandNum; // an SB can only observe one band
    3315             :         }
    3316             :       }
    3317             :       else{
    3318             :         os << LogIO::WARN << "Could not determine ALMA frequency band for frequency " 
    3319           0 :            << frequency << " Hz in MS Spectral Window " << spwId << ". Will try to continue." << LogIO::POST;
    3320           0 :           sbKey = obsId+10000*bandNum; // an SB can only observe one band
    3321             :       }
    3322             :       // memorize freq band info
    3323           0 :       prevSBKey = sbKey;
    3324           0 :       prevReprFreq = reprFreq;
    3325           0 :       prevFrequencyBand = frequencyBand;
    3326           0 :       prevRSB = rSB;
    3327             : 
    3328             :       //cout << "   SBKey " << sbKey << endl;
    3329             :       //cout << "   reprFreq " << reprFreq << endl;
    3330             : 
    3331           0 :       String sbsUid("uid://SAFFEC0C0/X1/X1");
    3332           0 :       ostringstream oss;
    3333           0 :       oss << sbKey;
    3334           0 :       sbsUid = sbsUid + String(oss);
    3335           0 :       EntityRef sbSummaryUID(sbsUid.c_str(), "", "ASDM", asdmVersion_p); // will be reset later when linking the ASDM to an APDM 
    3336           0 :       EntityRef projectUID("uid://SAFFEC0C0/X1/X2", "", "ASDM", asdmVersion_p); // dto.
    3337           0 :       EntityRef obsUnitSetId("uid://SAFFEC0C0/X1/X3", "", "ASDM", asdmVersion_p); // dto. 
    3338             : 
    3339           0 :       SBTypeMod::SBType sbType = SBTypeMod::OBSERVATORY; //???
    3340           0 :       Vector< Quantum< Double > > tRange;
    3341           0 :       tRange.reference(observation().timeRangeQuant()(obsId)); 
    3342           0 :       Double durationSecs = tRange[1].getValue("s") - tRange[0].getValue("s"); 
    3343           0 :       if(durationSecs == 0){ // try to derive the sched block duration in a different way
    3344           0 :         if(!warned){
    3345             :           os << LogIO::WARN << "Observation time range is zero length for obs ID "
    3346             :              << obsId << " in MS Observation table.\n Will try to proceed ..."
    3347           0 :              <<LogIO::POST;
    3348           0 :           warned = true;
    3349             :         }
    3350           0 :         durationSecs = timestampEndSecs(nMainTabRows-1) - timestampStartSecs(0);
    3351             :       } 
    3352           0 :       Interval sbDuration = ASDMInterval(durationSecs);
    3353           0 :       int numberRepeats = 1;
    3354             :       // limit the scheduling block duration (not the same as the observation duration)
    3355           0 :       if(durationSecs > schedBlockDuration_p){
    3356           0 :         sbDuration = ASDMInterval(schedBlockDuration_p);
    3357           0 :         numberRepeats = (int) ceil(durationSecs/schedBlockDuration_p);
    3358           0 :         durationSecs = schedBlockDuration_p;
    3359             :       }
    3360           0 :       vector< Angle > centerDirection;
    3361           0 :       Int fId = fieldId()(mainTabRow);
    3362             :       // an observation (and an SB) can have many fields. use the first one as representative direction
    3363           0 :       if(firstFieldIdFromObsId.find(obsId) != firstFieldIdFromObsId.end( )){
    3364           0 :         fId = firstFieldIdFromObsId[obsId];
    3365             :       }
    3366             :       else{
    3367           0 :         firstFieldIdFromObsId[obsId] = fId;
    3368             :       } 
    3369             :       ////MDirection theFieldDir = field().phaseDirMeas(fId,0);
    3370             :       ////centerDirection.push_back( theFieldDir.getAngle( unitASDMAngle() ).getValue()(0) ); // RA
    3371             :       ////centerDirection.push_back( theFieldDir.getAngle( unitASDMAngle() ).getValue()(1) ); // DEC
    3372             :       
    3373           0 :       int numObservingMode = 1;
    3374           0 :       vector< string > observingMode;
    3375           0 :       observingMode.push_back("observing mode t.b.d.");
    3376           0 :       int numScienceGoal = 1;
    3377           0 :       vector< string > scienceGoal;
    3378           0 :       scienceGoal.push_back("science goal t.b.d.");
    3379           0 :       int numWeatherConstraint = 1;
    3380           0 :       vector< string > weatherConstraint;
    3381           0 :       weatherConstraint.push_back("weather constraint t.b.d.");
    3382             :       
    3383           0 :       tR = tT.newRow(sbSummaryUID, projectUID, obsUnitSetId, reprFreq, frequencyBand, sbType, sbDuration, 
    3384             :                      ////centerDirection, 
    3385             :                      numObservingMode, observingMode, numberRepeats, numScienceGoal, 
    3386             :                      scienceGoal, numWeatherConstraint, weatherConstraint);
    3387             :       
    3388           0 :       asdm::SBSummaryRow* tR2 = 0;
    3389           0 :       tR2 = tT.add(tR);
    3390           0 :       Tag sBSummaryTag = tR2->getSBSummaryId();
    3391           0 :       if(tR2 == tR){ // adding the row led to the creation of a new tag
    3392           0 :         if(verbosity_p>2){
    3393           0 :           cout << "New SBSummary tag created: " << tR2 << endl;
    3394             :         }
    3395           0 :         if( asdmSBSummaryId_p.find(sbKey) != asdmSBSummaryId_p.end( ) ){
    3396             :           os << LogIO::WARN << "There is more than one scheduling block necessary for the obsid - freqBand pair (" 
    3397             :              << obsId << ", " << bandNum << ").\n This can presently not yet be handled properly.\n" 
    3398           0 :              << "(MS Main table row " << mainTabRow << ")" << LogIO::POST;
    3399             :         }
    3400             :         else{
    3401           0 :         asdmSBSummaryId_p[sbKey] = sBSummaryTag;
    3402             :         }
    3403             :       }
    3404             : 
    3405             :       // now have a valid SBSummaryID for the execblock
    3406             : 
    3407             :       // Step 2: write exec block table
    3408             : 
    3409             :       // has the exec block been started already?
    3410           0 :       if(execBlockStartTime.find(sBSummaryTag) != execBlockStartTime.end( )){ // yes
    3411             : 
    3412             :         // continue accumulation of min and max baseline
    3413           0 :         Double baseLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
    3414           0 :                                       (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
    3415           0 :                                       ).getLength().getValue(unitASDMLength());
    3416           0 :         if(baseLine>maxBaseline[sBSummaryTag]){
    3417           0 :         maxBaseline[sBSummaryTag] = baseLine;
    3418             :         }
    3419           0 :         else if(baseLine<minBaseline[sBSummaryTag]){
    3420           0 :         minBaseline[sBSummaryTag] = baseLine;
    3421             :         }
    3422             : 
    3423             :         // is the exec block complete?
    3424           0 :         Double endT = timestampEndSecs(mainTabRow);
    3425           0 :         if(endT > execBlockEndTime[sBSummaryTag]){ // integration intervals may be different for different DD Ids, take max endT
    3426           0 :         execBlockEndTime[sBSummaryTag] = endT;
    3427             :         }
    3428           0 :         if(verbosity_p>2){
    3429           0 :           cout << "interval = " << endT - execBlockStartTime[sBSummaryTag] << ", duration == " <<  durationSecs << endl;
    3430             :         }
    3431             : 
    3432           0 :         if(endT - execBlockStartTime[sBSummaryTag] >= durationSecs){ // yes, it is complete
    3433             :           // parameters for a new row
    3434             :   
    3435           0 :           ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
    3436           0 :           ArrayTime endTime = ASDMArrayTime(endT);
    3437           0 :           int execBlockNum = execBlockNumber[sBSummaryTag];
    3438           0 :           EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM 
    3439             :           try{
    3440           0 :             execBlockUID = EntityRef(asdmUID_p, "", "ASDM", asdmVersion_p);
    3441             :           }
    3442           0 :           catch(asdm::InvalidArgumentException x){
    3443             :             os << LogIO::SEVERE << "Error creating ASDM:  UID \"" << getCurrentUid() 
    3444           0 :                << "\" (intended for the ASDM) is not a valid Entity reference: " <<  x.getMessage()
    3445           0 :                << LogIO::POST;      
    3446           0 :             return false;
    3447           0 :           }
    3448           0 :           incrementUid();
    3449           0 :           EntityRef projectId = projectUID;
    3450           0 :           string configName = "configName t.b.d."; // ???
    3451           0 :           string telescopeName = telName_p;
    3452           0 :           string observerName = observation().observer()(obsId).c_str();
    3453           0 :           if(observerName==""){
    3454           0 :             observerName = "unknown";
    3455             :           }
    3456             :           ////string observingLog = "log not filled";
    3457           0 :           vector<string > observingLog(1);
    3458           0 :           int numObservingLog = 1;
    3459           0 :           observingLog[0] = "log not filled"; 
    3460           0 :           Vector< String > sV;
    3461           0 :           if(observation().log().isDefined(obsId)){// log string array not empty
    3462           0 :             sV.reference(observation().log()(obsId)); // the observation log is an array of strings
    3463           0 :             observingLog.resize(sV.size());
    3464           0 :             numObservingLog = observingLog.size();
    3465           0 :             for(uInt i=0; i<sV.size(); i++){
    3466           0 :               observingLog[i] = string(sV[i].c_str());
    3467             :             }
    3468             :           }
    3469             :           ////string sessionReference = "sessionReference t.b.d."; // ???
    3470             :           ////EntityRef sbSummary = sbSummaryUID;
    3471           0 :           EntityRef sessionReference = sbSummaryUID;
    3472             :           ////string schedulerMode = "CASA exportasdm"; //???
    3473           0 :           Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
    3474           0 :           Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
    3475           0 :           Length baseRmsMinor = Length(0); // ???
    3476           0 :           Length baseRmsMajor = Length(0); // ???
    3477           0 :           Angle basePa = Angle(0); // ???
    3478           0 :           bool aborted = false;
    3479           0 :           asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
    3480           0 :           int numAntenna = cDR->getNumAntenna();
    3481           0 :           vector< Tag > antennaId = cDR->getAntennaId();
    3482             : 
    3483           0 :           tER = tET.newRow(startTime, endTime, execBlockNum, execBlockUID, projectId, configName, telescopeName, observerName, 
    3484             :                            numObservingLog, observingLog, //// now vector< string>
    3485             :                            sessionReference, //// now of type EntityRef
    3486             :                            ////sbSummary, schedulerMode, 
    3487             :                            baseRangeMin, baseRangeMax, baseRmsMinor, baseRmsMajor, basePa, 
    3488             :                            ////siteAltitude, siteLongitude, siteLatitude, 
    3489             :                            aborted, numAntenna, antennaId, sBSummaryTag);
    3490             :           
    3491             :           asdm::ExecBlockRow* tER2;
    3492             : 
    3493           0 :           tER2 = tET.add(tER);
    3494           0 :           if(tER2 != tER){
    3495           0 :             os << LogIO::SEVERE << "Internal error: attempt to store duplicate exec block row." << LogIO::POST;
    3496           0 :             return false;
    3497             :           }
    3498           0 :           asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
    3499             : 
    3500           0 :           if(verbosity_p>2){
    3501           0 :             std::cout << "eblock id defined in loop 1 for start time " << std::setprecision(13) << execBlockStartTime[sBSummaryTag] << endl;
    3502           0 :             std::cout << "                                  end time " << std::setprecision(13) << execBlockEndTime[sBSummaryTag] << endl;
    3503             :           }
    3504             : 
    3505             :           // undefine the mapping for this Tag since the ExecBlock was completed
    3506           0 :       auto startptr = execBlockStartTime.find(sBSummaryTag);
    3507           0 :           if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
    3508           0 :       auto endptr = execBlockEndTime.find(sBSummaryTag);
    3509           0 :           if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
    3510           0 :       auto corptr = correspConfigDescRow.find(sBSummaryTag);
    3511           0 :           if ( corptr != correspConfigDescRow.end( ) ) correspConfigDescRow.erase(corptr);
    3512           0 :           auto sumptr = obsIdFromSBSum.find(sBSummaryTag);
    3513           0 :           if ( sumptr != obsIdFromSBSum.end( ) ) obsIdFromSBSum.erase(sumptr);
    3514           0 :           auto minptr = minBaseline.find(sBSummaryTag);
    3515           0 :           if ( minptr != minBaseline.end( ) ) minBaseline.erase(minptr);
    3516           0 :           auto maxptr = maxBaseline.find(sBSummaryTag);
    3517           0 :           if ( maxptr != maxBaseline.end( ) ) maxBaseline.erase(maxptr);
    3518             :           
    3519           0 :         }
    3520             : //      else{ // no, it is not complete  
    3521             : //      }
    3522             :       } 
    3523             :       else{// no, it has not been started, yet
    3524             : 
    3525             :         // check if there is another exec block which started at the same time
    3526           0 :           for ( auto iter = execBlockStartTime.begin( ); iter != execBlockStartTime.end( ); ++iter ) {
    3527           0 :               if ( iter->second == timestampStartSecs(mainTabRow) ){
    3528             :                   os << LogIO::SEVERE << "Observation of different frequency bands at the same time and under the same observation ID is not supported by the ASDM."
    3529           0 :                      << "\n  Please split out the different spectral bands into individual MSs and process separately." << LogIO::POST;
    3530           0 :                   return false;
    3531             :               }
    3532             :           }
    3533             : 
    3534           0 :           execBlockStartTime[sBSummaryTag] = timestampStartSecs(mainTabRow);
    3535           0 :           execBlockEndTime[sBSummaryTag] = timestampEndSecs(mainTabRow); // will be updated
    3536             : 
    3537           0 :         Int oldNum = 0;
    3538           0 :     auto numptr = execBlockNumber.find(sBSummaryTag);
    3539           0 :         if( numptr != execBlockNumber.end( ) ){ 
    3540             :           // increment exec block number
    3541           0 :         oldNum = numptr->second;
    3542           0 :         execBlockNumber.erase(numptr);
    3543             :         }
    3544           0 :         execBlockNumber[sBSummaryTag] = oldNum + 1; // sequential numbering starting at 1
    3545             : 
    3546           0 :         if(verbosity_p>2){
    3547           0 :           std::cout << "eblock number " << oldNum + 1 << " defined for start time " << std::setprecision (9) << timestampStartSecs(mainTabRow) << endl;
    3548             :         }
    3549             : 
    3550           0 :         obsIdFromSBSum[sBSummaryTag] = obsId; // remember the obsId for this exec block
    3551             :         
    3552           0 :         if( asdmConfigDescriptionId_p.find(mainTabRow) == asdmConfigDescriptionId_p.end( ) ){
    3553             :           os << LogIO::SEVERE << "Internal error: undefined config description id for MS main table row "
    3554           0 :              << mainTabRow << LogIO::POST;
    3555           0 :           return false;
    3556             :         }  
    3557           0 :         asdm::ConfigDescriptionRow* cDR = (ASDM_p->getConfigDescription()).getRowByKey(asdmConfigDescriptionId_p[mainTabRow]);
    3558           0 :         if(cDR ==0){
    3559             :           os << LogIO::SEVERE << "Internal error: no row in ASDM ConfigDesc Table for ConfigDescriptionId stored for main table row "
    3560           0 :              << mainTabRow << LogIO::POST;
    3561           0 :           return false;
    3562             :         }
    3563           0 :         correspConfigDescRow[sBSummaryTag] = cDR; // remember the config description row for this exec block
    3564             : 
    3565             :         // start accumulation of min and max baseline
    3566           0 :         Double bLine = MVBaseline( (antenna().positionMeas()(antenna1()(mainTabRow))).getValue(),
    3567           0 :                                    (antenna().positionMeas()(antenna2()(mainTabRow))).getValue()
    3568           0 :                                    ).getLength().getValue(unitASDMLength());
    3569           0 :         minBaseline[sBSummaryTag] = bLine;
    3570           0 :         maxBaseline[sBSummaryTag] = bLine;
    3571             :       }
    3572             :       // skip rest of this timestamp
    3573           0 :       Double tStamp = time()(mainTabRow);
    3574           0 :       while(mainTabRow<nMainTabRows 
    3575           0 :             && time()(mainTabRow)==tStamp
    3576           0 :             && dataDescId()(mainTabRow)==ddId){
    3577           0 :         mainTabRow++;
    3578             :       }
    3579           0 :       mainTabRow--;// we are inside a for loop which will perform the last mainTabRow++ 
    3580           0 :     } // end loop over main table
    3581             : 
    3582             :     // are there pending exec blocks?
    3583           0 :     while(execBlockStartTime.size()>0){ // yes
    3584           0 :       Tag sBSummaryTag = execBlockStartTime.begin( )->first;
    3585           0 :       tR = tT.getRowByKey(sBSummaryTag);
    3586           0 :       Int obsId = obsIdFromSBSum[sBSummaryTag];
    3587             :       // parameters for a new row      
    3588           0 :       ArrayTime startTime = ASDMArrayTime(execBlockStartTime[sBSummaryTag]);
    3589           0 :       ArrayTime endTime = ASDMArrayTime(execBlockEndTime[sBSummaryTag]);
    3590           0 :       int execBlockNum = execBlockNumber[sBSummaryTag];
    3591           0 :       EntityRef execBlockUID; // to be filled with the EntityRef of the containing ASDM 
    3592             :       try{
    3593           0 :         execBlockUID = EntityRef(asdmUID_p, "", "ASDM", asdmVersion_p);
    3594             :       }
    3595           0 :       catch(asdm::InvalidArgumentException x){
    3596             :         os << LogIO::SEVERE << "Error creating ASDM:  UID \"" << getCurrentUid() 
    3597           0 :            << "\" (intended for an exec block) not a valid Entity reference: " <<  x.getMessage()
    3598           0 :            << LogIO::POST;      
    3599           0 :         return false;
    3600           0 :       }
    3601           0 :       incrementUid();
    3602           0 :       EntityRef projectId = tR->getProjectUID();
    3603           0 :       string configName = "configName t.b.d."; // ???
    3604           0 :       string telescopeName = telName_p;
    3605           0 :       string observerName = observation().observer()(obsId).c_str();
    3606           0 :       if(observerName==""){
    3607           0 :         observerName = "unknown";
    3608             :       }
    3609             : 
    3610             :       ////string observingLog = "log not filled";
    3611           0 :       vector<string > observingLog(1);
    3612           0 :       int numObservingLog = 1;
    3613           0 :       observingLog[0] = "log not filled"; 
    3614           0 :       Vector< String > sV;
    3615           0 :       if(observation().log().isDefined(obsId)){// log string array not empty
    3616           0 :         sV.reference(observation().log()(obsId)); // the observation log is an array of strings
    3617           0 :         observingLog.resize(sV.size());
    3618           0 :         numObservingLog = observingLog.size();
    3619           0 :         for(uInt i=0; i<sV.size(); i++){
    3620           0 :           observingLog[i] = string(sV[i].c_str());
    3621             :         }
    3622             :       }
    3623             :     
    3624             :       //// string sessionReference = "sessionReference t.b.d."; // ???
    3625             :       ////EntityRef sbSummary = tR->getSbSummaryUID();
    3626           0 :       EntityRef sessionReference = tR->getSbSummaryUID();
    3627             :       ////string schedulerMode = "CASA exportasdm"; //???
    3628           0 :       Length baseRangeMin = Length( minBaseline[sBSummaryTag] );
    3629           0 :       Length baseRangeMax = Length( maxBaseline[sBSummaryTag] );
    3630           0 :       Length baseRmsMinor = Length(0); // ???
    3631           0 :       Length baseRmsMajor = Length(0); // ???
    3632           0 :       Angle basePa = Angle(0); // ???
    3633           0 :       bool aborted = false;
    3634           0 :       asdm::ConfigDescriptionRow* cDR = correspConfigDescRow[sBSummaryTag];
    3635           0 :       int numAntenna = cDR->getNumAntenna();
    3636           0 :       vector< Tag > antennaId = cDR->getAntennaId();
    3637             :       
    3638           0 :       tER = tET.newRow(startTime, endTime, execBlockNum, execBlockUID, projectId, configName, telescopeName, observerName, 
    3639             :                        numObservingLog, observingLog, 
    3640             :                        sessionReference, 
    3641             :                        ////sbSummary, schedulerMode, 
    3642             :                        baseRangeMin, baseRangeMax, baseRmsMinor, baseRmsMajor, basePa, 
    3643             :                        ////siteAltitude, siteLongitude, siteLatitude, 
    3644             :                        aborted, numAntenna, antennaId, sBSummaryTag);
    3645             :       
    3646             :       asdm::ExecBlockRow* tER2;
    3647             :       
    3648           0 :       tER2 = tET.add(tER);
    3649           0 :       if(tER2 != tER){
    3650           0 :         os << LogIO::SEVERE << "Internal error: attempt to store duplicate exec block row." << LogIO::POST;
    3651           0 :         return false;
    3652             :       }
    3653           0 :       asdmExecBlockId_p[execBlockStartTime[sBSummaryTag]] = tER->getExecBlockId();
    3654             : 
    3655           0 :       if(verbosity_p>2){
    3656           0 :         std::cout << "eblock id defined in loop 2 for start time " << std::setprecision(13) << execBlockStartTime[sBSummaryTag] << endl;
    3657           0 :         std::cout << "                                  end time " << std::setprecision(13) << execBlockEndTime[sBSummaryTag] << endl;
    3658             :       }
    3659             : 
    3660             :       // undefine the mapping for this Tag since the ExecBlock was completed
    3661           0 :       auto startptr = execBlockStartTime.find(sBSummaryTag); // need only remove from the map what is tested
    3662           0 :       if ( startptr != execBlockStartTime.end( ) ) execBlockStartTime.erase(startptr);
    3663           0 :       auto endptr = execBlockEndTime.find(sBSummaryTag);
    3664           0 :       if ( endptr != execBlockEndTime.end( ) ) execBlockEndTime.erase(endptr);
    3665             : 
    3666           0 :     }
    3667             : 
    3668             :     // finish the SBSummary table
    3669           0 :     EntityId theUid(getCurrentUid());
    3670           0 :     Entity ent = tT.getEntity();
    3671           0 :     ent.setEntityId(theUid);
    3672           0 :     tT.setEntity(ent);
    3673           0 :     if(verbosity_p>0){
    3674           0 :       os << LogIO::NORMAL << "Filled SBSummary table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    3675             :     }
    3676           0 :     incrementUid();
    3677             : 
    3678             :     // finish the ExecBlock table
    3679           0 :     theUid = getCurrentUid();
    3680           0 :     ent = tET.getEntity();
    3681           0 :     ent.setEntityId(theUid);
    3682           0 :     tET.setEntity(ent);
    3683           0 :     if(verbosity_p>0){
    3684           0 :       os << LogIO::NORMAL << "Filled ExecBlock table " << getCurrentUid() << " with " << tET.size() << " rows ..." << LogIO::POST;
    3685             :     }
    3686           0 :     incrementUid();
    3687             :     
    3688           0 :     return rstat;
    3689             :     
    3690           0 :   }
    3691             : 
    3692           0 :   Bool MS2ASDM::writeMainAndScanAndSubScan(const String& datacolumn){
    3693           0 :     LogIO os(LogOrigin("MS2ASDM", "writeMainAndScanAndSubScan()"));
    3694             :     
    3695           0 :     Bool rstat = true;
    3696             :     
    3697             :     // check if datacolumn exists
    3698             :     
    3699           0 :     String dataColumn(datacolumn);
    3700           0 :     dataColumn.upcase();
    3701             : 
    3702           0 :     if( (dataColumn == "CORRECTED" && !ms_p.tableDesc().isColumn("CORRECTED_DATA"))
    3703           0 :         || (dataColumn == "MODEL" && !ms_p.tableDesc().isColumn("MODEL_DATA"))
    3704           0 :         || (dataColumn == "DATA" && !ms_p.tableDesc().isColumn("DATA"))
    3705             :         ){
    3706             :       os << LogIO::SEVERE << "Error: column " << dataColumn << " does not exist in "
    3707           0 :          << ms_p.tableName() << LogIO::POST;      
    3708           0 :       return false;
    3709             :     }
    3710             :     else{
    3711           0 :       if(verbosity_p>0){
    3712           0 :         os << LogIO::NORMAL << "Using column " << dataColumn << "." << LogIO::POST;      
    3713             :       }
    3714             :     }      
    3715             :     
    3716           0 :     asdm::MainTable& tT = ASDM_p->getMain();
    3717           0 :     asdm::MainRow* tR = 0;
    3718             :     
    3719           0 :     asdm::ScanTable& tST = ASDM_p->getScan();
    3720           0 :     asdm::ScanRow* tSR = 0;
    3721             :     
    3722           0 :     asdm::SubscanTable& tSST = ASDM_p->getSubscan();
    3723           0 :     asdm::SubscanRow* tSSR = 0;
    3724             :     
    3725             :     
    3726             :     // Scheme
    3727             :     // loop over main table
    3728             :     //   asdmExecBlockId_p(time()(mainTabRow) defined?
    3729             :     //   if so, a new exec block has started
    3730             :     //      is there a previous exec block?
    3731             :     //        if so, finish it
    3732             :     //      set up new exec block
    3733             :     //      set scanNumber to 1
    3734             :     //      set subscanNumber to 1
    3735             :     //   end if
    3736             :     //   while(scan not finished)
    3737             :     //      find all DDIds in the time between now and now+subscanduration or until Scan ends
    3738             :     //        and memorize their start rows
    3739             :     //      for each DDId found
    3740             :     //        find all FieldIds in the time between now and now+subscanduration or until Scan ends
    3741             :     //        for each FieldId
    3742             :     //           Construct subscan == SDMDataObject
    3743             :     //              using the ConfigDescription table row asdmConfigDescriptionId_p(startRow)
    3744             :     //           and write it
    3745             :     //           write corresponding Main table row and subscan table row
    3746             :     //           subscanNumber++
    3747             :     //        end for
    3748             :     //      end for
    3749             :     //      next mainTabRow
    3750             :     //      error if asdmExecBlockId_p(time()(mainTabRow) defined: 
    3751             :     //   end while
    3752             :     //   write scan table row
    3753             :     //   scanNumber++
    3754             :     // end loop (i.e. next main table row)  
    3755             :     
    3756             :     
    3757             :     ////////////////////////////////////////////////
    3758             :     // Prepare loop over main table
    3759             :     Double scanStart;
    3760             :     
    3761           0 :     Tag execBlockId = Tag();
    3762           0 :     int subscanNumber = 0;
    3763             :     // parameters for the new Scan table row
    3764           0 :     int scanNumber = 0;
    3765           0 :     ArrayTime scanStartTime;
    3766           0 :     ArrayTime scanEndTime;
    3767           0 :     int scanNumIntent = 0;
    3768           0 :     int numSubScan = 0;
    3769           0 :     vector< ScanIntentMod::ScanIntent > scanIntent;
    3770           0 :     vector< CalDataOriginMod::CalDataOrigin > scanCalDataType;
    3771           0 :     vector< bool > scanCalibrationOnLine;
    3772             :     ////bool scanFlagRow = false; // always false ???
    3773             :     
    3774           0 :     uInt nMainTabRows = ms_p.nrow();
    3775           0 :     for(uInt mainTabRow=0; mainTabRow<nMainTabRows; mainTabRow++){
    3776             :       
    3777           0 :       Double rowTime = timestampStartSecs(mainTabRow);
    3778             :       
    3779             :       //   asdmExecBlockId_p defined for this timestamp?
    3780           0 :       if(asdmExecBlockId_p.find(rowTime) != asdmExecBlockId_p.end( )){ // a new exec block has started
    3781             :         // is there a previous exec block?
    3782           0 :         if(execBlockId != Tag()){
    3783             :           //  finish the old exec block
    3784             :         }
    3785             :         // set up new exec block
    3786             :         // parameters for the first scan
    3787           0 :         execBlockId = asdmExecBlockId_p[rowTime];
    3788           0 :         asdm::ExecBlockRow* EBR = (ASDM_p->getExecBlock()).getRowByKey(execBlockId);
    3789           0 :         scanNumber = 1; // ASDM scan numbering starts at 1
    3790           0 :         subscanNumber = 1; // dito for subscans
    3791           0 :         scanStart = rowTime;
    3792           0 :         scanStartTime = ASDMArrayTime( scanStart );
    3793           0 :         scanEndTime = EBR->getEndTime(); // preset to the end of the execblock
    3794           0 :         scanNumIntent = 0;
    3795           0 :         numSubScan = 0;
    3796           0 :         scanIntent.resize(0);
    3797           0 :         scanCalDataType.resize(0);
    3798           0 :         scanCalibrationOnLine.resize(0);
    3799             :         ////scanFlagRow = false;
    3800             :       } // end if a new exec block has started
    3801           0 :       else if(execBlockId == Tag()){
    3802           0 :         os << LogIO::WARN << "Encountered main tab row " << mainTabRow << " which is not part of an execblock." << LogIO::POST;
    3803           0 :         continue;
    3804             :       }
    3805           0 :       else if(MSTimeSecs(scanEndTime) - timestampEndSecs(mainTabRow) <= 0.9){
    3806             :         os << LogIO::NORMAL << "Potential problem at main tab row " << mainTabRow << ": misaligned scan and execblock end." 
    3807           0 :            << endl << "Will try to continue ..." << LogIO::POST;
    3808             :         // search back to see if the execblock start can be found
    3809             : 
    3810           0 :         Double searchIntervalSecs = 60.;
    3811             : 
    3812           0 :         uInt mainTabRowB = mainTabRow;
    3813           0 :         Bool foundEBStart = false;
    3814           0 :         Double rowTimeB = rowTime;
    3815           0 :         while(rowTime - rowTimeB < searchIntervalSecs && mainTabRowB>0){
    3816           0 :           rowTimeB = timestampStartSecs(--mainTabRowB);
    3817           0 :           if(asdmExecBlockId_p.find(rowTimeB) != asdmExecBlockId_p.end( )){
    3818           0 :             foundEBStart = true;
    3819           0 :             execBlockId = asdmExecBlockId_p[rowTimeB];
    3820           0 :             asdm::ExecBlockRow* EBR = (ASDM_p->getExecBlock()).getRowByKey(execBlockId);
    3821           0 :             scanNumber = 1; // ASDM scan numbering starts at 1
    3822           0 :             subscanNumber = 1; // dito for subscans
    3823           0 :             scanStart = rowTimeB;
    3824           0 :             scanStartTime = ASDMArrayTime( scanStart );
    3825           0 :             scanEndTime = EBR->getEndTime(); // preset to the end of the execblock
    3826           0 :             scanNumIntent = 0;
    3827           0 :             numSubScan = 0;
    3828           0 :             scanIntent.resize(0);
    3829           0 :             scanCalDataType.resize(0);
    3830           0 :             scanCalibrationOnLine.resize(0);
    3831             :             ////scanFlagRow = false;
    3832           0 :             break;
    3833             :           }
    3834             :         }
    3835           0 :         if(foundEBStart){
    3836           0 :           os << LogIO::NORMAL << "Problem resolved. Found execblock start " << rowTime - rowTimeB << " s earlier." << LogIO::POST;
    3837             :         }
    3838             :         else{
    3839             :           os << LogIO::SEVERE << "Searched back for " << searchIntervalSecs 
    3840           0 :              << " s. Could not resolve misalignment." << LogIO::POST;
    3841           0 :           return false;
    3842             :         }
    3843             :       }
    3844             :       
    3845             :       // while(scan not finished)
    3846           0 :       while( mainTabRow<nMainTabRows && 
    3847           0 :              MSTimeSecs(scanEndTime) - (rowTime = timestampStartSecs(mainTabRow)) > 1E-3 ){ // presently one scan per exec block ???
    3848             : 
    3849             :         // parameters for the new SubScan table row
    3850           0 :         Double subScanEnd = rowTime + subscanDuration_p; 
    3851           0 :         if(subScanEnd > MSTimeSecs(scanEndTime)){
    3852           0 :           subScanEnd = MSTimeSecs(scanEndTime);
    3853             :         }
    3854             :         
    3855             :         // find all DDIds in the time between now and end of subscan
    3856           0 :         uInt irow = mainTabRow;
    3857           0 :         std::map< Int, uInt > subScanDDIdStartRows;
    3858           0 :         while(irow<nMainTabRows &&
    3859           0 :               timestampStartSecs(irow) < subScanEnd){
    3860           0 :           Int ddId = dataDescId()(irow);
    3861           0 :           if(subScanDDIdStartRows.find(ddId) == subScanDDIdStartRows.end( )){
    3862           0 :           subScanDDIdStartRows[ddId] = irow;    // memorize their start rows
    3863             :           }
    3864           0 :           irow++;
    3865             :         }
    3866             :         
    3867             :         // for each DDId found
    3868           0 :         for( auto iter = subScanDDIdStartRows.begin( ); iter != subScanDDIdStartRows.end( ); ++iter ){
    3869           0 :           Int theDDId = iter->first;
    3870             : 
    3871             :           // find all FieldIds in the time between now and now+subscanduration or until Scan ends         
    3872           0 :           uInt irow2 = mainTabRow;
    3873           0 :           std::map< Int, uInt > subScanStartRows;
    3874           0 :           std::map< Int, uInt > subScanEndRows;
    3875           0 :           while(irow2<nMainTabRows &&
    3876           0 :                 timestampStartSecs(irow2) < subScanEnd){
    3877           0 :             Int ddId = dataDescId()(irow2);
    3878           0 :             Int fId = fieldId()(irow2);
    3879           0 :             if(ddId == theDDId){
    3880           0 :             if( subScanEndRows.find(fId) != subScanEndRows.end( ) ){
    3881           0 :                 subScanEndRows[fId] = irow2;    // update end row
    3882             :             }
    3883           0 :             if( subScanStartRows.find(fId) == subScanStartRows.end( ) ){
    3884           0 :                 subScanStartRows[fId] = irow2;    // memorize their start rows
    3885           0 :                 subScanEndRows[fId] = irow2;    // and end rows
    3886             :             }
    3887             :             }
    3888           0 :             irow2++;
    3889             :           }
    3890             :           // for each FieldId
    3891           0 :           for( auto iter = subScanStartRows.begin( ); iter != subScanStartRows.end( ); ++iter ) {
    3892           0 :             Int theFId = iter->first;
    3893           0 :             uInt startRow = subScanStartRows[theFId];
    3894           0 :             uInt endRow = subScanEndRows[theFId];
    3895             :             // write subscan
    3896             :             // parameters for the new SubScan table row
    3897           0 :             ArrayTime subScanStartArrayTime = ASDMArrayTime(timestampStartSecs(startRow)); 
    3898           0 :             ArrayTime subScanEndArrayTime = ASDMArrayTime(timestampEndSecs(endRow)); 
    3899           0 :             string fieldName = field().name()(fieldId()(startRow)).c_str(); 
    3900           0 :             SubscanIntentMod::SubscanIntent subscanIntent = SubscanIntentMod::ON_SOURCE;
    3901           0 :             vector< int > numberSubintegration;
    3902             :             ////bool flagRow = false;
    3903             : 
    3904             :             // parameters for the corresponding new Main table row
    3905           0 :             ArrayTime mainTime = ASDMArrayTime((timestampStartSecs(startRow) + timestampEndSecs(endRow))/2.); // midpoint!
    3906             : 
    3907           0 :             if(asdmConfigDescriptionId_p.find(startRow) == asdmConfigDescriptionId_p.end( )){
    3908             :               os << LogIO::SEVERE << "Internal error: undefined config description id for MS main table row "
    3909           0 :                  << startRow << LogIO::POST;
    3910           0 :               return false;
    3911             :             }  
    3912           0 :             Tag configDescriptionId = asdmConfigDescriptionId_p[startRow];
    3913           0 :             asdm::ConfigDescriptionRow* CDR = (ASDM_p->getConfigDescription()).getRowByKey(configDescriptionId);
    3914           0 :             if(CDR ==0){
    3915             :               os << LogIO::SEVERE << "Internal error: no row in ASDM ConfigDesc Table for ConfigDescriptionId stored for main table row "
    3916           0 :                  << startRow << LogIO::POST;
    3917           0 :               return false;
    3918             :             }
    3919             : 
    3920           0 :             Tag fieldIdTag = asdmFieldId_p[theFId];
    3921           0 :             int numAntenna = CDR->getNumAntenna();
    3922           0 :             TimeSamplingMod::TimeSampling timeSampling = TimeSamplingMod::INTEGRATION;
    3923           0 :             Interval interval = ASDMInterval(intervalQuant()(startRow).getValue("s")); // data sampling interval
    3924             :             int numIntegration; // to be set by the following method call
    3925             :             int dataSize; // to be set by the following method call
    3926           0 :             EntityRef dataOid; // to be set by the following method call
    3927           0 :             vector< Tag > stateIdV; // "
    3928             :           
    3929             :             // Note: for WVR data, a special case would have to be made here or inside
    3930             :             //       writeMainBinSubScanForOneDDIdFIdPair() which does not call corrDataHeader
    3931             :             //       and addIntegration but instead only SDMDataObjectWriter::wvrData()
    3932             : 
    3933           0 :             numIntegration = writeMainBinSubScanForOneDDIdFIdPair(theDDId, theFId, 
    3934             :                                                                   datacolumn, 
    3935             :                                                                   scanNumber, subscanNumber,
    3936             :                                                                   startRow, endRow,
    3937             :                                                                   execBlockId,
    3938             :                                                                   dataSize, dataOid, stateIdV);
    3939           0 :             if(numIntegration<0){ // error!
    3940             :               os << LogIO::SEVERE << "Error writing Subscan starting at main table row " 
    3941           0 :                  << startRow << LogIO::POST;
    3942           0 :               return false;
    3943             :             }
    3944             : 
    3945           0 :             for(uInt i=0; i<(uInt)numIntegration; i++){
    3946           0 :               numberSubintegration.push_back(0); // no subintegrations for the moment, no channel averaging (???)
    3947             :             }
    3948             :           
    3949             :             // end write subscan
    3950             :           
    3951             :             // write corresponding Main table row
    3952           0 :             tR = tT.newRow(mainTime, configDescriptionId, fieldIdTag, numAntenna, timeSampling, interval, numIntegration, 
    3953             :                            scanNumber, subscanNumber, dataSize, dataOid, stateIdV, execBlockId);
    3954           0 :             tT.add(tR);
    3955             :           
    3956             :             // write corresponding Subscan table row
    3957             :             
    3958           0 :             tSSR = tSST.newRow(execBlockId, scanNumber, subscanNumber, subScanStartArrayTime, subScanEndArrayTime, 
    3959             :                                fieldName, subscanIntent, numIntegration, numberSubintegration //// , flagRow
    3960             :                                );
    3961             :             
    3962           0 :             tSST.add(tSSR);
    3963             :             
    3964           0 :             subscanNumber++;
    3965           0 :             numSubScan++;
    3966             : 
    3967           0 :           } // end loop over Field indices         
    3968             : 
    3969           0 :         } // end loop over DD indices
    3970             :         // update mainTabRow
    3971           0 :         mainTabRow = irow;
    3972           0 :       } // end while scan continues
    3973             :       // scan finished
    3974             :       // complete and write scan table row
    3975           0 :       mainTabRow--; // return to the last row of the scan
    3976           0 :       scanEndTime = ASDMArrayTime( timestampEndSecs(mainTabRow) );        
    3977           0 :       scanNumIntent = 1; // hardwired (???)
    3978           0 :       for(uInt i=0; i<(uInt)scanNumIntent; i++){
    3979           0 :         scanIntent.push_back(ScanIntentMod::OBSERVE_TARGET); // hardwired for the moment (???)
    3980           0 :         scanCalDataType.push_back(CalDataOriginMod::FULL_RESOLUTION_CROSS); // hardwired for the moment (???)
    3981           0 :         scanCalibrationOnLine.push_back(false); // hardwired for the moment (???)
    3982             :       }
    3983             : 
    3984           0 :       tSR = tST.newRow(execBlockId, scanNumber, scanStartTime, scanEndTime, scanNumIntent, numSubScan, scanIntent, 
    3985             :                        scanCalDataType, scanCalibrationOnLine ////, scanFlagRow
    3986             :                        );
    3987             :       
    3988           0 :       tST.add(tSR);
    3989             :       
    3990           0 :       scanNumber++;
    3991             :       
    3992             :     }//  end for
    3993             : 
    3994           0 :     EntityId theUid(getCurrentUid());
    3995           0 :     Entity ent = tT.getEntity();
    3996           0 :     ent.setEntityId(theUid);
    3997           0 :     tT.setEntity(ent);
    3998           0 :     if(verbosity_p>0){
    3999           0 :       os << LogIO::NORMAL << "Filled Main table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    4000             :     }
    4001           0 :     incrementUid();
    4002             :     
    4003           0 :     theUid = getCurrentUid();
    4004           0 :     ent = tST.getEntity();
    4005           0 :     ent.setEntityId(theUid);
    4006           0 :     tST.setEntity(ent);
    4007           0 :     if(verbosity_p>0){
    4008           0 :       os << LogIO::NORMAL << "Filled Scan table " << getCurrentUid() << " with " << tST.size() << " rows ..." << LogIO::POST;
    4009             :     }
    4010           0 :     incrementUid();
    4011             :     
    4012           0 :     theUid = getCurrentUid();
    4013           0 :     ent = tSST.getEntity();
    4014           0 :     ent.setEntityId(theUid);
    4015           0 :     tSST.setEntity(ent);
    4016           0 :     if(verbosity_p>0){
    4017           0 :       os << LogIO::NORMAL << "Filled SubScan table " << getCurrentUid() << " with " << tSST.size() << " rows ..." << LogIO::POST;
    4018             :     }
    4019           0 :     incrementUid();
    4020             :     
    4021           0 :     return rstat;
    4022           0 :   }
    4023             : 
    4024           0 :   Bool MS2ASDM::writePointingModel(){ // create asdm PointingModel table 
    4025           0 :     LogIO os(LogOrigin("MS2ASDM", "writePointingModel()"));
    4026             :     
    4027           0 :     Bool rstat = true;
    4028             :     
    4029           0 :     asdm::PointingModelTable& tT = ASDM_p->getPointingModel();
    4030             :     
    4031           0 :     asdm::PointingModelRow* tR = 0;
    4032             :     
    4033           0 :     asdm::FeedTable& tFT = ASDM_p->getFeed();
    4034             :     
    4035           0 :     vector< asdm::FeedRow * > feedRowV = tFT.get();
    4036             : 
    4037             :     // loop over ASDM Feed table and create Pointing model rows for each
    4038             :     // receptor of each Feed table row 
    4039             : 
    4040           0 :     for(uInt feedRow=0; feedRow<feedRowV.size(); feedRow++){
    4041             :       
    4042             : 
    4043           0 :       uInt numRec = feedRowV[feedRow]->getNumReceptor();
    4044           0 :       vector< PolarizationTypeMod::PolarizationType > polTypeV = feedRowV[feedRow]->getPolarizationTypes();
    4045           0 :       vector< int > receivIdV = feedRowV[feedRow]->getReceiverId(); 
    4046             : 
    4047           0 :       for(uInt iRec=0; iRec<numRec; iRec++){ // loop over all receptors
    4048             : 
    4049           0 :         const vector< asdm::ReceiverRow * > recRowV = feedRowV[feedRow]->getReceivers(receivIdV[iRec]);
    4050             :         
    4051             :         // parameters for new PointingModel row
    4052             : 
    4053           0 :         Tag antennaId = feedRowV[feedRow]->getAntennaId();
    4054           0 :         int numCoeff = 2; // seems to be the dummy value ???, to be confirmed
    4055           0 :         vector< string > coeffName;
    4056           0 :         coeffName.push_back("IA");
    4057           0 :         coeffName.push_back("IE");
    4058           0 :         vector< float > coeffVal;
    4059           0 :         coeffVal.push_back(0.);
    4060           0 :         coeffVal.push_back(0.);
    4061             :         PolarizationTypeMod::PolarizationType polarizationType;
    4062             :         try{
    4063           0 :           polarizationType = polTypeV[iRec];
    4064             :         }
    4065             :         catch(std::string z){
    4066             :           os << LogIO::SEVERE << "Internal error: invalid polarization type in Feed table row  " << z
    4067             :              << LogIO::POST;      
    4068             :           return false;
    4069             :         }      
    4070             :           
    4071           0 :         ReceiverBandMod::ReceiverBand receiverBand = recRowV[0]->getFrequencyBand(); // take from the first receiver 
    4072           0 :         string assocNature = "NOT_SET";
    4073           0 :         int assocPointingModelId = -1;
    4074             : 
    4075           0 :         tR = tT.newRow(antennaId, numCoeff, coeffName, coeffVal, polarizationType, 
    4076             :                        receiverBand, assocNature, assocPointingModelId);
    4077             :     
    4078           0 :         asdm::PointingModelRow* tR2 = 0;
    4079             : 
    4080           0 :         tR2 = tT.add(tR);
    4081           0 :         if(asdmPointingModelId_p.find(antennaId) == asdmPointingModelId_p.end( )){
    4082           0 :         asdmPointingModelId_p[antennaId] = tR2->getPointingModelId();
    4083             :         }
    4084             : 
    4085           0 :       } // end loop over receptors
    4086             : 
    4087           0 :     } // end loop over ASDM Feed table
    4088             :     
    4089           0 :     EntityId theUid(getCurrentUid());
    4090           0 :     Entity ent = tT.getEntity();
    4091           0 :     ent.setEntityId(theUid);
    4092           0 :     tT.setEntity(ent);
    4093           0 :     if(verbosity_p>0){
    4094           0 :       os << LogIO::NORMAL << "Filled PointingModel table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    4095             :     }
    4096           0 :     incrementUid();
    4097             : 
    4098           0 :     return rstat;
    4099           0 :   }
    4100             : 
    4101           0 :   Bool MS2ASDM::writePointing(){ // create asdm pointing table
    4102           0 :     LogIO os(LogOrigin("MS2ASDM", "writePointing()"));
    4103             : 
    4104           0 :     Bool rstat = true;
    4105             :     
    4106           0 :     asdm::PointingTable& tT = ASDM_p->getPointing();
    4107             :     
    4108           0 :     asdm::PointingRow* tR = 0;
    4109             : 
    4110           0 :     uInt nPointingRows = pointing().nrow();
    4111             : 
    4112           0 :     if(nPointingRows==0){
    4113           0 :       os << LogIO::WARN << "MS Pointing table doesn't exist or is empty." << LogIO::POST;   
    4114           0 :       return true; // not an error
    4115             :     }
    4116             : 
    4117           0 :     Bool warned = false; // aux. var. to avoid repetition of warnings
    4118             : 
    4119             :     // loop over MS antenna table
    4120           0 :     for(Int aId=0; aId<(Int)antenna().nrow(); aId++){
    4121             : 
    4122           0 :       if(asdmAntennaId_p.find(aId) == asdmAntennaId_p.end( )){
    4123             :         os << LogIO::SEVERE << "Internal error: no tag defined for antenna id " 
    4124           0 :            << aId << LogIO::POST;
    4125           0 :         return false;
    4126             :       }
    4127             : 
    4128           0 :       uInt irow=0;
    4129           0 :       uInt totNumRows=0; // total of MS Pointing table rows for this antenna
    4130             : 
    4131           0 :       while(irow<nPointingRows){
    4132             : 
    4133             :         // find next pointing entry for this antenna in MS pointing table (== beginning of a new ASDM pointing table entry)
    4134           0 :         Int firstRow=-1;
    4135           0 :         while(irow<nPointingRows){
    4136           0 :           if(pointing().antennaId()(irow) == aId){
    4137           0 :             firstRow = irow;
    4138           0 :             break;
    4139             :           }
    4140           0 :           irow++;
    4141             :         }
    4142             : 
    4143           0 :         if(firstRow==-1){ // no further data for this antenna
    4144           0 :           break;
    4145             :         }
    4146             : 
    4147           0 :         uInt numRows=1; // number of rows with contiguous timestamps for this antenna 
    4148             :         
    4149             :         // parameters for the next pointing table row
    4150           0 :         Tag antennaId = asdmAntennaId_p[aId];
    4151           0 :         ArrayTimeInterval timeInterval( ASDMTimeInterval( pointing().timeQuant()(firstRow), pointing().intervalQuant()(firstRow)) );
    4152             : 
    4153           0 :         bool pointingTracking = pointing().tracking()(firstRow);
    4154             : 
    4155           0 :         bool usePolynomials = false;
    4156           0 :         int numTerm = 0; // to be updated later
    4157             : 
    4158           0 :         if(pointing().numPoly()(firstRow)>0){
    4159           0 :           usePolynomials = true;
    4160           0 :           numTerm = pointing().numPoly()(irow)+1;
    4161             :         }
    4162             : 
    4163           0 :         ArrayTime timeOrigin = ASDMArrayTime( pointing().timeOriginQuant()(firstRow).getValue("s") );
    4164             :         
    4165           0 :         vector< vector< Angle > > pointingDirection;
    4166           0 :         Vector< MDirection > dirV; // aux. vector to access array column
    4167           0 :         dirV.reference(pointing().directionMeasCol()(firstRow));
    4168           0 :         if(numTerm == 0){
    4169           0 :           pointingDirection.push_back(ASDMAngleV(dirV[0]));
    4170             :         }
    4171             :         else{
    4172           0 :           if(numTerm != (Int)dirV.size()){
    4173             :             os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
    4174           0 :                << ": numpoly + 1 should be == dimension of array DIRECTION." << LogIO::POST;      
    4175           0 :             return false;
    4176             :           }         
    4177           0 :           for(uInt i=0; i<(uInt)numTerm; i++){
    4178           0 :             pointingDirection.push_back(ASDMAngleV(dirV[i]));
    4179             :           }
    4180             :         }            
    4181             :         
    4182           0 :         vector< vector< Angle > > encoder;
    4183           0 :         if(pointing().encoderMeas().isNull()){ // encoder column is optional in MS but not in ASDM
    4184           0 :           if(numTerm == 0){
    4185             :             // use pointing Direction instead
    4186           0 :             if(!warned){
    4187             :               os << LogIO::WARN << "No ENCODER column in MS Pointing table. Will use DIRECTION instead." 
    4188           0 :                  << LogIO::POST;  
    4189           0 :               warned = true;
    4190             :             }
    4191           0 :             dirV.reference(pointing().directionMeasCol()(firstRow));
    4192           0 :             encoder.push_back(ASDMAngleV(dirV[0]));
    4193             :           }
    4194             :           else{ // cannot use pointing direction because it contains only polynomial terms
    4195           0 :             vector< Angle > angV;
    4196           0 :             angV.push_back(Angle(0.));
    4197           0 :             angV.push_back(Angle(0.));
    4198           0 :             if(!warned){
    4199             :               os << LogIO::WARN << "No ENCODER column in MS Pointing table. Will fill with zeros." 
    4200           0 :                  << LogIO::POST;  
    4201           0 :               warned = true;
    4202             :             }
    4203           0 :             encoder.push_back(angV);
    4204           0 :           }
    4205             :         }
    4206             :         else{
    4207           0 :           encoder.push_back(ASDMAngleV(pointing().encoderMeas()(firstRow)));
    4208             :         }
    4209             :         
    4210           0 :         vector< vector< Angle > > target;
    4211           0 :         dirV.reference(pointing().targetMeasCol()(firstRow));
    4212           0 :         if(numTerm == 0){
    4213           0 :           target.push_back(ASDMAngleV(dirV[0]));
    4214             :         }
    4215             :         else{
    4216           0 :           if(numTerm != (Int)dirV.size()){
    4217             :             os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
    4218           0 :                << ": numpoly + 1 should be == dimension of array TARGET." << LogIO::POST; 
    4219           0 :             return false;
    4220             :           }         
    4221           0 :           for(uInt i=0; i<(uInt)numTerm; i++){
    4222           0 :             target.push_back(ASDMAngleV(dirV[i]));
    4223             :           }
    4224             :         }            
    4225             :         
    4226           0 :         vector< vector< asdm::Angle > > offset;
    4227             :         // source offset column is optional in the MS but not in the ASDM
    4228           0 :         if(pointing().pointingOffsetMeasCol().isNull()){ // no MS source offset column 
    4229           0 :           vector< Angle > angV;
    4230           0 :           angV.push_back(Angle(0.));
    4231           0 :           angV.push_back(Angle(0.));
    4232           0 :           offset.push_back(angV);
    4233           0 :           if(numTerm>0){
    4234           0 :             for(uInt i=1; i<(uInt)numTerm; i++){
    4235           0 :               offset.push_back(angV);
    4236             :             }
    4237             :           }
    4238           0 :         }
    4239             :         else{
    4240           0 :           dirV.reference(pointing().pointingOffsetMeasCol()(firstRow));
    4241           0 :           if(numTerm==0){
    4242           0 :             offset.push_back(ASDMAngleV(dirV[0]));
    4243             :           }
    4244             :           else{
    4245           0 :             if(numTerm != (Int)dirV.size()){
    4246             :               os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
    4247           0 :                  << ": numpoly + 1 should be == dimension of array POINTING_OFFSET." << LogIO::POST;      
    4248           0 :               return false;
    4249             :             }       
    4250           0 :             for(uInt i=0; i<(uInt)numTerm; i++){
    4251           0 :               offset.push_back(ASDMAngleV(dirV[i]));
    4252             :             }
    4253             :           }
    4254             :         }       
    4255             :         
    4256           0 :         vector< vector< Angle > > sourceOffset; // optional in the ASDM and in the MS
    4257           0 :         if(!pointing().sourceOffsetMeasCol().isNull()){ // sourceOffset column is present
    4258           0 :           dirV.reference(pointing().sourceOffsetMeasCol()(firstRow));
    4259           0 :           if(numTerm==0){
    4260           0 :             sourceOffset.push_back(ASDMAngleV(dirV[0]));
    4261             :           }
    4262             :           else{
    4263           0 :             if(numTerm != (Int)dirV.size()){
    4264             :               os << LogIO::SEVERE << "Inconsistent MS: in pointing table row " << firstRow
    4265           0 :                  << ": numpoly + 1 should be == dimension of array SOURCE_OFFSET." << LogIO::POST;        
    4266           0 :               return false;
    4267             :             }       
    4268           0 :             for(uInt i=0; i<(uInt)numTerm; i++){
    4269           0 :               sourceOffset.push_back(ASDMAngleV(dirV[i]));
    4270             :             }
    4271             :           }
    4272             :         } 
    4273             : 
    4274           0 :         int pointingModelId = asdmPointingModelId_p[antennaId];
    4275           0 :         double endTimeMJD = timeInterval.getStartInMJD() + timeInterval.getDurationInDays();
    4276             : 
    4277             :         // check if there are more rows for this antenna with adjacent time intervals
    4278           0 :         irow++;
    4279             :         
    4280           0 :         while(irow<nPointingRows && numTerm==0){ // while we find more adjacent rows and don't use polynomials
    4281             : 
    4282           0 :           if(pointing().antennaId()(irow) != aId){
    4283           0 :             irow++;
    4284           0 :             continue;
    4285             :           }
    4286             : 
    4287             :           // need to do the comparison this way because this is close to how the PointingTable class
    4288             :           // decides how to add a new row
    4289             : 
    4290           0 :           ArrayTimeInterval thisTimeInterval = ASDMTimeInterval(pointing().timeQuant()(irow), pointing().intervalQuant()(irow));
    4291           0 :           if( !casacore::near(endTimeMJD,thisTimeInterval.getStartInMJD()) // row irow is adjacent in time to previous row
    4292           0 :               || pointingTracking != pointing().tracking()(irow) 
    4293           0 :               || (usePolynomials == false && pointing().numPoly()(irow)>0)
    4294             :               ){
    4295           0 :             break; // there will be no further samples for this ASDM pointing table row
    4296             :           }
    4297             : 
    4298             :           // found a second pointing row for the antenna ID, now accumulate directions
    4299             :           // until time ranges not contiguous or end of table
    4300             : 
    4301           0 :           numRows++;
    4302           0 :           endTimeMJD = thisTimeInterval.getStartInMJD() + thisTimeInterval.getDurationInDays();
    4303             : 
    4304             :           // update timeInterval - this may not be exactly the same as adding the durations
    4305           0 :           timeInterval.setDuration(endTimeMJD - timeInterval.getStartInMJD());
    4306             : 
    4307           0 :           dirV.reference(pointing().directionMeasCol()(irow));
    4308           0 :           pointingDirection.push_back(ASDMAngleV(dirV[0]));
    4309             :         
    4310           0 :           if(pointing().encoderMeas().isNull()){ // encoder column is optional
    4311             :             // use pointing Direction instead
    4312           0 :             encoder.push_back(ASDMAngleV(dirV[0]));
    4313             :           }
    4314             :           else{
    4315           0 :             encoder.push_back(ASDMAngleV(pointing().encoderMeas()(irow)));
    4316             :           }
    4317             :         
    4318           0 :           dirV.reference(pointing().targetMeasCol()(irow));
    4319           0 :           target.push_back(ASDMAngleV(dirV[0]));
    4320             :         
    4321           0 :           if(pointing().pointingOffsetMeasCol().isNull()){ // source offset column is optional
    4322           0 :             vector< Angle > angV;
    4323           0 :             angV.push_back(Angle(0.));
    4324           0 :             angV.push_back(Angle(0.));
    4325           0 :             offset.push_back(angV);
    4326           0 :           }
    4327             :           else{
    4328           0 :             dirV.reference(pointing().pointingOffsetMeasCol()(irow));
    4329           0 :             offset.push_back(ASDMAngleV(dirV[0]));
    4330             :           }     
    4331             :         
    4332           0 :           if(!pointing().sourceOffsetMeasCol().isNull()){ // source offset column is optional
    4333           0 :             dirV.reference(pointing().sourceOffsetMeasCol()(irow));
    4334           0 :             sourceOffset.push_back(ASDMAngleV(dirV[0]));
    4335             :           }     
    4336           0 :           irow++;
    4337             :         
    4338           0 :         } // end while accumulating for started  entry
    4339             : 
    4340             :         // finish the ASDM table row and add it to the table
    4341           0 :         int numSample = encoder.size(); 
    4342           0 :         if(!usePolynomials){
    4343           0 :           numTerm = numSample;
    4344             :         }
    4345             : 
    4346           0 :         tR = tT.newRow(antennaId, timeInterval, numSample, encoder, pointingTracking, usePolynomials, timeOrigin, 
    4347             :                        numTerm, pointingDirection, target, offset, pointingModelId);
    4348             :         
    4349           0 :         if(sourceOffset.size()>0){
    4350           0 :           tR->setSourceOffset(sourceOffset);
    4351             :         } 
    4352             : 
    4353           0 :         asdm::PointingRow* tR2 = 0;
    4354             :         
    4355             :         try{
    4356           0 :           tR2 = tT.add(tR);
    4357             :         }
    4358           0 :         catch(asdm::DuplicateKey){
    4359             :           os << LogIO::WARN << "Caught asdm::DuplicateKey error for antenna id " 
    4360           0 :              << aId << LogIO::POST;
    4361           0 :         }         
    4362           0 :         if(tR2 != tR){// no new row was inserted
    4363             :           os << LogIO::WARN << "Internal error: duplicate row in Pointing table for antenna id " 
    4364           0 :              << aId << LogIO::POST; 
    4365             :         }
    4366             :         else{
    4367           0 :           if(verbosity_p>1){
    4368             :             os << LogIO::NORMAL << "Combined " << numRows 
    4369             :                << " MS Pointing table rows into one ASDM Pointing table row for antenna id " 
    4370           0 :                << aId << LogIO::POST;       
    4371             :           }
    4372             :         }
    4373           0 :         totNumRows += numRows;
    4374             :         
    4375           0 :       } // end while rows left in pointing table
    4376             :       
    4377           0 :       if(totNumRows==0){
    4378             :         os << LogIO::WARN << "No MS Pointing table rows found for antenna id " 
    4379           0 :             << aId << LogIO::POST;  
    4380             :       } 
    4381             : 
    4382             :     } // end loop over antenna ids
    4383             :     
    4384           0 :     EntityId theUid(getCurrentUid());
    4385           0 :     Entity ent = tT.getEntity();
    4386           0 :     ent.setEntityId(theUid);
    4387           0 :     tT.setEntity(ent);
    4388           0 :     if(verbosity_p>0){
    4389           0 :       os << LogIO::NORMAL << "Filled Pointing table " << getCurrentUid() << " with " << tT.size() << " rows ..." << LogIO::POST;
    4390             :     }
    4391           0 :     incrementUid();
    4392             :     
    4393           0 :     return rstat;
    4394           0 :   }
    4395             : 
    4396           0 :   StokesParameterMod::StokesParameter MS2ASDM::ASDMStokesParameter( Stokes::StokesTypes s) {
    4397           0 :     switch (s) {
    4398           0 :     case Stokes::I:     return StokesParameterMod::I;         
    4399           0 :     case Stokes::Q:     return StokesParameterMod::Q;        
    4400           0 :     case Stokes::U:     return StokesParameterMod::U;        
    4401           0 :     case Stokes::V:     return StokesParameterMod::V;        
    4402           0 :     case Stokes::RR:    return StokesParameterMod::RR;       
    4403           0 :     case Stokes::RL:    return StokesParameterMod::RL;       
    4404           0 :     case Stokes::LR:    return StokesParameterMod::LR;       
    4405           0 :     case Stokes::LL:    return StokesParameterMod::LL;       
    4406           0 :     case Stokes::XX:    return StokesParameterMod::XX;       
    4407           0 :     case Stokes::XY:    return StokesParameterMod::XY;       
    4408           0 :     case Stokes::YX:    return StokesParameterMod::YX;       
    4409           0 :     case Stokes::YY:    return StokesParameterMod::YY;       
    4410           0 :     case Stokes::RX:    return StokesParameterMod::RX;       
    4411           0 :     case Stokes::RY:    return StokesParameterMod::RY;       
    4412           0 :     case Stokes::LX:    return StokesParameterMod::LX;       
    4413           0 :     case Stokes::LY:    return StokesParameterMod::LY;       
    4414           0 :     case Stokes::XR:    return StokesParameterMod::XR;       
    4415           0 :     case Stokes::XL:    return StokesParameterMod::XL;       
    4416           0 :     case Stokes::YR:    return StokesParameterMod::YR;       
    4417           0 :     case Stokes::YL:    return StokesParameterMod::YL;       
    4418           0 :     case Stokes::PP:    return StokesParameterMod::PP;       
    4419           0 :     case Stokes::PQ:    return StokesParameterMod::PQ;       
    4420           0 :     case Stokes::QP:    return StokesParameterMod::QP;       
    4421           0 :     case Stokes::QQ:    return StokesParameterMod::QQ;       
    4422           0 :     case Stokes::RCircular: return StokesParameterMod::RCIRCULAR;
    4423           0 :     case Stokes::LCircular: return StokesParameterMod::LCIRCULAR;
    4424           0 :     case Stokes::Linear:        return StokesParameterMod::LINEAR;   
    4425           0 :     case Stokes::Ptotal:        return StokesParameterMod::PTOTAL;   
    4426           0 :     case Stokes::Plinear:       return StokesParameterMod::PLINEAR;  
    4427           0 :     case Stokes::PFtotal:       return StokesParameterMod::PFTOTAL;  
    4428           0 :     case Stokes::PFlinear:      return StokesParameterMod::PFLINEAR; 
    4429           0 :     case Stokes::Pangle:        return StokesParameterMod::PANGLE; 
    4430           0 :     case Stokes::Undefined:
    4431             :     default:    
    4432           0 :       throw(AipsError("Undefined stokes parameter."+String((Int)s)) );
    4433             :     }
    4434             :   }
    4435             : 
    4436           0 :   AntennaTypeMod::AntennaType MS2ASDM::ASDMAntennaType( const String& type ){
    4437           0 :     LogIO os(LogOrigin("MS2ASDM", "(ASDMAntennaType)"));
    4438           0 :     if(type == "GROUND-BASED"){
    4439           0 :       return AntennaTypeMod::GROUND_BASED;
    4440             :     }
    4441           0 :     else if(type == "SPACE-BASED"){
    4442           0 :       return AntennaTypeMod::SPACE_BASED;
    4443             :     }      
    4444             :     else{
    4445           0 :       os << LogIO::WARN << "Unknown antenna type " << type << " assuming GROUND-BASED." << LogIO::POST;
    4446           0 :       return AntennaTypeMod::GROUND_BASED;
    4447             :     }      
    4448           0 :   } 
    4449             : 
    4450           0 :     ArrayTimeInterval MS2ASDM::ASDMTimeInterval( const Quantity midpoint, const Quantity interval){
    4451           0 :         Double sTime = midpoint.getValue("s");  
    4452           0 :         Double sInterval = interval.getValue("s");
    4453             : 
    4454             :         // watch for sInterval==0 which means these correspond to a constant value over the whole MS
    4455           0 :         if (sInterval == 0.) {
    4456           0 :             sTime = timestampStartSecs(0);
    4457           0 :             sInterval = timestampEndSecs(ms_p.nrow()-1) - sTime;
    4458             :         } else {
    4459             :             // very large values of sInterval also signify a constant value, probably in the original SDM
    4460             :             // this is somewhat arbitrary but is intended to be safe, there's probably no harm
    4461             :             // in writing out large values to the SDM as they will be recovered when read back in
    4462             :             // let "large" here be > about 1 year - could probably be smaller and still be safe
    4463             :             // 24*60*60*365
    4464           0 :             if (sInterval > 31536000.0) {
    4465           0 :                 sTime = timestampStartSecs(0);
    4466           0 :                 sInterval = timestampEndSecs(ms_p.nrow()-1) - sTime;
    4467             :             } else {
    4468             :                 // the usual case, turn sTime into the start time
    4469           0 :                 sTime -= sInterval/2.;
    4470             :             }
    4471             :         } 
    4472             :     
    4473           0 :     ArrayTimeInterval timeInterval( ASDMArrayTime(sTime),
    4474           0 :                                     ASDMInterval(sInterval) );
    4475           0 :     return timeInterval;
    4476             :   }
    4477             : 
    4478           0 :   vector< Angle > MS2ASDM::ASDMAngleV(const MDirection mDir){
    4479           0 :     vector< Angle > angV;
    4480           0 :     angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(0) ); 
    4481           0 :     angV.push_back( mDir.getAngle( unitASDMAngle() ).getValue()(1) ); 
    4482           0 :     return angV;
    4483           0 :   }
    4484             :     
    4485           0 :   DirectionReferenceCodeMod::DirectionReferenceCode MS2ASDM::ASDMDirRefCode(const MDirection::Types type){
    4486             : 
    4487           0 :     switch(type){
    4488           0 :     case MDirection::J2000:     return DirectionReferenceCodeMod::J2000;          
    4489           0 :     case MDirection::JMEAN:     return DirectionReferenceCodeMod::JMEAN;          
    4490           0 :     case MDirection::JTRUE:     return DirectionReferenceCodeMod::JTRUE;          
    4491           0 :     case MDirection::APP:       return DirectionReferenceCodeMod::APP;    
    4492           0 :     case MDirection::B1950:     return DirectionReferenceCodeMod::B1950;          
    4493           0 :     case MDirection::B1950_VLA: return DirectionReferenceCodeMod::B1950_VLA;    
    4494           0 :     case MDirection::BMEAN:     return DirectionReferenceCodeMod::BMEAN;          
    4495           0 :     case MDirection::BTRUE:     return DirectionReferenceCodeMod::BTRUE;          
    4496           0 :     case MDirection::GALACTIC:  return DirectionReferenceCodeMod::GALACTIC;     
    4497           0 :     case MDirection::HADEC:     return DirectionReferenceCodeMod::HADEC;          
    4498           0 :     case MDirection::AZELSW:    return DirectionReferenceCodeMod::AZELSW;         
    4499           0 :     case MDirection::AZELSWGEO: return DirectionReferenceCodeMod::AZELSWGEO; 
    4500             :       //case MDirection::AZELGEO:   return DirectionReferenceCodeMod::AZELNEGEO; //(same case as MDirection::AZELNEGEO!)        
    4501           0 :     case MDirection::AZELNEGEO: return DirectionReferenceCodeMod::AZELNEGEO;      
    4502           0 :     case MDirection::JNAT:      return DirectionReferenceCodeMod::JNAT;           
    4503           0 :     case MDirection::ECLIPTIC:  return DirectionReferenceCodeMod::ECLIPTIC;     
    4504           0 :     case MDirection::MECLIPTIC: return DirectionReferenceCodeMod::MECLIPTIC;    
    4505           0 :     case MDirection::TECLIPTIC: return DirectionReferenceCodeMod::TECLIPTIC;    
    4506           0 :     case MDirection::SUPERGAL:  return DirectionReferenceCodeMod::SUPERGAL;     
    4507           0 :     case MDirection::ITRF:      return DirectionReferenceCodeMod::ITRF;           
    4508           0 :     case MDirection::TOPO:      return DirectionReferenceCodeMod::TOPO;           
    4509           0 :     case MDirection::ICRS:      return DirectionReferenceCodeMod::ICRS;      
    4510             :     
    4511           0 :     case MDirection::MERCURY: return DirectionReferenceCodeMod::MERCURY; 
    4512           0 :     case MDirection::VENUS:   return DirectionReferenceCodeMod::VENUS;
    4513           0 :     case MDirection::MARS:    return DirectionReferenceCodeMod::MARS;
    4514           0 :     case MDirection::JUPITER: return DirectionReferenceCodeMod::JUPITER;
    4515           0 :     case MDirection::SATURN:  return DirectionReferenceCodeMod::SATURN;
    4516           0 :     case MDirection::URANUS:  return DirectionReferenceCodeMod::URANUS;
    4517           0 :     case MDirection::NEPTUNE: return DirectionReferenceCodeMod::NEPTUNE;
    4518           0 :     case MDirection::PLUTO:   return DirectionReferenceCodeMod::PLUTO;
    4519           0 :     case MDirection::SUN:     return DirectionReferenceCodeMod::SUN;
    4520           0 :     case MDirection::MOON:    return DirectionReferenceCodeMod::MOON;
    4521           0 :     default:
    4522           0 :       return DirectionReferenceCodeMod::J2000;
    4523             :     }
    4524             : 
    4525             :   }
    4526             : 
    4527             : 
    4528           0 :   BasebandNameMod::BasebandName MS2ASDM::ASDMBBName( Int BBCNo ){
    4529           0 :     switch(BBCNo){
    4530           0 :     case 1: return BasebandNameMod::BB_1;
    4531           0 :     case 2: return BasebandNameMod::BB_2;
    4532           0 :     case 3: return BasebandNameMod::BB_3;
    4533           0 :     case 4: return BasebandNameMod::BB_4;
    4534           0 :     case 5: return BasebandNameMod::BB_5;
    4535           0 :     case 6: return BasebandNameMod::BB_6;
    4536           0 :     case 7: return BasebandNameMod::BB_7;
    4537           0 :     case 8: return BasebandNameMod::BB_8;
    4538           0 :     case 0: 
    4539             :     default:
    4540           0 :       return BasebandNameMod::NOBB;
    4541             :     }
    4542             :   }
    4543             : 
    4544           0 :   NetSidebandMod::NetSideband MS2ASDM::ASDMNetSideBand( Int netSideB ){
    4545           0 :     switch(netSideB){
    4546           0 :     case 1: return NetSidebandMod::LSB;
    4547           0 :     case 2: return NetSidebandMod::USB;
    4548           0 :     case 3: return NetSidebandMod::DSB;
    4549           0 :     case 0:
    4550             :     default:
    4551           0 :       return NetSidebandMod::NOSB;
    4552             :     }
    4553             :   }
    4554             : 
    4555           0 :   FrequencyReferenceCodeMod::FrequencyReferenceCode MS2ASDM::ASDMFreqRefCode( const MFrequency::Types refFrame ){
    4556           0 :     LogIO os(LogOrigin("MS2ASDM", "(ASDMFreqRefCode)"));
    4557           0 :     switch( refFrame ){
    4558           0 :     case MFrequency::LSRD: return FrequencyReferenceCodeMod::LSRD;
    4559           0 :     case MFrequency::LSRK: return FrequencyReferenceCodeMod::LSRK;
    4560           0 :     case MFrequency::BARY: return FrequencyReferenceCodeMod::BARY;
    4561           0 :     case MFrequency::REST: return FrequencyReferenceCodeMod::REST;
    4562           0 :     case MFrequency::GEO: return FrequencyReferenceCodeMod::GEO;
    4563           0 :     case MFrequency::GALACTO: return FrequencyReferenceCodeMod::GALACTO;
    4564           0 :     case MFrequency::TOPO: return FrequencyReferenceCodeMod::TOPO;
    4565           0 :     default:
    4566             :       os << LogIO::SEVERE << "Unsupported CASA reference frame " << MFrequency::showType(refFrame) 
    4567           0 :          << ", assuming TOPO." << LogIO::POST;
    4568           0 :       return FrequencyReferenceCodeMod::TOPO; 
    4569             :     }
    4570           0 :   }
    4571             : 
    4572           0 :   Bool MS2ASDM::stokesTypePresent( const Vector< Int > corrT, 
    4573             :                                    const Stokes::StokesTypes st ){
    4574           0 :     Bool rval = false;
    4575           0 :     for(uInt j=0; j<corrT.size(); j++){
    4576           0 :       if(corrT[j]==static_cast<Int>(st)){
    4577           0 :          rval = true;
    4578           0 :          break;
    4579             :       }
    4580             :     }
    4581           0 :     return rval;
    4582             :   }
    4583             : 
    4584           0 :   Int MS2ASDM::setRecBands( const asdm::Frequency refFreq, 
    4585             :                             double& repFreq,
    4586             :                             ReceiverBandMod::ReceiverBand& frequencyBand,
    4587             :                             ReceiverSidebandMod::ReceiverSideband& receiverSideband){
    4588             : 
    4589             :     // return the band number as an Int, -1 means failure, 0 means unknown observatory
    4590           0 :     Int rval = -1;
    4591             : 
    4592           0 :     Quantity theFreq( refFreq.get(), String(Frequency::unit()) );
    4593           0 :     Double theFreqGHz = theFreq.getValue("GHz");
    4594             :     
    4595             :     //cout << "tel " << telName_p << endl;
    4596             :     //cout << "Freq (GHz) " << theFreqGHz << endl; 
    4597             : 
    4598             :     // default values
    4599           0 :     Quantity tempQ( ((Int)theFreqGHz)*1E9, "Hz");
    4600           0 :     repFreq =  tempQ.getValue(unitASDMFreq());
    4601           0 :     frequencyBand = ReceiverBandMod::UNSPECIFIED;
    4602           0 :     receiverSideband = ReceiverSidebandMod::NOSB;
    4603             : 
    4604             :     // implementation of the ALMA freq bands !!!
    4605           0 :     if(telName_p == "ALMA" || telName_p == "OSF" || telName_p == "ACA"){
    4606           0 :       if(31.<=theFreqGHz &&  theFreqGHz<45.){
    4607           0 :         repFreq = (31.+45.)/2.*1E9;
    4608           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_01;
    4609           0 :         receiverSideband = ReceiverSidebandMod::SSB; 
    4610           0 :         rval = 1;
    4611             :       }
    4612           0 :       else if(67.<=theFreqGHz &&  theFreqGHz<90.){
    4613           0 :         repFreq = (67.+90.)/2.*1E9;
    4614           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_02;
    4615           0 :         receiverSideband = ReceiverSidebandMod::SSB; 
    4616           0 :         rval = 2;
    4617             :       }
    4618           0 :       else if(84.<=theFreqGHz &&  theFreqGHz<116.){
    4619           0 :         repFreq = (84.+116.)/2.*1E9;
    4620           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_03;
    4621           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4622           0 :         rval = 3;
    4623             :       }
    4624           0 :       else if(125.<=theFreqGHz &&  theFreqGHz<163.){
    4625           0 :         repFreq = (125.+163.)/2.*1E9;
    4626           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_04;
    4627           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4628           0 :         rval = 4;
    4629             :       }   
    4630           0 :       else if(163.<=theFreqGHz &&  theFreqGHz<211.){
    4631           0 :         repFreq = (163.+211.)/2.*1E9;
    4632           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_05;
    4633           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4634           0 :         rval = 5;
    4635             :       }   
    4636           0 :       else if(211.<=theFreqGHz &&  theFreqGHz<275.){
    4637           0 :         repFreq = (211.+275.)/2.*1E9;
    4638           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_06;
    4639           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4640           0 :         rval = 6;
    4641             :       }   
    4642           0 :       else if(275.<=theFreqGHz &&  theFreqGHz<373.){
    4643           0 :         repFreq = (275.+373.)/2.*1E9;
    4644           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_07;
    4645           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4646           0 :         rval = 7;
    4647             :       }   
    4648           0 :       else if(385.<=theFreqGHz &&  theFreqGHz<500.){
    4649           0 :         repFreq = (385.+500.)/2.*1E9;
    4650           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_08;
    4651           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4652           0 :         rval = 8;
    4653             :       }   
    4654           0 :       else if(602.<=theFreqGHz &&  theFreqGHz<720.){
    4655           0 :         repFreq = (602.+720.)/2.*1E9;
    4656           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_09;
    4657           0 :         receiverSideband = ReceiverSidebandMod::DSB; 
    4658           0 :         rval = 9;
    4659             :       }   
    4660           0 :       else if(787.<=theFreqGHz &&  theFreqGHz<950.){
    4661           0 :         repFreq = (787.+950.)/2.*1E9;
    4662           0 :         frequencyBand = ReceiverBandMod::ALMA_RB_10;
    4663           0 :         receiverSideband = ReceiverSidebandMod::DSB; 
    4664           0 :         rval = 10;
    4665             :       }
    4666             :       else{
    4667           0 :         repFreq = theFreqGHz*1E9;
    4668           0 :         frequencyBand = ReceiverBandMod::UNSPECIFIED;
    4669           0 :         receiverSideband = ReceiverSidebandMod::TSB; 
    4670           0 :         rval = 0;
    4671             :       }
    4672             :         
    4673           0 :       Quantity tempQ2(repFreq, "Hz");
    4674           0 :       repFreq =  tempQ2.getValue(unitASDMFreq());
    4675           0 :       return rval;
    4676           0 :     }
    4677           0 :     else if(telName_p == "VLA" || telName_p == "EVLA" || telName_p == "JVLA"){
    4678             :       // EVLA freq band implementation!!
    4679           0 :       if( 0.033 <=theFreqGHz &&  theFreqGHz<0.081 ){
    4680           0 :         repFreq = (0.033/0.081)/2.*1E9;
    4681           0 :         frequencyBand = ReceiverBandMod::EVLA_4;
    4682           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4683           0 :         rval = 1;
    4684             :       }
    4685           0 :       else if(0.298<=theFreqGHz &&  theFreqGHz< 0.345){
    4686           0 :         repFreq = (0.298+0.345)/2.*1E9;
    4687           0 :         frequencyBand = ReceiverBandMod::EVLA_P;
    4688           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4689           0 :         rval = 2;
    4690             :       }
    4691           0 :       else if(1.0 <=theFreqGHz &&  theFreqGHz< 2.0){
    4692           0 :         repFreq = (1.+2.)/2.*1E9;
    4693           0 :         frequencyBand = ReceiverBandMod::EVLA_L;
    4694           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4695           0 :         rval = 3;
    4696             :       }
    4697           0 :       else if(2.0 <=theFreqGHz &&  theFreqGHz< 4.0){
    4698           0 :         repFreq = (2.+4.)/2.*1E9;
    4699           0 :         frequencyBand = ReceiverBandMod::EVLA_S;
    4700           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4701           0 :         rval = 4;
    4702             :       }   
    4703           0 :       else if(4.0 <=theFreqGHz &&  theFreqGHz< 8.0){
    4704           0 :         repFreq = (4.+8.)/2.*1E9;
    4705           0 :         frequencyBand = ReceiverBandMod::EVLA_C;
    4706           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4707           0 :         rval = 5;
    4708             :       }   
    4709           0 :       else if(8.0 <=theFreqGHz &&  theFreqGHz< 12.0){
    4710           0 :         repFreq = (8.+12.)/2.*1E9;
    4711           0 :         frequencyBand = ReceiverBandMod::EVLA_X;
    4712           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4713           0 :         rval = 6;
    4714             :       }   
    4715           0 :       else if(12. <=theFreqGHz &&  theFreqGHz< 18.){ 
    4716           0 :         repFreq = (12.+18.)/2.*1E9;
    4717           0 :         frequencyBand = ReceiverBandMod::EVLA_Ku; // a.k.a. U
    4718           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4719           0 :         rval = 7;
    4720             :       }   
    4721           0 :       else if(18.0 <=theFreqGHz &&  theFreqGHz< 26.5){
    4722           0 :         repFreq = (18.+26.5)/2.*1E9;
    4723           0 :         frequencyBand = ReceiverBandMod::EVLA_K;
    4724           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4725           0 :         rval = 8;
    4726             :       }   
    4727           0 :       else if(26.5 <=theFreqGHz &&  theFreqGHz< 40.){
    4728           0 :         repFreq = (26.5+40.)/2.*1E9;
    4729           0 :         frequencyBand = ReceiverBandMod::EVLA_Ka;
    4730           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4731           0 :         rval = 9;
    4732             :       }   
    4733           0 :       else if(40. <=theFreqGHz &&  theFreqGHz< 50.){
    4734           0 :         repFreq = (40.+50.)/2.*1E9;
    4735           0 :         frequencyBand = ReceiverBandMod::EVLA_Q;
    4736           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4737           0 :         rval = 10;
    4738             :       }
    4739             :       else{
    4740           0 :         repFreq = theFreqGHz*1E9;
    4741           0 :         frequencyBand = ReceiverBandMod::UNSPECIFIED;
    4742           0 :         receiverSideband = ReceiverSidebandMod::NOSB; 
    4743           0 :         rval = 0;
    4744             :       }
    4745           0 :       Quantity tempQ2(repFreq, "Hz");
    4746           0 :       repFreq =  tempQ2.getValue(unitASDMFreq());
    4747           0 :       return rval;
    4748           0 :     }
    4749             : 
    4750           0 :     return 0; // unknown observatory
    4751           0 :   }  
    4752             : 
    4753             : 
    4754             : } //#End casa namespace

Generated by: LCOV version 1.16