Beispiel #1
0
  /**
   * GetPointInfo builds the PvlGroup containing all the important 
   * information derived from the Camera.  
   * 
   * @return PvlGroup* Data taken directly from the Camera and 
   *         drived from Camera information. Ownership passed.
   */
  PvlGroup * CameraPointInfo::GetPointInfo() {
    CheckConditions();

    Brick b(3,3,1,currentCube->PixelType());
    
    int intSamp = (int)(camera->Sample() + 0.5);
    int intLine = (int)(camera->Line() + 0.5);
    b.SetBasePosition(intSamp, intLine, 1);
    currentCube->Read(b);

    double pB[3], spB[3], sB[3];
    string utc;
    double ssplat, ssplon, sslat, sslon, pwlon, oglat;

    // Create group with ground position
    PvlGroup * gp = new PvlGroup("GroundPoint");
    {
      gp->AddKeyword(PvlKeyword("Filename",currentCube->Filename()));
      gp->AddKeyword(PvlKeyword("Sample",camera->Sample()));
      gp->AddKeyword(PvlKeyword("Line",camera->Line()));
      gp->AddKeyword(PvlKeyword("PixelValue",PixelToString(b[0])));
      gp->AddKeyword(PvlKeyword("RightAscension",camera->RightAscension()));
      gp->AddKeyword(PvlKeyword("Declination",camera->Declination()));
      gp->AddKeyword(PvlKeyword("PlanetocentricLatitude",
                                camera->UniversalLatitude()));
  
      // Convert lat to planetographic
      double radii[3];
      camera->Radii(radii);
      oglat = Isis::Projection::ToPlanetographic(camera->UniversalLatitude(),
                                                 radii[0],radii[2]);
      gp->AddKeyword(PvlKeyword("PlanetographicLatitude",oglat));
      
      gp->AddKeyword(PvlKeyword("PositiveEast360Longitude",
                                camera->UniversalLongitude()));
  
      //Convert lon to -180 - 180 range
      gp->AddKeyword(PvlKeyword("PositiveEast180Longitude",
                                Isis::Projection::To180Domain(
                                  camera->UniversalLongitude())));

      //Convert lon to positive west
      pwlon = Isis::Projection::ToPositiveWest(camera->UniversalLongitude(),
                                               360);
      gp->AddKeyword(PvlKeyword("PositiveWest360Longitude",pwlon));

      //Convert pwlon to -180 - 180 range
      gp->AddKeyword(PvlKeyword("PositiveWest180Longitude",
                                Isis::Projection::To180Domain(pwlon)));
  
      camera->Coordinate(pB);
      PvlKeyword coord("BodyFixedCoordinate");
      coord.AddValue(pB[0],"km");
      coord.AddValue(pB[1],"km");
      coord.AddValue(pB[2],"km");
      gp->AddKeyword(coord);
  
      gp->AddKeyword(PvlKeyword("LocalRadius",camera->LocalRadius(),"m"));
      gp->AddKeyword(PvlKeyword("SampleResolution",camera->SampleResolution(),"m"));
      gp->AddKeyword(PvlKeyword("LineResolution",camera->LineResolution(),"m"));
  
      camera->InstrumentPosition(spB);
      PvlKeyword spcoord("SpacecraftPosition");
      spcoord.AddValue(spB[0],"km");
      spcoord.AddValue(spB[1],"km");
      spcoord.AddValue(spB[2],"km");
      spcoord.AddComment("Spacecraft Information");
      gp->AddKeyword(spcoord);
  
  
      gp->AddKeyword(PvlKeyword("SpacecraftAzimuth",camera->SpacecraftAzimuth()));
      gp->AddKeyword(PvlKeyword("SlantDistance",camera->SlantDistance(),"km"));
      gp->AddKeyword(PvlKeyword("TargetCenterDistance",camera->TargetCenterDistance(),"km"));
      camera->SubSpacecraftPoint(ssplat,ssplon);
      gp->AddKeyword(PvlKeyword("SubSpacecraftLatitude",ssplat));
      gp->AddKeyword(PvlKeyword("SubSpacecraftLongitude",ssplon));
      gp->AddKeyword(PvlKeyword("SpacecraftAltitude",camera->SpacecraftAltitude(),"km"));
      gp->AddKeyword(PvlKeyword("OffNadirAngle",camera->OffNadirAngle()));
      double subspcgrdaz;
      subspcgrdaz = camera->GroundAzimuth(camera->UniversalLatitude(),camera->UniversalLongitude(),
        ssplat,ssplon);
      gp->AddKeyword(PvlKeyword("SubSpacecraftGroundAzimuth",subspcgrdaz));
  
      camera->SunPosition(sB);
      PvlKeyword scoord("SunPosition");
      scoord.AddValue(sB[0],"km");
      scoord.AddValue(sB[1],"km");
      scoord.AddValue(sB[2],"km");
      scoord.AddComment("Sun Information");
      gp->AddKeyword(scoord);
  
      gp->AddKeyword(PvlKeyword("SubSolarAzimuth",camera->SunAzimuth()));
      gp->AddKeyword(PvlKeyword("SolarDistance",camera->SolarDistance(),"AU"));
      camera->SubSolarPoint(sslat,sslon);
      gp->AddKeyword(PvlKeyword("SubSolarLatitude",sslat));
      gp->AddKeyword(PvlKeyword("SubSolarLongitude",sslon));
      double subsolgrdaz;
      subsolgrdaz = camera->GroundAzimuth(camera->UniversalLatitude(),camera->UniversalLongitude(),
        sslat,sslon);
      gp->AddKeyword(PvlKeyword("SubSolarGroundAzimuth",subsolgrdaz));
  
      PvlKeyword phase("Phase",camera->PhaseAngle());
      phase.AddComment("Illumination and Other");
      gp->AddKeyword(phase);
      gp->AddKeyword(PvlKeyword("Incidence",camera->IncidenceAngle()));
      gp->AddKeyword(PvlKeyword("Emission",camera->EmissionAngle()));
      gp->AddKeyword(PvlKeyword("NorthAzimuth",camera->NorthAzimuth()));
  
      PvlKeyword et("EphemerisTime",camera->EphemerisTime(),"seconds");
      et.AddComment("Time");
      gp->AddKeyword(et);
      iTime t(camera->EphemerisTime());
      utc = t.UTC();
      gp->AddKeyword(PvlKeyword("UTC",utc));
      gp->AddKeyword(PvlKeyword("LocalSolarTime",camera->LocalSolarTime(),"hour"));
      gp->AddKeyword(PvlKeyword("SolarLongitude",camera->SolarLongitude()));
    }
    return gp;
  }
