/***
 * Framework independent implementation file for imager...
 *
 * Implement the imager component here.
 * 
 * // TODO: WRITE YOUR DESCRIPTION HERE! 
 
 ***/

#include <iostream>
#include <casacore/casa/Exceptions/Error.h>
#include <casacore/casa/BasicSL/String.h>
#include <casacore/casa/Containers/Record.h>
#include <casacore/casa/Utilities/Assert.h>
#include <casacore/ms/MeasurementSets.h>
#include <casacore/ms/MeasurementSets/MSHistoryHandler.h>
#include <casacore/casa/Logging/LogIO.h>

//#include <synthesis/ImagerObjects/TmpSwitch.h>


#include <synthesis/ImagerObjects/SynthesisImager.h>
#include <synthesis/ImagerObjects/SynthesisImagerVi2.h>
#include <synthesis/Parallel/Applicator.h>

#include <synthesis/ImagerObjects/SynthesisUtilMethods.h>

#include <synthesisimager_cmpt.h>

#ifdef USE_HPG
#include <hpg/hpg.hpp>
#endif
using namespace std;
using namespace casacore;
using namespace casa;
namespace casa{
           extern Applicator applicator;
};
     
using namespace casacore;
namespace casac {

  
  // Method used for creating the SynthesisImager object.  By default,
  // this will look at itsImager and decide if a new instance needs to
  // be constructed.  The second argument determines if
  // SynthesisImager (vi2=false) or SynthesisImagerVi2 (vi2=true)
  // should be constructed.
  SynthesisImager* synthesisimager::makeSI(
      bool forceNew, //default value = false
      bool oldvi // default value = false
  )
{
  Bool vi1_l = oldvi;
  vi1_l = (getenv("VI1") != NULL);
  if ((not itsImager) or forceNew) {
    itsImager = (not vi1_l) ?
        new SynthesisImagerVi2()
      : new SynthesisImager();
  }
  return itsImager;
}


