コード例 #1
0
ファイル: ifft.cpp プロジェクト: jlaura/isis3
void IsisMain() {
  // We will be processing by line first
  ProcessByTile lProc;
  lProc.Progress()->SetText("First pass");

  // Setup the input and output cubes
  Cube *magCube = lProc.SetInputCube("MAGNITUDE");
  Cube *phaseCube = lProc.SetInputCube("PHASE");

  AlphaCube acube(*magCube);
  int initSamples = acube.BetaSamples();
  int initLines = acube.BetaLines();

  int numSamples = magCube->sampleCount();
  int numLines = magCube->lineCount();
  int numBands = magCube->bandCount();

  // error checking for valid input cubes
  // i.e. the dimensions of the magnitude and phase cubes
  // are the same and are powers of two
  if(!fft.IsPowerOfTwo(numSamples) || !fft.IsPowerOfTwo(numLines)
      || magCube->sampleCount() != phaseCube->sampleCount()
      || magCube->lineCount() != phaseCube->lineCount()) {
    cerr << "Invalid Cubes: the dimensions of both cubes must be equal"
            " powers of 2." << endl;
    return;
  }

  lProc.SetTileSize(numSamples, 1);

  Isis::CubeAttributeOutput cao;

  lProc.SetOutputCube(tmpMagFileName, cao, numSamples, numLines, numBands);
  lProc.SetOutputCube(tmpPhaseFileName, cao, numSamples, numLines, numBands);

  // Start the line processing
  lProc.ProcessCubes(&IFFT2);
  lProc.Finalize();

  // Then process by sample
  ProcessByTile sProc;
  sProc.Progress()->SetText("Second pass");
  sProc.SetTileSize(1, numLines);

  // Setup the input and output cubes
  Isis::CubeAttributeInput cai;

  sProc.SetInputCube(tmpMagFileName, cai);
  sProc.SetInputCube(tmpPhaseFileName, cai);

  // the final output cube is cropped back to the original size
  sProc.SetOutputCube("TO", initSamples, initLines, numBands);

  //Start the sample proccessing
  sProc.ProcessCubes(&IFFT1);
  sProc.Finalize();

  remove(tmpMagFileName.toAscii().data());
  remove(tmpPhaseFileName.toAscii().data());
}
コード例 #2
0
ファイル: isis2ascii.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  // Create a process by line object
  ProcessByLine p;

  // Get the size of the cube
  Cube *icube = p.SetInputCube("FROM");

  //  Open output text file
  UserInterface &ui = Application::GetUserInterface();
  QString to = ui.GetFileName("TO", "txt");
  fout.open(to.toAscii().data());

  // Print header if needed
  if(ui.GetBoolean("HEADER")) {
    fout << "Input Cube:  " << icube->fileName() << endl;
    fout << "Samples:Lines:Bands:  " << icube->sampleCount() << ":" <<
         icube->lineCount() << ":" << icube->bandCount() << endl;
  }

  // List the cube
  p.StartProcess(isis2ascii);
  p.EndProcess();

  fout.close();
}
コード例 #3
0
ファイル: Hillier.cpp プロジェクト: corburn/ISIS
  /**
   * @brief Initialize class from input PVL and Cube files
   *
   * This method is typically called at class instantiation time,
   * but is reentrant.  It reads the parameter PVL file and
   * extracts Photometric model and Normalization models from it.
   * The cube is needed to match all potential profiles for each
   * band.
   *
   * @param pvl  Input PVL parameter files
   * @param cube Input cube file to correct
   *
   * @author Kris Becker - 2/22/2010
   * @history 2010-02-25 Kris Becker Added check for valid incidence angle
   */
  void Hillier::init(PvlObject &pvl, Cube &cube) {

    //  Make it reentrant
    _profiles.clear();
    _bandpho.clear();

    //  Interate over all Photometric groups
    _normProf = DbProfile(pvl.findObject("NormalizationModel").findGroup("Algorithm", Pvl::Traverse));
    _iRef = toDouble(ConfKey(_normProf, "IncRef", toString(30.0)));
    _eRef = toDouble(ConfKey(_normProf, "EmaRef", toString(0.0)));
    _gRef = toDouble(ConfKey(_normProf, "PhaRef", toString(_iRef)));

    // Check for valid incidence angle
    if(_iRef > fabs(90.0)) {
      ostringstream mess;
      mess << "Invalid incidence angle (" << _iRef
           << " >= 90.0) provided in PVL config file " << pvl.fileName();
      throw IException(IException::User, mess.str(), _FILEINFO_);
    }


    PvlObject &phoObj = pvl.findObject("PhotometricModel");
    DbProfile phoProf = DbProfile(phoObj);
    PvlObject::PvlGroupIterator algo = phoObj.beginGroup();
    while(algo != phoObj.endGroup()) {
      if(algo->name().toLower() == "algorithm") {
        _profiles.push_back(DbProfile(phoProf, DbProfile(*algo)));
      }
      ++algo;
    }

    Pvl *label = cube.label();
    PvlKeyword center = label->findGroup("BandBin", Pvl::Traverse)["Center"];
    QString errs("");
    for(int i = 0; i < cube.bandCount() ; i++) {
      Parameters parms = findParameters(toDouble(center[i]));
      if(parms.IsValid()) {
        parms.band = i + 1;
        _camera->SetBand(i + 1);
        parms.phoStd = photometry(parms, _iRef, _eRef, _gRef);
        _bandpho.push_back(parms);
      }
      else {  // Appropriate photometric parameters not found
        ostringstream mess;
        mess << "Band " << i + 1 << " with wavelength Center = " << center[i]
             << " does not have PhotometricModel Algorithm group/profile";
        IException e(IException::User, mess.str(), _FILEINFO_);
        errs += e.toString() + "\n";
      }
    }

    // Check for errors and throw them all at the same time
    if(!errs.isEmpty()) {
      errs += " --> Errors in the input PVL file \"" + pvl.fileName() + "\"";
      throw IException(IException::User, errs, _FILEINFO_);
    }

    return;
  }
