Exemple #1
0
/**
 * @brief Initializes the object by computing all calibration statistics
 * 
 * This method validates the input file, reads labels for needed values
 * and computes calibration statistics for data reduction.
 * 
 * @param [in] (CubeInfo &) cube Opened cube where label and ancillary data
 *                               is read from
 */
  void HiImageClean::init(Cube &cube) {

    _lines = cube.Lines();
    _samples = cube.Samples();
    _lastGoodLine = _lines - 1;
    _totalMaskNulled = _totalDarkNulled = 0;

    PvlGroup &instrument = cube.GetGroup("Instrument");

// It may be too late and a non-issue by this time, but should check to ensure
// this is a valid HiRISE image
    iString instId = (std::string) instrument["InstrumentId"];
    if (instId.UpCase() != "HIRISE") {
      string message = "Image must be a HiRISE image (InstrumentId != HIRISE)";
      iException::Message(iException::User, message, _FILEINFO_);
    }

// Extract what is needed
    _binning = instrument["Summing"];
    _tdi = instrument["Tdi"];
    _cpmm = instrument["CpmmNumber"];
    _channelNo = instrument["ChannelNumber"];

//  Initialize all HiRISE calibration blobs
    _calimg  = blobvert(HiCalibrationImage(cube));
    _calbuf  = blobvert(HiCalibrationBuffer(cube));
    _caldark = blobvert(HiCalibrationDark(cube));
    _ancbuf  = blobvert(HiAncillaryBuffer(cube));
    _ancdark = blobvert(HiAncillaryDark(cube));

//  Compute statistics from blobs
    computeStats();
    return;
  }
