LCOV - code coverage report
Current view: top level - synthesis/TransformMachines2 - VisModelData.cc (source / functions) Hit Total Coverage
Test: ctest_coverage.info Lines: 246 882 27.9 %
Date: 2023-11-06 10:06:49 Functions: 18 36 50.0 %

          Line data    Source code
       1             : //# VisImagingWeight.cc: imaging weight calculation for a give buffer
       2             : //# Copyright (C) 2011
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be adressed as follows:
      20             : //#        Internet email: aips2-request@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //#
      27             : //# $Id$
      28             : 
      29             : 
      30             : #include <casacore/casa/Utilities/CountedPtr.h>
      31             : #include <casacore/casa/Arrays/ArrayMath.h>
      32             : #include <casacore/casa/Arrays/Vector.h>
      33             : #include <casacore/casa/OS/Timer.h>
      34             : #include <casacore/casa/Containers/Record.h>
      35             : #include <casacore/casa/Logging/LogIO.h>
      36             : #include <casacore/tables/Tables/ScaRecordColDesc.h>
      37             : #include <casacore/tables/Tables/TableUtil.h>
      38             : #include <components/ComponentModels/ComponentList.h>
      39             : #include <casacore/ms/MSSel/MSSelection.h>
      40             : #include <casacore/ms/MSSel/MSSelectionTools.h>
      41             : #include <casacore/ms/MeasurementSets/MSSource.h>
      42             : #include <casacore/ms/MSSel/MSSourceIndex.h>
      43             : #include <casacore/ms/MeasurementSets/MSSourceColumns.h>
      44             : 
      45             : #include <msvis/MSVis/VisBuffer2.h>
      46             : #include <synthesis/TransformMachines2/VisModelData.h>
      47             : #include <synthesis/TransformMachines2/FTMachine.h>
      48             : #include <synthesis/TransformMachines2/SimpleComponentFTMachine.h>
      49             : #include <synthesis/TransformMachines2/GridFT.h>
      50             : //#include <synthesis/TransformMachines/rGridFT.h>
      51             : #include <synthesis/TransformMachines2/MosaicFTNew.h>
      52             : #include <synthesis/TransformMachines2/WProjectFT.h>
      53             : //#include <synthesis/TransformMachines/MultiTermFT.h>
      54             : #include <synthesis/TransformMachines2/MultiTermFTNew.h>
      55             : #include <synthesis/TransformMachines2/SetJyGridFT.h>
      56             : 
      57             : namespace {
      58             : 
      59        5437 :   casa::VisModelDataI * createRefImVisModelData (){
      60        5437 :     return new casa::refim::VisModelData ();
      61             :   }
      62             : 
      63             :   // FIXME compiler warning re: unused variable initializeVisModelDataFactory 
      64             :   bool initializeVisModelDataFactory = casa::VisModelDataI::setFactory (createRefImVisModelData, 1);
      65             : 
      66             : }
      67             : 
      68             : 
      69             : 
      70             : using namespace casacore;
      71             : namespace casa { //# NAMESPACE CASA - BEGIN
      72             : 
      73             : namespace refim {//namespace for refactor
      74             : 
      75             : using namespace casacore;
      76             : using namespace casa;
      77             : using namespace casacore;
      78             : using namespace casa::refim;
      79             : using namespace casacore;
      80             : using namespace casa::vi;
      81        5437 :   VisModelData::VisModelData(): clholder_p(0), ftholder_p(0), flatholder_p(0), version_p(-1){
      82             :   
      83        5437 :   cft_p=new SimpleComponentFTMachine();
      84        5437 :   }
      85             : 
      86       10874 :   VisModelData::~VisModelData(){
      87             : 
      88             : 
      89       10874 :   }
      90             : 
      91             : VisModelDataI *
      92           0 : VisModelData::clone ()
      93             : {
      94           0 :     return new VisModelData (* this);
      95             : }
      96             : 
      97             : 
      98           8 :   Bool VisModelData::hasAnyModel(const MeasurementSet& thems, Vector<Int>& fieldids){
      99           8 :     Bool retval=False;
     100           8 :     fieldids.resize();
     101          16 :     MSColumns msc(thems);
     102           8 :     Vector<Int> fields=msc.fieldId().getColumn();
     103           8 :     const Sort::Order order=Sort::Ascending;
     104           8 :     const Int option=Sort::HeapSort | Sort::NoDuplicates;
     105           8 :     Int nfields=GenSort<Int>::sort (fields, order, option);\
     106           8 :     if (nfields>0) {
     107          24 :       for (Int j=0; j< 2; ++j){
     108          16 :         const Table* thetab=&thems;
     109          16 :         if (j==1)
     110           8 :           thetab=&(thems.source());
     111          60 :         for (Int k=0; k< nfields; ++k){
     112          44 :                         if(thetab->keywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     113             :                 {
     114          12 :                   String elkey=thetab->keywordSet().asString("definedmodel_field_"+String::toString(fields[k]));
     115           4 :                   if(thetab->keywordSet().isDefined(elkey)){
     116           4 :                     fieldids.resize(fieldids.nelements()+1, True);
     117           4 :                     fieldids[fieldids.nelements()-1]=fields[k];
     118             :                   }
     119             :                 }
     120             :         }
     121             :       }
     122             :     }
     123           8 :     if(fieldids.nelements() >0)
     124           4 :       retval=True;
     125             : 
     126          16 :     return retval;
     127             :   }
     128             : 
     129           0 : void VisModelData::listModel(const MeasurementSet& thems){
     130             :  
     131             :   //Table newTab(thems);
     132             : 
     133           0 :   MSColumns msc(thems);
     134           0 :   Vector<String> fldnames=msc.field().name().getColumn();
     135           0 :   Vector<Int> fieldids;
     136           0 :   LogIO logio;
     137           0 :   if(hasAnyModel(thems, fieldids)){
     138           0 :       for (uInt k=0; k< fieldids.nelements(); ++k){
     139             :                         
     140           0 :         logio << " " << fldnames[fieldids[k]] << " (id = " << fieldids[k] << ")" << LogIO::POST;
     141             :                           
     142             :       }
     143             :     }
     144             :     else{
     145           0 :       logio <<  " None." << LogIO::POST;
     146             :     }
     147             :   
     148             :     
     149           0 : }
     150             : 
     151           0 : void VisModelData::deleteDiskImage(MeasurementSet& theMS, const String& theKey){
     152           0 :   TableRecord theRec;
     153           0 :   if(!VisModelData::getModelRecord(theKey, theRec, theMS))
     154           0 :     return;
     155           0 :   if(theRec.isDefined("numft")){
     156           0 :     Int numft=0;
     157           0 :     numft=theRec.asInt("numft");
     158           0 :     for (Int k=0; k < numft; ++k){
     159           0 :       String ftname=String("ft_")+String::toString(k);
     160           0 :       const Record& ftrec=theRec.asRecord(ftname);
     161           0 :       if(ftrec.asRecord("container").isDefined("diskimage")){
     162           0 :         String diskim=ftrec.asRecord("container").asString("diskimage");
     163           0 :         if(TableUtil::canDeleteTable(diskim))
     164           0 :           TableUtil::deleteTable(diskim);
     165             :       }
     166             : 
     167             :     }
     168             :   }
     169             : 
     170             : 
     171             : }
     172           0 : void VisModelData::removeRecordByKey(MeasurementSet& theMS, const String& theKey){
     173             : 
     174             : 
     175           0 :   deleteDiskImage(theMS, theKey);
     176           0 :   if(Table::isReadable(theMS.sourceTableName()) &&theMS.source().nrow() > 0 ){
     177           0 :     if(theMS.source().keywordSet().isDefined(theKey)){
     178           0 :       Int rowid=theMS.source().keywordSet().asInt(theKey);
     179           0 :       TableRecord elrec;
     180             :       //Replace the model with an empty record
     181           0 :       MSSourceColumns srcCol(theMS.source());
     182           0 :       srcCol.sourceModel().put(rowid, elrec);
     183           0 :       theMS.source().rwKeywordSet().removeField(theKey);
     184             :     }
     185             :   }
     186             :   //Remove from Main table if it is there
     187           0 :   if(theMS.rwKeywordSet().isDefined(theKey))
     188           0 :     theMS.rwKeywordSet().removeField(theKey);
     189           0 : }
     190             : 
     191          54 : void VisModelData::clearModel(const MeasurementSet& thems){
     192             :   //  Table newTab(thems);
     193          54 :   MeasurementSet& newTab=const_cast<MeasurementSet& >(thems);
     194          54 :   if(!newTab.isWritable())
     195           0 :     return;
     196          54 :   auto part_block = newTab.getPartNames(true);
     197          54 :   Vector<String> theParts(part_block.begin( ),part_block.end( ));
     198          54 :   if(theParts.nelements() > 1){
     199           0 :     for (uInt k=0; k < theParts.nelements(); ++k){
     200           0 :       MeasurementSet subms(theParts[k], newTab.lockOptions(), Table::Update);
     201           0 :       clearModel(subms);
     202             :     }
     203           0 :     return;
     204             :   }
     205          54 :   Bool alreadyLocked=newTab.hasLock(True);
     206          54 :   if(!alreadyLocked)
     207           0 :     newTab.lock(True);
     208          54 :   if(Table::isReadable(newTab.sourceTableName())){
     209          54 :     if(!newTab.source().isWritable())
     210           0 :       return;
     211          54 :     newTab.source().lock(True);   
     212             :   }
     213         108 :   LogIO logio;
     214             :   logio << "Clearing all model records in MS header."
     215          54 :           << LogIO::POST;
     216             : 
     217         108 :   MSColumns msc(thems);
     218         108 :   Vector<Int> fields=msc.fieldId().getColumn();
     219         108 :   Vector<String> fldnames=msc.field().name().getColumn();
     220          54 :   const Sort::Order order=Sort::Ascending;
     221          54 :   const Int option=Sort::HeapSort | Sort::NoDuplicates;
     222          54 :   Int nfields=GenSort<Int>::sort (fields, order, option);
     223         109 :   for (Int k=0; k< nfields; ++k){
     224         110 :     String elkey;
     225             :     Int srow;
     226             :     //if(newTab.rwKeywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     227          55 :       if(isModelDefined(fields[k], thems, elkey, srow))
     228             :       {
     229           0 :         logio << " " << fldnames[fields[k]] << " (id = " << fields[k] << ") deleted." << LogIO::POST;
     230             :         //Remove from Source table
     231           0 :         removeRecordByKey(newTab, elkey);
     232           0 :         if(srow > -1){
     233           0 :           if(thems.source().keywordSet().isDefined("definedmodel_field_"+String::toString(fields[k]))){
     234           0 :             newTab.source().rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     235             :           }
     236             :         }
     237             :         //Remove from Main table if it is there
     238           0 :         if(newTab.rwKeywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     239           0 :           newTab.rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     240             :       }
     241             :       else{
     242             :         ///remove keys that point to nowehere
     243             :         //cerr << "The key " << elkey << endl;
     244          55 :         if(!newTab.source().isNull() && newTab.source().rwKeywordSet().isDefined(elkey))
     245           0 :           newTab.source().rwKeywordSet().removeField(elkey);
     246          55 :         if(newTab.rwKeywordSet().isDefined(elkey))
     247           0 :           newTab.rwKeywordSet().removeField(elkey);
     248          55 :         if( !newTab.source().isNull() && newTab.source().rwKeywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     249           0 :           newTab.source().rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     250          55 :         if(newTab.rwKeywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     251           0 :            newTab.rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     252             :       }
     253             :   }
     254          54 :   if(!alreadyLocked)
     255           0 :     newTab.unlock();
     256          54 :   if(Table::isReadable(newTab.sourceTableName())){
     257          54 :     newTab.source().unlock();   
     258             :   }
     259             :   ////Cleaning out orphaned image disk models
     260         108 :   String srctable=thems.source().isNull() ? "" : thems.source().tableName();
     261         108 :   Vector<String> possibleFT(2); 
     262          54 :   possibleFT(0)=srctable+"/FT_MODEL*";
     263          54 :   possibleFT(1)=theParts[0]+"/FT_MODEL*";
     264             :   
     265         108 :   Vector<String> ftmods=Directory::shellExpand(possibleFT);
     266          54 :   for (uInt kk=0; kk < ftmods.nelements(); ++kk){
     267           0 :     if(TableUtil::canDeleteTable(ftmods[kk])){
     268           0 :       TableUtil::deleteTable(ftmods[kk]);
     269             :     }
     270             :   }
     271             : 
     272             : }
     273          17 :   void VisModelData::clearModel(const MeasurementSet& thems, const String field, const String specwindows){
     274          17 :     MeasurementSet& newTab=const_cast<MeasurementSet& >(thems);
     275          17 :     if(!newTab.isWritable())
     276           0 :       return;
     277          17 :   auto part_block = newTab.getPartNames(true);
     278          17 :   Vector<String> theParts(part_block.begin( ),part_block.end( ));
     279          17 :   if(theParts.nelements() > 1){
     280           0 :     for (uInt k =0; k < theParts.nelements(); ++k){
     281           0 :       MeasurementSet subms(theParts[k], newTab.lockOptions(), Table::Update);
     282           0 :       clearModel(subms, field, specwindows);
     283             :     }
     284           0 :     return;
     285             :   }
     286          17 :   if(!newTab.isWritable())
     287           0 :     return;
     288          17 :   Bool alreadyLocked=newTab.hasLock(True);
     289          17 :   if(!alreadyLocked)
     290           0 :     newTab.lock(True);
     291          17 :   if(Table::isReadable(newTab.sourceTableName())){
     292          17 :     if(!Table::isWritable(newTab.sourceTableName()))
     293           0 :       return;
     294          17 :     newTab.source().lock(True);   
     295             :   }
     296             : 
     297          34 :   MSColumns msc(thems);
     298          34 :   Vector<String> fldnames=msc.field().name().getColumn();
     299          17 :   Int nfields=0;
     300          34 :   Vector<Int> fields(0);
     301             :   {
     302             :     // Parse field specification
     303          34 :     MSSelection mss;
     304          17 :     mss.setFieldExpr(field);
     305          17 :     TableExprNode ten=mss.toTableExprNode(&thems);
     306          17 :     fields=mss.getFieldList();
     307          17 :     nfields=fields.nelements();
     308             :   }
     309             : 
     310             : 
     311          17 :   if (nfields==0)
     312             :     // Call the method that deletes them all
     313          17 :     VisModelData::clearModel(thems);
     314             :   else {
     315             : 
     316             :     //Now we have the two cases the whole field or specific spws
     317             :     // only delete the specified ones
     318           0 :     Vector<Int> spws(0);
     319           0 :     Int nspws=0;
     320             :     {
     321             :       // Parse field specification
     322           0 :       MSSelection mss;
     323           0 :       mss.setFieldExpr(field);
     324           0 :       mss.setSpwExpr(specwindows);
     325           0 :       TableExprNode ten=mss.toTableExprNode(&thems);
     326           0 :       spws=mss.getSpwList();
     327           0 :       nspws=spws.nelements();
     328             :     }
     329             : 
     330             :    
     331           0 :     LogIO logio;
     332             :     logio << "Clearing model records in MS header for selected fields." 
     333           0 :           << LogIO::POST;
     334             :     
     335           0 :     for (Int k=0; k< nfields; ++k){
     336           0 :       String elkey;
     337             :       Int srow;
     338           0 :       if(isModelDefined(fields[k], newTab, elkey, srow))
     339             :         
     340             :         {
     341             :         
     342           0 :           if(nspws==0){
     343           0 :             logio << " " << fldnames[fields[k]] << " (id = " << fields[k] << ") deleted." << LogIO::POST;
     344           0 :             removeRecordByKey(newTab, elkey);
     345           0 :             if(srow > -1 ){
     346           0 :               if(newTab.source().keywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     347           0 :                 newTab.source().rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));              
     348             :             }
     349           0 :             if(newTab.rwKeywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     350           0 :               newTab.rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     351             :           }
     352             :           else{
     353             :             //if(newTab.rwKeywordSet().isDefined(elkey)){
     354             :             
     355           0 :             TableRecord conteneur;  
     356           0 :             getModelRecord(elkey, conteneur, newTab); 
     357             :            
     358             :             //=newTab.rwKeywordSet().asRecord(elkey);
     359           0 :             if(removeSpw(conteneur, spws, fields)){
     360           0 :                 putRecordByKey(newTab, elkey, conteneur, srow);
     361             :             }
     362             :             else{
     363           0 :                 removeRecordByKey(newTab, elkey);
     364           0 :                 if(newTab.source().keywordSet().isDefined("definedmodel_field_"+String::toString(fields[k])))
     365           0 :                         newTab.source().rwKeywordSet().removeField("definedmodel_field_"+String::toString(fields[k]));
     366             :             }
     367             :               /*
     368             :               Vector<Int> defspws=conteneur.asArrayInt("spws");
     369             :               Vector<Int> newdefspw(defspws.nelements(), -1);
     370             :               Int counter=0;
     371             :               for(uInt k=0; k < defspws.nelements(); ++k){
     372             :                 for (Int j=0; j < nspws; ++j){
     373             :                   if(defspws[k] != spws[j]){
     374             :                     newdefspw[counter]=defspws[k];
     375             :                     ++counter;
     376             :                   }
     377             :                 }
     378             :               }
     379             :               if(counter==0){
     380             :                 //Now we have to remove this ftm or cft
     381             :                 newTab.rwKeywordSet().removeField(elkey);
     382             :               }
     383             :               else{
     384             :                 conteneur.define("spws", newdefspw);
     385             :                 updatespw(conteneur, 
     386             :               }
     387             :               */
     388             :           }
     389             :               
     390             :         
     391             :             
     392             :         }
     393             :       else
     394           0 :         logio << " " << fldnames[fields[k]] << " (id = " << fields[k] << ") not found." << LogIO::POST;
     395             :     }
     396             :     
     397             :   }
     398          17 :   if(!alreadyLocked)
     399           0 :     newTab.unlock();
     400          17 :   if(Table::isReadable(newTab.sourceTableName())){
     401          17 :     newTab.source().unlock();   
     402             :   }
     403             :   
     404             : 
     405             :   }
     406             : 
     407           0 :   Bool VisModelData::removeSpw(TableRecord& therec, const Vector<Int>& spws, const Vector<Int>& fields){
     408           0 :      Int numft=0;
     409           0 :      Vector<String> numtype(2);
     410           0 :      Vector<String> keyval(2);
     411           0 :      numtype[0]=String("numft");
     412           0 :      numtype[1]=String("numcl");
     413           0 :      keyval[0]="ft_";
     414           0 :      keyval[1]="cl_";
     415             :      
     416           0 :      for (Int j=0; j< 2; ++j){
     417           0 :          if(therec.isDefined(numtype[j])){
     418           0 :                  numft=therec.asInt(numtype[j]);
     419           0 :                  Vector<String> toberemoved(numft);
     420           0 :                  Int numrem=0;
     421           0 :                  for (Int k=0; k < numft; ++k){
     422           0 :                          RecordInterface& ftrec=therec.asrwRecord(keyval[j]+String::toString(k));
     423           0 :                          if(!ftrec.isDefined("version")){
     424           0 :                            Bool hasField=true;
     425           0 :                            if(fields.nelements() >0){
     426           0 :                              hasField=false;
     427           0 :                              Vector<Int> fieldsinrec;
     428           0 :                              ftrec.get("fields", fieldsinrec);
     429           0 :                              if(anyEQ(fieldsinrec, fields))
     430           0 :                                hasField=true;
     431             :                            }
     432           0 :                            if(hasField && !removeSpwFromMachineRec(ftrec, spws)){
     433           0 :                              toberemoved[numrem]=String(keyval[j]+String::toString(k));
     434           0 :                              ++numrem;
     435             :                            }
     436             :                          }
     437             :                          else{
     438             :                            //Version 2
     439           0 :                            const Matrix<Int>& ftcombind=ftrec.asArrayInt("indexcombination");
     440           0 :                            Matrix<Int> newComb;
     441           0 :                            for(uInt row=0; row < ftcombind.nrow(); ++row){
     442           0 :                              Vector<Int> rowcomb=ftcombind.row(row);      
     443           0 :                              Bool rowTobeRemoved=False;
     444           0 :                              for (uInt ff=0; ff < fields.nelements() ; ++ff){
     445           0 :                                for (uInt ss=0; ss < spws.nelements(); ++ss){
     446           0 :                                  if(rowcomb[0]==fields[ff] && rowcomb[1] == spws[ss] )
     447           0 :                                    rowTobeRemoved=True;
     448             :                                  
     449             :                                  
     450             :                                }
     451             :                              }
     452           0 :                              if(!rowTobeRemoved){
     453           0 :                                newComb.resize(newComb.nrow()+1,4, True);
     454           0 :                                newComb.row(newComb.nrow()-1)=rowcomb;
     455             :                              }
     456             :                            }
     457           0 :                            if(newComb.nrow()==0){
     458           0 :                              toberemoved[numrem]=String(keyval[j]+String::toString(k));
     459           0 :                              ++numrem;  
     460             :                            }
     461             :                            else{
     462           0 :                              ftrec.define("indexcombination", newComb);
     463             :                            }
     464             :                            
     465             :                            
     466             :                          }
     467             :                  }
     468           0 :                  if(numrem > 0){
     469           0 :                          for (Int k=0; k < numrem; ++k)
     470           0 :                                  removeFTFromRec(therec, toberemoved[k], k==(numrem-1));
     471             :                  }
     472             :          }
     473             :      }
     474           0 :      numft=0; Int numcl=0;
     475           0 :      if(therec.isDefined("numft")) numft=therec.asInt("numft");
     476           0 :      if(therec.isDefined("numcl")) numcl=therec.asInt("numcl");
     477           0 :      if (numft==0 && numcl==0)
     478           0 :          return false;
     479           0 :      return true;
     480             :   }
     481             : 
     482           0 :   Bool VisModelData::removeFTFromRec(TableRecord& therec, const String& keyval, const Bool relabel){
     483             : 
     484             : 
     485           0 :     String *splitkey=new String[2];
     486           0 :     Int nsep=split(keyval, splitkey, 2, String("_"));
     487           0 :     if (nsep <1 || !therec.isDefined(keyval)) 
     488           0 :       return false;
     489           0 :     String eltype=splitkey[0];
     490             :     //Int modInd=String::toInt(splitkey[1]);
     491           0 :     Int numcomp= (eltype==String("ft")) ? therec.asInt("numft"): therec.asInt("numcl");
     492           0 :     therec.removeField(keyval);
     493             :     
     494           0 :     numcomp=numcomp-1;
     495           0 :     if(eltype=="ft")
     496           0 :       therec.define("numft", numcomp);
     497             :     else
     498           0 :       therec.define("numcl", numcomp);
     499           0 :     if(relabel){
     500             : 
     501             :     
     502           0 :         eltype=eltype+String("_");
     503           0 :         Int id=0;
     504           0 :         for(uInt k=0; k < therec.nfields(); ++k){
     505           0 :                 if(therec.name(k).contains(eltype)){
     506           0 :                         therec.renameField(eltype+String::toString(id), k);
     507           0 :                         ++id;
     508             :                 }
     509             :         }
     510             :     }
     511             : 
     512           0 :     delete [] splitkey;
     513           0 :     return true;
     514             :   } 
     515             : 
     516           0 :   Bool VisModelData::removeSpwFromMachineRec(RecordInterface& ftclrec, const Vector<Int>& spws){
     517           0 :     Vector<Int> defspws=ftclrec.asArrayInt("spws");
     518           0 :     Vector<Int> newdefspw(defspws.nelements(), -1);
     519           0 :     Int counter=0;
     520           0 :     for(uInt k=0; k < defspws.nelements(); ++k){
     521           0 :       for (uInt j=0; j < spws.nelements(); ++j){
     522           0 :         if(defspws[k] == spws[j]){
     523           0 :           defspws[k]=-1;
     524           0 :           ++counter;
     525             :         }
     526             :       }
     527             :     }
     528           0 :     if(defspws.nelements() == uInt(counter)){
     529             :       //Now we have to remove this ft or cl model
     530             : 
     531           0 :       return false;
     532             : 
     533             :     }    
     534           0 :     newdefspw.resize(defspws.nelements()-counter);
     535           0 :     counter=0;
     536           0 :     for (uInt k=0; k < defspws.nelements(); ++k){
     537           0 :       if(defspws[k] != -1){
     538           0 :         newdefspw[counter]=defspws[k];
     539           0 :         ++counter;
     540             :       }
     541             :     }
     542             :     
     543           0 :     ftclrec.define("spws", newdefspw);
     544           0 :     return true;
     545             :   }
     546             : 
     547           0 :   Bool VisModelData::addToRec(TableRecord& therec, const Vector<Int>& spws){
     548             : 
     549           0 :     Int numft=0;
     550           0 :     Int numcl=0;
     551           0 :     Vector<Bool> hasSpw(spws.nelements(), false);
     552           0 :     if(therec.isDefined("numft")){
     553           0 :       numft=therec.asInt("numft");
     554           0 :       Vector<Int> ft_toremove(numft, 0);
     555           0 :       for(Int k=0; k < numft; ++k){
     556           0 :         const Record& ftrec=therec.asRecord("ft_"+String::toString(k));
     557           0 :         const Vector<Int>& ftspws=ftrec.asArrayInt("spws");
     558           0 :         for (uInt i=0; i<spws.nelements(); ++i){
     559           0 :           for (uInt j=0; j<ftspws.nelements(); ++j){
     560           0 :             if(spws[i]==ftspws[j]){
     561           0 :               hasSpw[i]=true;      
     562           0 :               ft_toremove[k]=1;
     563             :             }
     564             :           }     
     565             :         }
     566             :       }
     567           0 :       if(sum(ft_toremove) >0){
     568           0 :         for(Int k=0; k < numft; ++k){
     569           0 :           if(ft_toremove[k]==1)
     570           0 :             therec.removeField("ft_"+String::toString(k));
     571             :         }
     572           0 :         numft=numft-sum(ft_toremove);
     573           0 :         therec.define("numft", numft);
     574           0 :         Int id=0;
     575           0 :         for(uInt k=0; k < therec.nfields(); ++k){
     576           0 :           if(therec.name(k).contains("ft_")){
     577           0 :             therec.renameField("ft_"+String::toString(id), k);
     578           0 :             ++id;
     579             :           }
     580             :         }
     581             :       }
     582             :     }
     583           0 :     if(therec.isDefined("numcl")){
     584           0 :       numcl=therec.asInt("numcl");
     585           0 :       Vector<Int> cl_toremove(numcl, 0);
     586           0 :       for(Int k=0; k < numcl; ++k){
     587           0 :         const Record& clrec=therec.asRecord("cl_"+String::toString(k));
     588           0 :         const Vector<Int>& clspws=clrec.asArrayInt("spws");
     589           0 :         for (uInt i=0; i<spws.nelements(); ++i){
     590           0 :           for (uInt j=0; j<clspws.nelements(); ++j){
     591           0 :             if(spws[i]==clspws[j]){
     592           0 :               hasSpw[i]=true;       
     593           0 :               cl_toremove[k]=1;
     594             :             }
     595             :           }     
     596             :         }
     597             :       }
     598           0 :       if(sum(cl_toremove) >0){
     599           0 :         for(Int k=0; k < numcl; ++k){
     600           0 :           if(cl_toremove[k]==1)
     601           0 :             therec.removeField("cl_"+String::toString(k));
     602             :         }
     603           0 :         numcl=numcl-sum(cl_toremove);
     604           0 :         therec.define("numcl", numcl);
     605           0 :         Int id=0;
     606           0 :         for(uInt k=0; k < therec.nfields(); ++k){
     607           0 :           if(therec.name(k).contains("cl_")){
     608           0 :             therec.renameField("cl_"+String::toString(id), k);
     609           0 :             ++id;
     610             :           }
     611             :         }
     612             :       }
     613             :     }
     614           0 :     return (!allTrue(hasSpw) || ((numft+numcl)>0));
     615             :   }
     616             : 
     617           0 : Bool VisModelData::addToRec(TableRecord& therec, const Matrix<Int>& combind){
     618           0 :   if(therec.nfields() >0 && ((!therec.isDefined("version")) || (therec.asInt("version") !=2)))
     619           0 :     throw(AipsError("cannot combine with older version virtual model column;\n please clear it before proceeding"));
     620           0 :   Int numft=0;
     621           0 :   Int numcl=0;
     622           0 :   Vector<Bool> hasComb(combind.nrow(), false);
     623           0 :   if(therec.isDefined("numft")){
     624           0 :     numft=therec.asInt("numft");
     625           0 :     Vector<Int> ft_toremove(numft, 0);
     626           0 :     for(Int k=0; k < numft; ++k){
     627           0 :       const Record& ftrec=therec.asRecord("ft_"+String::toString(k));
     628           0 :       const Matrix<Int>& ftcombind=ftrec.asArrayInt("indexcombination");
     629           0 :       for (uInt i=0; i<combind.nrow(); ++i){
     630           0 :         for (uInt j=0; j<ftcombind.nrow(); ++j){
     631           0 :           if(allEQ(combind.row(i), ftcombind.row(j))){
     632             :             //We could upgrade this to just delete the intent from the ft
     633           0 :             hasComb[i]=true;       
     634           0 :             ft_toremove[k]=1;
     635             :           }
     636             :         }       
     637             :       }
     638             :     }
     639           0 :     if(sum(ft_toremove) >0){
     640           0 :       for(Int k=0; k < numft; ++k){
     641           0 :         if(ft_toremove[k]==1)
     642           0 :           therec.removeField("ft_"+String::toString(k));
     643             :       }
     644           0 :       numft=numft-sum(ft_toremove);
     645           0 :       therec.define("numft", numft);
     646           0 :       Int id=0;
     647           0 :       for(uInt k=0; k < therec.nfields(); ++k){
     648           0 :         if(therec.name(k).contains("ft_")){
     649           0 :           therec.renameField("ft_"+String::toString(id), k);
     650           0 :           ++id;
     651             :         }
     652             :       }
     653             :     }
     654             :   }
     655           0 :   if(therec.isDefined("numcl")){
     656           0 :     numcl=therec.asInt("numcl");
     657           0 :     Vector<Int> cl_toremove(numcl, 0);
     658           0 :     for(Int k=0; k < numcl; ++k){
     659           0 :       const Record& clrec=therec.asRecord("cl_"+String::toString(k));
     660           0 :       const Matrix<Int>& clcombind=clrec.asArrayInt("indexcombination");
     661           0 :       for (uInt i=0; i<combind.nrow(); ++i){
     662           0 :         for (uInt j=0; j<clcombind.nrow(); ++j){
     663           0 :           if(allEQ(combind.row(i),clcombind.row(j))){
     664           0 :             hasComb[i]=true;        
     665           0 :             cl_toremove[k]=1;
     666             :           }
     667             :         }       
     668             :       }
     669             :       }
     670           0 :     if(sum(cl_toremove) >0){
     671           0 :       for(Int k=0; k < numcl; ++k){
     672           0 :         if(cl_toremove[k]==1)
     673           0 :           therec.removeField("cl_"+String::toString(k));
     674             :       }
     675           0 :       numcl=numcl-sum(cl_toremove);
     676           0 :       therec.define("numcl", numcl);
     677           0 :       Int id=0;
     678           0 :       for(uInt k=0; k < therec.nfields(); ++k){
     679           0 :         if(therec.name(k).contains("cl_")){
     680           0 :           therec.renameField("cl_"+String::toString(id), k);
     681           0 :           ++id;
     682             :         }
     683             :       }
     684             :     }
     685             :   }
     686           0 :   return (!allTrue(hasComb) || ((numft+numcl)>0));
     687             : }
     688             :  
     689             :   
     690      711524 : Bool VisModelData::isModelDefined(const Int fieldId, const MeasurementSet& thems, String& thekey, Int& sourceRow){
     691      711524 :   sourceRow=-1;
     692     2134572 :   String modelkey=String("definedmodel_field_")+String::toString(fieldId);
     693      711524 :   thekey="";
     694      711524 :   if(Table::isReadable(thems.sourceTableName()) && thems.source().nrow() > 0 && (thems.source().keywordSet().isDefined(modelkey))){
     695             :       {
     696          57 :       thekey=thems.source().keywordSet().asString(modelkey);
     697          57 :       if(thems.source().keywordSet().isDefined(thekey))
     698          57 :         sourceRow=thems.source().keywordSet().asInt(thekey);
     699             :     }
     700             :   }else{
     701      711467 :     if(thems.keywordSet().isDefined(modelkey)){
     702           0 :       thekey=thems.keywordSet().asString(modelkey);  
     703             :     }
     704             :   }
     705      711524 :   if(thekey != "" )
     706          57 :     return VisModelData::isModelDefined(thekey, thems);
     707      711467 :   return false;
     708             :   
     709             : }
     710             : 
     711          57 :   Bool VisModelData::isModelDefined(const String& elkey, const MeasurementSet& thems){
     712             :     //Let's try the Source table
     713          57 :     if(Table::isReadable(thems.sourceTableName()) &&thems.source().nrow() > 0 ){
     714          57 :       if(thems.source().keywordSet().isDefined(elkey))
     715          57 :         return true;      
     716             :     }
     717             :     //Let's try the Main table 
     718           0 :     if(thems.keywordSet().isDefined(elkey))
     719           0 :       return true;
     720           0 :     return false;
     721             :   }
     722             : 
     723           5 :   Bool VisModelData::getModelRecord(const String& theKey, TableRecord& theRec, const MeasurementSet& theMs){
     724             :     //Let's try the Source table
     725           5 :     if(Table::isReadable(theMs.sourceTableName()) &&theMs.source().nrow() > 0 && (theMs.source().keywordSet().isDefined(theKey))){
     726             :         {
     727             :         //Get the row for the model 
     728           5 :         Int row=theMs.source().keywordSet().asInt(theKey);
     729             :         //MSSourceColumns srcCol(theMs.source());
     730             :      
     731          10 :         ScalarColumn<TableRecord> scol(theMs.source(), "SOURCE_MODEL");
     732           5 :         scol.get(row, theRec);
     733             :       }
     734           5 :       return true;
     735             :     }
     736             :     //Let's try the Main table 
     737           0 :     if(theMs.keywordSet().isDefined(theKey)){
     738           0 :       theRec=theMs.keywordSet().asRecord(theKey);
     739           0 :       return true;
     740             :     }
     741           0 :     return false;
     742             : 
     743             : 
     744             :   }
     745             : 
     746           0 :   void VisModelData::putRecordByKey(MeasurementSet& theMS, const String& theKey, const TableRecord& theRec, const Int sourceRowNum){
     747             :     //Prefer the Source table first    
     748           0 :     if( (sourceRowNum> -1) && Table::isReadable(theMS.sourceTableName()) && Int(theMS.source().nrow()) > sourceRowNum ){
     749           0 :       MSSource& mss=theMS.source();
     750           0 :       if(!mss.isColumn(MSSource::SOURCE_MODEL) ){
     751           0 :         mss.addColumn(ScalarRecordColumnDesc("SOURCE_MODEL"), true);
     752             :       }
     753           0 :       if(mss.rwKeywordSet().isDefined(theKey))
     754           0 :         mss.rwKeywordSet().removeField(theKey);
     755           0 :       mss.rwKeywordSet().define(theKey, sourceRowNum);
     756           0 :       MSSourceColumns srcCol(mss);
     757           0 :       srcCol.sourceModel().put(sourceRowNum, theRec);
     758           0 :       return;
     759             :     }
     760             :     //Oh well no source table so will add it to the main table
     761           0 :     theMS.rwKeywordSet().defineRecord(theKey, theRec);
     762             :     
     763             : 
     764             :   }
     765             : 
     766           0 :   Bool VisModelData::putModelRecord(const Vector<Int>& fieldIds, TableRecord& theRec, MeasurementSet& theMS){
     767           0 :     auto part_block = theMS.getPartNames(true);
     768           0 :     Vector<String> theParts(part_block.begin( ),part_block.end( ));
     769           0 :     if(theParts.nelements() > 1){
     770           0 :       Bool retval=true;
     771           0 :       for (uInt k =0; k < theParts.nelements(); ++k){
     772           0 :           MeasurementSet subms(theParts[k], theMS.lockOptions(), Table::Update);
     773           0 :           retval= retval && putModelRecord(fieldIds, theRec, subms);
     774             :       }
     775           0 :       return retval;
     776             :     }
     777             :  
     778           0 :     String elkey="model";
     779           0 :     for (uInt k=0; k < fieldIds.nelements();  ++k){
     780           0 :       elkey=elkey+"_"+String::toString(fieldIds[k]);
     781             :     }
     782           0 :     if(theMS.rwKeywordSet().isDefined(elkey))
     783           0 :       theMS.rwKeywordSet().removeField(elkey);
     784           0 :     Int row=-1;
     785             :     //Prefer the Source table first    
     786           0 :     MSFieldColumns fCol(theMS.field());
     787           0 :     if(Table::isReadable(theMS.sourceTableName()) && (theMS.source().nrow() > 0) &&  (!fCol.sourceId().isNull()) && (fCol.sourceId().get(fieldIds[0]) != -1) ){
     788             :       //
     789           0 :       row=0;
     790           0 :       MSSource& mss=theMS.source();
     791             :      
     792           0 :       Int sid=fCol.sourceId().get(fieldIds[0]);
     793           0 :       auto rows=MSSourceIndex(mss).getRowNumbersOfSourceID(sid);
     794           0 :       if(rows.nelements() > 0) 
     795           0 :         row=rows[0];
     796             :       else{
     797           0 :         LogIO logio;
     798           0 :         logio << "Invalid Source_id "+String::toString(sid)+" found in FIELD table\n" 
     799             :               <<"Model is being written at Source ID 0 position which will be erased\n" 
     800             :               << "Fix the FIELD table before proceeding " 
     801           0 :               <<  LogIO::WARN << LogIO::POST;
     802             :         
     803             :       }
     804             :           
     805             :         
     806             :       
     807           0 :       putRecordByKey(theMS, elkey, theRec, row);
     808           0 :       for (uInt k=0; k < fieldIds.nelements();  ++k){
     809           0 :         mss.rwKeywordSet().define("definedmodel_field_"+String::toString(fieldIds[k]), elkey);
     810             :       }
     811           0 :       return true;
     812             :       
     813             :     }
     814             :     //Oh well no source table so will add it to the main table
     815           0 :     putRecordByKey(theMS, elkey, theRec, -1);
     816           0 :     for (uInt k=0; k < fieldIds.nelements();  ++k){
     817           0 :       theMS.rwKeywordSet().define("definedmodel_field_"+String::toString(fieldIds[k]), elkey);        
     818             :     }
     819             : 
     820           0 :     return true;
     821             :   }
     822             : 
     823             : 
     824           0 : void VisModelData::putModel(const MeasurementSet& thems, const RecordInterface& rec, const Vector<Int>& validfieldids, const Vector<Int>& spws, const Vector<Int>& starts, const Vector<Int>& nchan,  const Vector<Int>& incr, Bool iscomponentlist, Bool incremental){
     825             : 
     826           0 :   LogIO logio;
     827             : 
     828             :   try{
     829             :     //A field can have multiple FTmachines and ComponentList associated with it 
     830             :     //For example having many flanking images for the model
     831             :     //For componentlist it may have multiple componentlist ...for different spw
     832             :   //Timer tim;
     833             :   //tim.mark();
     834           0 :     Int counter=0;
     835           0 :     Record modrec;
     836           0 :     modrec.define("fields", validfieldids);
     837           0 :     modrec.define("spws", spws);
     838           0 :     modrec.define("start", starts);
     839           0 :     modrec.define("nchan", nchan);
     840           0 :     modrec.define("incr", incr);
     841           0 :     modrec.defineRecord("container", rec);
     842           0 :     String elkey="model";
     843           0 :     for (uInt k=0; k < validfieldids.nelements();  ++k){
     844           0 :       elkey=elkey+"_"+String::toString(validfieldids[k]);
     845             :     }
     846           0 :     TableRecord outRec; 
     847           0 :     Bool addtorec=false;
     848           0 :     MeasurementSet& newTab=const_cast<MeasurementSet& >(thems);
     849           0 :     newTab.lock(True);
     850           0 :     if(Table::isReadable(newTab.sourceTableName())){
     851           0 :       newTab.source().lock(True);   
     852             :     }
     853           0 :     if(isModelDefined(elkey, newTab)){ 
     854           0 :       getModelRecord(elkey, outRec, thems);
     855             :       //if incremental no need to check & remove what is in the record
     856           0 :       if(!incremental)
     857           0 :           addtorec=addToRec(outRec, spws);
     858             :     }
     859             : 
     860             :     ///////even if it is not defined some other field model might be sitting on that
     861             :     //////model key
     862           0 :     Int hasSourceRecord=firstSourceRowRecord(validfieldids[0], thems, outRec);
     863           0 :     if(hasSourceRecord > -1 && outRec.nfields() > 0)
     864           0 :       addtorec=true;
     865             :     //cerr << "has Source " << hasSourceRecord << endl;
     866             :     ////
     867             : 
     868           0 :     incremental=incremental || addtorec;
     869           0 :     if(iscomponentlist){
     870           0 :       modrec.define("type", "componentlist");
     871           0 :       if(outRec.isDefined("numcl"))
     872           0 :         counter=incremental ? outRec.asInt("numcl") : 0;
     873             :             
     874             :     }
     875             :     else{
     876           0 :       modrec.define("type", "ftmachine");
     877           0 :       if(outRec.isDefined("numft"))
     878           0 :         counter=incremental ? outRec.asInt("numft") : 0;
     879             :     }
     880           0 :     iscomponentlist ? outRec.define("numcl", counter+1) : outRec.define("numft", counter+1); 
     881             :   
     882             :     //for (uInt k=0; k < validfieldids.nelements();  ++k){
     883             :     //  newTab.rwKeywordSet().define("definedmodel_field_"+String::toString(validfieldids[k]), elkey);
     884             :       
     885             :     // }
     886           0 :     iscomponentlist ? outRec.defineRecord("cl_"+String::toString(counter), modrec):
     887           0 :       outRec.defineRecord("ft_"+String::toString(counter), modrec);
     888             :     //////////////////;
     889             :     //for (uInt k=0; k < newTab.rwKeywordSet().nfields() ; ++k){
     890             :     //  cerr << "keys " << k << "  is  " << newTab.rwKeywordSet().name(k) << " type " << newTab.rwKeywordSet().dataType(k) << endl;
     891             :     //}
     892             :     ////////////////////////
     893             :     //if image for a given key is on disk and not incrementing ...lets remove it
     894           0 :     if(!incremental) 
     895           0 :       deleteDiskImage(newTab, elkey);
     896           0 :     putModelRecord(validfieldids, outRec, newTab);  
     897             :     //if(newTab.rwKeywordSet().isDefined(elkey))
     898             :     //  newTab.rwKeywordSet().removeField(elkey);
     899             :     //newTab.rwKeywordSet().defineRecord(elkey, outRec);
     900             :     
     901             :     // tim.show("Time taken to save record ");
     902             :  
     903             :       /*
     904             :       String subName=newTab.tableName()+"/"+elkey;
     905             :       if(Table::isReadable(subName) && !Table::canDeleteTable(subName, true))
     906             :         throw(AipsError("Cannot save model into MS"));
     907             :       else if ((Table::isReadable(subName) && Table::canDeleteTable(subName, true)))
     908             :         Table::deleteTable(subName, true);
     909             :       TableDesc td1 ("td1", TableDesc::New);
     910             :       //td1.addColumn (ArrayColumnDesc<Int> ("SPECTRAL_WINDOW_ID"));
     911             :       //td1.addColumn(ScalarColumnDesc<TableRecord>("MODEL"));
     912             :       SetupNewTable newtab1 (subName, td1, Table::New);
     913             :       Table tab1 (newtab1);
     914             :       newTab.rwKeywordSet().defineTable(elkey, tab1);
     915             :       tab1.rwKeywordSet().defineRecord(elkey, outRec);
     916             :       */
     917             :       //ArrayColumn<Int> spwCol(tab1, "SPECTRAL_WINDOW_ID");
     918             :       //ScalarColumn<TableRecord> modCol(tab1, "MODEL");
     919             :       //newTab.addRow(1,false);
     920             :       //spwCol.put(0,spws);
     921             :       //modCol.put(0,outRec);
     922             :       //newTab.flush();
     923             :     // MSSource& mss=newTab.source();
     924             :     //  cerr << "has model_source " << mss.isColumn(MSSource::SOURCE_MODEL) << endl;
     925             :     //  if(!mss.isColumn(MSSource::SOURCE_MODEL) ){
     926             :     //mss.addColumn(ScalarRecordColumnDesc("SOURCE_MODEL"), true);
     927             :     //  }
     928             :     //  MSSourceColumns srcCol(mss);
     929             :     //  srcCol.sourceModel().put(0, outRec);
     930           0 :     newTab.unlock();
     931           0 :     if(Table::isReadable(newTab.sourceTableName())){
     932           0 :       newTab.source().unlock();   
     933             :     }
     934             :   }
     935           0 :   catch(...){
     936           0 :     logio << "Could not save virtual model data column due to an artificial virtual model size limit. \nYou may need to use the scratch column if you need model visibilities" << LogIO::WARN << LogIO::POST ;
     937           0 :    const_cast<MeasurementSet& >(thems).unlock(); 
     938             :   }
     939             : 
     940           0 : }
     941           0 :   void VisModelData::putModel(const MeasurementSet& thems,const RecordInterface& rec, const Matrix<Int>& indexComb, const Matrix<Int>& chanSel,Bool iscomponentlist, Bool incremental){
     942           0 :     LogIO logio;
     943             :     
     944             :     try{
     945             :       //A field can have multiple FTmachines and ComponentList associated with it 
     946             :       //For example having many flanking images for the model
     947             :       //For componentlist it may have multiple componentlist ...for different spw
     948             :       //Timer tim;
     949             :       //tim.mark();
     950           0 :       Int counter=0;
     951           0 :       Record modrec;
     952           0 :       modrec.define("version", Int(2));
     953           0 :       Vector<Int> validfieldids;
     954           0 :       validfieldids=indexComb.column(0);
     955           0 :       Int nfields=GenSort<Int>::sort (validfieldids, Sort::Ascending, 
     956           0 :                                       Sort::QuickSort|Sort::NoDuplicates);
     957           0 :       validfieldids.resize(nfields, True);
     958           0 :       modrec.define("indexcombination", indexComb);
     959             :       //cerr << "modrec after indexcombination " << modrec << endl;
     960           0 :       modrec.define("channelselection", chanSel);
     961           0 :       modrec.defineRecord("container", rec);
     962           0 :       String elkey="model";
     963           0 :       for (uInt k=0; k < validfieldids.nelements();  ++k){
     964           0 :         elkey=elkey+"_"+String::toString(validfieldids[k]);
     965             :       }
     966           0 :       TableRecord outRec; 
     967           0 :       Bool addtorec=false;
     968           0 :       MeasurementSet& newTab=const_cast<MeasurementSet& >(thems);
     969           0 :       newTab.lock(True);
     970           0 :       if(Table::isReadable(newTab.sourceTableName())){
     971           0 :         newTab.source().lock(True);   
     972             :       }
     973             :       //cerr << elkey << " incr " << incremental << endl;
     974           0 :       if(isModelDefined(elkey, newTab)){ 
     975           0 :         getModelRecord(elkey, outRec, thems);
     976             :         //if incremental no need to check & remove what is in the record
     977           0 :         if(!incremental)
     978           0 :           addtorec=addToRec(outRec, indexComb);
     979             :         //cerr << "addToRec " << addtorec << endl;
     980             :       }
     981             :       else{
     982             :         ///////even if it is not defined some other field model might be sitting on that
     983             :         //////model key
     984           0 :         Int hasSourceRecord=firstSourceRowRecord(validfieldids[0], thems, outRec);
     985           0 :         if(hasSourceRecord > -1 && outRec.nfields() > 0)
     986           0 :           addtorec=true;
     987             :         //cerr << "has Source " << hasSourceRecord << " addToRec " << addtorec << endl;
     988             :         ////
     989             :       }
     990           0 :       if(outRec.nfields() >0 && ((!outRec.isDefined("version")) || (outRec.asInt("version") !=2)))
     991           0 :         throw(AipsError("cannot combine with older version virtual model column;\n please clear it before proceeding"));
     992           0 :       outRec.define("version", Int(2));
     993           0 :       incremental=incremental || addtorec;
     994           0 :       if(iscomponentlist){
     995           0 :         modrec.define("type", "componentlist");
     996           0 :         if(outRec.isDefined("numcl"))
     997           0 :           counter=incremental ? outRec.asInt("numcl") : 0;
     998             :         
     999             :       }
    1000             :       else{
    1001           0 :         modrec.define("type", "ftmachine");
    1002           0 :         if(outRec.isDefined("numft"))
    1003           0 :           counter=incremental ? outRec.asInt("numft") : 0;
    1004             :       }
    1005           0 :       iscomponentlist ? outRec.define("numcl", counter+1) : outRec.define("numft", counter+1); 
    1006             :       
    1007             :       //for (uInt k=0; k < validfieldids.nelements();  ++k){
    1008             :       //  newTab.rwKeywordSet().define("definedmodel_field_"+String::toString(validfieldids[k]), elkey);
    1009             :       
    1010             :       // }
    1011           0 :       iscomponentlist ? outRec.defineRecord("cl_"+String::toString(counter), modrec):
    1012           0 :         outRec.defineRecord("ft_"+String::toString(counter), modrec);
    1013             :       //////////////////;
    1014             :       //for (uInt k=0; k < newTab.rwKeywordSet().nfields() ; ++k){
    1015             :       //  cerr << "keys " << k << "  is  " << newTab.rwKeywordSet().name(k) << " type " << newTab.rwKeywordSet().dataType(k) << endl;
    1016             :       //}
    1017             :       ////////////////////////
    1018             :       //if image for a given key is on disk and not incrementing ...lets remove it
    1019           0 :       if(!incremental) 
    1020           0 :         deleteDiskImage(newTab, elkey);
    1021           0 :       putModelRecord(validfieldids, outRec, newTab);  
    1022           0 :       newTab.unlock();
    1023           0 :       if(Table::isReadable(newTab.sourceTableName())){
    1024           0 :         newTab.source().unlock();   
    1025             :     }
    1026             :     }
    1027           0 :     catch(...){
    1028           0 :       logio << "Could not save virtual model data for some reason \nYou may need clear the model and redo or  use the scratch column if you need model visibilities" << LogIO::WARN << LogIO::POST ;
    1029           0 :       const_cast<MeasurementSet& >(thems).unlock(); 
    1030             :     }
    1031             :     
    1032           0 :   }
    1033             : 
    1034           0 :   void VisModelData::modifyDiskImagePath(Record& rec, const VisBuffer2& vb){
    1035           0 :   Record& ftmac= rec.rwSubRecord("container");
    1036           0 :   if(ftmac.isDefined("diskimage")){
    1037           0 :     String theDiskImage=ftmac.asString("diskimage");
    1038           0 :     if(File(theDiskImage).exists())
    1039           0 :       return;
    1040           0 :     String subPathname[30];
    1041           0 :     String sep = "/";
    1042           0 :     uInt nw = split(theDiskImage, subPathname, 20, sep);
    1043           0 :     String theposs=(subPathname[nw-1]);
    1044             :     ///String msname=vb.msName(false);
    1045             :     ///As the above does not work ..returns some bogus reference table
    1046           0 :     String msname=(vb.ms()).antenna().tableName();
    1047           0 :     msname.erase(msname.length()-8);
    1048           0 :     for (uInt i=nw-2 ; i>0; --i){ 
    1049           0 :       if(File(msname+"/"+theposs).exists()){
    1050           0 :                 theDiskImage=msname+"/"+theposs;
    1051           0 :                 ftmac.define("diskmage", theDiskImage);
    1052           0 :                 return;
    1053             :       }
    1054           0 :       theposs=subPathname[i]+"/"+theposs;
    1055             :     }
    1056             :   }
    1057             : }
    1058             : 
    1059             : 
    1060             : 
    1061           0 :   void VisModelData::addModel(const RecordInterface& rec,  const Vector<Int>& /*msids*/, const VisBuffer2& vb){
    1062             :     
    1063             : 
    1064             : 
    1065           0 :     Int indexft=-1;
    1066           0 :     if(rec.isDefined("numft")){
    1067           0 :       Int numft=rec.asInt("numft");
    1068           0 :       if(numft >0){
    1069           0 :         for(Int ftk=0; ftk < numft; ++ftk){
    1070           0 :           Record ftrec(rec.asRecord("ft_"+String::toString(ftk)));
    1071           0 :           modifyDiskImagePath(ftrec, vb);
    1072           0 :           Vector<Int>fields;
    1073           0 :           Vector<Int> spws;
    1074           0 :           ftrec.get("fields", fields);
    1075           0 :           ftrec.get("spws", spws);
    1076           0 :           if(anyEQ(spws, vb.spectralWindows()(0))){
    1077           0 :             indexft=ftholder_p.nelements();
    1078           0 :             ftholder_p.resize(indexft+1, false, true);
    1079           0 :             ftholder_p[indexft].resize(1);
    1080           0 :             ftholder_p[indexft][0]=NEW_FT(ftrec.asRecord("container"));
    1081           0 :             if(!(ftholder_p[indexft][0]))
    1082           0 :               throw(AipsError("Unknown FTMachine saved in virtual model"));
    1083           0 :             ftholder_p[indexft][0]->initMaps(vb);
    1084             :             
    1085           0 :             for( uInt fi=0; fi < fields.nelements(); ++fi){
    1086           0 :               for(uInt spi=0; spi < spws.nelements(); ++spi){
    1087           0 :                 Int indx=-1;
    1088           0 :                 Int ftindx=-1;
    1089           0 :                 if(hasModel(vb.msId(), fields[fi], spws[spi]) && (ftindex_p(spws[spi], fields[fi], vb.msId()) >= 0 )){
    1090             :                  
    1091           0 :                   indx=ftindex_p(spws[spi], fields[fi], vb.msId());
    1092           0 :                   ftindx=ftholder_p[indx].nelements();
    1093           0 :                   Bool alreadyAdded=false;
    1094           0 :                   for (Int kk=1; kk < ftindx; ++kk){
    1095           0 :                     alreadyAdded= alreadyAdded || (ftholder_p[indexft][0]==ftholder_p[indx][kk]);
    1096             :                   }
    1097           0 :                   if(!alreadyAdded){
    1098           0 :                     ftholder_p[indx].resize(ftindx+1, true);
    1099           0 :                     ftholder_p[indx][ftindx]=ftholder_p[indexft][0];
    1100             :                   }
    1101             :                 }
    1102             :                 else{
    1103           0 :                   ftindex_p(spws[spi], fields[fi], vb.msId())=indexft;
    1104             :                 }
    1105             :               }
    1106             :             }
    1107             :           }
    1108             :           else{
    1109           0 :             if(hasModel(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0)) < 0)
    1110           0 :               ftindex_p(vb.spectralWindows()(0), vb.fieldId()(0), vb.msId())=-2;
    1111             :           }
    1112             : 
    1113             :           
    1114             :         }
    1115             :       }       
    1116             :     }
    1117           0 :     Int indexcl=-1;
    1118           0 :     if(rec.isDefined("numcl")){
    1119           0 :       Int numcl=rec.asInt("numcl");
    1120           0 :       if(numcl >0){
    1121           0 :         for(Int clk=0; clk < numcl; ++clk){
    1122           0 :           Vector<Int>fields;
    1123           0 :           Vector<Int> spws;
    1124           0 :           Record clrec(rec.asRecord("cl_"+String::toString(clk)));
    1125           0 :           clrec.get("fields", fields);
    1126           0 :           clrec.get("spws", spws);
    1127           0 :           if(anyEQ(spws, vb.spectralWindows()(0))){
    1128           0 :             indexcl=clholder_p.nelements();
    1129           0 :             clholder_p.resize(indexcl+1, false, true);
    1130           0 :             clholder_p[indexcl].resize(1);
    1131           0 :             clholder_p[indexcl][0]=new ComponentList();
    1132           0 :             String err;
    1133           0 :             if(!((clholder_p[indexcl][0])->fromRecord(err, clrec.asRecord("container"))))
    1134           0 :               throw(AipsError("Component model failed to load for field "+String::toString(fields)));
    1135           0 :             for( uInt fi=0; fi < fields.nelements(); ++fi){
    1136           0 :               for(uInt spi=0; spi < spws.nelements(); ++spi){
    1137           0 :                 Int indx=-1;
    1138           0 :                 Int clindx=-1;
    1139           0 :                 if(hasModel(vb.msId(), fields[fi], spws[spi]) && (clindex_p(spws[spi], fields[fi], vb.msId()) >= 0 )){
    1140           0 :                   indx=clindex_p(spws[spi], fields[fi], vb.msId());
    1141           0 :                   clindx=clholder_p[indx].nelements();
    1142           0 :                   Bool alreadyAdded=false;
    1143           0 :                   for (Int kk=1; kk < clindx; ++kk){
    1144           0 :                     alreadyAdded= alreadyAdded || (clholder_p[indexcl][0]==clholder_p[indx][kk]);
    1145             :                   } 
    1146           0 :                   if(!alreadyAdded){
    1147           0 :                     clholder_p[indx].resize(clindx+1, true);
    1148           0 :                     clholder_p[indx][clindx]=clholder_p[indexcl][0];
    1149             :                   }
    1150             :                 }
    1151             :                 else{
    1152             :                   //              cerr << "spws, field, msid " << spws[spi] << " " << fields[fi] << " " <<  vb.msId() << " index " << indexcl << endl;
    1153           0 :                   clindex_p(spws[spi], fields[fi], vb.msId())=indexcl;
    1154             :                 }
    1155             :               }
    1156             :             }
    1157             :           }
    1158             :           else{
    1159           0 :             if(hasModel(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0)) < 0)
    1160           0 :               clindex_p(vb.spectralWindows()(0), vb.fieldId()(0), vb.msId())=-2;
    1161             :           }
    1162             : 
    1163             :         }
    1164             :       }
    1165             :     }
    1166             : 
    1167             : 
    1168           0 :   }
    1169             : 
    1170           0 :   FTMachine* VisModelData::NEW_FT(const Record& ftrec){
    1171           0 :     String name=ftrec.asString("name");
    1172           0 :     if(name=="GridFT")
    1173           0 :       return new GridFT(ftrec);
    1174             :     //if(name=="rGridFT")
    1175             :     //  return new rGridFT(ftrec);
    1176           0 :     if(name=="WProjectFT")
    1177           0 :       return new WProjectFT(ftrec);
    1178             :     //if(name=="MultiTermFT")
    1179             :     //  return new MultiTermFT(ftrec);
    1180           0 :     if(name=="MosaicFT")
    1181           0 :       return new MosaicFT(ftrec);
    1182           0 :     if(name=="MosaicFTNew")
    1183           0 :       return new MosaicFTNew(ftrec);
    1184           0 :     if(name=="SetJyGridFT")
    1185           0 :       return new SetJyGridFT(ftrec);
    1186           0 :     if(name=="MultiTermFTNew")
    1187           0 :       return new MultiTermFTNew(ftrec);
    1188             :     //When the following have constructors from Record they should be uncommented
    1189             :     //   if(name=="AWProjectFT")
    1190             :     //  return new AWProjectFT(ftrec);
    1191             :     //if(name=="AWProjectWBFT")
    1192             :     //  return new  AWProjectWBFT(ftrec);
    1193             :     //if(name=="MultiTermAWProjectWBFT")
    1194             :     //  return new MultiTermAWProjectWBFT(ftrec);
    1195           0 :     return NULL;
    1196             :   }
    1197             : 
    1198      786954 :   Int VisModelData::hasModel(Int msid, Int field, Int spw){
    1199             : 
    1200     1573908 :     IPosition oldcubeShape=ftindex_p.shape();
    1201      786954 :     if(oldcubeShape(0) <(spw+1) || oldcubeShape(1) < (field+1) || oldcubeShape(2) < (msid+1)){
    1202        1076 :       Cube<Int> newind(max((spw+1), oldcubeShape(0)), max((field+1),oldcubeShape(1)) , max((msid+1), oldcubeShape(2)));
    1203         538 :       newind.set(-1);
    1204         538 :       newind(IPosition(3, 0,0,0), (oldcubeShape-1))=ftindex_p;
    1205         538 :       ftindex_p.assign(newind);
    1206         538 :       newind.set(-1);
    1207         538 :       newind(IPosition(3, 0,0,0), (oldcubeShape-1))=clindex_p;
    1208         538 :       clindex_p.assign(newind);
    1209             :     }
    1210             : 
    1211      786954 :     if( (clindex_p(spw, field, msid) + ftindex_p(spw, field, msid)) < -2)
    1212           0 :       return -2;
    1213      786954 :     else if( (clindex_p(spw, field, msid) ==-1)  &&  (ftindex_p(spw, field, msid) ==-1))
    1214      786954 :       return -1;
    1215           0 :     return 1;
    1216             : 
    1217             : 
    1218             :   }
    1219             : 
    1220           0 :    void VisModelData::initializeToVis(){
    1221             :     
    1222             : 
    1223           0 :   }
    1224             : 
    1225             : 
    1226             : 
    1227      262586 :   void VisModelData::getMatchingMachines(Vector<CountedPtr<FTMachine> >& ft, Vector<CountedPtr<ComponentList> >& cl, const vi::VisBuffer2& vb){
    1228      262586 :     if(isVersion2()){
    1229         536 :       Vector<Vector<Int> > combindx;
    1230         268 :       getUniqueIndicesComb(vb, combindx);
    1231         268 :       if(combindx.nelements() != 1)
    1232           0 :         throw(AipsError("Cannot deal with multiple intent per visbuffer "));
    1233         536 :       std::vector<Int> indexInBuf=combindx[0].tovector();
    1234         268 :       indexInBuf.push_back(vb.msId());
    1235         268 :       auto itFTMap = ftindex2_p.find(indexInBuf);
    1236         268 :       if(itFTMap != ftindex2_p.end() ) {
    1237         241 :         if((itFTMap->second) < 0){
    1238         241 :           ft.resize(0);
    1239             :         }
    1240             :         else{
    1241           0 :           ft=ftholder_p[itFTMap->second];
    1242             :                   }
    1243             :       }
    1244         268 :       auto itCLMap = clindex2_p.find(indexInBuf);
    1245         268 :       if(itCLMap != clindex2_p.end() ) {
    1246         244 :         if((itCLMap->second)< 0){
    1247         192 :           cl.resize(0);
    1248             :         }
    1249             :         else{
    1250             :           //cerr << "matching " << Vector<Int>(itCLMap->first) << "   " <<  itCLMap->second << endl;
    1251          52 :                         cl=clholder_p[itCLMap->second];
    1252             :                         //              cerr << "returned length  " << cl.nelements() << endl;
    1253             :         }
    1254             :       }
    1255             :       ///Now let's deal with a key that has not been visited before
    1256         268 :       if((itCLMap == clindex2_p.end()) && (itFTMap == ftindex2_p.end() )){
    1257             :         //cerr << "no matching holder " <<  Vector<Int>(indexInBuf) << " num of cl " << clholder_p.nelements() << endl;
    1258          24 :                   updateHolders(vb, indexInBuf);
    1259          24 :                   getMatchingMachines(ft, cl, vb);
    1260             :                   
    1261             :       }
    1262             :     }
    1263             :     else{
    1264      262318 :       cl=getCL(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0));
    1265      262318 :       ft=getFT(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0));
    1266             :     }
    1267      262586 :     return;
    1268             :           
    1269             :   }
    1270      262347 :   void VisModelData::updateHolders(const vi::VisBuffer2& vb, const std::vector<Int>& indexInBuf){
    1271      262347 :           Int fieldId=vb.fieldId()[0];
    1272      262347 :           const MeasurementSet& thems= vb.ms();
    1273      262347 :           Int snum=-1;
    1274      262347 :           Bool hasmodkey=False;
    1275      262347 :           String modelkey;
    1276             :           //cerr <<"IndexInBuf " << Vector<Int>(indexInBuf) << " nelem " << ftindex2_p.size() << "   " << clindex2_p.size() << endl; 
    1277      262347 :           hasmodkey=isModelDefined(fieldId, thems, modelkey, snum);
    1278      262347 :           if(!hasmodkey){
    1279             :             //cerr << "NOHAS KEY fieldId " << fieldId << endl;
    1280      262342 :                   clindex2_p[indexInBuf]=-1;
    1281      262342 :                   ftindex2_p[indexInBuf]=-1;
    1282      262342 :                   return;
    1283             :           }
    1284             :           //if we have already filled for this field
    1285           5 :          for (auto it=ftindex2_p.begin(); it != ftindex2_p.end(); ++it){
    1286             :             //  cerr << Vector<Int>(it->first) << "   val " << it->second << endl;
    1287           0 :            if((it->first)[0]==fieldId){
    1288           0 :              clindex2_p[indexInBuf]=-2;
    1289           0 :              ftindex2_p[indexInBuf]=-2;
    1290           0 :              return;
    1291             :            }
    1292             :              
    1293             :          } 
    1294             :           //We do have this key
    1295           5 :           TableRecord therec;
    1296           5 :           getModelRecord(modelkey, therec, thems);
    1297           5 :           if(!therec.isDefined("version") || (therec.asInt("version")!=2)){
    1298             :                 ///Set something versioning so as it can go to do version 1 way 
    1299           0 :                 version_p=1;
    1300           0 :                 clindex2_p[indexInBuf]=-1;
    1301           0 :                 ftindex2_p[indexInBuf]=-1;
    1302           0 :                 return;
    1303             :           }
    1304             :           else{
    1305           5 :             version_p=2;
    1306           5 :             Int indexft=-1;
    1307           5 :             if(therec.isDefined("numft")){
    1308           0 :               Int numft=therec.asInt("numft");
    1309           0 :               if(numft >0){
    1310           0 :                 for(Int ftk=0; ftk < numft; ++ftk){
    1311           0 :                   Record ftrec(therec.asRecord("ft_"+String::toString(ftk)));
    1312           0 :                   modifyDiskImagePath(ftrec, vb);
    1313           0 :                   const Matrix<Int>& ftcombind=ftrec.asArrayInt("indexcombination");
    1314             :                   //cerr << " ftcombind " << ftcombind << endl;
    1315           0 :                   indexft=ftholder_p.nelements();
    1316           0 :                   ftholder_p.resize(indexft+1, false, true);
    1317           0 :                   ftholder_p[indexft].resize(1);
    1318           0 :                   ftholder_p[indexft][0]=NEW_FT(ftrec.asRecord("container"));
    1319           0 :                   if(!( ftholder_p[indexft][0]))
    1320           0 :                     throw(AipsError("Unsupported FTMachine found in virtual MODEL_DATA column")); 
    1321           0 :                   ftholder_p[indexft][0]->initMaps(vb);
    1322           0 :                   for(uInt row=0; row < ftcombind.nrow(); ++row){
    1323           0 :                     std::vector<int> key=ftcombind.row(row).tovector();
    1324           0 :                     key.push_back(int(vb.msId()));
    1325             :                     
    1326           0 :                     if(ftindex2_p.count(key) >0){
    1327           0 :                       Int numftforkey=ftholder_p[ftindex2_p[key]].nelements();
    1328           0 :                       Int indx=ftindex2_p[key];
    1329           0 :                       Bool alreadyAdded=false;
    1330           0 :                       for (Int kk=1; kk < numftforkey; ++kk){
    1331           0 :                         alreadyAdded= alreadyAdded || (ftholder_p[indexft][0]==ftholder_p[indx][kk]);
    1332             :                       }
    1333           0 :                       if(!alreadyAdded){
    1334           0 :                         ftholder_p[indx].resize(numftforkey+1, true);
    1335           0 :                         ftholder_p[indx][numftforkey]=ftholder_p[indexft][0];
    1336             :                       }
    1337             :                     }
    1338             :                     else{
    1339           0 :                       ftindex2_p[key]=indexft;
    1340             :                     }
    1341             :                   }
    1342             :                   
    1343             :                 }
    1344             :               }
    1345             :             }
    1346           5 :             if(ftindex2_p.count(indexInBuf)==0)
    1347           5 :               ftindex2_p[indexInBuf]=-2;
    1348           5 :             Int indexcl=-1;
    1349             :             ////////////
    1350             :             //cerr <<"map " << endl;
    1351             :             //for (auto it=clindex2_p.begin(); it != clindex2_p.end(); ++it){
    1352             :             // cerr << Vector<Int>(it->first) << "   val " << it->second << endl;
    1353             : 
    1354             :             //}
    1355             :             ///////////
    1356           5 :             if(therec.isDefined("numcl")){
    1357           5 :                   Int numcl=therec.asInt("numcl");
    1358             :                   //cerr << "numcl " << numcl << endl;
    1359           5 :                   if(numcl >0){
    1360          25 :                     for(Int clk=0; clk < numcl; ++clk){
    1361             :           
    1362          60 :                       Record clrec(therec.asRecord("cl_"+String::toString(clk)));
    1363          40 :                       const Matrix<Int>& clcombind=clrec.asArrayInt("indexcombination");
    1364             :                       
    1365             :                       
    1366          20 :                       indexcl=clholder_p.nelements();
    1367          20 :                       clholder_p.resize(indexcl+1, false, true);
    1368          20 :                       clholder_p[indexcl].resize(1);
    1369          20 :                       clholder_p[indexcl][0]=new ComponentList();
    1370          40 :                       String err;
    1371          20 :                       if(!((clholder_p[indexcl][0])->fromRecord(err, clrec.asRecord("container"))))
    1372           0 :                         throw(AipsError("Component model failed to load for field "+String::toString(clcombind.column(0))));
    1373          56 :                       for(uInt row=0; row < clcombind.nrow(); ++row){
    1374          72 :                         std::vector<int> key=clcombind.row(row).tovector();
    1375             :                         
    1376          36 :                         key.push_back(int(vb.msId()));
    1377             :                         //cerr << "key " <<  Vector<Int>(key) << endl;
    1378          36 :                         if(clindex2_p.count(key) >0){
    1379           0 :                           Int numclforkey=clholder_p[clindex2_p[key]].nelements();
    1380           0 :                           Int indx=clindex2_p[key];
    1381           0 :                           Bool alreadyAdded=false;
    1382           0 :                           for (Int kk=1; kk < numclforkey; ++kk){
    1383           0 :                             alreadyAdded= alreadyAdded || (clholder_p[indexcl][0]==clholder_p[indx][kk]);
    1384             :                           }
    1385           0 :                           if(!alreadyAdded){
    1386           0 :                             clholder_p[indx].resize(numclforkey+1, true);
    1387           0 :                             clholder_p[indx][numclforkey]=clholder_p[indexcl][0];
    1388             :                           }
    1389             :                         }
    1390             :                         else{
    1391          36 :                           clindex2_p[key]=indexcl;
    1392             :                         }
    1393             :                       }
    1394             :                 
    1395             :                     }
    1396             :                   }
    1397             :                 }
    1398           5 :                 if(clindex2_p.count(indexInBuf)==0)
    1399           0 :                   clindex2_p[indexInBuf]=-2;
    1400             :           }
    1401             :           //cerr <<"update holder " << clholder_p.nelements() << endl; 
    1402             :          
    1403             :           
    1404             :   }
    1405         268 :   void VisModelData::getUniqueIndicesComb(const vi::VisBuffer2& vb, Vector< Vector<Int> >& retval){
    1406         268 :            const Vector<Int>& state = vb.stateId();
    1407         268 :            const Vector<Int>& scan=vb.scan();
    1408         268 :            const Vector<Double>& t=vb.time();
    1409         268 :            const Vector<Int>& fldid=vb.fieldId();
    1410         268 :            const Vector<Int>& spwid=vb.spectralWindows();
    1411         536 :            Vector<uInt>  uniqIndx;
    1412         268 :            uInt nTimes=GenSortIndirect<Double>::sort (uniqIndx, t, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates);
    1413         536 :            Vector<Int> comb(4);
    1414             :            
    1415         890 :            for (uInt k=0; k < nTimes; ++k){
    1416         622 :              comb(0)=fldid(uniqIndx[k]);
    1417         622 :              comb(1)=spwid(uniqIndx[k]);
    1418         622 :              comb(2)=scan(uniqIndx[k]);
    1419         622 :              comb(3)=state(uniqIndx[k]);
    1420         622 :              Bool hasComb=False;
    1421         622 :              if(retval.nelements() >0){
    1422         708 :                for (uInt j=0; j < retval.nelements(); ++j){
    1423         354 :                  if(allEQ(retval[j], comb))
    1424         354 :                    hasComb=True;
    1425             :                }
    1426             :                                    
    1427             :              }
    1428         622 :              if(!hasComb){
    1429         268 :                retval.resize(retval.nelements()+1, True);
    1430         268 :                retval[retval.nelements()-1]=comb;
    1431             :              }
    1432             :            }
    1433             :            
    1434         268 :   }
    1435             : 
    1436      262562 :   void VisModelData::init(const VisBuffer2& vb){
    1437      262562 :     if(version_p < 1){
    1438      262323 :       updateHolders(vb, std::vector<Int>({vb.fieldId()(0), vb.spectralWindows()(0), vb.scan()(0), vb.stateId()(0), vb.msId()}));
    1439             : 
    1440             :     }
    1441             : 
    1442      262562 :   }
    1443             :   
    1444             :   
    1445      262562 :   Bool VisModelData::getModelVis(VisBuffer2& vb){
    1446             : 
    1447             :     //Vector<CountedPtr<ComponentList> >cl=getCL(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0));
    1448             :     //Vector<CountedPtr<FTMachine> > ft=getFT(vb.msId(), vb.fieldId()(0), vb.spectralWindows()(0));
    1449      525124 :     Vector<CountedPtr<ComponentList> >cl(0);
    1450      525124 :     Vector<CountedPtr<FTMachine> > ft(0);
    1451      262562 :     getMatchingMachines(ft, cl, vb);
    1452             :     //Fill the buffer with 0.0; also prevents reading from disk if MODEL_DATA exists
    1453             :     ///Oh boy this is really dangerous...
    1454             :     //nCorr etc are public..who know who changed these values before reaching here.
    1455      262562 :     Cube<Complex> mod(vb.nCorrelations(), vb.nChannels(), vb.nRows(), Complex(0.0));
    1456      262562 :     vb.setVisCubeModel(mod);
    1457      262562 :     Bool incremental=false;
    1458             :     //cerr << "CL nelements visbuff " << cl.nelements() << endl;
    1459      262562 :     if( cl.nelements()>0){
    1460             :       //     cerr << "In cft " << cl.nelements() << endl;
    1461         104 :       for (uInt k=0; k < cl.nelements(); ++k)
    1462          52 :         if(!cl[k].null()){
    1463          52 :           cft_p->get(vb, *(cl[k]), -1); 
    1464             :           //cerr << "max " << max(vb.visCubeModel()) << endl;
    1465             :           //cout << "max " << max(vb.visCubeModel()) << endl;
    1466          52 :           incremental=true;
    1467             :         }
    1468             :     }
    1469      262562 :     if(ft.nelements()>0){
    1470           0 :       Cube<Complex> tmpModel;
    1471           0 :       if(incremental || ft.nelements() >1)
    1472           0 :         tmpModel.assign(vb.visCubeModel());
    1473           0 :       Bool allnull=true;
    1474           0 :       for (uInt k=0; k < ft.nelements(); ++k){
    1475           0 :         if(!ft[k].null()){
    1476           0 :           if(k >0) vb.setVisCubeModel(Cube<Complex> (vb.nCorrelations(), vb.nChannels(), vb.nRows(), Complex(0.0)));
    1477             :     
    1478           0 :           ft[k]->get(vb, -1);
    1479           0 :           if(ft.nelements()>1 || incremental){
    1480           0 :             tmpModel+=vb.visCubeModel();
    1481             :           }
    1482           0 :           allnull=false;
    1483             :         }
    1484             :       }
    1485             :       //cerr << "min max after ft " << min(vb.visCubeModel()) << max(vb.visCubeModel()) << endl;
    1486           0 :       if(!allnull){
    1487           0 :         if(ft.nelements()>1 || incremental)
    1488           0 :           vb.setVisCubeModel(tmpModel);
    1489           0 :         incremental=true;
    1490             :       }      
    1491             :     }
    1492      262562 :     if(!incremental){
    1493             :       //No model was set so....
    1494             :       ///Set the Model to 1.0 for parallel hand and 0.0 for x-hand
    1495             :       
    1496      262510 :       vb.setVisCubeModel(Complex(1.0));
    1497      525020 :       Cube<Complex> modelCube(vb.visCubeModel());
    1498      525020 :       Vector<Stokes::StokesTypes> corrType=vb.getCorrelationTypesSelected();
    1499      262510 :       uInt nCorr = corrType.nelements();
    1500     1269980 :       for (uInt i=0; i<nCorr; i++) {
    1501     1985288 :           if(corrType[i]==Stokes::RL || corrType[i]==Stokes::LR ||
    1502     1985288 :              corrType[i]==Stokes::XY || corrType[i]==Stokes::YX){
    1503      489780 :                   modelCube.yzPlane(i)=0.0;
    1504             :           }
    1505             :       }
    1506             :     }
    1507             :     
    1508      525124 :     return true;
    1509             :     
    1510             :   }
    1511             : 
    1512             : 
    1513      262318 :   Vector<CountedPtr<ComponentList> > VisModelData::getCL(const Int msId, const Int fieldId, const Int spwId){
    1514      262318 :     if(!hasModel(msId, fieldId, spwId))
    1515           0 :       return Vector<CountedPtr<ComponentList> >(0);
    1516      262318 :     Int indx=clindex_p(spwId, fieldId, msId);
    1517             :     //  cerr << "indx " << indx << "   " << clholder_p[indx].nelements() <<  " spw " << spwId << " field " << fieldId << endl;
    1518      262318 :     if(indx <0)
    1519      262318 :       return Vector<CountedPtr<ComponentList> >(0);
    1520             :     // cerr << "CL " << clholder_p[indx][0]->summarize(0) << endl;
    1521           0 :     return clholder_p[indx];
    1522             :         
    1523             : 
    1524             :   }
    1525             : 
    1526      262318 :   Vector<CountedPtr<FTMachine> >VisModelData::getFT(const Int msId, const Int fieldId, Int spwId){
    1527             : 
    1528      262318 :     if(!hasModel(msId, fieldId, spwId))
    1529           0 :       return Vector<CountedPtr<FTMachine> >(0);
    1530      262318 :     Int indx=ftindex_p(spwId, fieldId, msId);
    1531             :     //cerr << "indx " << indx << endl;
    1532      262318 :     if(indx <0)
    1533      262318 :       return Vector<CountedPtr<FTMachine> >(0);
    1534           0 :     return ftholder_p[indx];
    1535             :   }
    1536             : 
    1537           0 :   Int VisModelData::firstSourceRowRecord(const Int field, const MeasurementSet& theMS, TableRecord& rec){
    1538           0 :     Int row=-1;
    1539             :     
    1540             :     //Prefer the Source table first    
    1541           0 :     MSFieldColumns fCol(theMS.field());
    1542           0 :     if(Table::isReadable(theMS.sourceTableName()) && (theMS.source().nrow() > 0) &&  (!fCol.sourceId().isNull()) && (fCol.sourceId().get(field) != -1) ){
    1543             :     
    1544           0 :       const MSSource& mss=theMS.source();
    1545             :       
    1546           0 :       Int sid=fCol.sourceId().get(field);
    1547           0 :       auto rows=MSSourceIndex(mss).getRowNumbersOfSourceID(sid);
    1548           0 :       if(rows.nelements() > 0) 
    1549           0 :         row=rows[0];
    1550           0 :       const TableRecord& keywords=mss.keywordSet();
    1551           0 :       Bool rowIsUsed=false;
    1552           0 :       for (uInt n=0; n< keywords.nfields(); ++n){
    1553           0 :         if(keywords.dataType(n) == TpInt){
    1554           0 :           if(row==keywords.asInt(n)){
    1555           0 :             rowIsUsed=true;
    1556             :           }
    1557             :         }
    1558             :       }
    1559             :       //nobody is using that row ..any record there must be dangling
    1560           0 :       if(!rowIsUsed)
    1561           0 :         return -1;
    1562           0 :       if(row >-1 && mss.isColumn(MSSource::SOURCE_MODEL)){
    1563           0 :         ScalarColumn<TableRecord> scol(theMS.source(), "SOURCE_MODEL");
    1564           0 :         scol.get(row, rec);
    1565             :       }
    1566             :     }
    1567           0 :     return row;
    1568             :   }
    1569             : 
    1570             : 
    1571             : }// end namespace refim
    1572             : }//# NAMESPACE CASA - END
    1573             : 

Generated by: LCOV version 1.16