コード例 #4
0
ファイル: decorstretch.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  ProcessByBrick p;
  Cube *icube = p.SetInputCube("FROM");
  int numDimensions = icube->bandCount();
  p.SetBrickSize(128, 128, numDimensions);

  // The output cube with no attributes and real pixel type
  Isis::CubeAttributeOutput cao;
  cao.setPixelType(Isis::Real);

  p.SetOutputCube(tmpFileName, cao, icube->sampleCount(), icube->lineCount(), icube->bandCount());

  // Get the data for the transform matrix
  pca = Isis::PrincipalComponentAnalysis(numDimensions);
  ProcessByBrick p2;
  p2.SetBrickSize(128, 128, numDimensions);
  p2.SetInputCube("FROM");
  p2.Progress()->SetText("Computing Transform");
  p2.StartProcess(GetData);
  p2.EndProcess();
  pca.ComputeTransform();

  p.Progress()->SetText("Transforming Cube");
  p.StartProcess(Transform);
  p.EndProcess();

  Isis::CubeAttributeInput cai;

  Cube *icube2 = p.SetInputCube(tmpFileName, cai);
  for(int i = 0; i < numDimensions; i++) {
    stretches.push_back(new GaussianStretch(*(icube2->histogram(i + 1))));
  }
  p.SetOutputCube("TO");

  p.SetBrickSize(128, 128, numDimensions);
  p.Progress()->SetText("Stretching Cube");
  p.StartProcess(NormalizeAndInvert);

  for(int i = 0; i < numDimensions; i++) delete stretches[i];
  stretches.clear();

  p.EndProcess();

  remove(tmpFileName.toAscii().data());
}
コード例 #5
0
ファイル: gaussstretch.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  ProcessByLine p;
  Cube *icube = p.SetInputCube("FROM");
  p.SetOutputCube("TO");
  double gsigma = Isis::Application::GetUserInterface().GetDouble("GSIGMA");

  for(int i = 0; i < icube->bandCount(); i++) {
    Histogram hist = *(icube->histogram(i + 1));
    double mean = (hist.Maximum() + hist.Minimum()) / 2.0;
    double stdev = (hist.Maximum() - hist.Minimum()) / (2.0 * gsigma);
    stretch.push_back(new GaussianStretch(hist, mean, stdev));
  }

  p.StartProcess(gauss);
  for(int i = 0; i < icube->bandCount(); i++) delete stretch[i];
  stretch.clear();
  p.EndProcess();
}
コード例 #6
0
ファイル: ProcessMapMosaic.cpp プロジェクト: corburn/ISIS
  /**
   * Set the output cube to specified file name and specified input images
   * and output attributes and lat,lons
   */
  Isis::Cube *ProcessMapMosaic::SetOutputCube(const QString &inputFile, PvlGroup mapping,
      CubeAttributeOutput &oAtt, const QString &mosaicFile) {
    if (OutputCubes.size() != 0) {
      QString msg = "You can only specify one output cube and projection";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    if (mapping.hasKeyword("UpperLeftCornerX"))
      mapping.deleteKeyword("UpperLeftCornerX");

    if (mapping.hasKeyword("UpperLeftCornerY"))
      mapping.deleteKeyword("UpperLeftCornerY");

    if (p_createMosaic) {
      Pvl newMap;
      newMap.addGroup(mapping);
      int samps, lines, bands;
      delete ProjectionFactory::CreateForCube(newMap, samps, lines, false);

      // Initialize the mosaic
      ProcessByLine p;
      CubeAttributeInput inAtt(inputFile);
      Cube *propCube = p.SetInputCube(inputFile, inAtt);
      bands = propCube->bandCount();

      // If track set, create the origin band
      if (GetTrackFlag()) {
        bands += 1;
      }
      // For average priority, get the new band count
      else if (GetImageOverlay() == AverageImageWithMosaic) {
        bands *= 2;
      }

      p.PropagateHistory(false);
      p.PropagateLabels(false);
      Cube *ocube = p.SetOutputCube(mosaicFile, oAtt, samps, lines, bands);
      p.Progress()->SetText("Initializing mosaic");
      p.ClearInputCubes();

      p.StartProcess(ProcessMapMosaic::FillNull);

      // CreateForCube created some keywords in the mapping group that needs to be added
      ocube->putGroup(newMap.findGroup("Mapping", Pvl::Traverse));
      p.EndProcess();
    }

    Cube *mosaicCube = new Cube();
    AddOutputCube(mosaicCube);
    mosaicCube->open(mosaicFile, "rw");
    mosaicCube->addCachingAlgorithm(new UniqueIOCachingAlgorithm(2));

    return mosaicCube;
  }
コード例 #7
0
ファイル: lrowaccal.cpp プロジェクト: corburn/ISIS
void CopyCubeIntoBuffer ( QString &fileString, Buffer* &data) {
  Cube cube;
  FileName filename(fileString);
  if (filename.isVersioned())
    filename = filename.highestVersion();
  if (!filename.fileExists()) {
    QString msg = fileString + " does not exist.";
    throw IException(IException::User, msg, _FILEINFO_);
  }
  cube.open(filename.expanded());
  Brick brick(cube.sampleCount(), cube.lineCount(), cube.bandCount(), cube.pixelType());
  brick.SetBasePosition(1, 1, 1);
  cube.read(brick);

  data = new Buffer(brick);

  fileString = filename.expanded();
}
コード例 #8
0
ファイル: rotate.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  ProcessRubberSheet p;

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

  // Set up the transform object
  UserInterface &ui = Application::GetUserInterface();
  Transform *transform = new Rotate(icube->sampleCount(), icube->lineCount(),
                                    ui.GetDouble("DEGREES"));

  // Determine the output size
  int samples = transform->OutputSamples();
  int lines = transform->OutputLines();

  // Allocate the output file
  p.SetOutputCube("TO", samples, lines, icube->bandCount());

  // 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 {
    QString msg = "Unknow value for INTERP [" +
                  ui.GetString("INTERP") + "]";
    throw IException(IException::Programmer, msg, _FILEINFO_);
  }

  p.StartProcess(*transform, *interp);
  p.EndProcess();

  delete transform;
  delete interp;
}
コード例 #9
0
ファイル: map2map.cpp プロジェクト: jlaura/isis3
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->group("Mapping");
  TProjection *inproj = (TProjection *) 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", toString(ui.GetDouble("MINLAT"))), Pvl::Replace);
  }

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

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

  if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.addKeyword(PvlKeyword("MaximumLongitude", toString(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(((QString)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"] = toString(minLon);
    outMappingGrp["MinimumLongitude"] = toString(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", toString(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", toString(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(((QString)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) {
          outMappingGrp[longitudes[index].name()] = toString(
            TProjection::ToPositiveEast(outMappingGrp[longitudes[index].name()],
                                        outMappingGrp["LongitudeDomain"]));
        }
        else {
          outMappingGrp[longitudes[index].name()] = toString(
              TProjection::ToPositiveWest(outMappingGrp[longitudes[index].name()],
                                          outMappingGrp["LongitudeDomain"]));
        }
      }
    }
  }

  // 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()] = toString(
                TProjection::To180Domain(outMappingGrp[longitudes[index].name()]));
          }
          else {
            outMappingGrp[longitudes[index].name()] = toString(
                TProjection::To360Domain(outMappingGrp[longitudes[index].name()]));
          }
        }
      }

    }
  }

  // Third, planetographic/planetocentric
  if(userMappingGrp.hasKeyword("LatitudeType")) { // user set a new domain?
    if(((QString)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(((QString)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) {
            outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetographic(
                  (double)fromMappingGrp[latitudes[index].name()],
                  (double)fromMappingGrp["EquatorialRadius"],
                  (double)fromMappingGrp["PolarRadius"]));
          }
          else {
            outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetocentric(
                  (double)fromMappingGrp[latitudes[index].name()],
                  (double)fromMappingGrp["EquatorialRadius"],
                  (double)fromMappingGrp["PolarRadius"]));
          }
        }
      }

    }
  }

  // Try a couple equivalent longitudes to fix the ordering of min,max for border cases
  if ((double)outMappingGrp["MinimumLongitude"] >=
      (double)outMappingGrp["MaximumLongitude"]) {

    if ((QString)outMappingGrp["MinimumLongitude"] == "180.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 180)
      outMappingGrp["MinimumLongitude"] = "-180";

    if ((QString)outMappingGrp["MaximumLongitude"] == "-180.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 180)
      outMappingGrp["MaximumLongitude"] = "180";

    if ((QString)outMappingGrp["MinimumLongitude"] == "360.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 360)
      outMappingGrp["MinimumLongitude"] = "0";

    if ((QString)outMappingGrp["MaximumLongitude"] == "0.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 360)
      outMappingGrp["MaximumLongitude"] = "360";
  }

  // 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")) {
      QString msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude].";
      msg += " Please specify these values in the [MINLON,MAXLON] parameters";
      throw IException(IException::Unknown, 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.
  TProjection *outproj = (TProjection *) 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->sampleCount(),
                                     icube->lineCount(),
                                     (TProjection *) 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->bandCount());

  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 {
    QString msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]";
    throw IException(IException::Programmer, msg, _FILEINFO_);
  }

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

  Application::Log(cleanOutGrp);

  // Cleanup
  delete transform;
  delete interp;
}
コード例 #10
0
ファイル: smtk.cpp プロジェクト: corburn/ISIS
/** The ISIS smtk main application */
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();

  // Open the first cube.  It is the left hand image.
  Cube lhImage;
  CubeAttributeInput &attLeft = ui.GetInputAttribute("FROM");
  vector<QString> bandLeft = attLeft.bands();
  lhImage.setVirtualBands(bandLeft);
  lhImage.open(ui.GetFileName("FROM"),"r");

  // Open the second cube, it is geomertricallty altered.  We will be matching the
  // first to this one by attempting to compute a sample/line offsets
  Cube rhImage;
  CubeAttributeInput &attRight = ui.GetInputAttribute("MATCH");
  vector<QString> bandRight = attRight.bands();
  rhImage.setVirtualBands(bandRight);
  rhImage.open(ui.GetFileName("MATCH"),"r");

  // Ensure only single bands
  if (lhImage.bandCount() != 1 || rhImage.bandCount() != 1) {
    QString msg = "Input Cubes must have only one band!";
    throw IException(IException::User,msg,_FILEINFO_);
  }

  //  Both images must have a Camera and can also have a Projection.  We will
  //  only deal with a Camera, however as a projected, non-mosaicked image
  //  uses a Projection internal to the Camera object.
  Camera *lhCamera = NULL;
  Camera *rhCamera = NULL;
  try {
    lhCamera = lhImage.camera();
    rhCamera = rhImage.camera();
  }
  catch (IException &ie) {
    QString msg = "Both input images must have a camera";
    throw IException(ie, IException::User, msg, _FILEINFO_);
  }

  //  Since we are generating a DEM, we must turn off any existing
  //  DEM that may have been initialized with spiceinit.
  lhCamera->IgnoreElevationModel(true);
  rhCamera->IgnoreElevationModel(true);

  // Get serial number
  QString serialLeft = SerialNumber::Compose(lhImage, true);
  QString serialRight = SerialNumber::Compose(rhImage, true);

//  This still precludes band to band registrations.
  if (serialLeft == serialRight) {
    QString sLeft = FileName(lhImage.fileName()).name();
    QString sRight = FileName(rhImage.fileName()).name();
    if (sLeft == sRight) {
      QString msg = "Cube Serial Numbers must be unique - FROM=" + serialLeft +
                   ", MATCH=" + serialRight;
      throw IException(IException::User,msg,_FILEINFO_);
    }
    serialLeft = sLeft;
    serialRight = sRight;
  }

  Progress prog;
  prog.SetText("Finding Initial Seeds");

  int nl = lhImage.lineCount();
  int ns = lhImage.sampleCount();
  BigInt numAttemptedInitialPoints = 0;

  //  Declare Gruen matcher
  SmtkMatcher matcher(ui.GetFileName("REGDEF"), &lhImage, &rhImage);

  // Get line/sample linc/sinc parameters
  int space   = ui.GetInteger("SPACE");
  int linc (space), sinc(space);

  // Do we have a seed points from a control net file?
  bool useseed = ui.WasEntered("CNET");

  // Base points on an input cnet
  SmtkQStack gstack;
  double lastEigen(0.0);
  if (useseed) {
    ControlNet cnet(ui.GetFileName("CNET"));
    prog.SetMaximumSteps(cnet.GetNumPoints());
    prog.CheckStatus();

    gstack.reserve(cnet.GetNumPoints());

    for (int cpIndex = 0; cpIndex < cnet.GetNumPoints(); cpIndex ++) {
      ControlPoint *cp = cnet.GetPoint(cpIndex);

      if (!cp->IsIgnored()) {
        ControlMeasure *cmLeft(0), *cmRight(0);
        for(int cmIndex = 0; cmIndex < cp->GetNumMeasures(); cmIndex ++) {
          ControlMeasure *cm = cp->GetMeasure(cmIndex);
          if (!cm->IsIgnored()) {
            if (cm->GetCubeSerialNumber() == serialLeft)
              cmLeft = cp->GetMeasure(cmIndex);
            if (cm->GetCubeSerialNumber() == serialRight)
              cmRight = cp->GetMeasure(cmIndex);
          }
        }

        //  If we have both left and right images in the control point, save it
        if ( (cmLeft != 0) && (cmRight != 0) ) {
          Coordinate left = Coordinate(cmLeft->GetLine(), cmLeft->GetSample());
          Coordinate right = Coordinate(cmRight->GetLine(), cmRight->GetSample());
          SmtkPoint spnt = matcher.Create(left, right);

          // Insert the point (unregistered)
          if ( spnt.isValid() ) {
            int line = (int) cmLeft->GetLine();
            int samp = (int) cmLeft->GetSample();
            matcher.isValid(spnt);
            gstack.insert(qMakePair(line, samp), spnt);
            lastEigen = spnt.GoodnessOfFit();
          }
        }
      }

      prog.CheckStatus();
    }
  }
  else {
  // We want to create a grid of control points that is N rows by M columns.

    int rows = (lhImage.lineCount() + linc - 1)/linc;
    int cols = (lhImage.sampleCount() + sinc - 1)/sinc;

    prog.SetMaximumSteps(rows * cols);
    prog.CheckStatus();

    // First pass stack and eigen value statistics
    SmtkQStack fpass;
    fpass.reserve(rows * cols);
    Statistics temp_mev;

    // Loop through grid of points and get statistics to compute
    // initial set of points
    for (int line = linc / 2 + 1; line < nl; line += linc) {
      for (int samp = sinc / 2 + 1 ; samp < ns; samp += sinc) {
        numAttemptedInitialPoints ++;
        SmtkPoint spnt = matcher.Register(Coordinate(line,samp));
        if ( spnt.isValid() ) {
          matcher.isValid(spnt);
          fpass.insert(qMakePair(line, samp), spnt);
          temp_mev.AddData(spnt.GoodnessOfFit());
        }
        prog.CheckStatus();
      }
    }

    //  Now select a subset of fpass points as the seed points
    cout << "Number of Potential Seed Points: " << fpass.size() << "\n";
    cout << "Min / Max Eigenvalues Matched: " << temp_mev.Minimum() << ", "
         << temp_mev.Maximum() << "\n";

    // How many seed points are requested
    double nseed = ui.GetDouble("NSEED");
    int inseed;
    if (nseed >= 1.0) inseed = (int) nseed;
    else if (nseed > 0.0) inseed = (int) (nseed * (double) (fpass.size()));
    else inseed = (int) ((double) (fpass.size()) * 0.05);

    double seedsample = ui.GetDouble("SEEDSAMPLE");

    // Generate a new stack
    gstack.reserve(inseed);
    while ((gstack.size() < inseed) && (!fpass.isEmpty() )) {
      SmtkQStack::iterator bestm;
      if (seedsample <= 0.0) {
        bestm = matcher.FindSmallestEV(fpass);
      }
      else {
        bestm = matcher.FindExpDistEV(fpass, seedsample, temp_mev.Minimum(),
                                      temp_mev.Maximum());
      }

      //  Add point to stack
      if (bestm != fpass.end()) {
        Coordinate right = bestm.value().getRight();
        matcher.isValid(bestm.value());
        gstack.insert(bestm.key(), bestm.value());
        lastEigen = bestm.value().GoodnessOfFit();
        fpass.erase(bestm);
      }
    }

    // If a user wants to see the seed network, write it out here
    if (ui.WasEntered("OSEEDNET")) {
      WriteCnet(ui.GetFileName("OSEEDNET"), gstack,
                lhCamera->target()->name(), serialLeft, serialRight);
    }

  }

  ///////////////////////////////////////////////////////////////////////
  // All done with seed points.  Sanity check ensures we actually found
  // some.
  ///////////////////////////////////////////////////////////////////////
  if (gstack.size() <= 0) {
    QString msg = "No seed points found - may need to check Gruen parameters.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  //  Report seed point status
  if (!useseed) {
    cout << "Number of Seed Points used: " << gstack.size() << "\n";
    cout << "EV of last Seed Point:      " << lastEigen << "\n";
  }
  else {
    cout << "Number of Manual Seed Points:   " << gstack.size() << "\n";
  }

  // Use seed points (in stack) to grow
  SmtkQStack bmf;
  bmf.reserve(gstack.size());  // Probably need much more but for starters...

  BigInt numOrigPoints = gstack.size();
  BigInt passpix2 = 0;

  int subcbox = ui.GetInteger("SUBCBOX");
  int halfBox((subcbox-1)/2);
  while (!gstack.isEmpty()) {

    SmtkQStackIter cstack = matcher.FindSmallestEV(gstack);

    // Print number on stack
    if ((gstack.size() % 1000) == 0) {
      cout << "Number on Stack: " << gstack.size()
           << ". " << cstack.value().GoodnessOfFit() << "\n";
    }

    // Test to see if already determined
    SmtkQStackIter bmfPt = bmf.find(cstack.key());
    if (bmfPt == bmf.end()) {
      // Its not in the final stack, process it

      //  Retrieve the point
      SmtkPoint spnt = cstack.value();
      //  Register if its not already registered
      if (!spnt.isRegistered()) {
        spnt = matcher.Register(spnt, spnt.getAffine());
      }

      // Still must check for validity if the point was just registered,
      // otherwise should be good
      if ( spnt.isValid() ) {
        passpix2++;
        bmf.insert(cstack.key(), spnt);  // inserts (0,0) offset excluded below
        int line   = cstack.key().first;
        int sample = cstack.key().second;

        //  Determine match points
        double eigen(spnt.GoodnessOfFit());
        for (int sampBox = -halfBox ; sampBox <= halfBox ; sampBox++ ) {
          int csamp = sample + sampBox;
          for (int lineBox = -halfBox ; lineBox <= halfBox ; lineBox++) {
            int cline = line + lineBox;
            if ( !( (sampBox == 0) && (lineBox == 0)) ) {// Already added above
              SmtkQPair dupPair(cline, csamp);
              SmtkQStackIter temp = bmf.find(dupPair);
              SmtkPoint bmfpnt;
              if (temp != bmf.end()) {
                if (temp.value().GoodnessOfFit() > eigen) {
                  // Create cloned point with better fit
                  bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp));
                }
              }
              else {  // ISIS2 is BMF(SAMP,LINE,7) .EQ VALID_MAX4)
                // Clone new point for insert
                bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp));
              }

              //  Add if good point
              if (bmfpnt.isValid()) {
                bmf.insert(dupPair, bmfpnt);
              }
            }
          }
        }

        // Grow stack with spacing adding info to stack
        for (int i = -1 ; i <= 1 ; i ++) {  // Sample
          for (int j = -1 ; j <= 1 ; j ++) {  // Line
            // Don't re-add the original sample, line
            if ( !((i == 0) && (j == 0)) ) {
              //  Grow based upon spacing
              double ssamp = sample + (i * space);
              double sline = line   + (j * space);
              Coordinate pnt = Coordinate(sline, ssamp);
              SmtkPoint gpnt = matcher.Clone(spnt, pnt);

              if ( gpnt.isValid() ) {
                SmtkQPair growpt((int) sline, (int) ssamp);

                // double check we don't have a finalized result at this position
                SmtkQStackIter temp = bmf.find(growpt);
                if(temp == bmf.end()) {
                  gstack.insert(growpt, gpnt);
                }
              }
            }
          }
        }
      }
    }

    // Remove the current point from the grow stack (hole)
    gstack.erase(cstack);
  }