Beispiel #2
0
bool TryKernels(Cube *icube, Process &p,
                Kernel lk, Kernel pck, 
                Kernel targetSpk, Kernel ck,
                Kernel fk, Kernel ik, Kernel sclk, 
                Kernel spk, Kernel iak, 
                Kernel dem, Kernel exk) {
  Pvl lab = *icube->Label();

  // Add the new kernel files to the existing kernels group
  PvlKeyword lkKeyword("LeapSecond");
  PvlKeyword pckKeyword("TargetAttitudeShape");
  PvlKeyword targetSpkKeyword("TargetPosition");
  PvlKeyword ckKeyword("InstrumentPointing");
  PvlKeyword ikKeyword("Instrument");
  PvlKeyword sclkKeyword("SpacecraftClock");
  PvlKeyword spkKeyword("InstrumentPosition");
  PvlKeyword iakKeyword("InstrumentAddendum");
  PvlKeyword demKeyword("ShapeModel");
  PvlKeyword exkKeyword("Extra");

  for (int i=0; i<lk.size(); i++) {
    lkKeyword.AddValue(lk[i]);
  }
  for (int i=0; i<pck.size(); i++) {
    pckKeyword.AddValue(pck[i]);
  }
  for (int i=0; i<targetSpk.size(); i++) {
    targetSpkKeyword.AddValue(targetSpk[i]);
  }
  for (int i=0; i<ck.size(); i++) {
    ckKeyword.AddValue(ck[i]);
  }
  for (int i=0; i<ik.size(); i++) {
    ikKeyword.AddValue(ik[i]);
  }
  for (int i=0; i<sclk.size(); i++) {
    sclkKeyword.AddValue(sclk[i]);
  }
  for (int i=0; i<spk.size(); i++) {
    spkKeyword.AddValue(spk[i]);
  }
  for (int i=0; i<iak.size(); i++) {
    iakKeyword.AddValue(iak[i]);
  }
  for (int i=0; i<dem.size(); i++) {
    demKeyword.AddValue(dem[i]);
  }
  for (int i=0; i<exk.size(); i++) {
    exkKeyword.AddValue(exk[i]);
  }

  PvlGroup originalKernels = icube->GetGroup("Kernels");
  PvlGroup currentKernels = originalKernels;
  currentKernels.AddKeyword(lkKeyword, Pvl::Replace);
  currentKernels.AddKeyword(pckKeyword, Pvl::Replace);
  currentKernels.AddKeyword(targetSpkKeyword, Pvl::Replace);
  currentKernels.AddKeyword(ckKeyword, Pvl::Replace);
  currentKernels.AddKeyword(ikKeyword, Pvl::Replace);
  currentKernels.AddKeyword(sclkKeyword, Pvl::Replace);
  currentKernels.AddKeyword(spkKeyword, Pvl::Replace);
  currentKernels.AddKeyword(iakKeyword, Pvl::Replace);
  currentKernels.AddKeyword(demKeyword, Pvl::Replace);

  // report qualities
  PvlKeyword spkQuality("InstrumentPositionQuality");
  spkQuality.AddValue(spiceInit::kernelTypeEnum(spk.kernelType));
  currentKernels.AddKeyword(spkQuality, Pvl::Replace);

  PvlKeyword ckQuality("InstrumentPointingQuality");
  ckQuality.AddValue(spiceInit::kernelTypeEnum(ck.kernelType));
  currentKernels.AddKeyword(ckQuality, Pvl::Replace);

  if (!exkKeyword.IsNull()) {
    currentKernels.AddKeyword(exkKeyword, Pvl::Replace);
  }
  else if( currentKernels.HasKeyword("EXTRA") ) {
    currentKernels.DeleteKeyword( "EXTRA" );
  }

  // Get rid of old keywords from previously inited cubes
  if (currentKernels.HasKeyword("SpacecraftPointing")) {
    currentKernels.DeleteKeyword("SpacecraftPointing");
  }
  if (currentKernels.HasKeyword("SpacecraftPosition")) {
    currentKernels.DeleteKeyword("SpacecraftPosition");
  }
  if (currentKernels.HasKeyword("ElevationModel")) {
    currentKernels.DeleteKeyword("ElevationModel");
  }
  if (currentKernels.HasKeyword("Frame")) {
    currentKernels.DeleteKeyword("Frame");
  }
  if (currentKernels.HasKeyword("StartPadding")) {
    currentKernels.DeleteKeyword("StartPadding");
  }
  if (currentKernels.HasKeyword("EndPadding")) {
    currentKernels.DeleteKeyword("EndPadding");
  }

  UserInterface &ui = Application::GetUserInterface();
  // Add any time padding the user specified to the spice group
  if(ui.GetDouble("STARTPAD") > DBL_EPSILON) {
     currentKernels.AddKeyword(PvlKeyword("StartPadding", ui.GetDouble("STARTPAD"), "seconds"));
  }

  if(ui.GetDouble("ENDPAD") > DBL_EPSILON) {
     currentKernels.AddKeyword(PvlKeyword("EndPadding", ui.GetDouble("ENDPAD"), "seconds"));
  }

  currentKernels.AddKeyword(PvlKeyword("CameraVersion",CameraFactory::CameraVersion(lab)), Pvl::Replace);

  // Add the modified Kernels group to the input cube labels
  icube->PutGroup(currentKernels);

  // Create the camera so we can get blobs if necessary
  try {
    Camera *cam;
    try {
      cam = icube->Camera();
      Application::Log(currentKernels);
    } catch (iException &e) {
      Pvl errPvl = e.PvlErrors();

      if(errPvl.Groups() > 0) {
        currentKernels += PvlKeyword("Error", errPvl.Group(errPvl.Groups()-1)["Message"][0]); 
      }
      
      Application::Log(currentKernels);
      icube->PutGroup(originalKernels);
      throw e;
    }
    if (ui.GetBoolean("ATTACH")) {
      Table ckTable = cam->InstrumentRotation()->Cache("InstrumentPointing");
      ckTable.Label() += PvlKeyword("Description", "Created by spiceinit");
      ckTable.Label() += PvlKeyword("Kernels");

      for (int i=0; i<ckKeyword.Size(); i++) {
        ckTable.Label()["Kernels"].AddValue(ckKeyword[i]);
      }
      icube->Write(ckTable);

      Table spkTable = cam->InstrumentPosition()->Cache("InstrumentPosition");
      spkTable.Label() += PvlKeyword("Description", "Created by spiceinit");
      spkTable.Label() += PvlKeyword("Kernels");
      for (int i=0; i<spkKeyword.Size(); i++) {
        spkTable.Label()["Kernels"].AddValue(spkKeyword[i]);
      }
      icube->Write(spkTable);

      Table bodyTable = cam->BodyRotation()->Cache("BodyRotation");
      bodyTable.Label() += PvlKeyword("Description", "Created by spiceinit");
      bodyTable.Label() += PvlKeyword("Kernels");
      for (int i=0; i<targetSpkKeyword.Size(); i++) {
        bodyTable.Label()["Kernels"].AddValue(targetSpkKeyword[i]);
      }
      for (int i=0; i<pckKeyword.Size(); i++) {
        bodyTable.Label()["Kernels"].AddValue(pckKeyword[i]);
      }
      bodyTable.Label() += PvlKeyword("SolarLongitude", cam->SolarLongitude());
      icube->Write(bodyTable);

      Table sunTable = cam->SunPosition()->Cache("SunPosition");
      sunTable.Label() += PvlKeyword("Description", "Created by spiceinit");
      sunTable.Label() += PvlKeyword("Kernels");
      for (int i=0; i<targetSpkKeyword.Size(); i++) {
        sunTable.Label()["Kernels"].AddValue(targetSpkKeyword[i]);
      }
      icube->Write(sunTable);

      //  Save original kernels in keyword before changing to Table
      PvlKeyword origCk = currentKernels["InstrumentPointing"];
      PvlKeyword origSpk = currentKernels["InstrumentPosition"];
      PvlKeyword origTargPos = currentKernels["TargetPosition"];

      currentKernels["InstrumentPointing"] = "Table";
      for (int i=0; i<origCk.Size(); i++) {
        currentKernels["InstrumentPointing"].AddValue(origCk[i]);
      }
      currentKernels["InstrumentPosition"] = "Table";
      for (int i=0; i<origSpk.Size(); i++) {
        currentKernels["InstrumentPosition"].AddValue(origSpk[i]);
      }
      currentKernels["TargetPosition"] = "Table";
      for (int i=0; i<origTargPos.Size(); i++) {
        currentKernels["TargetPosition"].AddValue(origTargPos[i]);
      }
      icube->PutGroup(currentKernels);
    }
    //modify Kernels group only
    else {
      Pvl *label = icube->Label();
      int i=0;
      while (i < label->Objects()) {
        PvlObject currObj = label->Object(i);
        if (currObj.IsNamed("Table")) {
          if (currObj["Name"][0] == iString("InstrumentPointing")) {
            label->DeleteObject(i);
          } else if (currObj["Name"][0] == iString("InstrumentPosition")) {
            label->DeleteObject(i);
          } else if (currObj["Name"][0] == iString("BodyRotation")) {
            label->DeleteObject(i);
          } else if (currObj["Name"][0] == iString("SunPosition")) {
            label->DeleteObject(i);
          } else {
            i++;
          }
        } else {
          i++;
        }
      }
    }

    p.WriteHistory(*icube);
  } catch (iException &e) {
    e.Clear();
    icube->PutGroup(originalKernels);
    return false;
  }

  return true;
}
Beispiel #3
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;
}