Exemple #2
0
void IsisMain() {

    // We will be processing by line
    ProcessByLine p;

    // Setup the input and output cubes
    Cube *icube = p.SetInputCube("FROM");
    p.SetOutputCube ("TO");

    // Get exposure duration and tranfer time
    // Override the lable values if the user entered a value
    double expTime,xferTime;
    UserInterface &ui = Application::GetUserInterface();
    if (ui.WasEntered ("DURATION")) {
        expTime = ui.GetDouble ("DURATION");
    }
    else {
        PvlGroup grp = icube->GetGroup("ISIS_INSTRUMENT");
        expTime = grp["EXPOSURE_DURATION"];
    }

    if (ui.WasEntered ("TRANSFER")) {
        xferTime = ui.GetDouble ("TRANSFER");
    }
    else {
        PvlGroup grp = icube->GetGroup("ISIS_INSTRUMENT");
        xferTime = grp["TRANSFER_TIME"];
    }

    // Calculate the smear scale
    smearScale = xferTime / expTime / icube->Lines();

    // Start the processing
    p.StartProcess(desmear);
    p.EndProcess();
}
Exemple #3
0
void IsisMain() {
  // We will be processing by brick
  ProcessByBrick p;
  
  Isis::Cube *amatrixCube=NULL; 
  Isis::Cube *bmatrixCube=NULL; 

  // Setup the user input for the input/output files and the option
  UserInterface &ui = Application::GetUserInterface();

  // Setup the input HiRise cube
  Isis::Cube *icube = p.SetInputCube("FROM");

  if (icube->Bands() != 1) {
    std::string msg = "Only single-band HiRise cubes can be calibrated";
    throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
  }

  //Get pertinent label information to determine which band of matrix cube to use
  HiLab hilab(icube);

  int ccd = hilab.getCcd();

  int channel = hilab.getChannel();

  if (channel != 0  && channel != 1) {
    std::string msg = "Only unstitched cubes can be calibrated";
    throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
  }
  int band = 1 + ccd*2 + channel;

  string option = ui.GetString("OPTION");

  // Set attributes (input band number) for the matrix cube(s);
  CubeAttributeInput att("+" + iString(band));

  // Determine the file specification to the matrix file(s) if defaulted
  // and open 
  
  if (ui.WasEntered ("MATRIX") ) {
    if (option == "GAIN") {
      string matrixFile = ui.GetFilename("MATRIX");
      amatrixCube = p.SetInputCube(matrixFile, att);
    }
    else if (option == "OFFSET") {
      string matrixFile = ui.GetFilename("MATRIX");
      bmatrixCube = p.SetInputCube(matrixFile, att);
    }
    else { //(option == "BOTH")
      std::string 
        msg = "The BOTH option cannot be used if a MATRIX is entered";
      throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
    }
  }
  else {
    int tdi = hilab.getTdi();
    int bin = hilab.getBin();

    if (option == "OFFSET" || option == "BOTH") {
      std::string bmatrixFile = "$mro/calibration";
      bmatrixFile += "/B_matrix_tdi";
      bmatrixFile += iString(tdi) + "_bin" + iString(bin);
      bmatrixCube = p.SetInputCube(bmatrixFile, att);
    }
    if (option == "GAIN" || option == "BOTH") {
       std::string amatrixFile = "$mro/calibration";
       amatrixFile += "/A_matrix_tdi";
       amatrixFile += iString(tdi) + "_bin" + iString(bin);
       amatrixCube = p.SetInputCube(amatrixFile, att);
    }
  }

  // Open the output file and set processing parameters
  Cube *ocube = p.SetOutputCube ("TO");
  p.SetWrap (true);
  p.SetBrickSize ( icube->Samples(), 1, 1);

  // Add the radiometry group if it is not there yet.  Otherwise
  // read the current value of the keyword CalibrationParameters.
  // Then delete the keyword and rewrite it after appending the
  // new value to it.  Do it this way to avoid multiple Calibration
  // Parameter keywords.
  PvlGroup calgrp;
  PvlKeyword calKey;

  if (ocube->HasGroup("Radiometry")) {
    calgrp = ocube->GetGroup ("Radiometry");

    if (calgrp.HasKeyword("CalibrationParameters")) {
      calKey = calgrp.FindKeyword("CalibrationParameters");
      calgrp.DeleteKeyword( "CalibrationParameters" );
    }
    else {
      calKey.SetName ("CalibrationParameters");
    }
  }
  else {
    calgrp.SetName("Radiometry");
    calKey.SetName ("CalibrationParameters");
  }

  string keyValue = option;
  if (option == "GAIN") {
    keyValue += ":" + amatrixCube->Filename();
  }
  else if (option == "OFFSET") {
    keyValue += ":" + bmatrixCube->Filename();
  }
  else { // "BOTH"
    keyValue += ":"+bmatrixCube->Filename()+":"+amatrixCube->Filename();
  }

  calKey += keyValue;
  calgrp += calKey;
  ocube->PutGroup(calgrp);

  // Start the processing based on the option
  if (option == "GAIN") {
    p.StartProcess(mult);
  }
  else if (option == "OFFSET") {
    p.StartProcess(sub);
  }
  else { //(option == "BOTH") 
    p.StartProcess(multSub);
  }

  // Cleanup
  p.EndProcess();
}
Exemple #4
0
// Main program
void IsisMain(){
  
  // Create an object for exporting Isis data
  ProcessExport p;
  // Open the input cube
  Cube *icube = p.SetInputCube("FROM");
 
  // Conform to the Big-Endian format for FITS
  if(IsLsb()) p.SetOutputEndian(Isis::Msb);

  // Generate the name of the fits file and open it
  UserInterface &ui = Application::GetUserInterface();
    
  // specify the bits per pixel
  string bitpix;
  if (ui.GetString ("BITTYPE") == "8BIT") bitpix = "8";
  else if (ui.GetString ("BITTYPE") == "16BIT") bitpix = "16";
  else if (ui.GetString ("BITTYPE") == "32BIT") bitpix = "-32";
  else {
    string msg = "Pixel type of [" + ui.GetString("BITTYPE") + "] is unsupported"; 
    throw iException::Message(iException::User, msg, _FILEINFO_);
  }

  //  Determine bit size and calculate number of bytes to write
  //  for each line.
  if (bitpix == "8") p.SetOutputType(Isis::UnsignedByte);
  if (bitpix == "16") p.SetOutputType(Isis::SignedWord);
  if (bitpix == "-32") p.SetOutputType(Isis::Real);
  
  // determine core base and multiplier, set up the stretch
  PvlGroup pix = icube->Label()->FindObject("IsisCube").FindObject("Core").FindGroup("Pixels");
  double scale = pix["Multiplier"][0].ToDouble();
  double base = pix["Base"][0].ToDouble();

  if (ui.GetString("STRETCH") != "NONE" && bitpix != "-32") {
    if (ui.GetString("STRETCH") == "LINEAR") {
      p.SetInputRange();
    }
    else if (ui.GetString("STRETCH") == "MANUAL") {
       p.SetInputRange(ui.GetDouble("MINIMUM"), ui.GetDouble("MAXIMUM"));
    }
    
    // create a proper scale so pixels look like 32bit data.
    scale = ((p.GetInputMaximum() - p.GetInputMinimum()) *
            (p.GetOutputMaximum() - p.GetOutputMinimum()));

    // round off after 14 decimals to avoid system architecture differences
    scale = ((floor(scale * 1e14)) / 1e14);

    // create a proper zero point so pixels look like 32bit data.
    base = -1.0 * (scale * p.GetOutputMinimum()) + p.GetInputMinimum();
    // round off after 14 decimals to avoid system architecture differences
    base = ((floor(base * 1e14)) / 1e14);
  }

  
  //////////////////////////////////////////
  // Write the minimal fits header	  //
  //////////////////////////////////////////
  string header;
  
  // specify that this file conforms to simple fits standard
  header += FitsKeyword("SIMPLE", true, "T");  
  
  
  // specify the bits per pixel
  header += FitsKeyword("BITPIX", true, bitpix);
  
  // specify the number of data axes (2: samples by lines)
  int axes = 2;
  if (icube->Bands() > 1) {
    axes = 3;
  }
  
  header += FitsKeyword("NAXIS", true, iString(axes));
  
  // specify the limit on data axis 1 (number of samples)
  header += FitsKeyword("NAXIS1", true, iString(icube->Samples()));

  // specify the limit on data axis 2 (number of lines)
  header += FitsKeyword("NAXIS2", true, iString(icube->Lines()));
 
  if (axes == 3){
    header += FitsKeyword("NAXIS3", true, iString(icube->Bands()));
  }

  header += FitsKeyword("BZERO", true,  base);

  header += FitsKeyword("BSCALE", true, scale);
  
  // Sky and All cases  
  if (ui.GetString("INFO") == "SKY" || ui.GetString("INFO") == "ALL") {  
    iString msg = "cube has not been skymapped";
    PvlGroup map;

    if (icube->HasGroup("mapping")) {
      map = icube->GetGroup("mapping");   
      msg = (string)map["targetname"];
    }
    // If we have sky we want it
    if (msg == "Sky") {
      double midRa = 0, midDec = 0;
  
      midRa = ((double)map["MaximumLongitude"] +
               (double)map["MinimumLongitude"])/2;
  
      midDec = ((double)map["MaximumLatitude"] +
                (double)map["MinimumLatitude"])/2;
  
      header += FitsKeyword("OBJCTRA", true, iString(midRa));
  
      // Specify the Declination
      header += FitsKeyword("OBJCTDEC", true, iString(midDec));
  
    }

    if (ui.GetString("INFO") == "ALL") {
      header += WritePvl("INSTRUME","Instrument","InstrumentId", icube, true);  
      header += WritePvl("OBSERVER","Instrument","SpacecraftName", icube, true);
      header += WritePvl("OBJECT  ","Instrument","TargetName", icube, true);
      // StartTime is sometimes middle of the exposure and somtimes beginning, 
      // so StopTime can't be calculated off of exposure reliably.
      header += WritePvl("DATE-OBS","Instrument","StartTime", icube, true);
      // Some cameras don't have StopTime
      if (icube->HasGroup("Instrument")) {
        PvlGroup inst = icube->GetGroup("Instrument");
        if (inst.HasKeyword("StopTime")) {
          header += WritePvl("TIME_END","Instrument","StopTime", icube, true);
        }
        if (inst.HasKeyword("ExposureDuration")) {
          header += WritePvl("EXPTIME","Instrument","ExposureDuration", icube, false);
        }
      }
    }  
    // If we were set on SKY and Sky doesn't exist
    else if (msg != "Sky") {  
      throw iException::Message(iException::User,msg,_FILEINFO_);
    }
  }
  
  // signal the end of the header
  header += FitsKeyword("END", false, "");

  // fill the rest of the fits header with space so to conform with the fits header
  // size of 2880 bytes
  for (int i = header.length() % 2880 ; i < 2880 ; i++) header += " ";

  // open the cube for writing
  string to = ui.GetFilename("TO","fits");
  ofstream fout;  
  fout.open (to.c_str (), ios::out|ios::binary);
  if (!fout.is_open ()) {
    string msg = "Cannot open fits output file";
    throw iException::Message(iException::Programmer,msg,_FILEINFO_);
  }
 
  fout.seekp(0);
  fout.write(header.c_str(),header.length());
  // write the raw cube data
  p.StartProcess (fout);

  // Finish off data area to a number n % 2880 == 0 is true
  // 2880 is the size of the data blocks
  int count = 2880 - (fout.tellp() % 2880);
  for (int i = 0; i < count; i++) {
    // Write nul characters as needed. ascii 0, hex 00...
    fout.write("\0", 1);  
  }
  fout.close();  
  p.EndProcess();
}
Exemple #5
0
void IsisMain(){

  const std::string hical_program = "hicalbeta";
  const std::string hical_version = "3.5";
  const std::string hical_revision = "$Revision: 1.14 $";
  const std::string hical_runtime = Application::DateTime();

  UserInterface &ui = Application::GetUserInterface();

  string procStep("prepping phase");
  try {
//  The output from the last processing is the input into subsequent processing
    ProcessByLine p;

    Cube *hifrom = p.SetInputCube("FROM");
    int nsamps = hifrom->Samples();
    int nlines = hifrom->Lines();

//  Initialize the configuration file
    string conf(ui.GetAsString("CONF"));
    HiCalConf hiconf(*(hifrom->Label()), conf);
    DbProfile hiprof = hiconf.getMatrixProfile();

// Check for label propagation and set the output cube
    Cube *ocube = p.SetOutputCube("TO");
    if ( !IsTrueValue(hiprof,"PropagateTables", "TRUE") ) {
      RemoveHiBlobs(*(ocube->Label()));
    }

//  Set specified profile if entered by user
    if (ui.WasEntered("PROFILE")) {
      hiconf.selectProfile(ui.GetAsString("PROFILE"));
    }


//  Add OPATH parameter to profiles
    if (ui.WasEntered("OPATH")) {
      hiconf.add("OPATH",ui.GetAsString("OPATH"));
    }
    else {
      //  Set default to output directory
      hiconf.add("OPATH", Filename(ocube->Filename()).Path());
    }

//  Do I/F output DN conversions
    string units = ui.GetString("UNITS");

    //  Allocate the calibration list
    calVars = new MatrixList;

//  Set up access to HiRISE ancillary data (tables, blobs) here.  Note it they
//  are gone, this will error out. See PropagateTables in conf file.
    HiCalData caldata(*hifrom);

////////////////////////////////////////////////////////////////////////////
//  FixGaps (Z_f) Get buffer pixels and compute coefficients for equation
//     y = a[0] + a[1]*x + a[2] * exp(a[3] * x)
//        where y is the average of the buffer pixel region,
//          and x is the time at each line in electrons/sec/pixel
    procStep = "Zf module";
    hiconf.selectProfile("Zf");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZfHist;
    ZfHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      DriftBuffer driftB(caldata, hiconf);
      calVars->add("Zf", driftB.ref());
      ZfHist = driftB.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        driftB.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      //  NOT RECOMMENDED!  This is required for the next step!
      //  SURELY must be skipped with Z_d step as well!
      calVars->add("Zf", HiVector(nlines, 0.0));
      ZfHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////////
// DriftCorrect (Z_d)
//  Now compute the equation of fit
// 
    procStep = "Zd module";
    HiHistory ZdHist;
    hiconf.selectProfile("Zd");
    hiprof = hiconf.getMatrixProfile();
    ZdHist.add("Profile["+ hiprof.Name()+"]");
    if (!SkipModule(hiconf.getMatrixProfile("Zd")) ) { 
      DriftCorrect driftC(hiconf);
      calVars->add("Zd", driftC.Normalize(driftC.Solve(calVars->get("Zf"))));
      ZdHist = driftC.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        driftC.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zd", HiVector(nlines, 0.0));
      ZdHist.add("Debug::SkipModule invoked!");
    }


 ////////////////////////////////////////////////////////////////////
 //  ZeroCorrect (Z_z)  Get reverse clock 
    procStep = "Zz module";
    hiconf.selectProfile("Zz"); 
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZzHist;
    ZzHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      OffsetCorrect zoff(caldata, hiconf);
      calVars->add("Zz", zoff.ref());
      ZzHist = zoff.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zoff.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zz", HiVector(nsamps, 0.0));
      ZzHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////
// DarkSubtract (Z_b) Remove dark current
// 
    procStep = "Zb module";
    hiconf.selectProfile("Zb");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZbHist;
    ZbHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      DarkSubtractComp dark(hiconf);
      calVars->add("Zb", dark.ref());
      ZbHist = dark.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        dark.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zb", HiVector(nsamps, 0.0));
      ZbHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
// GainVLineCorrect (Z_g) Correct for gain-based drift
// 
    procStep = "Zg module";
    hiconf.selectProfile("Zg");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZgHist;
    ZgHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainVLineComp gainV(hiconf);
      calVars->add("Zg", gainV.ref());
      ZgHist = gainV.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gainV.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zg", HiVector(nlines, 1.0));
      ZgHist.add("Debug::SkipModule invoked!");
    }


////////////////////////////////////////////////////////////////////
//  GainCorrect (Z_gg)  Correct for gain with the G matrix 
    procStep = "Zgg module";
    hiconf.selectProfile("Zgg"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZggHist;
    ZggHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      double bin = ToDouble(hiprof("Summing"));
      double tdi = ToDouble(hiprof("Tdi"));
      double factor = 128.0 / tdi / (bin*bin);
      HiVector zgg =  hiconf.getMatrix("G", hiprof);
      for ( int i = 0 ; i < zgg.dim() ; i++ ) { zgg[i] *= factor; }
      calVars->add("Zgg", zgg);;
      ZggHist.add("LoadMatrix(G[" + hiconf.getMatrixSource("G",hiprof) +
                  "],Band[" + ToString(hiconf.getMatrixBand(hiprof)) + 
                  "],Factor[" + ToString(factor) + "])"); 
      if ( hiprof.exists("DumpModuleFile") ) { 
        Component zg("GMatrix", ZggHist);
        zg.Process(zgg);
        zg.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zgg", HiVector(nsamps, 1.0));
      ZggHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  FlatField (Z_a)  Flat field correction with A matrix
    procStep = "Za module";
    hiconf.selectProfile("Za"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZaHist;
    ZaHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      FlatFieldComp flat(hiconf);
      calVars->add("Za", flat.ref());
      ZaHist = flat.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        flat.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Za", HiVector(nsamps, 1.0));
      ZaHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  FlatField (Z_t)  Temperature-dependant gain correction
    procStep = "Zt module";
    hiconf.selectProfile("Zt"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZtHist;
    ZtHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      TempGainCorrect tcorr(hiconf);
      calVars->add("Zt", tcorr.ref());
      ZtHist = tcorr.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        tcorr.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zt", HiVector(nsamps, 1.0));
      ZtHist.add("Debug::SkipModule invoked!");
    }


////////////////////////////////////////////////////////////////////
//  I/FCorrect (Z_iof) Conversion to I/F
// 
    procStep = "Ziof module";
    hiconf.selectProfile("Ziof");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZiofHist;
    ZiofHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      double sed = ToDouble(hiprof("ScanExposureDuration"));  // units = us
      if ( IsEqual(units, "IOF") ) {
        //  Add solar I/F correction parameters
        double au = hiconf.sunDistanceAU();
        ZiofHist.add("SunDist[" + ToString(au) + " (AU)]");
        double suncorr =  1.5 / au;
        suncorr *= suncorr;

        double zbin  = ToDouble(hiprof("ZiofBinFactor"));
        ZiofHist.add("ZiofBinFactor[" + ToString(zbin) + "]");

        double zgain = ToDouble(hiprof("FilterGainCorrection"));
        ZiofHist.add("FilterGainCorrection[" + ToString(zgain) + "]");
        ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]");
        double ziof = (zbin * zgain) * (sed * 1.0e-6)  * suncorr; 

        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("I/F_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[I/F Reflectance]");
      }
      else if (  IsEqual(units, "DN/US") ) {
        // Ziof is a divisor in calibration equation
        double ziof = sed;
        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]");
        ZiofHist.add("DN/US_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[DNs/microsecond]");
      }
      else {
        // Units are already in DN
        double ziof = 1.0;
        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("DN_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[DN]");
      }
    }
    else {
      calVars->add("Ziof", HiVector(1,1.0));
      ZiofHist.add("Debug::SkipModule invoked!");
      ZiofHist.add("Units[Unknown]");
    }

    //  Reset the profile selection to default
    hiconf.selectProfile();

//----------------------------------------------------------------------
// 
/////////////////////////////////////////////////////////////////////////
//  Call the processing function
    procStep = "calibration phase";
    p.StartProcess(calibrate);

    // Get the default profile for logging purposes
    hiprof = hiconf.getMatrixProfile();
    const std::string conf_file = hiconf.filepath(conf);

    // Quitely dumps parameter history to alternative format file.  This
    // is completely controlled by the configuration file
    if ( hiprof.exists("DumpHistoryFile") ) {
      procStep = "logging/reporting phase";
      Filename hdump(hiconf.getMatrixSource("DumpHistoryFile",hiprof));
      string hdumpFile = hdump.Expanded();
      ofstream ofile(hdumpFile.c_str(), ios::out);
      if (!ofile) {
        string mess = "Unable to open/create history dump file " + 
                      hdump.Expanded();
        iException::Message(iException::User, mess, _FILEINFO_).Report();
      }
      else {
        ofile << "Program:  " << hical_program << endl;
        ofile << "RunTime:  " << hical_runtime << endl;
        ofile << "Version:  " << hical_version << endl;
        ofile << "Revision: " << hical_revision << endl << endl;

        ofile << "FROM:     " << hifrom->Filename() << endl;
        ofile << "TO:       " << ocube->Filename()  << endl;
        ofile << "CONF:     " << conf_file  << endl << endl;

        ofile << "/* " << hical_program << " application equation */" << endl
              << "/* hdn = (idn - Zd(Zf) - Zz - Zb) */"
              << endl << "/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */" 
              << endl << endl;

        ofile << "****** PARAMETER GENERATION HISTORY *******" << endl;
        ofile << "\nZf   = " << ZfHist << endl;
        ofile << "\nZd   = " << ZdHist << endl;
        ofile << "\nZz   = " << ZzHist << endl;
        ofile << "\nZb   = " << ZbHist << endl;
        ofile << "\nZg   = " << ZgHist << endl;
        ofile << "\nZgg  = " << ZggHist << endl;
        ofile << "\nZa   = " << ZaHist << endl;
        ofile << "\nZt   = " << ZtHist << endl;
        ofile << "\nZiof = " << ZiofHist << endl;

        ofile.close();
      }
    }

//  Ensure the RadiometricCalibration group is out there
    const std::string rcalGroup("RadiometricCalibration");
    if (!ocube->HasGroup(rcalGroup)) {
      PvlGroup temp(rcalGroup);
      ocube->PutGroup(temp);
    }

    PvlGroup &rcal = ocube->GetGroup(rcalGroup);
    rcal += PvlKeyword("Program", hical_program);
    rcal += PvlKeyword("RunTime", hical_runtime);
    rcal += PvlKeyword("Version",hical_version);
    rcal += PvlKeyword("Revision",hical_revision);

    PvlKeyword key("Conf", conf_file);
    key.AddCommentWrapped("/* " + hical_program + " application equation */");
    key.AddComment("/* hdn = (idn - Zd(Zf) - Zz - Zb) */");
    key.AddComment("/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */");
    rcal += key;

    //  Record parameter generation history.  Controllable in configuration
    //  file.  Note this is optional because of a BUG!! in the ISIS label
    //  writer as this application was initially developed
    if ( IsEqual(ConfKey(hiprof,"LogParameterHistory",string("TRUE")),"TRUE")) { 
      rcal += ZfHist.makekey("Zf");
      rcal += ZdHist.makekey("Zd");
      rcal += ZzHist.makekey("Zz");
      rcal += ZbHist.makekey("Zb");
      rcal += ZgHist.makekey("Zg");
      rcal += ZggHist.makekey("Zgg");
      rcal += ZaHist.makekey("Za");
      rcal += ZiofHist.makekey("Ziof");
    }

    p.EndProcess();
  } 
  catch (iException &ie) {
    delete calVars;
    calVars = 0;
    string mess = "Failed in " + procStep;
    ie.Message(iException::User, mess.c_str(), _FILEINFO_);
    throw;
  }
  