/////////////////////////////////////////////////////////////////////////
// All done with creating points.  Perform output options.
/////////////////////////////////////////////////////////////////////////

  // If a TO parameter was specified, create DEM with errors
  if (ui.WasEntered("TO")) {
    //  Create the output DEM
    cout << "\nCreating output DEM from " << bmf.size() << " points.\n";
    Process  p;
    Cube *icube = p.SetInputCube("FROM");
    Cube *ocube = p.SetOutputCube("TO", icube->sampleCount(),
                                  icube->lineCount(), 3);
    p.ClearInputCubes();

    int boxsize = ui.GetInteger("BOXSIZE");
    double plotdist = ui.GetDouble("PLOTDIST");

    TileManager dem(*ocube), eigen(*ocube), stErr(*ocube);
    dem.SetTile(1, 1);      //  DEM Data/elevation
    stErr.SetTile(1, 2);    //  Error in stereo computation
    eigen.SetTile(1, 3);    //  Eigenvalue of the solution

    int nBTiles(eigen.Tiles()/3);  // Total tiles / 3 bands

    prog.SetText("Creating DEM");
    prog.SetMaximumSteps(nBTiles);
    prog.CheckStatus();

    Statistics stAng;
    while ( !eigen.end() ) {   // Must use the last band for this!!
      PointPlot tm = for_each(bmf.begin(), bmf.end(), PointPlot(dem, plotdist));
      tm.FillPoints(*lhCamera, *rhCamera, boxsize, dem, stErr, eigen, &stAng);

      ocube->write(dem);
      ocube->write(stErr);
      ocube->write(eigen);

      dem.next();
      stErr.next();
      eigen.next();

      prog.CheckStatus();
    }

    //  Report Stereo separation angles
    PvlGroup stresultsPvl("StereoSeparationAngle");
    stresultsPvl += PvlKeyword("Minimum", toString(stAng.Minimum()), "deg");
    stresultsPvl += PvlKeyword("Average", toString(stAng.Average()), "deg");
    stresultsPvl += PvlKeyword("Maximum", toString(stAng.Maximum()), "deg");
    stresultsPvl += PvlKeyword("StandardDeviation", toString(stAng.StandardDeviation()), "deg");
    Application::Log(stresultsPvl);

    // Update the label with BandBin keywords
    PvlKeyword filter("FilterName", "Elevation", "meters");
    filter.addValue("ElevationError", "meters");
    filter.addValue("GoodnessOfFit", "unitless");
    PvlKeyword center("Center", "1.0");
    center.addValue("1.0");
    center.addValue("1.0");

    PvlGroup &bandbin = ocube->label()->findGroup("BandBin", PvlObject::Traverse);
    bandbin.addKeyword(filter, PvlContainer::Replace);
    bandbin.addKeyword(center, PvlContainer::Replace);
    center.setName("Width");
    bandbin.addKeyword(center, PvlContainer::Replace);


    p.EndProcess();
  }

  // If a cnet file was entered, write the ControlNet pvl to the file
  if (ui.WasEntered("ONET")) {
    WriteCnet(ui.GetFileName("ONET"), bmf, lhCamera->target()->name(), serialLeft,
              serialRight);
  }

  // Create output data
  PvlGroup totalPointsPvl("Totals");
  totalPointsPvl += PvlKeyword("AttemptedPoints", toString(numAttemptedInitialPoints));
  totalPointsPvl += PvlKeyword("InitialSuccesses", toString(numOrigPoints));
  totalPointsPvl += PvlKeyword("GrowSuccesses", toString(passpix2));
  totalPointsPvl += PvlKeyword("ResultingPoints", toString(bmf.size()));

  Application::Log(totalPointsPvl);

  Pvl arPvl = matcher.RegistrationStatistics();
  PvlGroup smtkresultsPvl("SmtkResults");
  smtkresultsPvl += PvlKeyword("SpiceOffImage", toString(matcher.OffImageErrorCount()));
  smtkresultsPvl += PvlKeyword("SpiceDistanceError", toString(matcher.SpiceErrorCount()));
  arPvl.addGroup(smtkresultsPvl);

  for(int i = 0; i < arPvl.groups(); i++) {
    Application::Log(arPvl.group(i));
  }

  // add the auto registration information to print.prt
  PvlGroup autoRegTemplate = matcher.RegTemplate();
  Application::Log(autoRegTemplate);

  // Don't need the cubes opened anymore
  lhImage.close();
  rhImage.close();
}
コード例 #11
0
ファイル: reduce.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  try {
    // We will be processing by line
    ProcessByLine p;
    double sscale, lscale;
    int ins, inl, inb;
    int ons, onl;
    vector<QString> bands;
    Cube inCube;

    // To propogate labels, set input cube,
    // this cube will be cleared after output cube is set.
    p.SetInputCube("FROM");

    // Setup the input and output cubes
    UserInterface &ui = Application::GetUserInterface();
    QString replaceMode = ui.GetAsString("VPER_REPLACE");
    CubeAttributeInput cai(ui.GetAsString("FROM"));
    bands = cai.bands();

    inCube.setVirtualBands(bands);

    QString from = ui.GetFileName("FROM");
    inCube.open(from);

    ins = inCube.sampleCount();
    inl = inCube.lineCount();
    inb = inCube.bandCount();

    QString alg  = ui.GetString("ALGORITHM");
    double vper = ui.GetDouble("VALIDPER") / 100.;

    if(ui.GetString("MODE") == "TOTAL") {
      ons = ui.GetInteger("ONS");
      onl = ui.GetInteger("ONL");
      sscale = (double)ins / (double)ons;
      lscale = (double)inl / (double)onl;
    }
    else {
      sscale = ui.GetDouble("SSCALE");
      lscale = ui.GetDouble("LSCALE");
      ons = (int)((double)ins / sscale + 0.5);
      onl = (int)((double)inl / lscale + 0.5);
    }

    if(ons > ins || onl > inl) {
      QString msg = "Number of output samples/lines must be less than or equal";
      msg = msg + " to the input samples/lines.";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    //  Allocate output file
    Cube *ocube = p.SetOutputCube("TO", ons, onl, inb);
    // Our processing routine only needs 1
    // the original set was for info about the cube only
    p.ClearInputCubes();

    // Start the processing
    PvlGroup results;
    if(alg == "AVERAGE"){
      Average average(&inCube, sscale, lscale, vper, replaceMode);
      p.ProcessCubeInPlace(average, false);
      results = average.UpdateOutputLabel(ocube);
    }
    else if(alg == "NEAREST") {
      Nearest near(&inCube, sscale, lscale);
      p.ProcessCubeInPlace(near, false);
      results = near.UpdateOutputLabel(ocube);
    }

    // Cleanup
    inCube.close();
    p.EndProcess();

    // Write the results to the log
    Application::Log(results);
  } // REFORMAT THESE ERRORS INTO ISIS TYPES AND RETHROW
  catch (IException &) {
    throw;
  }
  catch (std::exception const &se) {
    QString message = "std::exception: " + (QString)se.what();
    throw IException(IException::User, message, _FILEINFO_);
  }
  catch (...) {
    QString message = "Other Error";
    throw IException(IException::User, message, _FILEINFO_);
  }
}
コード例 #12
0
ファイル: cubeit.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  // Get the list of cubes to stack
  Process p;
  UserInterface &ui = Application::GetUserInterface();
  FileList cubeList(ui.GetFileName("FROMLIST"));

  // Loop through the list
  int nsamps(0), nlines(0), nbands(0);
  PvlGroup outBandBin("BandBin");
  try {
    for(int i = 0; i < cubeList.size(); i++) {
      Cube cube;
      CubeAttributeInput inatt(cubeList[i].original());
      vector<QString> bands = inatt.bands();
      cube.setVirtualBands(bands);
      cube.open(cubeList[i].toString());
      if(i == 0) {
        nsamps = cube.sampleCount();
        nlines = cube.lineCount();
        nbands = cube.bandCount();
      }
      else {
        // Make sure they are all the same size
        if((nsamps != cube.sampleCount()) || (nlines != cube.lineCount())) {
          QString msg = "Spatial dimensions of cube [" +
                        cubeList[i].toString() + "] does not match other cubes in list";
          throw IException(IException::User, msg, _FILEINFO_);
        }
        // Get the total number of bands
        nbands += cube.bandCount();
      }

      // Build up the band bin group
      PvlObject &isiscube = cube.label()->findObject("IsisCube");
      if(isiscube.hasGroup("BandBin")) {
        PvlGroup &inBandBin = isiscube.findGroup("BandBin");
        for(int key = 0; key < inBandBin.keywords(); key++) {
          PvlKeyword &inKey = inBandBin[key];
          if(!outBandBin.hasKeyword(inKey.name())) {
            outBandBin += inKey;
          }
          else {
            PvlKeyword &outKey = outBandBin[inKey.name()];
            for(int index = 0; index < (int)inKey.size(); index++) {
              outKey.addValue(inKey[index], inKey.unit(index));
            }
          }
        }
      }
      cube.close();
    }
  }
  catch(IException &e) {
    QString msg = "Invalid cube in list file [" + ui.GetFileName("FROMLIST") + "]";
    throw IException(e, IException::User, msg, _FILEINFO_);
  }

  // Setup to propagate from the first input cube
  ProcessByLine p2;
  CubeAttributeInput inatt;

  int index = 0;
  if(ui.WasEntered("PROPLAB")) {
    bool match = false;
    QString fname = ui.GetFileName("PROPLAB");
    for(int i = 0; i < cubeList.size(); i++) {
      if(fname == cubeList[i].toString()) {
        index = i;
        match = true;
        break;
      }
    }
    if(!match) {
      QString msg = "FileName [" + ui.GetFileName("PROPLAB") +
                    "] to propagate labels from is not in the list file [" +
                    ui.GetFileName("FROMLIST") + "]";
      throw IException(IException::User, msg, _FILEINFO_);
    }
  }
  p2.SetInputCube(cubeList[index].toString(), inatt);


  // Create the output cube
  Cube *ocube = p2.SetOutputCube("TO", nsamps, nlines, nbands);
  p2.ClearInputCubes();

  p2.Progress()->SetText("Allocating cube");
  p2.StartProcess(NullBand);

  // Add the band bin group if necessary
  if(outBandBin.keywords() > 0) {
    ocube->putGroup(outBandBin);
  }
  p2.EndProcess();

  // Now loop and mosaic in each cube
  int sband = 1;
  for(int i = 0; i < cubeList.size(); i++) {
    ProcessMosaic m;
    m.SetBandBinMatch(false);

    Progress *prog = m.Progress();
    prog->SetText("Adding band " + toString((int)i + 1) +
                  " of " + toString(nbands));
    m.SetOutputCube("TO");
    CubeAttributeInput attrib(cubeList[i].toString());
    Cube *icube = m.SetInputCube(cubeList[i].toString(), attrib);
    m.SetImageOverlay(ProcessMosaic::PlaceImagesOnTop);
    m.StartProcess(1, 1, sband);
    sband += icube->bandCount();
    m.EndProcess();
  }
}
コード例 #13
0
ファイル: lrowaccal.cpp プロジェクト: corburn/ISIS
void IsisMain () {
  ResetGlobals();
  UserInterface &ui = Application::GetUserInterface();

  ProcessByBrick p;
  Cube *icube = p.SetInputCube("FROM");

  // Make sure it is a WAC cube
  Isis::PvlGroup &inst = icube->label()->findGroup("Instrument", Pvl::Traverse);
  QString instId = (QString) inst["InstrumentId"];
  instId = instId.toUpper();
  if (instId != "WAC-VIS" && instId != "WAC-UV") {
    QString msg = "This program is intended for use on LROC WAC images only. [";
    msg += icube->fileName() + "] does not appear to be a WAC image.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  // And check if it has already run through calibration
  if (icube->label()->findObject("IsisCube").hasGroup("Radiometry")) {
    QString msg = "This image has already been calibrated";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  if (icube->label()->findObject("IsisCube").hasGroup("AlphaCube")) {
    QString msg = "This application can not be run on any image that has been geometrically transformed (i.e. scaled, rotated, sheared, or reflected) or cropped.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  g_dark = ui.GetBoolean("DARK");
  g_flatfield = ui.GetBoolean("FLATFIELD");
  g_radiometric = ui.GetBoolean("RADIOMETRIC");
  g_iof = (ui.GetString("RADIOMETRICTYPE") == "IOF");
  g_specpix = ui.GetBoolean("SPECIALPIXELS");
  g_temprature = ui.GetBoolean("TEMPERATURE");

  // Determine the dark/flat files to use
  QString offset = (QString) inst["BackgroundOffset"];
  QString mode = (QString) inst["Mode"];
  QString instModeId = (QString) inst["InstrumentModeId"];
  instModeId = instModeId.toUpper();

  if (instModeId == "COLOR" && (QString) inst["InstrumentId"] == "WAC-UV")
    instModeId = "UV";
  else if (instModeId == "VIS")
    instModeId = "COLOR";

  g_startTemperature = (double) inst["BeginTemperatureFpa"];
  g_endTemperature = (double) inst["EndTemperatureFpa"];

  g_numFrames = (int) inst["NumFramelets"];

  vector<QString> darkFiles;
  ui.GetAsString("DARKFILE", darkFiles);
  QString flatFile = ui.GetAsString("FLATFIELDFILE");
  QString radFile = ui.GetAsString("RADIOMETRICFILE");
  QString specpixFile = ui.GetAsString("SPECIALPIXELSFILE");
  QString tempFile = ui.GetAsString("TEMPERATUREFILE");

  // Figure out which bands are input
  for (int i = 1; i <= icube->bandCount(); i++) {
    g_bands.push_back(icube->physicalBand(i));
  }

  Isis::PvlGroup &bandBin = icube->label()->findGroup("BandBin", Pvl::Traverse);
  QString filter = (QString) bandBin["Center"][0];
  QString filterNum = (QString) bandBin["FilterNumber"][0];
  //We have to pay special attention incase we are passed a 
  //single band image that has been "exploded" from a multiband wac
  if (instModeId == "COLOR" && g_bands.size() == 1)
   g_bands[0] = (toInt(filterNum) -2);
  else if (instModeId == "UV" && g_bands.size() == 1)
   g_bands[0] = (toInt(filterNum));

  if (g_dark) {
    if (darkFiles.size() == 0 || darkFiles[0] =="Default" || darkFiles[0].length() == 0) {
      darkFiles.resize(2);
      double temp = (double) inst["MiddleTemperatureFpa"];
      double time = iTime(inst["StartTime"][0]).Et();
      QString darkFile = "$lro/calibration/wac_darks/WAC_" + instModeId;
      if (instModeId == "BW")
        darkFile += "_" + filter + "_Mode" + mode;
      darkFile += "_Offset" + offset + "_*C_*T_Dark.????.cub";
      GetDark (darkFile, temp, time, g_darkCube1, g_darkCube2, g_temp1, g_temp2, darkFiles[0], darkFiles[1]);
    }
    else if (darkFiles.size() == 1) {
      CopyCubeIntoBuffer(darkFiles[0], g_darkCube1);
      g_temp1 = 0.0;
      g_darkCube2 = new Buffer(*g_darkCube1);
      g_temp2 = g_temp1;
    }
    else {
      CopyCubeIntoBuffer(darkFiles[0], g_darkCube1);
      int index = darkFiles[0].lastIndexOf("_");
      g_temp1 = IString(darkFiles[0].mid( darkFiles[0].lastIndexOf("_", index-1), index)).ToDouble();
      CopyCubeIntoBuffer(darkFiles[1], g_darkCube2);
      index = darkFiles[1].lastIndexOf("_");
      g_temp2 = IString(darkFiles[1].mid( darkFiles[1].lastIndexOf("_", index-1), index)).ToDouble();
    }
  }

  if (g_flatfield) {
    if (flatFile.toLower() == "default" || flatFile.length() == 0) {
      flatFile = "$lro/calibration/wac_flats/WAC_" + instModeId;
      if (instModeId == "BW")
        flatFile += "_" + filter + "_Mode" + mode;
      flatFile += "_Flatfield.????.cub";
    }
    CopyCubeIntoBuffer(flatFile, g_flatCube);

    // invert the flat-field data here so we don't have to divide for every pixel of the wac
    for (int i = 0; i < g_flatCube->size(); i++) {
      (*g_flatCube)[i] = 1.0 / (*g_flatCube)[i];
    }
  }

  PvlKeyword responsivity;

  if (g_radiometric) {

    Isis::PvlKeyword &bands = icube->label()->findGroup("BandBin", Pvl::Traverse).findKeyword("FilterNumber");

    if (radFile.toLower() == "default" || radFile.length() == 0)
      radFile = "$lro/calibration/WAC_RadiometricResponsivity.????.pvl";

    FileName radFileName(radFile);
    if (radFileName.isVersioned())
      radFileName = radFileName.highestVersion();
    if (!radFileName.fileExists()) {
      QString msg = radFile + " does not exist.";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    Pvl radPvl(radFileName.expanded());

    if (g_iof) {
      responsivity = radPvl["IOF"];

      for (int i = 0; i < bands.size(); i++)
        g_iofResponsivity.push_back(toDouble(responsivity[toInt(bands[i]) - 1]));

      try {
        iTime startTime((QString) inst["StartTime"]);
        double etStart = startTime.Et();
        // Get the distance between the Moon and the Sun at the given time in
        // Astronomical Units (AU)
        QString bspKernel1 = p.MissionData("lro", "/kernels/tspk/moon_pa_de421_1900-2050.bpc", false);
        QString bspKernel2 = p.MissionData("lro", "/kernels/tspk/de421.bsp", false);
        furnsh_c(bspKernel1.toAscii().data());
        furnsh_c(bspKernel2.toAscii().data());
        QString pckKernel1 = p.MissionData("base", "/kernels/pck/pck?????.tpc", true);
        QString pckKernel2 = p.MissionData("lro", "/kernels/pck/moon_080317.tf", false);
        QString pckKernel3 = p.MissionData("lro", "/kernels/pck/moon_assoc_me.tf", false);
        furnsh_c(pckKernel1.toAscii().data());
        furnsh_c(pckKernel2.toAscii().data());
        furnsh_c(pckKernel3.toAscii().data());
        double sunpos[6], lt;
        spkezr_c("sun", etStart, "MOON_ME", "LT+S", "MOON", sunpos, &lt);
        g_solarDistance = vnorm_c(sunpos) / KM_PER_AU;
        unload_c(bspKernel1.toAscii().data());
        unload_c(bspKernel2.toAscii().data());
        unload_c(pckKernel1.toAscii().data());
        unload_c(pckKernel2.toAscii().data());
        unload_c(pckKernel3.toAscii().data());
      }
      catch (IException &e) {
        QString msg = "Can not find necessary SPICE kernels for converting to IOF";
        throw IException(e, IException::User, msg, _FILEINFO_);
      }
    }
    else {
      responsivity = radPvl["Radiance"];
      for (int i = 0; i < bands.size(); i++)
        g_radianceResponsivity.push_back(toDouble(responsivity[toInt(bands[i]) - 1]));
    }
  }

  if (g_specpix) {
    if (specpixFile.toLower() == "default" || specpixFile.length() == 0) {
      specpixFile = "$lro/calibration/wac_masks/WAC_" + instModeId;
      double temp = (double) inst["MiddleTemperatureFpa"];
      if (instModeId == "BW")
        specpixFile += "_" + filter + "_Mode" + mode;
      specpixFile += "_*C_SpecialPixels.????.cub";
      GetMask(specpixFile, temp, g_specpixCube);
    }
    else
      CopyCubeIntoBuffer(specpixFile, g_specpixCube);
  }

  if (g_temprature) {
    if (tempFile.toLower() == "default" || tempFile.length() == 0)
      tempFile = "$lro/calibration/WAC_TempratureConstants.????.pvl";

    FileName tempFileName(tempFile);
    if (tempFileName.isVersioned())
      tempFileName = tempFileName.highestVersion();
    if (!tempFileName.fileExists()) {
      QString msg = tempFile + " does not exist.";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    Isis::PvlKeyword &bands = icube->label()->findGroup("BandBin", Pvl::Traverse).findKeyword("FilterNumber");
    Pvl tempPvl(tempFileName.expanded());
    for (int b = 0; b < bands.size(); b++){
        g_TempratureConstants[g_bands[b]][0]=toDouble(tempPvl[bands[b]][0]);
        g_TempratureConstants[g_bands[b]][1]=toDouble(tempPvl[bands[b]][1]);
    }
  }

  if (instModeId == "BW") {
    if (mode == "1" || mode == "0")
      p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size()));
    else
      p.SetBrickSize(POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size()));
  }
  else if (instModeId == "COLOR") {
    p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(COLOR_BANDS, g_bands.size()));
  }
  else if (instModeId == "UV") {
    p.SetBrickSize(UV_SAMPLES, UV_LINES, (int)min(UV_BANDS, g_bands.size()));
  }

  g_exposure = inst["ExposureDuration"];

  Cube *ocube = p.SetOutputCube("TO");
  p.ProcessCube(Calibrate, false);

  // Add an output group with the appropriate information
  PvlGroup calgrp("Radiometry");
  if (g_dark) {
    PvlKeyword darks("DarkFiles");
    darks.addValue(darkFiles[0]);
    if (darkFiles.size() > 1)
      darks.addValue(darkFiles[1]);
    calgrp += darks;
  }
  if (g_flatfield)
    calgrp += PvlKeyword("FlatFile", flatFile);
  if (g_radiometric) {
    PvlKeyword vals("ResponsivityValues");
    if (g_iof) {
      calgrp += PvlKeyword("RadiometricType", "IOF");
      for (unsigned int i=0; i< g_iofResponsivity.size(); i++)
        vals.addValue(toString(g_iofResponsivity[i]));
    }
    else {
      calgrp += PvlKeyword("RadiometricType", "AbsoluteRadiance");
      for (unsigned int i=0; i< g_radianceResponsivity.size(); i++)
        vals.addValue(toString(g_radianceResponsivity[i]));
    }
    calgrp += vals;
    calgrp += PvlKeyword("SolarDistance", toString(g_solarDistance));
  }
  if (g_specpix)
    calgrp += PvlKeyword("SpecialPixelsFile", specpixFile);
  ocube->putGroup(calgrp);

}
コード例 #14
0
ファイル: caminfo.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  const QString caminfo_program  = "caminfo";
  UserInterface &ui = Application::GetUserInterface();

  QList< QPair<QString, QString> > *general = NULL, *camstats = NULL, *statistics = NULL;
  BandGeometry *bandGeom = NULL;

  // Get input filename
  FileName in = ui.GetFileName("FROM");

  // Get the format
  QString sFormat = ui.GetAsString("FORMAT");

  // if true then run spiceinit, xml default is FALSE
  // spiceinit will use system kernels
  if(ui.GetBoolean("SPICE")) {
    QString parameters = "FROM=" + in.expanded();
    ProgramLauncher::RunIsisProgram("spiceinit", parameters);
  }

  Process p;
  Cube *incube = p.SetInputCube("FROM");

  // General data gathering
  general = new QList< QPair<QString, QString> >;
  general->append(MakePair("Program",     caminfo_program));
  general->append(MakePair("IsisVersion", Application::Version()));
  general->append(MakePair("RunDate",     iTime::CurrentGMT()));
  general->append(MakePair("IsisId",      SerialNumber::Compose(*incube)));
  general->append(MakePair("From",        in.baseName() + ".cub"));
  general->append(MakePair("Lines",       toString(incube->lineCount())));
  general->append(MakePair("Samples",     toString(incube->sampleCount())));
  general->append(MakePair("Bands",       toString(incube->bandCount())));

  // Run camstats on the entire image (all bands)
  // another camstats will be run for each band and output
  // for each band.
  if(ui.GetBoolean("CAMSTATS")) {
    camstats = new QList< QPair<QString, QString> >;

    QString filename = ui.GetAsString("FROM");
    int sinc = ui.GetInteger("SINC");
    int linc = ui.GetInteger("LINC");
    CameraStatistics stats(filename, sinc, linc);
    Pvl camPvl = stats.toPvl();

    PvlGroup cg = camPvl.findGroup("Latitude", Pvl::Traverse);
    camstats->append(MakePair("MinimumLatitude", cg["latitudeminimum"][0]));
    camstats->append(MakePair("MaximumLatitude", cg["latitudemaximum"][0]));

    cg = camPvl.findGroup("Longitude", Pvl::Traverse);
    camstats->append(MakePair("MinimumLongitude", cg["longitudeminimum"][0]));
    camstats->append(MakePair("MaximumLongitude", cg["longitudemaximum"][0]));

    cg = camPvl.findGroup("Resolution", Pvl::Traverse);
    camstats->append(MakePair("MinimumResolution", cg["resolutionminimum"][0]));
    camstats->append(MakePair("MaximumResolution", cg["resolutionmaximum"][0]));

    cg = camPvl.findGroup("PhaseAngle", Pvl::Traverse);
    camstats->append(MakePair("MinimumPhase", cg["phaseminimum"][0]));
    camstats->append(MakePair("MaximumPhase", cg["phasemaximum"][0]));

    cg = camPvl.findGroup("EmissionAngle", Pvl::Traverse);
    camstats->append(MakePair("MinimumEmission", cg["emissionminimum"][0]));
    camstats->append(MakePair("MaximumEmission", cg["emissionmaximum"][0]));

    cg = camPvl.findGroup("IncidenceAngle", Pvl::Traverse);
    camstats->append(MakePair("MinimumIncidence", cg["incidenceminimum"][0]));
    camstats->append(MakePair("MaximumIncidence", cg["incidencemaximum"][0]));

    cg = camPvl.findGroup("LocalSolarTime", Pvl::Traverse);
    camstats->append(MakePair("LocalTimeMinimum", cg["localsolartimeMinimum"][0]));
    camstats->append(MakePair("LocalTimeMaximum", cg["localsolartimeMaximum"][0]));
  }

  // Compute statistics for entire cube
  if(ui.GetBoolean("STATISTICS")) {
    statistics = new QList< QPair<QString, QString> >;

    LineManager iline(*incube);
    Statistics stats;
    Progress progress;
    progress.SetText("Statistics...");
    progress.SetMaximumSteps(incube->lineCount()*incube->bandCount());
    progress.CheckStatus();
    iline.SetLine(1);
    for(; !iline.end() ; iline.next()) {
      incube->read(iline);
      stats.AddData(iline.DoubleBuffer(), iline.size());
      progress.CheckStatus();
    }

    //  Compute stats of entire cube
    double nPixels     = stats.TotalPixels();
    double nullpercent = (stats.NullPixels() / (nPixels)) * 100;
    double hispercent  = (stats.HisPixels() / (nPixels)) * 100;
    double hrspercent  = (stats.HrsPixels() / (nPixels)) * 100;
    double lispercent  = (stats.LisPixels() / (nPixels)) * 100;
    double lrspercent  = (stats.LrsPixels() / (nPixels)) * 100;

    // Statitics output for band
    statistics->append(MakePair("MeanValue", toString(stats.Average())));
    statistics->append(MakePair("StandardDeviation", toString(stats.StandardDeviation())));
    statistics->append(MakePair("MinimumValue", toString(stats.Minimum())));
    statistics->append(MakePair("MaximumValue", toString(stats.Maximum())));
    statistics->append(MakePair("PercentHIS", toString(hispercent)));
    statistics->append(MakePair("PercentHRS", toString(hrspercent)));
    statistics->append(MakePair("PercentLIS", toString(lispercent)));
    statistics->append(MakePair("PercentLRS", toString(lrspercent)));
    statistics->append(MakePair("PercentNull", toString(nullpercent)));
    statistics->append(MakePair("TotalPixels", toString(stats.TotalPixels())));
  }

  bool getFootBlob = ui.GetBoolean("USELABEL");
  bool doGeometry = ui.GetBoolean("GEOMETRY");
  bool doPolygon = ui.GetBoolean("POLYGON");
  if(doGeometry || doPolygon || getFootBlob) {
    Camera *cam = incube->camera();

    QString incType = ui.GetString("INCTYPE");
    int polySinc, polyLinc;
    if(doPolygon && incType.toUpper() == "VERTICES") {
      ImagePolygon poly;
      poly.initCube(*incube);
      polySinc = polyLinc = (int)(0.5 + (((poly.validSampleDim() * 2) +
                                 (poly.validLineDim() * 2) - 3.0) /
                                 ui.GetInteger("NUMVERTICES")));
    }
    else if (incType.toUpper() == "LINCSINC"){
      if(ui.WasEntered("POLYSINC")) {
        polySinc = ui.GetInteger("POLYSINC");
      }
      else {
        polySinc = (int)(0.5 + 0.10 * incube->sampleCount());
        if(polySinc == 0) polySinc = 1;
      }
      if(ui.WasEntered("POLYLINC")) {
        polyLinc = ui.GetInteger("POLYLINC");
      }
      else {
        polyLinc = (int)(0.5 + 0.10 * incube->lineCount());
        if(polyLinc == 0) polyLinc = 1;
      }
    }
    else {
      QString msg = "Invalid INCTYPE option[" + incType + "]";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    bandGeom = new BandGeometry();
    bandGeom->setSampleInc(polySinc);
    bandGeom->setLineInc(polyLinc);
    bandGeom->setMaxIncidence(ui.GetDouble("MAXINCIDENCE"));
    bandGeom->setMaxEmission(ui.GetDouble("MAXEMISSION"));
    bool precision = ui.GetBoolean("INCREASEPRECISION");

    if (getFootBlob) {
      // Need to read history to obtain parameters that were used to
      // create the footprint
      History hist("IsisCube", in.expanded());
      Pvl pvl = hist.ReturnHist();
      PvlObject::PvlObjectIterator objIter;
      bool found = false;
      PvlGroup fpgrp;
      for (objIter=pvl.endObject()-1; objIter>=pvl.beginObject(); objIter--) {
        if (objIter->name().toUpper() == "FOOTPRINTINIT") {
          found = true;
          fpgrp = objIter->findGroup("UserParameters");
          break;
        }
      }
      if (!found) {
        QString msg = "Footprint blob was not found in input image history";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      QString prec = (QString)fpgrp.findKeyword("INCREASEPRECISION");
      prec = prec.toUpper();
      if (prec == "TRUE") {
        precision = true;
      }
      else {
        precision = false;
      }
      QString inctype = (QString)fpgrp.findKeyword("INCTYPE");
      inctype = inctype.toUpper();
      if (inctype == "LINCSINC") {
        int linc = fpgrp.findKeyword("LINC");
        int sinc = fpgrp.findKeyword("SINC");
        bandGeom->setSampleInc(sinc);
        bandGeom->setLineInc(linc);
      }
      else {
        int vertices = fpgrp.findKeyword("NUMVERTICES");
        int lincsinc = (int)(0.5 + (((incube->sampleCount() * 2) +
                       (incube->lineCount() * 2) - 3.0) /
                       vertices));
        bandGeom->setSampleInc(lincsinc);
        bandGeom->setLineInc(lincsinc);
      }
      if (fpgrp.hasKeyword("MAXINCIDENCE")) {
        double maxinc = fpgrp.findKeyword("MAXINCIDENCE");
        bandGeom->setMaxIncidence(maxinc);
      }
      if (fpgrp.hasKeyword("MAXEMISSION")) {
        double maxema = fpgrp.findKeyword("MAXEMISSION");
        bandGeom->setMaxEmission(maxema);
      }
    }
    
    bandGeom->collect(*cam, *incube, doGeometry, doPolygon, getFootBlob, precision);

    // Check if the user requires valid image center geometry
    if(ui.GetBoolean("VCAMERA") && (!bandGeom->hasCenterGeometry())) {
      QString msg = "Image center does not project in camera model";
      throw IException(IException::Unknown, msg, _FILEINFO_);
    }
  }

  if(sFormat.toUpper() == "PVL")
    GeneratePVLOutput(incube, general, camstats, statistics, bandGeom);
  else
    GenerateCSVOutput(incube, general, camstats, statistics, bandGeom);

  // Clean the data
  delete general;
  general = NULL;
  if(camstats) {
    delete camstats;
    camstats = NULL;
  }
  if(statistics) {
    delete statistics;
    statistics = NULL;
  }
  if(bandGeom) {
    delete bandGeom;
    bandGeom = NULL;
  }

}
コード例 #15
0
ファイル: hicubenorm.cpp プロジェクト: corburn/ISIS
// Main Program
void IsisMain() {
  vector<double> filter;
  int rowcol;                    // how many rows or cols per band
  bool normalizeUsingAverage;    // mult/sub using average or median?
  int totalBands;
  // Used for filtering the initial cubenorm averages and median values
  int filtsize;
  bool pause_crop;
  int channel;
  // ERROR CHECK:  The user must specify at least the TO or STATS
  // parameters.
  UserInterface &ui = Application::GetUserInterface();
  if(!(ui.WasEntered("TO")) && !(ui.WasEntered("STATS"))) {
    QString msg = "User must specify a TO and/or STATS file.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  // We will be processing by tile.
  ProcessByTile p;

  // Setup the input cube;
  // Obtain information from the input file
  Cube *icube = p.SetInputCube("FROM");
  totalSamples = icube->sampleCount();
  totalLines   = icube->lineCount();
  totalBands   = icube->bandCount();
  channel = icube->group("Instrument")["ChannelNumber"];

  // Cubenorm New Version Flag
  bool bNewVersion = ui.GetBoolean("NEW_VERSION");

  // Setup the tile size for columnar processing
  p.SetTileSize(1, totalLines);
  rowcol = totalSamples;

  // Gather statistics from the configured source
  if(!bNewVersion && ui.GetString("STATSOURCE") == "CUBE") {
    p.StartProcess(getStats);
  }
  else if(ui.GetString("STATSOURCE") == "TABLE") {
    tableIn(ui.GetFileName("FROMSTATS"));
  }
  else {
    PVLIn(ui.GetFileName("FROMSTATS"));
  }

  // Check to make sure the first vector has as many elements as the last
  // vector, and that there is a vector element for each row/col
  if(!bNewVersion && band.size() != (unsigned int)(rowcol * totalBands)) {
    QString message = "You have entered an invalid input file " +
                      ui.GetFileName("FROMSTATS");
    throw IException(IException::Io, message, _FILEINFO_);
  }

  // Get the information needed to filter the statistics
  filtsize   = ui.GetInteger("FILTER");
  pause_crop = ui.GetBoolean("PAUSECROP");

  if(bNewVersion) {
    CorrectCubenormStats(filtsize, pause_crop, channel, ui.GetString("HIGHPASS_MODE"));
  }
  else {
    // Filter the column averages
    filter = average;
    filterStats(filter, filtsize, pause_crop, channel);
    average = filter;

    // Filter the column medians
    filter = median;
    filterStats(filter, filtsize, pause_crop, channel);
    median = filter;
  }

  // If a STATS file was specified then create statistics file
  if(ui.WasEntered("STATS")) {
    QString op = ui.GetString("FORMAT");
    if(op == "PVL"){
      pvlOut(ui.GetFileName("STATS"));
    }
    if(op == "TABLE"){
      tableOut(ui.GetFileName("STATS"));
    }
  }

  // Update the statistics vectors before creating the output
  // file. Now get the statistics for each column
  normalizeUsingAverage = ui.GetString("NORMALIZER") == "AVERAGE";

  if(normalizeUsingAverage) {
    normalizer = average;
  }
  else {
    normalizer = median;
  }

  // If an output file was specified then normalize the cube
  if(ui.WasEntered("TO")) {
    // Before creating a normalized cube check to see if there
    // are any column averages less than or equal to zero.
    if(ui.GetString("MODE") == "MULTIPLY") {
      for(unsigned int i = 0; i < band.size(); i++) {
        if(IsValidPixel(normalizer[i]) && normalizer[i] <= 0.0) {
          QString msg = "Cube file can not be normalized with [MULTIPLY] ";
          msg += "option, some column averages <= 0.0";
          throw IException(IException::User, msg, _FILEINFO_);
        }
      }
    }

    // Setup the output file and apply the coefficients by either
    // subtracting or multipling them
    p.SetOutputCube("TO");

    // Should we preserve the average/median of the input image???
    if(ui.GetBoolean("PRESERVE")) {
      if(ui.GetString("MODE") == "SUBTRACT") {
        keepSame(totalBands, rowcol, SUBTRACT);
      }
      else {
        keepSame(totalBands, rowcol, DIVIDE);
      }
    }

    // Process based on the mode
    if(ui.GetString("MODE") == "SUBTRACT") {
      p.StartProcess(subtract);
    }
    else {
      p.StartProcess(multiply);
    }
  }

  // Cleanup
  p.EndProcess();
  stddev.clear();
  validpixels.clear();
  minimum.clear();
  maximum.clear();
  band.clear();
  element.clear();
  median.clear();
  average.clear();
  normalizer.clear();
  filter.clear();
}
コード例 #16
0
ファイル: cam2cam.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  // Open the match cube and get the camera model on it
  ProcessRubberSheet m;
  Cube *mcube = m.SetInputCube("MATCH");
  Cube *ocube = m.SetOutputCube("TO");

  // Set up the default reference band to the middle of the cube
  // If we have even bands it will be close to the middle
  int referenceBand = ocube->bandCount();
  referenceBand += (referenceBand % 2);
  referenceBand /= 2;

  // See if the user wants to override the reference band
  UserInterface &ui = Application::GetUserInterface();
  if(ui.WasEntered("REFBAND")) {
    referenceBand = ui.GetInteger("REFBAND");
  }

  // Using the Camera method out of the object opack will not work, because the
  // filename required by the Camera is not passed by the process class in this
  // case.  Use the CameraFactory to create the Camera instead to get around this
  // problem.
  Camera *outcam = CameraFactory::Create(*(mcube->label()));

  // Set the reference band we want to match
  PvlGroup instgrp = mcube->group("Instrument");
  if(!outcam->IsBandIndependent()) {
    PvlKeyword rBand("ReferenceBand", toString(referenceBand));
    rBand.addComment("# All bands are aligned to reference band");
    instgrp += rBand;
    mcube->putGroup(instgrp);
    delete outcam;
    outcam = NULL;
  }

  // Only recreate the output camera if it was band dependent
  if(outcam == NULL) outcam = CameraFactory::Create(*(mcube->label()));

  // We might need the instrument group later, so get a copy before clearing the input
  //   cubes.
  m.ClearInputCubes();

  Cube *icube = m.SetInputCube("FROM");
  incam = icube->camera();

  // Set up the transform object which will simply map
  // output line/samps -> output lat/lons -> input line/samps
  Transform *transform = new cam2cam(icube->sampleCount(),
                                     icube->lineCount(),
                                     incam,
                                     ocube->sampleCount(),
                                     ocube->lineCount(),
                                     outcam);


  // Add the reference band to the output if necessary
  ocube->putGroup(instgrp);

  // Set up the interpolator
  Interpolator *interp = NULL;
  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);
  }

  // See if we need to deal with band dependent camera models
  if(!incam->IsBandIndependent()) {
    m.BandChange(BandChange);
  }

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

  // Cleanup
  delete transform;
  delete interp;
}
コード例 #17
0
ファイル: stats.cpp プロジェクト: corburn/ISIS
void IsisMain() {

  UserInterface &ui = Application::GetUserInterface();
  Process p;

  // Get the histogram
  Cube *icube = p.SetInputCube("FROM");

  double validMin = Isis::ValidMinimum;
  double validMax = Isis::ValidMaximum;

  if(ui.WasEntered("VALIDMIN")) {
    validMin = ui.GetDouble("VALIDMIN");
  }

  if(ui.WasEntered("VALIDMAX")) {
    validMax = ui.GetDouble("VALIDMAX");
  }
  
  // Set a global Pvl for storing results
  Pvl mainpvl;
  
  // Get the number of bands to process
  int bandcount = icube->bandCount();
  
  for (int i = 1; i <= bandcount; i++) {
    Histogram *stats = icube->histogram(i, validMin, validMax);

    // Construct a label with the results
    PvlGroup results("Results");  
    results += PvlKeyword("From", icube->fileName());
    results += PvlKeyword("Band", toString(icube->physicalBand(i)));
    if(stats->ValidPixels() != 0) {
      results += PvlKeyword("Average", toString(stats->Average()));
      results += PvlKeyword("StandardDeviation", toString(stats->StandardDeviation()));
      results += PvlKeyword("Variance", toString(stats->Variance()));
      // These statistics only worked on a histogram
      results += PvlKeyword("Median", toString(stats->Median()));
      results += PvlKeyword("Mode", toString(stats->Mode()));
      results += PvlKeyword("Skew", toString(stats->Skew()));
      results += PvlKeyword("Minimum", toString(stats->Minimum()));
      results += PvlKeyword("Maximum", toString(stats->Maximum()));
      results += PvlKeyword("Sum", toString(stats->Sum()));
    }
    results += PvlKeyword("TotalPixels", toString(stats->TotalPixels()));
    results += PvlKeyword("ValidPixels", toString(stats->ValidPixels()));
    results += PvlKeyword("OverValidMaximumPixels", toString(stats->OverRangePixels()));
    results += PvlKeyword("UnderValidMinimumPixels", toString(stats->UnderRangePixels()));
    results += PvlKeyword("NullPixels", toString(stats->NullPixels()));
    results += PvlKeyword("LisPixels", toString(stats->LisPixels()));
    results += PvlKeyword("LrsPixels", toString(stats->LrsPixels()));
    results += PvlKeyword("HisPixels", toString(stats->HisPixels()));
    results += PvlKeyword("HrsPixels", toString(stats->HrsPixels()));
    
    mainpvl.addGroup(results);
    
    delete stats;
    // Write the results to the log
    Application::Log(results);
  }
  
  // Write the results to the output file if the user specified one
  if(ui.WasEntered("TO")) {
    QString outFile = FileName(ui.GetFileName("TO")).expanded();
    bool exists = FileName(outFile).fileExists();
    bool append = ui.GetBoolean("APPEND");
    ofstream os;
    bool writeHeader = false;
    //write the results in the requested format.
    if(ui.GetString("FORMAT") == "PVL") {
      if(append) {
        mainpvl.append(outFile);
      }
      else {
        mainpvl.write(outFile);
      }
    }
    else {
      //if the format was not PVL, write out a flat file.
      if(append) {
        os.open(outFile.toAscii().data(), ios::app);
        if(!exists) {
          writeHeader = true;
        }
      }
      else {
        os.open(outFile.toAscii().data(), ios::out);
        writeHeader = true;
      }

      if(writeHeader) {
        for(int i = 0; i < mainpvl.group(0).keywords(); i++) {
          os << mainpvl.group(0)[i].name();
          if( i < mainpvl.group(0).keywords() - 1 ) {
            os << ",";
          }
        }
        os << endl;
      }
      
      for(int i = 0; i < mainpvl.groups(); i++) {
        for (int j = 0; j < mainpvl.group(i).keywords(); j++) {
          os << (QString)mainpvl.group(i)[j];
          if(j < mainpvl.group(i).keywords() - 1) {
            os << ",";
          }
        }
        os << endl;
      }
    }
  }
}
コード例 #18
0
ファイル: ProcessMapMosaic.cpp プロジェクト: corburn/ISIS
  /**
   * Set the output cube to specified file name and specified input images
   * and output attributes
   */
  Isis::Cube *ProcessMapMosaic::SetOutputCube(FileList &propagationCubes, CubeAttributeOutput &oAtt,
      const QString &mosaicFile) {
    int bands = 0;
    double xmin = DBL_MAX;
    double xmax = -DBL_MAX;
    double ymin = DBL_MAX;
    double ymax = -DBL_MAX;
    double slat = DBL_MAX;
    double elat = -DBL_MAX;
    double slon = DBL_MAX;
    double elon = -DBL_MAX;

    Projection *proj = NULL;

    if (propagationCubes.size() < 1) {
      QString msg = "The list does not contain any data";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    for (int i = 0; i < propagationCubes.size(); i++) {
      // Open the cube and get the maximum number of band in all cubes
      Cube cube;
      cube.open(propagationCubes[i].toString());
      bands = max(bands, cube.bandCount());

      // See if the cube has a projection and make sure it matches
      // previous input cubes
      Projection *projNew =
          Isis::ProjectionFactory::CreateFromCube(*(cube.label()));
      if ((proj != NULL) && (*proj != *projNew)) {
        QString msg = "Mapping groups do not match between cubes [" +
                     propagationCubes[0].toString() + "] and [" + propagationCubes[i].toString() + "]";
        throw IException(IException::User, msg, _FILEINFO_);
      }

      // Figure out the x/y range as it may be needed later
      double x = projNew->ToProjectionX(0.5);
      double y = projNew->ToProjectionY(0.5);
      if (x < xmin) xmin = x;
      if (y < ymin) ymin = y;
      if (x > xmax) xmax = x;
      if (y > ymax) ymax = y;

      x = projNew->ToProjectionX(cube.sampleCount() + 0.5);
      y = projNew->ToProjectionY(cube.lineCount() + 0.5);
      if (x < xmin) xmin = x;
      if (y < ymin) ymin = y;
      if (x > xmax) xmax = x;
      if (y > ymax) ymax = y;

      slat = min(slat, projNew->MinimumLatitude());
      elat = max(elat, projNew->MaximumLatitude());
      slon = min(slon, projNew->MinimumLongitude());
      elon = max(elon, projNew->MaximumLongitude());

      // Cleanup
      cube.close();
      if (proj) delete proj;
      proj = projNew;
    }

    if (proj) delete proj;

    return SetOutputCube(propagationCubes[0].toString(), xmin, xmax, ymin, ymax,
                         slat, elat, slon, elon, bands, oAtt, mosaicFile);
  }
コード例 #19
0
ファイル: grid.cpp プロジェクト: corburn/ISIS
void IsisMain() {
  latLonGrid = NULL;

  // We will be processing by line
  ProcessByLine p;
  Cube *icube = p.SetInputCube("FROM");

  UserInterface &ui = Application::GetUserInterface();
  QString mode = ui.GetString("MODE");

  outline = ui.GetBoolean("OUTLINE");
  ticks = ui.GetBoolean("TICKS");

  if (ticks) {
    tickSize = ui.GetInteger("TICKSIZE") / 2;
    diagonalTicks = ui.GetBoolean("DIAGONALTICKS");
  }

  lineWidth = ui.GetInteger("LINEWIDTH") / 2;
 
  QString bval = ui.GetString("BKGNDVALUE").toUpper();

  image = (bval == "IMAGE");
  bkgndValue = Null;

  if (bval == "HRS") {
    bkgndValue = Hrs;
  }
  else if (bval == "LRS") {
    bkgndValue = Lrs;
  }
  else if (bval == "DN") {
    bkgndValue = ui.GetDouble("BKGNDDNVALUE");
  }

  QString lval = ui.GetString("LINEVALUE").toUpper();
  if (lval == "HRS") {
    lineValue = Hrs;
  }
  else if (lval == "LRS") {
    lineValue = Lrs;
  }
  else if (lval == "NULL") {
    lineValue = Null;
  }
  else if (lval == "DN") {
    if (ui.WasEntered("DNVALUE")) {
      lineValue = ui.GetDouble("DNVALUE");
    }
    else {
      throw IException(IException::User, "Must enter value in DNVALUE", _FILEINFO_);
    }
  }
  else {
    IString msg = "Invalid LINEVALUE string [" + ui.GetString("LINEVALUE");
    msg += "], must be one of HRS, LRS, NULL, or DN.";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  inputSamples = icube->sampleCount();
  inputLines   = icube->lineCount();

  // Line & sample based grid
  if (mode == "IMAGE") {
    p.SetOutputCube("TO");
    baseLine = ui.GetInteger("BASELINE");
    baseSample = ui.GetInteger("BASESAMPLE");
    lineInc = ui.GetInteger("LINC");
    sampleInc = ui.GetInteger("SINC");
    p.StartProcess(imageGrid);
    p.EndProcess();
  }
  // Lat/Lon based grid
  else {
    CubeAttributeOutput oatt("+32bit");
    p.SetOutputCube(ui.GetFileName("TO"), oatt, icube->sampleCount(),
                    icube->lineCount(), icube->bandCount());

    UniversalGroundMap *gmap = new UniversalGroundMap(*icube,
        UniversalGroundMap::ProjectionFirst);
    latLonGrid = new GroundGrid(gmap, ticks, icube->sampleCount(), icube->lineCount());

    baseLat = Latitude(ui.GetDouble("BASELAT"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);
    baseLon = Longitude(ui.GetDouble("BASELON"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);
    latInc = Angle(ui.GetDouble("LATINC"), Angle::Degrees);
    lonInc = Angle(ui.GetDouble("LONINC"), Angle::Degrees);

    Progress progress;
    progress.SetText("Calculating Grid");

    Latitude minLat, maxLat;

    if (ui.WasEntered("MINLAT"))
      minLat = Latitude(ui.GetDouble("MINLAT"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);

    if (ui.WasEntered("MAXLAT"))
      maxLat = Latitude(ui.GetDouble("MAXLAT"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);

    Longitude minLon, maxLon;

    if (ui.WasEntered("MINLON"))
      minLon = Longitude(ui.GetDouble("MINLON"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);

    if (ui.WasEntered("MAXLON"))
      maxLon = Longitude(ui.GetDouble("MAXLON"),
        *latLonGrid->GetMappingGroup(), Angle::Degrees);

    latLonGrid->SetGroundLimits(minLat, minLon, maxLat, maxLon);

    latLonGrid->CreateGrid(baseLat, baseLon, latInc, lonInc, &progress);

    if (ui.GetBoolean("BOUNDARY"))
      latLonGrid->WalkBoundary();

    p.StartProcess(groundGrid);
    p.EndProcess();

    delete latLonGrid;
    latLonGrid = NULL;

    delete gmap;
    gmap = NULL;
  }
}
コード例 #20
0
ファイル: ProcessMapMosaic.cpp プロジェクト: corburn/ISIS
  /**
   * Set the output cube to specified file name and specified input images
   * and output attributes and lat,lons
   */
  Isis::Cube *ProcessMapMosaic::SetOutputCube(FileList &propagationCubes,
      double slat, double elat, double slon, double elon,
      CubeAttributeOutput &oAtt, const QString &mosaicFile) {
    if (propagationCubes.size() < 1) {
      QString msg = "The list does not contain any data";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    int samples, lines, bands = 0;
    Pvl label;
    label.read(propagationCubes[0].toString());
    PvlGroup mGroup = label.findGroup("Mapping", Pvl::Traverse);
    mGroup.addKeyword(PvlKeyword("MinimumLatitude", toString(slat)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MaximumLatitude", toString(elat)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MinimumLongitude", toString(slon)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MaximumLongitude", toString(elon)), Pvl::Replace);

    if (mGroup.hasKeyword("UpperLeftCornerX"))
      mGroup.deleteKeyword("UpperLeftCornerX");

    if (mGroup.hasKeyword("UpperLeftCornerY"))
      mGroup.deleteKeyword("UpperLeftCornerY");

    Pvl mapPvl;
    mapPvl += mGroup;

    // Use CreateForCube because our range differs from any of the cubes (manually specified)
    Projection *proj = Isis::ProjectionFactory::CreateForCube(mapPvl, samples, lines, false);

    double xmin, xmax, ymin, ymax;
    proj->XYRange(xmin, xmax, ymin, ymax);

    // The xmin/ymax should be rounded for the labels
    xmin = mapPvl.findGroup("Mapping")["UpperLeftCornerX"];
    ymax = mapPvl.findGroup("Mapping")["UpperLeftCornerY"];

    for (int i = 0; i < propagationCubes.size(); i++) {
      Cube cube;
      cube.open(propagationCubes[i].toString());
      bands = max(cube.bandCount(), bands);

      // See if the cube has a projection and make sure it matches
      // previous input cubes
      Projection *projNew =
          Isis::ProjectionFactory::CreateFromCube(*(cube.label()));

      if (proj == NULL) {
      }
      else if (*proj != *projNew) {
        QString msg = "Mapping groups do not match between cube [" + propagationCubes[i].toString() +
                     "] and [" + propagationCubes[0].toString() + "]";
        throw IException(IException::User, msg, _FILEINFO_);
      }

      if (proj) delete proj;
      proj = projNew;
    }

    if (proj) delete proj;

    return SetOutputCube(propagationCubes[0].toString(), xmin, xmax, ymin, ymax,
                         slat, elat, slon, elon, bands, oAtt, mosaicFile);
  }
コード例 #21
0
ファイル: hirdrgen.cpp プロジェクト: corburn/ISIS
void IsisMain() {

  QString projName;

  Process pHist;
  Cube *icube = pHist.SetInputCube("FROM");

  // Check to see if the input cube looks like a HiRISE RDR
  if (icube->bandCount() > 3) {
    QString msg = "Input file [" +
                 Application::GetUserInterface().GetFileName("FROM") +
                 "] does not appear to be a HiRISE RDR product. Number of " +
                 "bands is greater than 3";
    throw IException(IException::Programmer, msg, _FILEINFO_);
  }

  // Setup to get a histogram for each band
  g_min = new double[icube->bandCount()];
  g_max = new double[icube->bandCount()];

  UserInterface &ui = Application::GetUserInterface();

  // Determine if the data is to be converted to JPEG2000
  IString enctype = ui.GetString("ENCODING_TYPE");
  enctype.DownCase();

  for (int band = 1; band <= icube->bandCount(); ++band) {

    if (ui.GetString("TYPE").compare("AUTOMATIC") == 0) {
      // Set up a histogram for this band. This call sets the input range
      // by making an initial stats pass to find the data min and max
      Histogram hist(*icube, band, pHist.Progress());

      // Loop and accumulate histogram
      pHist.Progress()->SetText("Gathering Histogram");
      pHist.Progress()->SetMaximumSteps(icube->lineCount());
      pHist.Progress()->CheckStatus();
      LineManager line(*icube);
      for (int i = 1; i <= icube->lineCount(); i++) {
        line.SetLine(i, band);
        icube->read(line);
        hist.AddData(line.DoubleBuffer(), line.size());
        pHist.Progress()->CheckStatus();
      }

      // get the requested cumulative percentages
      g_min[band-1] = ui.GetDouble("MINPER") == 0.0 ? hist.Minimum() : hist.Percent(ui.GetDouble("MINPER"));
      g_max[band-1] = ui.GetDouble("MAXPER") == 100.0 ? hist.Maximum() : hist.Percent(ui.GetDouble("MAXPER"));
    }
    else {
      g_min[band-1] = ui.GetDouble("MIN");
      g_max[band-1] = ui.GetDouble("MAX");
    }
  }

  // Find the minimum min and maximum max for all bands
  double minmin = g_min[0];
  double maxmax = g_max[0];
  for (int band = 1; band < icube->bandCount(); ++band) {
    if (g_min[band] < minmin) minmin = g_min[band];
    if (g_max[band] > maxmax) maxmax = g_max[band];
  }

  pHist.EndProcess();

  // Set up for writing the data to a PDS formatted file
  ProcessExportPds p;
  Cube *icube2 = p.SetInputCube("FROM");

  if (enctype.Equal("jp2")) {
    g_jp2buf = new char* [icube2->bandCount()];
    FileName lblFile(ui.GetFileName("TO"));
    QString lblFileName = lblFile.path() + "/" + lblFile.baseName() + ".lbl";
    p.SetDetached(lblFileName);
    p.setFormat(ProcessExport::JP2);
  }

  // Set the output pixel type and the special pixel values
  int nbits = ui.GetInteger("BITS");
  if (nbits == 8) {
    if (enctype.Equal("jp2")) {
      for (int i = 0; i < icube2->bandCount(); i++) {
        g_jp2buf[i] = new char[icube2->sampleCount()];
      }
    }
    g_oType = Isis::UnsignedByte;
    p.SetOutputType(g_oType);
    p.SetOutputRange(VALID_MIN1, VALID_MAX1);
    p.SetOutputNull(NULL1);
    p.SetOutputLis(LOW_INSTR_SAT1);
    p.SetOutputLrs(LOW_REPR_SAT1);
    p.SetOutputHis(HIGH_INSTR_SAT1);
    p.SetOutputHrs(HIGH_REPR_SAT1);
  }
  else if (nbits == 16) {
    if (enctype.Equal("jp2")) {
      for (int i = 0; i < icube2->bandCount(); i++) {
        g_jp2buf[i] = new char[icube2->sampleCount()*2];
      }
    }
    g_oType = UnsignedWord;
    p.SetOutputType(g_oType);
    p.SetOutputRange(VALID_MINU2, VALID_MAXU2);
    p.SetOutputNull(NULLU2);
    p.SetOutputLis(LOW_INSTR_SATU2);
    p.SetOutputLrs(LOW_REPR_SATU2);
    p.SetOutputHis(HIGH_INSTR_SATU2);
    p.SetOutputHrs(HIGH_REPR_SATU2);
  }
  else {
    if (enctype.Equal("jp2")) {
      for (int i = 0; i < icube2->bandCount(); i++) {
        g_jp2buf[i] = new char[icube2->sampleCount()*2];
      }
    }
    g_oType = UnsignedWord;
    p.SetOutputType(g_oType);
    p.SetOutputRange(3.0, pow(2.0, (double)(nbits)) - 1.0 - 2.0);
    p.SetOutputNull(0);
    p.SetOutputLrs(1);
    p.SetOutputLis(2);
    p.SetOutputHis(pow(2.0, (double)(nbits)) - 1.0 - 1.0);
    p.SetOutputHrs(pow(2.0, (double)(nbits)) - 1.0);
  }
  p.SetOutputEndian(Isis::Msb);
  p.SetInputRange(minmin, maxmax);

  // Get the PDS label from the process
  ProcessExportPds::PdsFileType type;
  if (enctype.Equal("jp2")) {
    type = ProcessExportPds::JP2Image;
  }
  else {
    type = ProcessExportPds::Image;
  }
  Pvl &pdsLabel = p.StandardPdsLabel(type);

  // Translate the keywords from the input cube label that go in the PDS label
  PvlTranslationManager cubeLab(*(icube2->label()),
                                "$mro/translations/hirisePdsRdrCubeLabel.trn");
  cubeLab.Auto(pdsLabel);

  // Translate the keywords from the original EDR PDS label that go in
  // this RDR PDS label
  OriginalLabel origBlob;
  icube2->read(origBlob);
  Pvl origLabel;
  PvlObject origLabelObj = origBlob.ReturnLabels();
  origLabelObj.setName("OriginalLabelObject");
  origLabel.addObject(origLabelObj);
  PvlTranslationManager orig(origLabel,
                             "$mro/translations/hirisePdsRdrOriginalLabel.trn");
  orig.Auto(pdsLabel);

  // Add labels to the PDS product that could not be handled by the translater

  if (ui.WasEntered("RATIONALE_DESC")) {
    pdsLabel.addKeyword(
        PvlKeyword("RATIONALE_DESC", ui.GetString("RATIONALE_DESC")),
        Pvl::Replace);
  }

  // Add PRODUCT_CREATION_TIME
  time_t startTime = time(NULL);
  struct tm *tmbuf = gmtime(&startTime);
  char timestr[80];
  strftime(timestr, 80, "%Y-%m-%dT%H:%M:%S", tmbuf);
  QString dateTime = (QString) timestr;
  iTime tmpDateTime(dateTime);
  PvlGroup &timeParam = pdsLabel.findGroup("TIME_PARAMETERS");
  timeParam += PvlKeyword("PRODUCT_CREATION_TIME", tmpDateTime.UTC());

  // Add the N/A constant keyword to the ROOT
  pdsLabel += PvlKeyword("NOT_APPLICABLE_CONSTANT", toString(-9998));

  // Add SOFTWARE_NAME to the ROOT
  QString sfname;
  sfname.clear();
  sfname += "Isis " + Application::Version() + " " +
            Application::GetUserInterface().ProgramName();
  pdsLabel += PvlKeyword("SOFTWARE_NAME", sfname);

  // Add the PRODUCT_VERSION_ID from the user parameter VERSION
  pdsLabel += PvlKeyword("PRODUCT_VERSION_ID", ui.GetString("VERSION"));

  // Add MRO:CCD_FLAG, MRO:BINNING, MRO:TDI
  // As pulled from the input Isis cube, the values are in CPMM order, so
  // convert them to CCD order
  PvlKeyword ccdFlag("MRO:CCD_FLAG");
  PvlKeyword &cpmmFlag = origLabel.findObject("OriginalLabelObject").
                         findGroup("INSTRUMENT_SETTING_PARAMETERS").
                         findKeyword("MRO:POWERED_CPMM_FLAG");
  PvlKeyword ccdBin("MRO:BINNING");
  PvlKeyword &cpmmBin = icube2->label()->findObject("IsisCube").
                        findGroup("Mosaic")["cpmmSummingFlag"];
  PvlKeyword ccdTdi("MRO:TDI");
  PvlKeyword &cpmmTdi = icube2->label()->findObject("IsisCube").
                        findGroup("Mosaic")["cpmmTdiFlag"];
  PvlKeyword ccdSpecial("MRO:SPECIAL_PROCESSING_FLAG");
  PvlKeyword &cpmmSpecial = icube2->label()->findObject("IsisCube").
                            findGroup("Mosaic")["SpecialProcessingFlag"];
  for (int ccd = 0; ccd < 14; ++ccd) {
    const unsigned int cpmmByCcd[] = {0, 1, 2, 3, 5, 8, 10,
                                      11, 12, 13, 6, 7, 4, 9};
    ccdFlag.addValue(cpmmFlag[cpmmByCcd[ccd]]);
    ccdBin.addValue(cpmmBin[cpmmByCcd[ccd]] != "Null" ? cpmmBin[cpmmByCcd[ccd]] : "-9998");
    ccdTdi.addValue(cpmmTdi[cpmmByCcd[ccd]] != "Null" ? cpmmTdi[cpmmByCcd[ccd]] : "-9998");
    IString tmp = cpmmSpecial[cpmmByCcd[ccd]];
    tmp.Trim("\"");
    ccdSpecial.addValue(tmp.ToQt());
  }

  if (!pdsLabel.hasGroup("INSTRUMENT_SETTING_PARAMETERS")) {
    pdsLabel.addGroup(PvlGroup("INSTRUMENT_SETTING_PARAMETERS"));
  }
  pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdFlag;
  pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdBin;
  pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdTdi;
  pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdSpecial;

  // Add/modify projection info if there is a projection
  if (pdsLabel.hasObject("IMAGE_MAP_PROJECTION")) {
    PvlObject &mapObject = pdsLabel.findObject("IMAGE_MAP_PROJECTION");
    mapObject += PvlKeyword("^DATA_SET_MAP_PROJECTION", "DSMAP.CAT");

    // Add the HiRISE comment to the CENTER_LATITUDE keyword
    PvlKeyword &clat = mapObject["CENTER_LATITUDE"];
    clat.addComment("/* NOTE:  CENTER_LATITUDE and CENTER_LONGITUDE describe the location  */");
    clat.addComment("/* of the center of projection, which is not necessarily equal to the */");
    clat.addComment("/* location of the center point of the image.                         */");

    if (mapObject.hasKeyword("CENTER_LATITUDE")) {
      PvlKeyword &centerLat = mapObject["CENTER_LATITUDE"];
      // if (centerLat[0] == "N/A") centerLat = -9998;
      if (centerLat[0] == "N/A") mapObject.deleteKeyword("CENTER_LATITUDE");
    }
    if (mapObject.hasKeyword("CENTER_LONGITUDE")) {
      PvlKeyword &centerLon = mapObject["CENTER_LONGITUDE"];
      // if (centerLon[0] == "N/A") centerLon = -9998;
      if (centerLon[0] == "N/A") mapObject.deleteKeyword("CENTER_LONGITUDE");
    }
    if (mapObject.hasKeyword("REFERENCE_LATITUDE")) {
      PvlKeyword &refLat = mapObject["REFERENCE_LATITUDE"];
      // if (refLat[0] == "N/A") refLat = -9998;
      if (refLat[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LATITUDE");
    }
    if (mapObject.hasKeyword("REFERENCE_LONGITUE")) {
      PvlKeyword &refLon = mapObject["REFERENCE_LONGITUDE"];
      // if (refLon[0] == "N/A") refLon = -9998;
      if (refLon[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LONGITUDE");
    }
    if (mapObject.hasKeyword("FIRST_STANDARD_PARALLEL")) {
      PvlKeyword &firstSP = mapObject["FIRST_STANDARD_PARALLEL"];
      // if (firstSP[0] == "N/A") firstSP = -9998;
      if (firstSP[0] == "N/A") mapObject.deleteKeyword("FIRST_STANDARD_PARALLEL");
    }
    if (mapObject.hasKeyword("SECOND_STANDARD_PARALLEL")) {
      PvlKeyword &secondSP = mapObject["SECOND_STANDARD_PARALLEL"];
      // if (secondSP[0] == "N/A") secondSP = -9998;
      if (secondSP[0] == "N/A") mapObject.deleteKeyword("SECOND_STANDARD_PARALLEL");
    }

    // For Equirectangular ONLY
    // Modify the radii in the pds label to use the radius at the center latitude
    // instead of the target radii from NAIF
    if (mapObject["MAP_PROJECTION_TYPE"][0] == "EQUIRECTANGULAR") {
      Projection *proj = ProjectionFactory::CreateFromCube(*icube2);
      PvlGroup &mapping = icube2->label()->findGroup("MAPPING", Pvl::Traverse);
      double radius = proj->LocalRadius((double)mapping["CenterLatitude"]) / 1000.0;
      mapObject["A_AXIS_RADIUS"].setValue(toString(radius), "KM");
      mapObject["B_AXIS_RADIUS"].setValue(toString(radius), "KM");
      mapObject["C_AXIS_RADIUS"].setValue(toString(radius), "KM");
    }

    projName = mapObject["MAP_PROJECTION_TYPE"][0];
  }

  // Calculate the min/max per band keywords
  // These come from the input real DN and are converted to the PDS file DN
  // The input to output mapping is opposite from the one above
  double slope = (p.GetOutputMaximum() - p.GetOutputMinimum()) / (maxmax - minmin);
  double intercept = p.GetOutputMaximum() - slope * maxmax;
  PvlKeyword minimum("MRO:MINIMUM_STRETCH", toString(slope * g_min[0] + intercept));
  PvlKeyword maximum("MRO:MAXIMUM_STRETCH", toString(slope * g_max[0] + intercept));
  for (int band = 1; band < icube2->bandCount(); ++band) {
    minimum += toString(slope * g_min[band] + intercept);
    maximum += toString(slope * g_max[band] + intercept);
  }

  if (enctype.Equal("jp2")) {
    // Add keywords to the PDS JP2 IMAGE object
    PvlObject &imagejp2 = pdsLabel.findObject("UNCOMPRESSED_FILE").findObject("IMAGE");

    // Add the HiRISE specific description of the IMAGE object
    imagejp2 += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product");

    // Add the SCALLING_FACTOR and OFFSET keywords
    imagejp2.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace);
    imagejp2.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace);

    // Reformat some keyword units in the image object
    // This is lame, but PDS units are difficult to work with, so for now???
    PvlKeyword &oldFilterNamejp2 = imagejp2["FILTER_NAME"];
    PvlKeyword newFilterName("FILTER_NAME");
    for (int val = 0; val < oldFilterNamejp2.size(); ++val) {
      QString  filtname(oldFilterNamejp2[val].toUpper());
      if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN";
      else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED";
      newFilterName.addValue(filtname);
    }
    imagejp2.addKeyword(newFilterName, Pvl::Replace);

    PvlKeyword &oldCenterjp2 = imagejp2["CENTER_FILTER_WAVELENGTH"];
    PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH");
    for (int val = 0; val < oldCenterjp2.size(); ++val) {
      if (((IString)(oldCenterjp2.unit(val))).UpCase() == "NANOMETERS") {
        newCenter.addValue(oldCenterjp2[val], "NM");
      }
      else {
        newCenter.addValue(oldCenterjp2[val], oldCenterjp2.unit(val));
      }
    }
    imagejp2.addKeyword(newCenter, Pvl::Replace);

    PvlKeyword &oldBandWidthjp2 = imagejp2["BAND_WIDTH"];
    PvlKeyword newBandWidth("BAND_WIDTH");
    for (int val = 0; val < oldBandWidthjp2.size(); ++val) {
      if (((IString)(oldBandWidthjp2.unit(val))).UpCase() == "NANOMETERS") {
        newBandWidth.addValue(oldBandWidthjp2[val], "nm");
      }
      else {
        newBandWidth.addValue(oldBandWidthjp2[val], oldBandWidthjp2.unit(val));
      }
    }
    imagejp2.addKeyword(newBandWidth, Pvl::Replace);

    // Add the min/max per band keywords
    imagejp2 += minimum;
    imagejp2 += maximum;

    // Modify the default SAMPLE_BIT_MASK keyword placed there by the
    // ProcessExportPds
    if (nbits != 8 && nbits != 16) {
      imagejp2.addKeyword(PvlKeyword("SAMPLE_BIT_MASK",
                                     toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)),
                          Pvl::Replace);
    }
  }
  else {
    // Add keywords to the PDS IMAGE object
    PvlObject &image = pdsLabel.findObject("IMAGE");

    // Add the HiRISE specific description of the IMAGE object
    image += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product");

    /**
     *  Calculate the SCALING_FACTOR and OFFSET keywords
     *  Set these so the unsigned 16bit PDS disk values can be converted back
     *  to the correct values Isis had
     *  These keywords are used to map stored/disk values to the correct values so,
     *  the input(x axis) values are the unsigned Xbit values from the PDS file
     */
    // ??? unneccessary calculation - this is done by ProcessExportPds class.
    double slope = (maxmax - minmin) / (p.GetOutputMaximum() - p.GetOutputMinimum()); 
    double intercept = maxmax - slope * p.GetOutputMaximum();
    image.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace);
    image.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace);

    // Reformat some keyword units in the image object
    // This is lame, but PDS units are difficult to work with, so for now
    PvlKeyword &oldFilterName = image["FILTER_NAME"];
    PvlKeyword newFilterName("FILTER_NAME");
    for (int val = 0; val < oldFilterName.size(); ++val) {
      QString  filtname(oldFilterName[val].toUpper());
      if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN";
      else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED";
      newFilterName.addValue(filtname);
    }
    image.addKeyword(newFilterName, Pvl::Replace);

    PvlKeyword &oldCenter = image["CENTER_FILTER_WAVELENGTH"];
    PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH");
    for (int val = 0; val < oldCenter.size(); ++val) {
      if (((IString)(oldCenter.unit(val))).UpCase() == "NANOMETERS") {
        newCenter.addValue(oldCenter[val], "NM");
      }
      else {
        newCenter.addValue(oldCenter[val], oldCenter.unit(val));
      }
    }
    image.addKeyword(newCenter, Pvl::Replace);

    PvlKeyword &oldBandWidth = image["BAND_WIDTH"];
    PvlKeyword newBandWidth("BAND_WIDTH");
    for (int val = 0; val < oldBandWidth.size(); ++val) {
      if (((IString)(oldBandWidth.unit(val))).UpCase() == "NANOMETERS") {
        newBandWidth.addValue(oldBandWidth[val], "NM");
      }
      else {
        newBandWidth.addValue(oldBandWidth[val], oldBandWidth.unit(val));
      }
    }
    image.addKeyword(newBandWidth, Pvl::Replace);

    // Add the min/max per band keywords
    image += minimum;
    image += maximum;

    // Modify the default SAMPLE_BIT_MASK keyword placed there by the
    // ProcessExportPds
    if (nbits != 8 && nbits != 16) {
      image.addKeyword(PvlKeyword("SAMPLE_BIT_MASK",
                                  toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)),
                       Pvl::Replace);
    }
  }

  // Modify the units in the viewing_parameters group
//  if (pdsLabel.hasGroup("VIEWING_PARAMETERS")) {
//    PvlGroup &viewGroup = pdsLabel.findGroup("VIEWING_PARAMETERS");

//    PvlKeyword &incidence = viewGroup["INCIDENCE_ANGLE"];
//    IString tstr = incidence.unit();
//    if (tstr.UpCase() == "DEG") incidence.setValue((QString)incidence, "deg");

//    PvlKeyword &emission = viewGroup["EMISSION_ANGLE"];
//    tstr = emission.unit();
//    if (tstr.UpCase() == "DEG") emission.setValue((QString)emission, "deg");

//    PvlKeyword &phase = viewGroup["PHASE_ANGLE"];
//    tstr = phase.unit();
//    if (tstr.UpCase() == "DEG") phase.setValue((QString)phase, "deg");

//    PvlKeyword &solarLon = viewGroup["SOLAR_LONGITUDE"];
//    tstr = solarLon.unit();   q
//    if (tstr.UpCase() == "DEG") solarLon.setValue((QString)solarLon, "deg");

//    PvlKeyword &localTime = viewGroup["LOCAL_TIME"];
//    tstr = localTime.unit();
//    if (tstr.UpCase() == "LOCALDAY/24") localTime.setValue((QString)localTime, "local day/24");
//  }

  // Add a keyword type (i.e., QString, bool, int...) file to the PDS label Pvl
  PvlFormat *formatter = pdsLabel.format();
  formatter->add("$mro/translations/hirisePdsRdrExtras.typ");

  // Add an output format template (group, object, & keyword output order) to
  // the PDS PVL
  if (projName == "EQUIRECTANGULAR") {
    if (enctype.Equal("jp2")) {
      pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEquiJP2.pft");
    }
    else {
      pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEqui.pft");
    }
  }
  else {
    if (enctype.Equal("jp2")) {
      pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolarJP2.pft");
    }
    else {
      pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolar.pft");
    }
  }

  // Open the output PDS file and dump the label and cube data
  if (enctype.Equal("jp2")) {
    p.OutputDetachedLabel();
    g_jp2Encoder = new JP2Encoder(ui.GetFileName("TO"), icube2->sampleCount(),
                                 icube2->lineCount(), icube2->bandCount(), g_oType);
    g_jp2Encoder->OpenFile();
    g_jp2ns = icube2->sampleCount();
    g_jp2nb = icube2->bandCount();
    g_jp2band = 0;
    p.StartProcess(writeJP2Image);
    p.EndProcess();
    delete g_jp2Encoder;
    for (int i = 0; i < icube2->bandCount(); i++) {
      delete [] g_jp2buf[i];
    }
  }
  else {
    FileName outFile(ui.GetFileName("TO"));
    ofstream oCube(outFile.expanded().toAscii().data());
    p.OutputLabel(oCube);
    p.StartProcess(oCube);
    oCube.close();
    p.EndProcess();
  }

  delete [] g_min;
  delete [] g_max;
}
コード例 #22
0
ファイル: bit2bit.cpp プロジェクト: corburn/ISIS
void IsisMain(){
  UserInterface &ui = Application::GetUserInterface();

  
  //We will process by line
  ProcessByLine p;
  Cube* cubeptr = p.SetInputCube("FROM");
  

  // Histogram* histptr = (cubeptr -> Histogram());
  double max = ui.GetDouble("MAXVAL");
  double min = ui.GetDouble("MINVAL");
  
  /*
  A histogram is made from the input cube, as the default min of the
  bit2bit output is at .5% of the data range, and the default max is at 99.5%
  */  
  Histogram* histptr = cubeptr -> histogram();
  
  double maxper = histptr -> Percent(ui.GetDouble("MAXPER"));
  double minper = histptr -> Percent(ui.GetDouble("MINPER"));
  double validMin = Isis::ValidMinimum;
  double validMax = Isis::ValidMaximum;
  
  

  // Set properties MIN,MAX, and PixelType for output cube
  CubeAttributeOutput outputProperties;
  if(ui.GetString("CLIP") == "PERCENT"){
    outputProperties.setMaximum(maxper);
    outputProperties.setMinimum(minper);
    validMax = maxper;
    validMin = minper;
  }
  else{
    outputProperties.setMaximum(max);
    outputProperties.setMinimum(min);
    validMax = max;
    validMin = min;
  }
  if(ui.GetString("BITTYPE")=="8BIT"){
    outputProperties.setPixelType(UnsignedByte);
  }
  else if(ui.GetString("BITTYPE")=="16BIT"){
    outputProperties.setPixelType(SignedWord);
  }
  else {
    outputProperties.setPixelType(Real);
  }    


  if(ui.GetBoolean("STATS")) { //! Run extended statistics
    Cube* ocubeptr = p.SetOutputCube (ui.GetFileName("TO"),outputProperties,
                     cubeptr->sampleCount(),cubeptr->lineCount(),
                     cubeptr->bandCount());
  
    p.StartProcess(populate);
  
    Histogram* ohistptr =  (ocubeptr -> histogram(1,validMin,validMax));
    int iLrs = histptr -> LrsPixels();
    int iHrs = histptr -> HrsPixels();
    int iNull = histptr -> NullPixels();
    int oLrs = ohistptr -> LrsPixels();
    int oHrs = ohistptr -> HrsPixels();
    int oNull = ohistptr -> NullPixels(); 
    double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0);
    double invalid_po = (( (ohistptr -> TotalPixels()) - (ohistptr -> ValidPixels()))*100.0) / ((ohistptr -> TotalPixels())*1.0);  
  
    p.EndProcess();

    //!Write bit2bit summary to the screen
    cout << "\n\nIN:\n";
    cout << "              LRS:\t\t" << iLrs << endl;
    cout << "              HRS:\t\t" << iHrs << endl;
    cout << "             NULL:\t\t" << iNull << endl;
    cout << "  Invalid Pixel %:\t\t" << invalid_pi << endl;
    cout << "\nOUT:\n\n";
    cout << "       Data Range:\t\t";
    cout << validMin << " < x < " << validMax << endl;
    cout << "              LRS:\t\t" << oLrs << endl;
    cout << "              HRS:\t\t" << oHrs << endl;
    cout << "             NULL:\t\t" << oNull << endl;
    cout << "  Invalid Pixel %:\t\t" << invalid_po << endl<< endl;
  
    //!Write bit2bit summary to print.prt logfile
    PvlGroup results("bit2bit_Results");
    results += PvlKeyword ("INPUT_LRS",toString(iLrs));
    results += PvlKeyword ("INPUT_HRS",toString(iHrs));
    results += PvlKeyword ("INPUT_NULL",toString(iNull));
    results += PvlKeyword ("INPUT_INVALID_PERCENT",toString(invalid_pi));
    results += PvlKeyword ("OUTPUT_MIN",toString(validMin));
    results += PvlKeyword ("OUTPUT_MAX",toString(validMax));
    results += PvlKeyword ("OUTPUT_LRS",toString(oLrs));
    results += PvlKeyword ("OUTPUT_HRS",toString(oHrs));
    results += PvlKeyword ("OUTPUT_NULL",toString(oNull));
    results += PvlKeyword ("OUTPUT_INVALID_PERCENT",toString(invalid_po));
    Application::Log(results);
  
    delete histptr;
    delete ohistptr;  
  }
  else{ //! run minimal statistics (runs faster)
    int iLrs = histptr -> LrsPixels();
    int iHrs = histptr -> HrsPixels();
    int iNull = histptr -> NullPixels();
    double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0);
    
    p.EndProcess();

    //!Write bit2bit summary to the screen
    cout << "\n\nIN:\n";
    cout << "              LRS:\t\t" << iLrs << endl;
    cout << "              HRS:\t\t" << iHrs << endl;
    cout << "             NULL:\t\t" << iNull << endl;
    cout << "  Invalid Pixel %:\t\t" << invalid_pi << endl;
    cout << "\nOUT:\n\n";
    cout << "       Data Range:\t\t";
    cout << validMin << " < x < " << validMax << endl;

  
    //!Write bit2bit summary to print.prt logfile
    PvlGroup results("bit2bit_Results");
    results += PvlKeyword ("INPUT_LRS",toString(iLrs));
    results += PvlKeyword ("INPUT_HRS",toString(iHrs));
    results += PvlKeyword ("INPUT_NULL",toString(iNull));
    results += PvlKeyword ("INPUT_INVALID_PERCENT",toString(invalid_pi));
    results += PvlKeyword ("OUTPUT_MIN",toString(validMin));
    results += PvlKeyword ("OUTPUT_MAX",toString(validMax));
    Application::Log(results);
  
    delete histptr;
  }
}