  synthesisimager::synthesisimager() 
{
  
  // itsImager = new SynthesisImagerVi2();
  itsLog = new LogIO();
  //itsImager = new SynthesisImager();
  itsImager = makeSI(true);
}

synthesisimager::~synthesisimager()
{
  done();
}



bool
synthesisimager::setdata(const std::string& msname,
			    const std::string& spw,
			    const std::string& freqbeg, // ? why here ? to limit selection with image definition
			    const std::string& freqend, // ? why here ?   ditto
			    const std::string& freqframe, // ? why here ? ditto
			    const std::string& field, 
			    const std::string& antenna,
			    const std::string& timestr,
			    const std::string& scan,
			    const std::string& obs,
			    const std::string& state,
			    const std::string& uvdist,
			    const std::string& taql,
			    const bool usescratch,
			    const bool readonly,
			    const bool incrmodel) {
	Bool rstat=false;
	 try {
	   //if( ! itsImager ) itsImager = new SynthesisImagerVi2();
                 itsImager = makeSI();
		 MFrequency::Types freqtype;
		 MFrequency::getType(freqtype, freqframe);
		 rstat=itsImager->selectData(msname, spw, freqbeg, freqend, freqtype,field, antenna, timestr, scan, obs, state,
				 uvdist, taql, usescratch, readonly, incrmodel );

	 }
	 catch  (AipsError x)
	     {
	       RETHROW(x);
	     }

	   return rstat;
}

bool 
synthesisimager::selectdata(const casac::record& selpars)
{
  Bool rstat(false);
  
  try 
    {

      //if( ! itsImager ) itsImager = new SynthesisImagerVi2();
      itsImager = makeSI();
      const std::unique_ptr<const casacore::Record> recpars(toRecord( selpars ));
      SynthesisParamsSelect pars;
      pars.fromRecord( *recpars );

      itsImager->selectData( pars );

      //      itsImager->selectData( pars.msname, pars.spw, 
      //		     pars.freqbeg, pars.freqend, pars.freqframe,
      //		     pars.field, pars.antenna, pars.timestr, pars.scan, 
      //		     pars.obs, pars.state, pars.uvdist, pars.taql,
      //		     pars.usescratch, pars.readonly, pars.incrmodel );

    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}


::casac::record * synthesisimager::tuneselectdata()
{
  ::casac::record* rstat=NULL;

  try
    {

      if( ! itsImager )
          ThrowCc("You have to run selectdata and defineimage before tuneselectdata");

      casacore::Record outRec;
      Vector<SynthesisParamsSelect> leDataParams;


      leDataParams=itsImager->tuneSelectData();
      for (uInt k=0; k < leDataParams.nelements(); ++k){
    	  outRec.defineRecord(casacore::String("ms")+casacore::String::toString(k), leDataParams[k].toRecord() );

      }
      rstat = fromRecord(outRec);

      //      itsImager->selectData( pars.msname, pars.spw,
      //		     pars.freqbeg, pars.freqend, pars.freqframe,
      //		     pars.field, pars.antenna, pars.timestr, pars.scan,
      //		     pars.obs, pars.state, pars.uvdist, pars.taql,
      //		     pars.usescratch, pars.readonly, pars.incrmodel );

    }
  catch  (AipsError x)
    {
      RETHROW(x);
    }

  return rstat;
}

  variant* synthesisimager::estimatememory(){
    *itsLog << casacore::LogOrigin("synthesisimager", __func__);
    long mem1=0;
    variant * mem_ptr=new variant (mem1);
    try 
    {
      if(!itsImager)
        throw(AipsError("cannot estimate memory without setup"));
      mem1=itsImager->estimateRAM();
      *mem_ptr=variant(mem1);
    } catch  (AipsError x) {
    RETHROW(x);
  }
    return mem_ptr;

  }
bool synthesisimager::defineimage(const casac::record& impars, const casac::record& gridpars)
{
  Bool rstat(false);
  *itsLog << casacore::LogOrigin("synthesisimager", __func__);
  try 
    {
    
    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
    const std::unique_ptr<casacore::Record> irecpars(toRecord( impars ));
    ////Temporary fix till we get the checking for phasecenter in fromRecord 
    ////to deal with this
    //////////////
    String movingSource="";
    if( irecpars->dataType("phasecenter") == TpString ){
      String pcen=irecpars->asString("phasecenter");
      //seems to be a table so assuming ephemerides table 
      //Or A known planet
      //Or special case
      casacore::MDirection::Types refType;
      Bool trackingNearSource= (Table::isReadable(pcen, False))
	|| ( (casacore::MDirection::getType(refType, pcen)) && (refType > casacore::MDirection::N_Types && refType < casacore::MDirection:: N_Planets ))
	|| (pcen==String("TRACKFIELD"));
      if(trackingNearSource){
	*itsLog << "Detected tracking of moving source " <<  casacore::LogIO::POST;
	if(refType > casacore::MDirection::N_Types && refType < casacore::MDirection::COMET){
	  
	  *itsLog << "Will be Using measures internal ephemeris  for  " << casacore::MDirection::showType(refType) << " to track " << casacore::LogIO::POST;
	} 
	movingSource=pcen;
	irecpars->define("phasecenter", "");
      }
      else {
        //extract strings separated by a space
        String tmpref, tmpra, tmpdec;
        std::istringstream iss(pcen);
        iss >> tmpref >> tmpra >> tmpdec;
        // if only a single string extracted assume it is ephemeris object related specification
        if( tmpref.length() != 0 && tmpra.length() == 0 &&  tmpdec.length() == 0 ){
          throw(AipsError("Cannot translate the specified phasecenter, "+pcen+ " as a valid ephemeris table or major solar system object defined or a special case option (in all uppercase), 'TRACKFIELD'"));
        }
      }
      //cerr << "PCEN " << pcen << "  " << irecpars.asString("phasecenter")<< endl;
    }

    SynthesisParamsImage ipars;
    ipars.fromRecord( *irecpars );
    
      
    const std::unique_ptr<const casacore::Record> grecpars (toRecord( gridpars ));
    SynthesisParamsGrid gpars;
    gpars.fromRecord( *grecpars );
    ipars.trackSource=False;
    if(movingSource != casacore::String("")){
      itsImager->setMovingSource(movingSource);
      ipars.trackSource=True;
      ipars.movingSource=movingSource;
      casacore::MDirection::Types refType;
      if((casacore::MDirection::getType(refType, movingSource)) && (refType > casacore::MDirection::N_Types && refType < casacore::MDirection:: N_Planets ))
	ipars.trackDir=casacore::MDirection(refType);
      
    }
    itsImager->defineImage( ipars, gpars );
    

    
    /*
    itsImager->defineImage( ipars.imageName, ipars.imsize[0], ipars.imsize[1], 
			    ipars.cellsize[0], ipars.cellsize[1], ipars.stokes, ipars.phaseCenter,
			    ipars.nchan, ipars.freqStart, ipars.freqStep, ipars.restFreq, ipars.facets, 
			    gpars.ftmachine, ipars.nTaylorTerms, ipars.refFreq, 
			    ipars.projection, gpars.distance, ipars.freqFrame, 
			    gpars.trackSource, gpars.trackDir, ipars.overwrite,
			    gpars.padding, gpars.useAutoCorr, gpars.useDoublePrec, gpars.wprojplanes, 
			    gpars.convFunc, ipars.startModel, gpars.aTermOn,
			    gpars.psTermOn, gpars.mTermOn, gpars.wbAWP, gpars.cfCache,
			    gpars.usePointing,gpars.pointingsigdev,gpars.doPBCorr,gpars.conjBeams,
			    gpars.computePAStep,gpars.rotatePAStep);
    */

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}

  
  bool
  synthesisimager::setimage(const std::string& imagename,
			    const long nx, 
			    const long ny,			
			    const ::casac::variant& cellx, 
			    const ::casac::variant& celly,
			    const std::string& stokes,
			    const ::casac::variant& phasecenter,
			    const long nchan,
			    const ::casac::variant& freqstart,
			    const ::casac::variant& freqstep,
			    const ::casac::variant& restfreq,
			    const long facets,
			    const std::string& ftmachine,
			    const long ntaylorterms,
			    const ::casac::variant& reffreq,
			    const std::string& projection,
			    const ::casac::variant& distance,
			    const std::string& freqframe, 
			    const bool tracksource,
			    const ::casac::variant& trackdir,
			    const bool overwrite,
			    const float padding,
			    const bool useautocorr,
			    const bool usedoubleprec,
			    const long wprojplanes,
			    const std::string& convfunc,
			    const std::string& startmodel,
			    const bool aterm,//    = true,
			    const bool psterm,//   = true,
			    const bool mterm,//    = false,
			    const bool wbawp,//      = true,
			    const std::string& cfcache,//  = "",
			    const bool usepointing,// = false,
			    const ::casac::variant& /* pointingoffsetsigdev*/,//=10.0, //unused!
			    const bool dopbcorr,//   = true,
			    const bool conjbeams,//  = false,
			    const float computepastep,         //=360.0
			    const float rotatepastep          //=5.0
			    )
{
  Bool rstat(false);

  try 
    {

      //if( ! itsImager ) itsImager = new SynthesisImager();   // any more here ?
      itsImager = makeSI();
      // Check nx, ny
      Int nX, nY;
      nX=nx;
      nY=ny;
      if(nY < 1)
	nY=nx;

      // Convert cellx, celly
      casacore::Quantity cellX=casaQuantity(cellx);
      if(cellX.getValue()==0.0)
	cellX=casacore::Quantity(1.0, "arcsec");
      casacore::Quantity cellY;
      if(toCasaString(celly) == String("")){
	cellY=cellX;
      }
      else{
	cellY=casaQuantity(celly);
      }

      // Convert phasecenter ( If it is an integer, it's a field, id, connect to last MS.... )
      casacore::MDirection  phaseCenter;
      //Int fieldid=-1;
      //If phasecenter is a simple numeric value then its taken as a fieldid 
      //otherwise its converted to a MDirection
      if(phasecenter.type()==::casac::variant::DOUBLEVEC 
	 || phasecenter.type()==::casac::variant::DOUBLE
	 || phasecenter.type()==::casac::variant::INTVEC
	 || phasecenter.type()==::casac::variant::INT){
	  //fieldid=phasecenter.toInt();
      }
      else{
	if(toCasaString(phasecenter)==String("")){
	    //fieldid=0;
	}
	else{
	  if(!casaMDirection(phasecenter, phaseCenter)){
	    throw(AipsError("cmpt : Could not interprete phasecenter parameter"));
	  }
	}
      }


      // Convert projection.
      casacore::String projectionStr = toCasaString( projection );
      casacore::Projection imageprojection = Projection::type( projectionStr );

      // Convert distance
      casacore::Quantity cdistance = casaQuantity( distance );

      // Convert trackDir
      casacore::MDirection  trackDir;
      if( toCasaString(trackdir) != casacore::String("")){
	  if(!casaMDirection(trackdir, trackDir)){
	    throw(AipsError("cmpt : Could not interprete trackdir parameter"));
	  }
	}

      //----------------------------------------------------------------------------------------------------------------
      //------------------------------- Frequency Frame Setup : Start ----------------------------------
      //----------------------------------------------------------------------------------------------------------------
      //------ Convert all inputs into LSRK start, step and reference -------------------------
      //----------------------------------------------------------------------------------------------------------------

      // Convert freqstart, freqstep, restfreq - whatever units.
      casacore::Quantity freqStart, freqStep, refFreq;
      freqStart = casaQuantity(freqstart);
      freqStep = casaQuantity(freqstep);
      refFreq = casaQuantity(reffreq);

      // Convert rest-freq
      casacore::Vector<casacore::Quantity> restFreq;
      toCasaVectorQuantity( restfreq, restFreq );

      // Convert freqframe
      casacore::MFrequency::Types freqframetype;
      if( !casacore::MFrequency::getType(freqframetype, freqframe) )
	throw(AipsError("cmpt : Invalid Frequency Frame " + freqframe));

      //----------------------------------------------------------------------------------------------------------------
      //------------------------------- Frequency Frame Setup : End ------------------------------------
      //----------------------------------------------------------------------------------------------------------------


      rstat=itsImager->defineImage( imagename, nX, nY, cellX, cellY, stokes, phaseCenter,
				    nchan, freqStart, freqStep, restFreq, facets, ftmachine, 
				    ntaylorterms, refFreq, 
				    imageprojection, cdistance, freqframetype, tracksource, trackDir, overwrite,
				    padding, useautocorr, usedoubleprec, wprojplanes, convfunc, startmodel, aterm,
				    psterm, mterm,wbawp, cfcache,usepointing,dopbcorr,conjbeams,computepastep,rotatepastep);
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}

bool synthesisimager::normalizerinfo(const casac::record& normpars)
{
  Bool rstat(false);
  *itsLog << casacore::LogOrigin("synthesisimager", __func__);
  try 
    {
    
    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
    const std::unique_ptr<const casacore::Record> normrecpars(toRecord( normpars ));
      
   
    itsImager->normalizerinfo( *normrecpars );
    
    rstat=true;
    
  

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}


bool synthesisimager::setweighting(const std::string& type,
				   const std::string& rmode,
				   const ::casac::variant& noise,
				   const double robust,
				   const ::casac::variant& fieldofview,
				   const long npixels,
				   const bool multifield,
				   const bool usecubebriggs,
				   const std::vector<std::string>& uvtaper
				   /*				   const std::string& filtertype,
				   const ::casac::variant& filterbmaj,
				   const ::casac::variant& filterbmin,
				   const ::casac::variant& filterbpa */
				   )
{
  Bool rstat(false);

  try 
    {

      //if( ! itsImager ) itsImager = new SynthesisImager(); // More here ? Check that defineImage has been called
      itsImager = makeSI();
      casacore::Quantity cnoise = casaQuantity( noise );
      casacore::Quantity cfov = casaQuantity( fieldofview );

      Vector<String> uvtaperpars( toVectorString(uvtaper) );

      casacore::Quantity bmaj(0.0,"deg"), bmin(0.0,"deg"), bpa(0.0,"deg");
      String filtertype("");
      if(uvtaperpars.nelements()>0) bmaj = casaQuantity( uvtaperpars[0] );
      if(uvtaperpars.nelements()>1) bmin = casaQuantity( uvtaperpars[1] );
      if(uvtaperpars.nelements()>2) bpa = casaQuantity( uvtaperpars[2] );
      if(uvtaperpars.nelements()==1) bmin = bmaj;

      if(uvtaperpars.nelements()>0 && uvtaperpars[0].length()>0) filtertype=String("gaussian");

      itsImager->weight( type, rmode, cnoise, robust, cfov, npixels, multifield, usecubebriggs, filtertype, bmaj, bmin, bpa  );

    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}

  bool synthesisimager::makepsf()
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      itsImager->makePSF();
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }


  casac::record* synthesisimager::apparentsens()
  {
    casac::record* rstat(0);
    try{ 

      itsImager = makeSI();
      itsImager->makePSF();
      rstat = fromRecord( itsImager->apparentSensitivity() );

    } catch (AipsError x) { 
      RETHROW(x);
    }
    return rstat;
  }



  bool synthesisimager::drygridding(const std::vector<std::string>& cfList)
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      Vector<String> const cfListV(cfList);
      itsImager->dryGridding(cfListV);
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

  bool synthesisimager::fillcfcache(const std::vector<std::string>& cfList,
				    const std::string& ftmName,
				    const std::string& cfcPath,
				    const bool psTermOn,
				    const bool aTermOn,
				    const bool conjBeams)
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      //Bool conjBeams=itsImager->getSynthesisParamsGrid().conjBeams;
      Vector<String> const cfListV(cfList);
      itsImager->fillCFCache(cfListV,ftmName, cfcPath, psTermOn, aTermOn, conjBeams);
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

  bool synthesisimager::reloadcfcache()
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      itsImager->reloadCFCache();
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

  bool synthesisimager::predictmodel()
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      itsImager->predictModel();
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

bool synthesisimager::executemajorcycle(const casac::record& controls)
{
  Bool rstat(false);

  try {

    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
    const std::unique_ptr<const casacore::Record> recpars(toRecord( controls ));
    itsImager->executeMajorCycle( *recpars );

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}

  bool synthesisimager::makepb()
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      itsImager->makePB();
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

bool synthesisimager::makesdimage()
{
  Bool rstat(false);

  try {

    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
    itsImager->makeSdImage();

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}

bool synthesisimager::makeimage(const std::string& type, const std::string& image,
                       const std::string& compleximage, const long model)
{
  Bool rstat(true);

  try {
    itsImager = makeSI();
    itsImager->makeImage(String(type), String(image), String(compleximage), 
			 model );

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}


bool synthesisimager::makesdpsf()
{
  Bool rstat(false);

  try {

    //if( ! itsImager ) itsImager = new SynthesisImager();
//std::cout << "makesdpdf()<0>" << std::flush << std::endl;
    itsImager = makeSI();
//std::cout << "makesdpdf()<1>" << std::flush << std::endl;
    itsImager->makeSdImage(true);
//std::cout << "makesdpdf()<2>" << std::flush << std::endl;

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}
bool synthesisimager::unlockimages(const long id)
{
  Bool rstat(false);

  try {

    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
    rstat=(itsImager->imageStore(id))->releaseLocks();

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}
synthesisimstore* synthesisimager::getimstore(const long id)
{
  synthesisimstore *rstat;
  try {

    //if( ! itsImager ) itsImager = new SynthesisImager();
    itsImager = makeSI();
      rstat = new synthesisimstore( &*(itsImager->imageStore( id )) );

  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}

std::string synthesisimager::getImageName(const long facetId, const std::string& imageId, long taylorTerm)
{
    std::string rstat = "";
    try {
        itsImager = makeSI();
        CountedPtr<SIImageStore> itsImStore = itsImager->imageStore(facetId);
        if (imageId == "MASK") {
            rstat = itsImStore->mask((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "PSF") {
            rstat = itsImStore->psf((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "MODEL") {
            rstat = itsImStore->model((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "RESIDUAL") {
            rstat = itsImStore->residual((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "WEIGHT") {
            rstat = itsImStore->weight((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "IMAGE") {
            rstat = itsImStore->image((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "SUMWT") {
            rstat = itsImStore->sumwt((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "GRIDWT") {
            throw AipsError("Retrieval of gridwt image name not supported at this time.");
        } else if (imageId == "PB") {
            rstat = itsImStore->pb((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "FORWARDGRID") {
            rstat = itsImStore->forwardGrid((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "BACKWARDGRID") {
            rstat = itsImStore->backwardGrid((casacore::uInt)taylorTerm)->name();
        } else if (imageId == "IMAGEPBCOR") {
            rstat = itsImStore->imagepbcor((casacore::uInt)taylorTerm)->name();
        } else {
            throw AipsError("Image id \""+imageId+"\" not recognized.");
        }
    } catch  (AipsError x) {
        RETHROW(x);
    }
    return rstat;
}

casac::record* synthesisimager::getcsys()
{
   casac::record* rstat(0);
   try 
     {
       if ( itsImager ) 
         {
            rstat = fromRecord( itsImager->getcsys() );
         }
     }
   catch (AipsError x) 
     {
       RETHROW(x);
     }
   return rstat;
}

long synthesisimager::updatenchan()
{
  int rstat=-1;
  try
    {
      if ( itsImager )
        {
           rstat = itsImager->updateNchan();
        }
    }
  catch (AipsError x)
    {
      RETHROW(x);
    }
  return rstat;
}
       
  string synthesisimager::getweightdensity()
  {
    string rstat("");
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      rstat=(itsImager->getWeightDensity());
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }
  bool synthesisimager::setweightdensity(const std::string& wgtdensity )
  {
    Bool rstat(false);
    
    try {
      
      //if( ! itsImager ) itsImager = new SynthesisImager();
      itsImager = makeSI();
      itsImager->setWeightDensity(wgtdensity);
      
    } catch  (AipsError x) {
      RETHROW(x);
    }
    return rstat;
  }

bool
synthesisimager::initmpi()
{
  Bool rstat(false);

  try 
    {
      //cerr << "is applicator initialized " << applicator.initialized() << endl;
      //if(!applicator.initialized()){

      {int argc=1;
          char * *argv=nullptr;
          casa::applicator.init ( argc, argv );
          //cerr << "controller ?" <<  applicator.isController() <<  " worker? " <<  applicator.isWorker() <<  " numprocs " << applicator.numProcs() <<  endl;
        rstat=true;
	}
      //else{
      //  rstat=false;
      //  cerr << "controller ?" <<  applicator.isController() <<  " worker? " <<  applicator.isWorker() <<  " numprocs " << applicator.numProcs() <<  endl;
      // }
      
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}

bool synthesisimager::releasempi(){
  try{
  cerr <<"master "<< applicator.isController() << " init "<< applicator.initialized() << endl;
      if(applicator.initialized() &&  applicator.isController()){

        applicator.destroyThreads();
      }
 } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
      return true;
}

bool synthesisimager::inithpg()
{
  Bool rstat(false);

  try 
    {

      itsImager = makeSI();
      rstat=itsImager->inithpg();
      
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
bool synthesisimager::hpg_enabled()
{

  itsImager = makeSI();

  return (itsImager->hpg_enabled());
}


bool
synthesisimager::done()
{
  Bool rstat(false);

  try 
    {
    
      if (itsImager)
	{
	  delete itsImager;
	  itsImager=NULL;
	}
      if(itsLog)
	delete itsLog;
      itsLog=NULL;
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}


  /* PRIVATE HELPER FUNCTIONS */

casacore::String checkStr(std::string instr)
{
  casacore::String cstr = toCasaString( instr );
  if( cstr == String("-1") )
    {
      cstr = "";
    }
  return cstr;
}


/*
  bool synthesisimager::setupdeconvolution(const casac::record& decpars)
{
  Bool rstat(false);

  try 
    {
      casacore::Record rec = *toRecord( decpars );
      itsDeconvolver->setupDeconvolution( rec );
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
*/
 /*
casac::record* synthesisimager::getiterationdetails()
{
  casac::record* rstat(0);

  try 
    {
      rstat=fromRecord(itsIterBot->getIterationDetails());
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
 */

  /*
casac::record* synthesisimager::getiterationsummary()
{
  casac::record* rstat(0);

  try 
    {
      rstat=fromRecord(itsIterBot->getIterationSummary());
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
  */

   /*
casac::record* synthesisimager::setupiteration(const casac::record& iterpars)
{

  try 
    {
      casacore::Record recpars = *toRecord( iterpars );
      itsIterBot->setupIteration( recpars );
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return getiterationdetails();
}
   */

/*
bool synthesisimager::cleanComplete()
{
  Bool rstat(false);

  try 
    {
      rstat = itsIterBot->cleanComplete( );
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
*/

  /*
   casac::record* synthesisimager::endloops()
  {
  try 
    {
      itsImager->endLoops();
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return getiterationdetails();
  }
  */

 /*
bool synthesisimager::runmajorcycle()
{
  Bool rstat(false);

  try 
    {
      // This is a convenience function for tool-level usage, for the non-parallel case.
      // Duplicates the code from getmajorcyclecontrols(), executemajorcycle(), endmajorcycle().
      casacore::Record recpars; // = itsImager->getMajorCycleControls();
      itsImager->executeMajorCycle( recpars );
      itsIterBot->endMajorCycle();
    } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }
  
  return rstat;
}
 */
  /*
casac::record* synthesisimager::getmajorcyclecontrols()
{
  casac::record* rstat(0);
  try {
    rstat=fromRecord(itsImager->getMajorCycleControls());
  } catch  (AipsError x) 
    {
      RETHROW(x);
    }

  return rstat;
}  
  */

/*
bool synthesisimager::endmajorcycle()
{
  Bool rstat(false);
  
  try 
    {
      itsIterBot->endMajorCycle();
     } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }

  return rstat;
}
*/

 /*
bool synthesisimager::runminorcycle()
{
  Bool rstat(false);
  
  try 
    {
      // This is a convenience function for tool-level usage, for the non-parallel case.
      // Duplicates the code from getsubiterbot(), executeminorcycle(), endminorcycle().
      casacore::Record iterbotrec = itsIterBot->getSubIterBot();
      iterbotrec = itsDeconvolver->executeMinorCycle(iterbotrec);
      itsImager->endMinorCycle(iterbotrec);
     } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }

  return rstat;
}
 */

  /*
casac::record* synthesisimager::getsubiterbot()
{
  casac::record* rstat(0);
  try {
    rstat=fromRecord(itsImager->getSubIterBot());
  } catch  (AipsError x) 
    {
      RETHROW(x);
    }

  return rstat;
}  
  */

   /*
casac::record* synthesisimager::executeminorcycle(const casac::record& iterbot)
{
  casac::record* rstat(false);
  try {
    casacore::Record recpars = *toRecord( iterbot );
    rstat = fromRecord(itsImager->executeMinorCycle( recpars ));
  } catch  (AipsError x) {
    RETHROW(x);
  }
  return rstat;
}
   */
    /*
bool synthesisimager::endminorcycle(const casac::record& iterbot)
{
  Bool rstat(false);
  
  try 
    {
      casacore::Record recpars = *toRecord( iterbot );
      itsImager->endMinorCycle(recpars);
     } 
  catch  (AipsError x) 
    {
      RETHROW(x);
    }

  return rstat;
}
    */


} // casac namespace