// Clean up parameters
  delete calVars;
  calVars = 0;
}
Exemple #6
0
void IsisMain ()
{
    stretch.ClearPairs();

    for (int i=0; i<6; i++) {
        gapCount[i] = 0;
        suspectGapCount[i] = 0;
        invalidCount[i] = 0;
        lisCount[i] = 0;
        hisCount[i] = 0;
        validCount[i] = 0;
    }

    void TranslateHiriseEdrLabels (Filename &labelFile, Cube *);
    void SaveHiriseCalibrationData (ProcessImportPds &process, Cube *,
                                    Pvl &pdsLabel);
    void SaveHiriseAncillaryData (ProcessImportPds &process, Cube *);
    void FixDns8 (Buffer &buf);
    void FixDns16 (Buffer &buf);

    ProcessImportPds p;
    Pvl pdsLabel;
    UserInterface &ui = Application::GetUserInterface();

    // Get the input filename and make sure it is a HiRISE EDR
    Filename inFile = ui.GetFilename("FROM");
    iString id;
    bool projected;
    try {
        Pvl lab(inFile.Expanded());
        id = (string) lab.FindKeyword ("DATA_SET_ID");
        projected = lab.HasObject("IMAGE_MAP_PROJECTION");
    }
    catch (iException &e) {
        string msg = "Unable to read [DATA_SET_ID] from input file [" +
                     inFile.Expanded() + "]";
        throw iException::Message(iException::Io,msg, _FILEINFO_);
    }

    //Checks if in file is rdr
    if( projected ) {
        string msg = "[" + inFile.Name() + "] appears to be an rdr file.";
        msg += " Use pds2isis.";
        throw iException::Message(iException::User,msg, _FILEINFO_);
    }

    id.ConvertWhiteSpace();
    id.Compress();
    id.Trim(" ");
    if (id != "MRO-M-HIRISE-2-EDR-V1.0") {
        string msg = "Input file [" + inFile.Expanded() + "] does not appear to be " +
                     "in HiRISE EDR format. DATA_SET_ID is [" + id + "]";
        throw iException::Message(iException::Io,msg, _FILEINFO_);
    }

    p.SetPdsFile (inFile.Expanded(), "", pdsLabel);

    // Make sure the data we need for the BLOBs is saved by the Process
    p.SaveFileHeader();
    p.SaveDataPrefix();
    p.SaveDataSuffix();

    // Let the Process create the output file but override any commandline
    // output bit type and min/max. It has to be 16bit for the rest of hi2isis
    // to run.
    // Setting the min/max to the 16 bit min/max keeps all the dns (including
    // the 8 bit special pixels from changing their value when they are mapped
    // to the 16 bit output.
    CubeAttributeOutput &outAtt = ui.GetOutputAttribute("TO");
    outAtt.PixelType (Isis::SignedWord);
    outAtt.Minimum((double)VALID_MIN2);
    outAtt.Maximum((double)VALID_MAX2);
    Cube *ocube = p.SetOutputCube(ui.GetFilename("TO"), outAtt);
    p.StartProcess ();
    TranslateHiriseEdrLabels (inFile, ocube);

    // Pull out the lookup table so we can apply it in the second pass
    // and remove it from the labels.
    // Add the UNLUTTED keyword to the instrument group so we know
    // if the lut has been used to convert back to 14 bit data
    PvlGroup &instgrp = ocube->GetGroup("Instrument");
    PvlKeyword lutKey = instgrp["LookupTable"];
    PvlSequence lutSeq;
    lutSeq = lutKey;

    // Set up the Stretch object with the info from the lookup table
    // If the first entry is (0,0) then no lut was applied.
    if ((lutKey.IsNull()) ||
            (lutSeq.Size()==1 && lutSeq[0][0]=="0" && lutSeq[0][1]=="0")) {
        stretch.AddPair(0.0, 0.0);
        stretch.AddPair(65536.0, 65536.0);
        instgrp.AddKeyword(PvlKeyword("Unlutted","TRUE"));
        instgrp.DeleteKeyword ("LookupTable");
    }
    // The user wants it unlutted
    else if (ui.GetBoolean("UNLUT")) {
        for (int i=0; i<lutSeq.Size(); i++) {
            stretch.AddPair(i, (((double)lutSeq[i][0] + (double)lutSeq[i][1]) / 2.0));
        }
        instgrp.AddKeyword(PvlKeyword("Unlutted","TRUE"));
        instgrp.DeleteKeyword ("LookupTable");
    }
    // The user does not want the data unlutted
    else {
        stretch.AddPair(0.0, 0.0);
        stretch.AddPair(65536.0, 65536.0);
        instgrp.AddKeyword(PvlKeyword("Unlutted","FALSE"));
    }
    ocube->PutGroup(instgrp);

    // Save the calibration and ancillary data as BLOBs. Both get run thru the
    // lookup table just like the image data.
    SaveHiriseCalibrationData (p, ocube, pdsLabel);
    SaveHiriseAncillaryData (p, ocube);

    // Save off the input bit type so we know how to process it on the
    // second pass below.
    Isis::PixelType inType = p.PixelType();

    // All finished with the ImportPds object
    p.EndProcess ();


    // Make another pass thru the data using the output file in read/write mode
    // This allows us to correct gaps, remap special pixels and accumulate some
    // counts
    lsbGap = ui.GetBoolean("LSBGAP");
    ProcessByLine p2;
    string ioFile = ui.GetFilename("TO");
    CubeAttributeInput att;
    p2.SetInputCube(ioFile, att, ReadWrite);
    p2.Progress()->SetText("Converting special pixels");
    section = 4;
    p2.StartProcess((inType == Isis::UnsignedByte) ? FixDns8 : FixDns16);
    p2.EndProcess();


    // Log the results of the image conversion
    PvlGroup results("Results");
    results += PvlKeyword ("From", inFile.Expanded());

    results += PvlKeyword ("CalibrationBufferGaps", gapCount[0]);
    results += PvlKeyword ("CalibrationBufferLIS", lisCount[0]);
    results += PvlKeyword ("CalibrationBufferHIS", hisCount[0]);
    results += PvlKeyword ("CalibrationBufferPossibleGaps", suspectGapCount[0]);
    results += PvlKeyword ("CalibrationBufferInvalid", invalidCount[0]);
    results += PvlKeyword ("CalibrationBufferValid", validCount[0]);

    results += PvlKeyword ("CalibrationImageGaps", gapCount[1]);
    results += PvlKeyword ("CalibrationImageLIS", lisCount[1]);
    results += PvlKeyword ("CalibrationImageHIS", hisCount[1]);
    results += PvlKeyword ("CalibrationImagePossibleGaps", suspectGapCount[1]);
    results += PvlKeyword ("CalibrationImageInvalid", invalidCount[1]);
    results += PvlKeyword ("CalibrationImageValid", validCount[1]);

    results += PvlKeyword ("CalibrationDarkGaps", gapCount[2]);
    results += PvlKeyword ("CalibrationDarkLIS", lisCount[2]);
    results += PvlKeyword ("CalibrationDarkHIS", hisCount[2]);
    results += PvlKeyword ("CalibrationDarkPossibleGaps", suspectGapCount[2]);
    results += PvlKeyword ("CalibrationDarkInvalid", invalidCount[2]);
    results += PvlKeyword ("CalibrationDarkValid", validCount[2]);

    results += PvlKeyword ("ObservationBufferGaps", gapCount[3]);
    results += PvlKeyword ("ObservationBufferLIS", lisCount[3]);
    results += PvlKeyword ("ObservationBufferHIS", hisCount[3]);
    results += PvlKeyword ("ObservationBufferPossibleGaps", suspectGapCount[3]);
    results += PvlKeyword ("ObservationBufferInvalid", invalidCount[3]);
    results += PvlKeyword ("ObservationBufferValid", validCount[3]);

    results += PvlKeyword ("ObservationImageGaps", gapCount[4]);
    results += PvlKeyword ("ObservationImageLIS", lisCount[4]);
    results += PvlKeyword ("ObservationImageHIS", hisCount[4]);
    results += PvlKeyword ("ObservationImagePossibleGaps", suspectGapCount[4]);
    results += PvlKeyword ("ObservationImageInvalid", invalidCount[4]);
    results += PvlKeyword ("ObservationImageValid", validCount[4]);

    results += PvlKeyword ("ObservationDarkGaps", gapCount[5]);
    results += PvlKeyword ("ObservationDarkLIS", lisCount[5]);
    results += PvlKeyword ("ObservationDarkHIS", hisCount[5]);
    results += PvlKeyword ("ObservationDarkPossibleGaps", suspectGapCount[5]);
    results += PvlKeyword ("ObservationDarkInvalid", invalidCount[5]);
    results += PvlKeyword ("ObservationDarkValid", validCount[5]);

    // Write the results to the log
    Application::Log(results);

    return;
}
Exemple #7
0
void IsisMain(){

  UserInterface &ui = Application::GetUserInterface();

  ProcessByLine proc;
  Cube *cube = proc.SetInputCube("FROM");
  BigInt npixels(cube->Lines() * cube->Samples());
  
//  Initialize the cleaner routine
  try {
    delete iclean;
    iclean = new HiImageClean(*cube);
  } 
  catch (iException &ie) {
    std::string message = "Error attempting to initialize HiRISE cleaner object";
    throw (iException::Message(iException::Programmer,message,_FILEINFO_));
  }
  catch (...) {
    std::string message = "Unknown error occured attempting to initialize "
                          "HiRISE cleaner object";
    throw (iException::Message(iException::Programmer,message,_FILEINFO_));
  }

//  For IR10, channel 1 lets restrict the last 3100 lines of dark current
  PvlGroup &instrument = cube->GetGroup("Instrument");
  std::string ccd = (std::string) instrument["CcdId"];
  int channel = instrument["ChannelNumber"];
  if ((ccd == "IR10") && (channel  == 1)) {
    int bin = instrument["Summing"];
    int lastLine = cube->Lines() - ((3100/bin) + iclean->getFilterWidth()/2);
    if (lastLine > 1) { iclean->setLastGoodLine(lastLine); }
  }

#if defined(DEBUG)
  std::cout << "Lines: " << cube->Lines() << "   GoodLines: " 
            << iclean->getLastGoodLine() << std::endl;    
#endif

//  Get the output file reference for label update
  Cube *ocube = proc.SetOutputCube("TO");
  proc.StartProcess(cleanImage);
  iclean->propagateBlobs(ocube);
  proc.EndProcess();

//  Write statistics to file if requested
  if (ui.WasEntered("CLEANSTATS")) {
    std::string darkfile = ui.GetFilename("CLEANSTATS");
    std::ofstream dfile;
    dfile.open(darkfile.c_str(), std::ios::out | std::ios::trunc);
    dfile << *iclean;
    dfile.close();
  }

//  Dump stats to standard out
  Pvl p;
  PvlGroup grp;
  iclean->PvlImageStats(grp);
  p.AddGroup(grp);
  Application::Log(grp);
  BigInt nNulled = iclean->TotalNulled();

  delete iclean;
  iclean = 0;

// Check for calibration problems
  if (nNulled != 0) {
    double tpixels((double) nNulled / (double) npixels);
    std::ostringstream mess;
    mess << "There were " << nNulled << " of " << npixels << " ("
         << std::setw(6) << std::setprecision(2) << (tpixels * 100.0)
         << "%) due to insufficient calibration data (LUTTED or Gaps)" 
         << std::ends;
    throw (iException::Message(iException::Math,mess.str(),_FILEINFO_));
  }
}
Exemple #8
0
void IsisMain () 
{
	UserInterface &ui = Application::GetUserInterface();
    Filename inFile = ui.GetFilename("FROM");

	// Set the processing object
	ProcessExportMiniRFLroPds cProcess;

	// Setup the input cube
	Cube *cInCube = cProcess.SetInputCube("FROM");	
	Pvl * cInLabel =  cInCube->Label();

	// Get the output label file
	Filename outFile(ui.GetFilename("TO", "lbl"));
	string outFilename(outFile.Expanded());

	cProcess.SetDetached  (true, outFilename);	

	cProcess.SetExportType ( ProcessExportPds::Fixed );

	//Set the resolution to  Kilometers  
	cProcess.SetPdsResolution( ProcessExportPds::Kilometer );	
	
	// 32bit
	cProcess.SetOutputType(Isis::Real);
    cProcess.SetOutputNull(Isis::NULL4);
    cProcess.SetOutputLrs(Isis::LOW_REPR_SAT4);
    cProcess.SetOutputLis(Isis::LOW_INSTR_SAT4);
    cProcess.SetOutputHrs(Isis::HIGH_REPR_SAT4);
    cProcess.SetOutputHis(Isis::HIGH_INSTR_SAT4);
	cProcess.SetOutputRange(-DBL_MAX, DBL_MAX);

	cProcess.SetOutputEndian(Isis::Msb);

	// Turn off Keywords
	cProcess.ForceScalingFactor(false);
    cProcess.ForceSampleBitMask(false);
    cProcess.ForceCoreNull     (false);
    cProcess.ForceCoreLrs      (false);
    cProcess.ForceCoreLis      (false);
    cProcess.ForceCoreHrs      (false);
    cProcess.ForceCoreHis      (false);	

	// Standard label Translation
	Pvl &pdsLabel = cProcess.StandardPdsLabel( ProcessExportPds::Image); 	

	// bLevel => Level 2 = True, Level 3 = False
	bool bLevel2 = cInCube->HasGroup("Instrument");

	// Translate the keywords from the original EDR PDS label that go in 
    // this RDR PDS label for Level2 images only
	if (bLevel2) {
		OriginalLabel cOriginalBlob;
		cInCube->Read(cOriginalBlob);
		Pvl cOrigLabel;
		PvlObject cOrigLabelObj = cOriginalBlob.ReturnLabels();
		cOrigLabelObj.SetName("OriginalLabelObject");
		cOrigLabel.AddObject(cOrigLabelObj);
	   
		// Translates the ISIS labels along with the original EDR labels
		cOrigLabel.AddObject( *(cInCube->Label()) );
		PvlTranslationManager cCubeLabel2(cOrigLabel, "$lro/translations/mrfExportOrigLabel.trn");
		cCubeLabel2.Auto(pdsLabel);	

		
		if (cInLabel->FindObject("IsisCube").FindGroup("Instrument").HasKeyword("MissionName")) {
			PvlKeyword & cKeyMissionName = cInLabel->FindObject("IsisCube").FindGroup("Instrument").FindKeyword("MissionName");			
			size_t sFound = cKeyMissionName[0].find("CHANDRAYAAN");
			if (sFound != string::npos ) {
				cCubeLabel2 = PvlTranslationManager(cOrigLabel, "$lro/translations/mrfExportOrigLabelCH1.trn");
				cCubeLabel2.Auto(pdsLabel);
			}
			else {
				cCubeLabel2 = PvlTranslationManager(cOrigLabel, "$lro/translations/mrfExportOrigLabelLRO.trn");
				cCubeLabel2.Auto(pdsLabel);
			}
		}
	}
	else { //Level3 - add Band_Name keyword 
		PvlGroup & cBandBinGrp = cInCube->GetGroup("BandBin");
		PvlKeyword cKeyBandBin = PvlKeyword("BAND_NAME");
		PvlKeyword cKeyInBandBin;
		if (cBandBinGrp.HasKeyword("OriginalBand")){
			cKeyInBandBin = cBandBinGrp.FindKeyword("OriginalBand");					
		}
		else if (cBandBinGrp.HasKeyword("FilterName")){
			cKeyInBandBin = cBandBinGrp.FindKeyword("FilterName");					
		}
		for (int i=0; i<cKeyInBandBin.Size(); i++) {
			cKeyBandBin += cKeyInBandBin[i];
		}
		PvlObject &cImageObject( pdsLabel.FindObject("IMAGE") );
		cImageObject += cKeyBandBin;
	}
	
	// Get the Sources Product ID if entered for Level2 only as per example
	if (ui.WasEntered("SRC") && bLevel2) {
		std::string sSrcFile = ui.GetFilename("SRC");
		std::string sSrcType = ui.GetString("TYPE");
		GetSourceProductID(sSrcFile, sSrcType, pdsLabel);
	}	
  
	// Get the User defined Labels
	if (ui.WasEntered("USERLBL")) {
		std::string sUserLbl = ui.GetFilename("USERLBL");
		GetUserLabel(sUserLbl, pdsLabel, bLevel2);
	}
	
	// Calculate CheckSum
	Statistics * cStats =  cInCube->Statistics();
	iCheckSum = (unsigned int )cStats->Sum();
		
	FixLabel(pdsLabel, bLevel2);	
	
	// Add an output format template to	the PDS PVL
	// Distinguish betweeen Level 2 and 3 images by calling the camera()
	// function as only non mosaic images(Level2) have a camera	
	if (bLevel2) {
		pdsLabel.SetFormatTemplate ("$lro/translations/mrfPdsLevel2.pft");
	} else {		
		pdsLabel.SetFormatTemplate ("$lro/translations/mrfPdsLevel3.pft");
	}

	size_t iFound = outFilename.find(".lbl");
	outFilename.replace(iFound, 4, ".img");
	ofstream oCube(outFilename.c_str());
	cProcess.OutputDetatchedLabel(); 		
	//cProcess.OutputLabel(oCube);		
	cProcess.StartProcess(oCube);		
	oCube.close();
	cProcess.EndProcess();	
}
Exemple #9
0
void IsisMain() {
  // We will be warping a cube
  ProcessRubberSheet p;

  // Get the map projection file provided by the user
  UserInterface &ui = Application::GetUserInterface();
  Pvl userPvl(ui.GetFilename("MAP"));
  PvlGroup &userMappingGrp = userPvl.FindGroup("Mapping",Pvl::Traverse);

  // Open the input cube and get the projection
  Cube *icube = p.SetInputCube ("FROM");

  // Get the mapping group
  PvlGroup fromMappingGrp = icube->GetGroup("Mapping");
  Projection *inproj = icube->Projection();
  PvlGroup outMappingGrp = fromMappingGrp;

  // If the default range is FROM, then wipe out any range data in user mapping file
  if(ui.GetString("DEFAULTRANGE").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) {
    if(userMappingGrp.HasKeyword("MinimumLatitude")) {
      userMappingGrp.DeleteKeyword("MinimumLatitude");
    }

    if(userMappingGrp.HasKeyword("MaximumLatitude")) {
      userMappingGrp.DeleteKeyword("MaximumLatitude");
    }

    if(userMappingGrp.HasKeyword("MinimumLongitude")) {
      userMappingGrp.DeleteKeyword("MinimumLongitude");
    }

    if(userMappingGrp.HasKeyword("MaximumLongitude")) {
      userMappingGrp.DeleteKeyword("MaximumLongitude");
    }
  }

  // Deal with user overrides entered in the GUI. Do this by changing the user's mapping group, which
  // will then overlay anything in the output mapping group.
  if(ui.WasEntered("MINLAT") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MinimumLatitude", ui.GetDouble("MINLAT")), Pvl::Replace );
  }

  if(ui.WasEntered("MAXLAT") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MaximumLatitude", ui.GetDouble("MAXLAT")), Pvl::Replace );
  }

  if(ui.WasEntered("MINLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MinimumLongitude", ui.GetDouble("MINLON")), Pvl::Replace );
  }

  if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MaximumLongitude", ui.GetDouble("MAXLON")), Pvl::Replace );
  }

  /**
   * If the user is changing from positive east to positive west, or vice-versa, the output minimum is really
   * the input maximum. However, the user mapping group must be left unaffected (an input minimum must be the
   * output minimum). To accomplish this, we swap the minimums/maximums in the output group ahead of time. This
   * causes the minimums and maximums to correlate to the output minimums and maximums. That way when we copy
   * the user mapping group into the output group a mimimum overrides a minimum and a maximum overrides a maximum.
   */
  bool sameDirection = true;
  if(userMappingGrp.HasKeyword("LongitudeDirection")) {
    if(((string)userMappingGrp["LongitudeDirection"]).compare(fromMappingGrp["LongitudeDirection"]) != 0) {
      sameDirection = false;
    }
  }

  // Since the out mapping group came from the from mapping group, which came from a valid cube,
  // we can assume both min/max lon exists if min longitude exists.
  if(!sameDirection && outMappingGrp.HasKeyword("MinimumLongitude")) {
    double minLon = outMappingGrp["MinimumLongitude"];
    double maxLon = outMappingGrp["MaximumLongitude"];

    outMappingGrp["MaximumLongitude"] = minLon;
    outMappingGrp["MinimumLongitude"] = maxLon;
  }

  if(ui.GetString("PIXRES").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) {
    // Resolution will be in fromMappingGrp and outMappingGrp at this time
    //   delete from user mapping grp
    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }
  }
  else if(ui.GetString("PIXRES").compare("MAP") == 0 || ui.GetBoolean("MATCHMAP")) {
    // Resolution will be in userMappingGrp - delete all others
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")); {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }
  }
  else if(ui.GetString("PIXRES").compare("MPP") == 0) {
    // Resolution specified - delete all and add to outMappingGrp
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")) {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }

    outMappingGrp.AddKeyword(PvlKeyword("PixelResolution", ui.GetDouble("RESOLUTION"), "meters/pixel"), Pvl::Replace);
  }
  else if(ui.GetString("PIXRES").compare("PPD") == 0) {
    // Resolution specified - delete all and add to outMappingGrp
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")) {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }

    outMappingGrp.AddKeyword(PvlKeyword("Scale", ui.GetDouble("RESOLUTION"), "pixels/degree"), Pvl::Replace);
  }

  // Rotation will NOT Propagate
  if(outMappingGrp.HasKeyword("Rotation")) {
    outMappingGrp.DeleteKeyword("Rotation");
  }


  /**
   * The user specified map template file overrides what ever is in the
   * cube's mapping group.
   */
  for(int keyword = 0; keyword < userMappingGrp.Keywords(); keyword ++) {
    outMappingGrp.AddKeyword(userMappingGrp[keyword], Pvl::Replace);
  }

  /**
   * Now, we have to deal with unit conversions. We convert only if the following are true:
   *   1) We used values from the input cube
   *   2) The values are longitudes or latitudes
   *   3) The map file or user-specified information uses a different measurement system than
   *        the input cube for said values.
   *
   * The data is corrected for:
   *   1) Positive east/positive west
   *   2) Longitude domain
   *   3) planetographic/planetocentric.
   */

  // First, the longitude direction
  if(!sameDirection) {
    PvlGroup longitudes = inproj->MappingLongitudes();

    for(int index = 0; index < longitudes.Keywords(); index ++) {
      if(!userMappingGrp.HasKeyword(longitudes[index].Name())) {
        // use the from domain because that's where our values are coming from
        if(((string)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) {
          outMappingGrp[longitudes[index].Name()] =
            Projection::ToPositiveEast(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]);
        }
        else {
          outMappingGrp[longitudes[index].Name()] =
            Projection::ToPositiveWest(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]);
        }
      }
    }
  }

  // The minimum/maximum longitudes should be in order now. However, if the user entered a
  // maximum that was lower than the minimum, or a minimum that was higher than the maximum this
  // may still fail. Let it throw an error when we instantiate the projection.

  // Second, longitude domain
  if(userMappingGrp.HasKeyword("LongitudeDomain")) { // user set a new domain?
    if((int)userMappingGrp["LongitudeDomain"] != (int)fromMappingGrp["LongitudeDomain"]) { // new domain different?

      PvlGroup longitudes = inproj->MappingLongitudes();

      for(int index = 0; index < longitudes.Keywords(); index ++) {
        if(!userMappingGrp.HasKeyword(longitudes[index].Name())) {
          if((int)userMappingGrp["LongitudeDomain"] == 180) {
            outMappingGrp[longitudes[index].Name()] = Projection::To180Domain(outMappingGrp[longitudes[index].Name()]);
          }
          else {
            outMappingGrp[longitudes[index].Name()] = Projection::To360Domain(outMappingGrp[longitudes[index].Name()]);
          }
        }
      }

    }
  }

  // Third, planetographic/planetocentric
  if(userMappingGrp.HasKeyword("LatitudeType")) { // user set a new domain?
    if(((string)userMappingGrp["LatitudeType"]).compare(fromMappingGrp["LatitudeType"]) != 0) { // new lat type different?

      PvlGroup latitudes = inproj->MappingLatitudes();

      for(int index = 0; index < latitudes.Keywords(); index ++) {
        if(!userMappingGrp.HasKeyword(latitudes[index].Name())) {
          if(((string)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) {
            outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetographic(
                                                      (double)fromMappingGrp[latitudes[index].Name()],
                                                      (double)fromMappingGrp["EquatorialRadius"],
                                                      (double)fromMappingGrp["PolarRadius"]);
          }
          else {
            outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetocentric(
                                                      (double)fromMappingGrp[latitudes[index].Name()],
                                                      (double)fromMappingGrp["EquatorialRadius"],
                                                      (double)fromMappingGrp["PolarRadius"]);
          }
        }
      }

    }
  }

  // If MinLon/MaxLon out of order, we weren't able to calculate the correct values
  if((double)outMappingGrp["MinimumLongitude"] >= (double)outMappingGrp["MaximumLongitude"]) {
    if(!ui.WasEntered("MINLON") || !ui.WasEntered("MAXLON")) {
      string msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude].";
      msg += " Please specify these values in the [MINLON,MAXLON] parameters";
      throw iException::Message(iException::Pvl,msg,_FILEINFO_);
    }
  }

  int samples,lines;
  Pvl mapData;
  // Copy to preserve cube labels so we can match cube size
  if (userPvl.HasObject("IsisCube")) {
    mapData = userPvl;
    mapData.FindObject("IsisCube").DeleteGroup("Mapping");
    mapData.FindObject("IsisCube").AddGroup(outMappingGrp);
  }
  else {
    mapData.AddGroup(outMappingGrp);
  }

  // *NOTE: The UpperLeftX,UpperLeftY keywords will not be used in the CreateForCube
  //   method, and they will instead be recalculated. This is correct.
  Projection *outproj = ProjectionFactory::CreateForCube(mapData,samples,lines,
                                                         ui.GetBoolean("MATCHMAP"));

  // Set up the transform object which will simply map
  // output line/samps -> output lat/lons -> input line/samps
  Transform *transform = new map2map (icube->Samples(),
                                       icube->Lines(),
                                       icube->Projection(),
                                       samples,
                                       lines,
                                       outproj,
                                       ui.GetBoolean("TRIM"));

  // Allocate the output cube and add the mapping labels
  Cube *ocube = p.SetOutputCube ("TO", transform->OutputSamples(),
                                            transform->OutputLines(),
                                            icube->Bands());

  PvlGroup cleanOutGrp = outproj->Mapping();

  // ProjectionFactory::CreateForCube updated mapData to have the correct
  //   upperleftcornerx, upperleftcornery, scale and resolution. Use these
  //   updated numbers.
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerX"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerY"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["Scale"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["PixelResolution"], Pvl::Replace);

  ocube->PutGroup(cleanOutGrp);

  // Set up the interpolator
  Interpolator *interp;
  if (ui.GetString("INTERP") == "NEARESTNEIGHBOR") {
    interp = new Interpolator(Interpolator::NearestNeighborType);
  }
  else if (ui.GetString("INTERP") == "BILINEAR") {
    interp = new Interpolator(Interpolator::BiLinearType);
  }
  else if (ui.GetString("INTERP") == "CUBICCONVOLUTION") {
    interp = new Interpolator(Interpolator::CubicConvolutionType);
  }
  else {
    string msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]";
    throw iException::Message(iException::Programmer,msg,_FILEINFO_);
  }

  // Warp the cube
  p.StartProcess(*transform, *interp);
  p.EndProcess();

  Application::Log(cleanOutGrp);

  // Cleanup
  delete transform;
  delete interp;
}