Example #1
0
void IsisMain() {
  // Set the input image, get the camera model
  Process p;
  Cube *icube = p.SetInputCube("FROM");
  Camera *cam = icube->camera();

  // Get the ra/dec range and resolution
  double minRa, maxRa, minDec, maxDec;
  cam->RaDecRange(minRa, maxRa, minDec, maxDec);
  double res = cam->RaDecResolution();

  // Get the center ra/dec
  cam->SetImage(icube->sampleCount() / 2.0, icube->lineCount() / 2.0);
  double centerRa  = cam->RightAscension();
  double centerDec = cam->Declination();

  // Compute the rotation
  cam->SetRightAscensionDeclination(centerRa, centerDec + 2.0 * res);
  double x = cam->Sample() - icube->sampleCount() / 2.0;
  double y = cam->Line() - icube->lineCount() / 2.0;
  double rot = atan2(-y, x) * 180.0 / Isis::PI;
  rot = 90.0 - rot;
  if(rot < 0.0) rot += 360.0;

  // Setup and log results
  PvlGroup results("Range");
  results += PvlKeyword("MinimumRightAscension", toString(minRa), "degrees");
  results += PvlKeyword("MaximumRightAscension", toString(maxRa), "degrees");
  results += PvlKeyword("MinimumDeclination", toString(minDec), "degrees");
  results += PvlKeyword("MaximumDeclination", toString(maxDec), "degrees");
  results += PvlKeyword("MinimumRightAscension", Projection::ToHMS(minRa), "hms");
  results += PvlKeyword("MaximumRightAscension", Projection::ToHMS(maxRa), "hms");
  results += PvlKeyword("MinimumDeclination", Projection::ToDMS(minDec), "dms");
  results += PvlKeyword("MaximumDeclination", Projection::ToDMS(maxDec), "dms");
  results += PvlKeyword("Resolution", toString(res), "degrees/pixel");
  Application::Log(results);

  // Setup and log orientation
  PvlGroup orient("Orientation");
  orient += PvlKeyword("CenterSample", toString(icube->sampleCount() / 2.0));
  orient += PvlKeyword("CenterLine", toString(icube->lineCount() / 2.0));
  orient += PvlKeyword("CenterRightAscension", toString(centerRa), "degrees");
  orient += PvlKeyword("CenterDeclination", toString(centerDec), "degrees");
  orient += PvlKeyword("CelestialNorthClockAngle", toString(rot), "degrees");
  orient += PvlKeyword("Resolution", toString(res), "degrees/pixel");
  Application::Log(orient);

  // Write the output file if requested
  UserInterface ui = Application::GetUserInterface();
  if(ui.WasEntered("TO")) {
    Pvl temp;
    temp.addGroup(results);
    temp.addGroup(orient);
    temp.write(ui.GetFileName("TO", "txt"));
  }

  p.EndProcess();
}
Example #2
0
//Helper function to get camera resolution.
void ComputePixRes () {
  Process p;
  UserInterface &ui = Application::GetUserInterface();
  Cube *latCube = p.SetInputCube("LATCUB");
  Cube *lonCube = p.SetInputCube("LONCUB");
  Brick latBrick(1,1,1,latCube->PixelType());
  Brick lonBrick(1,1,1,lonCube->PixelType());
  latBrick.SetBasePosition(1,1,1);
  latCube->Read(latBrick);

  lonBrick.SetBasePosition(1,1,1);
  lonCube->Read(lonBrick);
      
  double a = latBrick.at(0) * PI/180.0;
  double c = lonBrick.at(0) * PI/180.0;
  
  latBrick.SetBasePosition(latCube->Samples(),latCube->Lines(),1);
  latCube->Read(latBrick);

  lonBrick.SetBasePosition(lonCube->Samples(),lonCube->Lines(),1);     
  lonCube->Read(lonBrick);

  double b = latBrick.at(0) * PI/180.0;
  double d = lonBrick.at(0) * PI/180.0;

  double angle = acos(cos(a) * cos(b) * cos(c - d) + sin(a) * sin(b));
  angle *= 180/PI;

  double pixels = sqrt(pow(latCube->Samples() -1.0, 2.0) + pow(latCube->Lines() -1.0, 2.0));

  p.EndProcess();

  ui.Clear("RESOLUTION");
  ui.PutDouble("RESOLUTION", pixels/angle);

  ui.Clear("PIXRES");
  ui.PutAsString("PIXRES","PPD");
}
Example #3
0
void IsisMain() {
  // Open the input cube
  Process p;
  UserInterface &ui = Application::GetUserInterface();
  CubeAttributeInput cai;
  Cube *icube = p.SetInputCube(ui.GetFilename("FROM"), cai, ReadWrite);

  // Make sure at least one CK & SPK quality was selected
  if (!ui.GetBoolean("CKPREDICTED") && !ui.GetBoolean("CKRECON") && !ui.GetBoolean("CKSMITHED") && !ui.GetBoolean("CKNADIR")) {
    string msg = "At least one CK quality must be selected";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }
  if (!ui.GetBoolean("SPKPREDICTED") && !ui.GetBoolean("SPKRECON") && !ui.GetBoolean("SPKSMITHED")) {
    string msg = "At least one SPK quality must be selected";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  // Make sure it is not projected
  Projection *proj = NULL;
  try {
    proj = icube->Projection();
  } catch (iException &e) {
    proj = NULL;
    e.Clear();
  }

  if (proj != NULL) {
    string msg = "Can not initialize SPICE for a map projected cube";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  Pvl lab = *icube->Label();

  // if cube has existing polygon delete it
  if (icube->Label()->HasObject("Polygon")) {
    icube->Label()->DeleteObject("Polygon");
  }

  // Set up for getting the mission name
  // Get the directory where the system missions translation table is.
  string transFile = p.MissionData("base", "translations/MissionName2DataDir.trn");

  // Get the mission translation manager ready
  PvlTranslationManager missionXlater (lab, transFile);

  // Get the mission name so we can search the correct DB's for kernels
  string mission = missionXlater.Translate ("MissionName");

  // Get system base kernels
  unsigned int allowed = 0;
  unsigned int allowedCK = 0;
  unsigned int allowedSPK = 0;
  if (ui.GetBoolean("CKPREDICTED"))  allowedCK |= spiceInit::kernelTypeEnum("PREDICTED");
  if (ui.GetBoolean("CKRECON"))      allowedCK |= spiceInit::kernelTypeEnum("RECONSTRUCTED");
  if (ui.GetBoolean("CKSMITHED"))    allowedCK |= spiceInit::kernelTypeEnum("SMITHED");
  if (ui.GetBoolean("CKNADIR"))      allowedCK |= spiceInit::kernelTypeEnum("NADIR");
  if (ui.GetBoolean("SPKPREDICTED")) allowedSPK |= spiceInit::kernelTypeEnum("PREDICTED");
  if (ui.GetBoolean("SPKRECON"))     allowedSPK |= spiceInit::kernelTypeEnum("RECONSTRUCTED");
  if (ui.GetBoolean("SPKSMITHED"))   allowedSPK |= spiceInit::kernelTypeEnum("SMITHED");
  KernelDb baseKernels (allowed);
  KernelDb ckKernels (allowedCK);
  KernelDb spkKernels (allowedSPK);

  baseKernels.LoadSystemDb(mission);
  ckKernels.LoadSystemDb(mission);
  spkKernels.LoadSystemDb(mission);

  Kernel lk, pck, targetSpk, fk, ik, sclk, spk, iak, dem, exk;
  std::priority_queue< Kernel > ck;
  lk        = baseKernels.LeapSecond(lab);
  pck       = baseKernels.TargetAttitudeShape(lab);
  targetSpk = baseKernels.TargetPosition(lab);
  ik        = baseKernels.Instrument(lab);
  sclk      = baseKernels.SpacecraftClock(lab);
  iak       = baseKernels.InstrumentAddendum(lab);
  fk        = ckKernels.Frame(lab);
  ck        = ckKernels.SpacecraftPointing(lab);
  spk       = spkKernels.SpacecraftPosition(lab);

  if (ui.GetBoolean("CKNADIR")) {
    // Only add nadir if no spacecraft pointing found
    std::vector<std::string> kernels;
    kernels.push_back("Nadir");
    ck.push(Kernel((spiceInit::kernelTypes)0, kernels));
  }

  // Get user defined kernels and override ones already found
  GetUserEnteredKernel("LS", lk);
  GetUserEnteredKernel("PCK", pck);
  GetUserEnteredKernel("TSPK", targetSpk);
  GetUserEnteredKernel("FK", fk);
  GetUserEnteredKernel("IK", ik);
  GetUserEnteredKernel("SCLK", sclk);
  GetUserEnteredKernel("SPK", spk);
  GetUserEnteredKernel("IAK", iak);
  GetUserEnteredKernel("EXTRA", exk);

  // Get shape kernel
  if (ui.GetString ("SHAPE") == "USER") {
    GetUserEnteredKernel("MODEL", dem);
  } else if (ui.GetString("SHAPE") == "SYSTEM") {
    dem = baseKernels.Dem(lab);
  }

  bool kernelSuccess = false;

  if (ck.size() == 0 && !ui.WasEntered("CK")) {
    throw iException::Message(iException::Camera, 
                              "No Camera Kernel found for the image ["+ui.GetFilename("FROM")
                              +"]", 
                              _FILEINFO_);
  }
  else if(ui.WasEntered("CK")) {
    // ck needs to be array size 1 and empty kernel objects
    while(ck.size()) ck.pop();
    ck.push(Kernel());
  }

  while(ck.size() != 0 && !kernelSuccess) {
    Kernel realCkKernel = ck.top();
    ck.pop();

    if (ui.WasEntered("CK")) {
      ui.GetAsString("CK", realCkKernel.kernels);
    }

    // Merge SpacecraftPointing and Frame into ck
    for (int i = 0; i < fk.size(); i++) {
      realCkKernel.push_back(fk[i]);
    }

    kernelSuccess = TryKernels(icube, p, lk, pck, targetSpk,
                   realCkKernel, fk, ik, sclk, spk, iak, dem, exk);
  }

  if(!kernelSuccess) {
    throw iException::Message(iException::Camera, 
                              "Unable to initialize camera model", 
                              _FILEINFO_);
  }

  p.EndProcess();
}
Example #4
0
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();
  Cube cube;
  cube.open(ui.GetFileName("FROM"), "rw");

  // Make sure cube has been run through spiceinit
  try {
    cube.camera();
  }
  catch(IException &e) {
    string msg = "Spiceinit must be run before initializing the polygon";
    throw IException(e, IException::User, msg, _FILEINFO_);
  }

  Progress prog;
  prog.SetMaximumSteps(1);
  prog.CheckStatus();

  QString sn = SerialNumber::Compose(cube);

  ImagePolygon poly;
  if(ui.WasEntered("MAXEMISSION")) {
    poly.Emission(ui.GetDouble("MAXEMISSION"));
  }
  if(ui.WasEntered("MAXINCIDENCE")) {
    poly.Incidence(ui.GetDouble("MAXINCIDENCE"));
  }
  if(ui.GetString("LIMBTEST") == "ELLIPSOID") {
    poly.EllipsoidLimb(true);
  }

  int sinc = 1;
  int linc = 1;
  IString incType = ui.GetString("INCTYPE");
  if(incType.UpCase() == "VERTICES") {
    poly.initCube(cube);
    sinc = linc = (int)(0.5 + (((poly.validSampleDim() * 2) +
                       (poly.validLineDim() * 2) - 3.0) /
                       ui.GetInteger("NUMVERTICES")));
    if (sinc < 1.0 || linc < 1.0)
      sinc = linc = 1.0;
  }
  else if (incType.UpCase() == "LINCSINC"){
    sinc = ui.GetInteger("SINC");
    linc = ui.GetInteger("LINC");
  }
  else {
    string msg = "Invalid INCTYPE option[" + incType + "]";
    throw IException(IException::Programmer, msg, _FILEINFO_);
  }

  bool precision = ui.GetBoolean("INCREASEPRECISION");
  try {
    poly.Create(cube, sinc, linc, 1, 1, 0, 0, 1, precision);
  }
  catch (IException &e) {
    QString msg = "Cannot generate polygon for [" + ui.GetFileName("FROM") + "]";
    throw IException(e, IException::User, msg, _FILEINFO_);
  }

  if(ui.GetBoolean("TESTXY")) {
    Pvl cubeLab(ui.GetFileName("FROM"));
    PvlGroup inst = cubeLab.findGroup("Instrument", Pvl::Traverse);
    QString target = inst["TargetName"];
    PvlGroup radii = Projection::TargetRadii(target);

    Pvl map(ui.GetFileName("MAP"));
    PvlGroup &mapping = map.findGroup("MAPPING");

    if(!mapping.hasKeyword("TargetName"))
      mapping += Isis::PvlKeyword("TargetName", target);
    if(!mapping.hasKeyword("EquatorialRadius"))
      mapping += Isis::PvlKeyword("EquatorialRadius", (QString)radii["EquatorialRadius"]);
    if(!mapping.hasKeyword("PolarRadius"))
      mapping += Isis::PvlKeyword("PolarRadius", (QString)radii["PolarRadius"]);
    if(!mapping.hasKeyword("LatitudeType"))
      mapping += Isis::PvlKeyword("LatitudeType", "Planetocentric");
    if(!mapping.hasKeyword("LongitudeDirection"))
      mapping += Isis::PvlKeyword("LongitudeDirection", "PositiveEast");
    if(!mapping.hasKeyword("LongitudeDomain"))
      mapping += Isis::PvlKeyword("LongitudeDomain", "360");
    if(!mapping.hasKeyword("CenterLatitude"))
      mapping += Isis::PvlKeyword("CenterLatitude", "0");
    if(!mapping.hasKeyword("CenterLongitude"))
      mapping += Isis::PvlKeyword("CenterLongitude", "0");

    sinc = poly.getSinc();
    linc = poly.getLinc();
    bool polygonGenerated = false;
    while (!polygonGenerated) {
      Projection *proj = NULL;
      geos::geom::MultiPolygon *xyPoly = NULL;

      try {
        proj = ProjectionFactory::Create(map, true);
        xyPoly = PolygonTools::LatLonToXY(*poly.Polys(), proj);

        polygonGenerated = true;
      }
      catch (IException &e) {
        if (precision && sinc > 1 && linc > 1) {
          sinc = sinc * 2 / 3;
          linc = linc * 2 / 3;
          poly.Create(cube, sinc, linc);
        }
        else {
          delete proj;
          delete xyPoly;
          e.print(); // This should be a NAIF error
          QString msg = "Cannot calculate XY for [";
          msg += ui.GetFileName("FROM") + "]";
          throw IException(e, IException::User, msg, _FILEINFO_);
        }
      }

      delete proj;
      delete xyPoly;
    }
  }

  cube.deleteBlob("Polygon", sn);
  cube.write(poly);

  if(precision) {
    PvlGroup results("Results");
    results.addKeyword(PvlKeyword("SINC", toString(sinc)));
    results.addKeyword(PvlKeyword("LINC", toString(linc)));
    Application::Log(results);
  }

  Process p;
  p.SetInputCube("FROM");
  p.WriteHistory(cube);

  cube.close();
  prog.CheckStatus();
}
Example #5
0
void IsisMain() {

  //get the number of samples to skip from the left and right ends
  // of the prefix and suffix data
  UserInterface &ui = Application::GetUserInterface();

  int imageLeft      = 0;
  int imageRight     = 0;
  int rampLeft       = 0;
  int rampRight      = 0;
  int calLeftBuffer  = 0;
  int calRightBuffer = 0;
  int calLeftDark    = 0;
  int calRightDark   = 0;
  int leftBuffer     = 0;
  int rightBuffer    = 0;
  int leftDark       = 0;
  int rightDark      = 0;

  if(ui.GetBoolean("USEOFFSETS")) {
    imageLeft      = ui.GetInteger("LEFTIMAGE");
    imageRight     = ui.GetInteger("RIGHTIMAGE");
    rampLeft       = ui.GetInteger("LEFTIMAGE");
    rampRight      = ui.GetInteger("RIGHTIMAGE");
    calLeftBuffer  = ui.GetInteger("LEFTCALBUFFER");
    calRightBuffer = ui.GetInteger("LEFTCALBUFFER");
    calLeftDark    = ui.GetInteger("LEFTCALDARK");
    calRightDark   = ui.GetInteger("RIGHTCALDARK");
    leftBuffer     = ui.GetInteger("LEFTBUFFER");
    rightBuffer    = ui.GetInteger("RIGHTBUFFER");
    leftDark       = ui.GetInteger("LEFTDARK");
    rightDark      = ui.GetInteger("RIGHTDARK");
  }


  Isis::FileName fromFile = ui.GetFileName("FROM");
  Isis::Cube inputCube;
  inputCube.open(fromFile.expanded());

  //Check to make sure we got the cube properly
  if(!inputCube.isOpen()) {
    QString msg = "Could not open FROM cube " + fromFile.expanded();
    throw IException(IException::User, msg, _FILEINFO_);
  }

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

  // Get statistics from the cube prefix and suffix data
  Table hifix("HiRISE Ancillary");
  icube->read(hifix);
  Statistics darkStats, bufStats, rampDarkStats;
  int tdi = icube->group("Instrument")["Tdi"];
  int binning_mode = icube->group("Instrument")["Summing"];

  //This gets us the statistics for the dark and buffer pixels
  // alongside of the image itself
  for(int rec = 2; rec < hifix.Records(); rec++) {
    vector<int> dark = hifix[rec]["DarkPixels"];
    vector<int> buf = hifix[rec]["BufferPixels"];
    if(buf.size() <= (unsigned int)(leftBuffer + rightBuffer)) {
      ThrowException(buf.size(), leftBuffer, rightBuffer, "image buffer");
    }
    if(dark.size() <= (unsigned int)(leftDark + rightDark)) {
      ThrowException(dark.size(), leftDark, rightDark, "image dark reference");
    }

    for(int i = leftDark; i < (int)dark.size() - rightDark; i++) {
      double d;
      if(dark[i] == NULL2) d = NULL8;
      else if(dark[i] == LOW_REPR_SAT2) d = LOW_REPR_SAT8;
      else if(dark[i] == LOW_INSTR_SAT2) d = LOW_INSTR_SAT8;
      else if(dark[i] == HIGH_INSTR_SAT2) d = HIGH_INSTR_SAT8;
      else if(dark[i] == HIGH_REPR_SAT2) d = HIGH_REPR_SAT8;
      else d = dark[i];
      darkStats.AddData(&d, 1);
    }


    for(int i = leftBuffer; i < (int)buf.size() - rightBuffer; i++) {
      double d;
      if(buf[i] == NULL2) d = NULL8;
      else if(buf[i] == LOW_REPR_SAT2) d = LOW_REPR_SAT8;
      else if(buf[i] == LOW_INSTR_SAT2) d = LOW_INSTR_SAT8;
      else if(buf[i] == HIGH_INSTR_SAT2) d = HIGH_INSTR_SAT8;
      else if(buf[i] == HIGH_REPR_SAT2) d = HIGH_REPR_SAT8;
      else d = buf[i];
      bufStats.AddData(&d, 1);
    }
  }

  // Get statistics from the calibration image

  //Calculate boundaries of the reverse readout lines,
  // Masked lines, and ramp lines.

  //There are always 20 reverse readout lines
  int reverseReadoutLines = 20;

  //Number of mask pixels depends on Binning mode
  int maskLines;
  maskLines = 20 / binning_mode;

  //mask lines go after reverse lines
  maskLines += reverseReadoutLines;

// Actual starting line, number Ramp lines
  int rampStart = maskLines;
  int rampLines = tdi / binning_mode;

  Table calimg("HiRISE Calibration Image");
  icube->read(calimg);
  Statistics calStats;
  //Statistics for the Reverse readout lines of the cal image
  Statistics reverseStats;
  //Statistics for the masked lines of the cal image
  Statistics maskStats;
  //Statistics for the ramped lines of the cal image
  Statistics rampStats;

  //Iterate through the calibration image

  //Add in reverse data
  for(int rec = 2 ; rec <= 18 ; rec++) { //Lines [2,18]
    vector<int> lineBuffer = calimg[rec]["Calibration"];
    for(unsigned int i = 2 ; i < lineBuffer.size() - 1 ; i++) { //Samples [2, * -1]
      double d = lineBuffer[i];
      if(lineBuffer[i] == NULL2) {
        d = NULL8;
      }
      else if(lineBuffer[i] == LOW_REPR_SAT2)  {
        d = LOW_REPR_SAT8;
      }
      else if(lineBuffer[i] == LOW_INSTR_SAT2) {
        d = LOW_INSTR_SAT8;
      }
      else if(lineBuffer[i] == HIGH_INSTR_SAT2) {
        d = HIGH_INSTR_SAT8;
      }
      else if(lineBuffer[i] == HIGH_REPR_SAT2) {
        d = HIGH_REPR_SAT8;
      }
      reverseStats.AddData(&d, 1);
    }
  }

  //Add in the mask data
  for(int rec = 22 ; rec < maskLines - 1 ; rec++) {//Lines [22, 38] !!!!dependant on bin
    vector<int> lineBuffer = calimg[rec]["Calibration"];
    for(int i = 2 ; i < (int)lineBuffer.size() - 1 ; i++) { //Samples [2, *-1]
      double d = lineBuffer[i];
      if(d == NULL2) {
        d = NULL8;
      }
      else if(d == LOW_REPR_SAT2)  {
        d = LOW_REPR_SAT8;
      }
      else if(d == LOW_INSTR_SAT2) {
        d = LOW_INSTR_SAT8;
      }
      else if(d == HIGH_INSTR_SAT2) {
        d = HIGH_INSTR_SAT8;
      }
      else if(d == HIGH_REPR_SAT2) {
        d = HIGH_REPR_SAT8;
      }
      maskStats.AddData(&d, 1);
    }
  }

  //Add in the ramp data
  for(int rec = maskLines + 2; rec < calimg.Records() - 1; rec++) {
    vector<int> buf = calimg[rec]["Calibration"];
    //loop through all but the first and last sample of the calibration image
    for(int i = rampLeft; i < (int)buf.size() - rampRight; i++) {
      double d;
      if(buf[i] == NULL2) d = NULL8;
      else if(buf[i] == LOW_REPR_SAT2) d = LOW_REPR_SAT8;
      else if(buf[i] == LOW_INSTR_SAT2) d = LOW_INSTR_SAT8;
      else if(buf[i] == HIGH_INSTR_SAT2) d = HIGH_INSTR_SAT8;
      else if(buf[i] == HIGH_REPR_SAT2) d = HIGH_REPR_SAT8;
      else d = buf[i];
      //Determine which group of stats to add to
      rampStats.AddData(&d, 1);
    }
  }

  // Get statistics from the calibration prefix and suffix data
  Table calfix("HiRISE Calibration Ancillary");
  icube->read(calfix);
  Statistics calDarkStats, calBufStats;
  int rampLine0 = rampStart + 1;
  int rampLineN = (rampStart + rampLines - 1) - 1;
  rampLineN = calfix.Records() - 1;
  for(int rec = 0; rec < calfix.Records(); rec++) {
    vector<int> dark = calfix[rec]["DarkPixels"];
    vector<int> buf = calfix[rec]["BufferPixels"];
    if(buf.size() <= (unsigned int)(calLeftBuffer + calRightBuffer)) {
      ThrowException(buf.size(), calLeftBuffer, calRightBuffer, "calibration buffer");
    }
    if(dark.size() <= (unsigned int)(calLeftDark + calRightDark)) {
      ThrowException(dark.size(), calLeftDark, calRightDark, "calibration dark reference");
    }
    for(int i = calLeftDark; i < (int)dark.size() - calRightDark; i++) {
      double d;
      if(dark[i] == NULL2) d = NULL8;
      else if(dark[i] == LOW_REPR_SAT2) d = LOW_REPR_SAT8;
      else if(dark[i] == LOW_INSTR_SAT2) d = LOW_INSTR_SAT8;
      else if(dark[i] == HIGH_INSTR_SAT2) d = HIGH_INSTR_SAT8;
      else if(dark[i] == HIGH_REPR_SAT2) d = HIGH_REPR_SAT8;
      else d = dark[i];
      calDarkStats.AddData(&d, 1);
      if((rec > rampLine0) && (rec < rampLineN)) {
        rampDarkStats.AddData(&d, 1);
      }
    }
    for(int i = calLeftBuffer; i < (int)buf.size() - calRightBuffer; i++) {
      double d;
      if(buf[i] == NULL2) d = NULL8;
      else if(buf[i] == LOW_REPR_SAT2) d = LOW_REPR_SAT8;
      else if(buf[i] == LOW_INSTR_SAT2) d = LOW_INSTR_SAT8;
      else if(buf[i] == HIGH_INSTR_SAT2) d = HIGH_INSTR_SAT8;
      else if(buf[i] == HIGH_REPR_SAT2) d = HIGH_REPR_SAT8;
      else d = buf[i];
      calBufStats.AddData(&d, 1);
    }
  }

  Statistics linesPostrampStats;
  Statistics imageStats;
  Isis::LineManager imageBuffer(inputCube);
  imageBuffer.begin();

  Buffer out(imageBuffer.SampleDimension() - (imageLeft + imageRight),
             imageBuffer.LineDimension(),
             imageBuffer.BandDimension(),
             imageBuffer.PixelType());


  for(int postRampLine = 0 ; postRampLine < LINES_POSTRAMP ; postRampLine++) {
    inputCube.read(imageBuffer);
    for(int postRampSamp = 0 ; postRampSamp < out.SampleDimension() ; postRampSamp++) {
      out[postRampSamp] = imageBuffer[postRampSamp + imageLeft];
    }
    linesPostrampStats.AddData(out.DoubleBuffer(), out.size());
    imageBuffer++;
  }

  for(int imageLine = LINES_POSTRAMP; imageLine < inputCube.lineCount(); imageLine++) {
    inputCube.read(imageBuffer);
    for(int imageSample = 0 ; imageSample < out.SampleDimension(); imageSample++) {
      out[imageSample] = imageBuffer[imageSample + imageLeft];
    }
    imageStats.AddData(out.DoubleBuffer(), out.size());
    imageBuffer++;
  }


  // Generate the statistics in pvl form
  const int NUM_GROUPS = 10;
  PvlGroup groups[NUM_GROUPS];
  groups[0] = PvlStats(linesPostrampStats, "IMAGE_POSTRAMP");
  groups[1] = PvlStats(imageStats, "IMAGE");
  groups[2] = PvlStats(darkStats, "IMAGE_DARK");
  groups[3] = PvlStats(bufStats, "IMAGE_BUFFER");
  groups[4] = PvlStats(reverseStats, "CAL_REVERSE");
  groups[5] = PvlStats(maskStats, "CAL_MASK");
  groups[6] = PvlStats(rampStats, "CAL_RAMP");
  groups[7] = PvlStats(calDarkStats, "CAL_DARK");
  groups[8] = PvlStats(rampDarkStats, "CAL_DARK_RAMP");
  groups[9] = PvlStats(calBufStats, "CAL_BUFFER");

  // Write the results to the output file if the user specified one
  if(ui.WasEntered("TO")) {
    Pvl temp;
    for(int i = 0 ; i < NUM_GROUPS ; i++) {
      temp.addGroup(groups[i]);
    }
    temp.write(ui.GetFileName("TO"));
  }
  else {
    // Log the results
    for(int i = 0 ; i < NUM_GROUPS ; i++) {
      Application::Log(groups[i]);
    }
  }
}
Example #6
0
void IsisMain() {
  Process p;
  Cube *icube = p.SetInputCube("FROM");
  Camera *cam = icube->camera();

  UserInterface &ui = Application::GetUserInterface();

  QString from = ui.GetFileName("FROM");
  int sinc = ui.GetInteger("SINC");
  int linc = ui.GetInteger("LINC");
  CameraStatistics camStats(cam, sinc, linc, from);

  // Send the Output to the log area
  Pvl statsPvl = camStats.toPvl();
  for (int i = 0; i < statsPvl.groups(); i++) {
    Application::Log(statsPvl.group(i));
  }

  if(ui.WasEntered("TO")) {
    QString outfile = FileName(ui.GetFileName("TO")).expanded();
    bool exists = FileName(outfile).fileExists();
    bool append = ui.GetBoolean("APPEND");

    // If the user chose a format of PVL, then write to the output file ("TO")
    if(ui.GetString("FORMAT") == "PVL") {
      (append) ? statsPvl.append(outfile) : statsPvl.write(outfile);
    }
    else {
      // Create a flatfile of the data with columhn headings the flatfile is
      // comma-delimited and can be imported in to spreadsheets
      ofstream os;
      bool writeHeader = true;
      if(append) {
        os.open(outfile.toAscii().data(), ios::app);
        if(exists) {
          writeHeader = false;
        }
      }
      else {
        os.open(outfile.toAscii().data(), ios::out);
      }

      // if new file or append and no file exists then write header
      if(writeHeader) {
        os << "Filename," <<
           "LatitudeMinimum," <<
           "LatitudeMaximum," <<
           "LatitudeAverage," <<
           "LatitudeStandardDeviation," <<
           "LongitudeMinimum," <<
           "LongitudeMaximum," <<
           "LongitudeAverage," <<
           "LongitudeStandardDeviation," <<
           "SampleResolutionMinimum," <<
           "SampleResolutionMaximum," <<
           "SampleResolutionAverage," <<
           "SampleResolutionStandardDeviation," <<
           "LineResolutionMinimum," <<
           "LineResolutionMaximum," <<
           "LineResolutionAverage," <<
           "LineResolutionStandardDeviation," <<
           "ResolutionMinimum," <<
           "ResolutionMaximum," <<
           "ResolutionAverage," <<
           "ResolutionStandardDeviation," <<
           "AspectRatioMinimum," <<
           "AspectRatioMaximum," <<
           "AspectRatioAverage," <<
           "AspectRatioStandardDeviation," <<
           "PhaseMinimum," <<
           "PhaseMaximum," <<
           "PhaseAverage," <<
           "PhaseStandardDeviation," <<
           "EmissionMinimum," <<
           "EmissionMaximum," <<
           "EmissionAverage," <<
           "EmissionStandardDeviation," <<
           "IncidenceMinimum," <<
           "IncidenceMaximum," <<
           "IncidenceAverage," <<
           "IncidenceStandardDeviation," <<
           "LocalSolarTimeMinimum," <<
           "LocalSolarTimeMaximum," <<
           "LocalSolarTimeAverage," <<
           "LocalSolarTimeStandardDeviation," <<
           "LocalRadiusMaximum," <<
           "LocalRadiusMaximum," <<
           "LocalRadiusAverage," <<
           "LocalRadiusStandardDeviation," <<
           "NorthAzimuthMinimum," <<
           "NorthAzimuthMaximum," <<
           "NorthAzimuthAverage," <<
           "NorthAzimuthStandardDeviation," << endl;
      }
      os << FileName(from).expanded() << ",";
      //call the function to write out the values for each group
      writeFlat(os, camStats.getLatStat());
      writeFlat(os, camStats.getLonStat());
      writeFlat(os, camStats.getSampleResStat());
      writeFlat(os, camStats.getLineResStat());
      writeFlat(os, camStats.getResStat());
      writeFlat(os, camStats.getAspectRatioStat());
      writeFlat(os, camStats.getPhaseStat());
      writeFlat(os, camStats.getEmissionStat());
      writeFlat(os, camStats.getIncidenceStat());
      writeFlat(os, camStats.getLocalSolarTimeStat());
      writeFlat(os, camStats.getLocalRaduisStat());
      writeFlat(os, camStats.getNorthAzimuthStat());
      os << endl;
    }
  }

  if(ui.GetBoolean("ATTACH")) {

    QString cam_name = "CameraStatistics";

    //Creates new CameraStatistics Table
    TableField fname("Name", Isis::TableField::Text, 20);
    TableField fmin("Minimum", Isis::TableField::Double);
    TableField fmax("Maximum", Isis::TableField::Double);
    TableField favg("Average", Isis::TableField::Double);
    TableField fstd("StandardDeviation", Isis::TableField::Double);

    TableRecord record;
    record += fname;
    record += fmin;
    record += fmax;
    record += favg;
    record += fstd;

    Table table(cam_name, record);

    // Place all the gathered camera statistics in a table and attach it to the
    // cube. Skip "User Parameters" group.
    for (int i = 1; i < statsPvl.groups(); i++) {
      PvlGroup &group = statsPvl.group(i);

      int entry = 0;
      record[entry] = group.name();
      entry++;
      for (int j = 0; j < group.keywords(); j++) {
        record[entry] = toDouble(group[j][0]);
        entry++;
      }
      table += record;
    }

    icube->reopen("rw");
    icube->write(table);
    p.WriteHistory(*icube);
    icube->close();
  }
}
Example #7
0
void IsisMain() {

    // Use a regular Process
    Process p;

    // Get user parameters and error check
    UserInterface &ui = Application::GetUserInterface();
    QString from = ui.GetFileName("FROM");
    QString to = FileName(ui.GetFileName("TO")).expanded();
//TO DO: UNCOMMENT THIS LINE ONCE HRSC IS WORKING IN SS
//  double HRSCNadirCenterTime = ui.GetDouble("HRSC_NADIRCENTERTIME");

    // Open input cube and Make sure this is a lev1 image (ie, not map projected)
    Cube cube;
    cube.open(from);

    if (cube.isProjected()) {
        QString msg = "Input images is a map projected cube ... not a level 1 image";
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // Initialize the camera
    Cube *input = p.SetInputCube("FROM");
    Pvl *cubeHeader = input->label();
    Camera *cam = input->camera();
    CameraDetectorMap *detectorMap = cam->DetectorMap();
    CameraFocalPlaneMap *focalMap = cam->FocalPlaneMap();
    CameraDistortionMap *distortionMap = cam->DistortionMap();
    CameraGroundMap *groundMap = cam->GroundMap();

    // Make sure the image contains the InstrumentPointing (aka CK) blob/table
    PvlGroup test = cube.label()->findGroup("Kernels", Pvl::Traverse);
    QString InstrumentPointing = (QString) test["InstrumentPointing"];
    if (InstrumentPointing != "Table") {
        QString msg = "Input image does not contain needed SPICE blobs...run spiceinit with attach=yes.";
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // Open output line scanner keyword file
    ofstream toStrm;
    toStrm.open(to.toAscii().data(), ios::trunc);
    if (toStrm.bad()) {
        QString msg = "Unable to open output TO file";
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // Get required keywords from instrument and band groups
    PvlGroup inst = cube.label()->findGroup("Instrument", Pvl::Traverse);
    QString instrumentId = (QString) inst["InstrumentId"];

    bool     isMocNA = false;
//TO DO: UNCOMMENT THIS LINES ONCE MOC IS WORKING IN SS
//  bool     isMocWARed = false;
    bool     isHiRise = false;
    bool     isCTX = false;
    bool     isLroNACL = false;
    bool     isLroNACR = false;
    bool     isHRSC = false;
//TO DO: UNCOMMENT THESE LINE ONCE MOC IS WORKING IN SS
//  if (instrumentId == "MOC") {
//    PvlGroup band = cube.label()->findGroup("BandBin", Pvl::Traverse);
//    QString filter = (QString) band["FilterName"];
//
//    if (strcmp(filter.toAscii().data(), "BROAD_BAND") == 0)
//      isMocNA = true;
//    else if (strcmp(filter.toAscii().data(), "RED") == 0)
//      isMocWARed = true;
//    else if (strcmp(filter.toAscii().data(), "BLUE") == 0) {
//      QString msg = "MOC WA Blue filter images not supported for Socet Set mapping";
//      throw IException(IException::User, msg, _FILEINFO_);
//    }
//  }
//  else if (instrumentId == "IdealCamera") {
//TO DO: DELETE THIS LINE ONCE MOC IS WORKING IN SS
    if (instrumentId == "IdealCamera") {
        PvlGroup orig = cube.label()->findGroup("OriginalInstrument",  Pvl::Traverse);
        QString origInstrumentId = (QString) orig["InstrumentId"];
        if (origInstrumentId == "HIRISE") {
            isHiRise = true;
        }
        else {
            QString msg = "Unsupported instrument: " + origInstrumentId;
            throw IException(IException::User, msg, _FILEINFO_);
        }
    }
    else if (instrumentId == "HIRISE") {
        isHiRise = true;
    }
    else if (instrumentId == "CTX") {
        isCTX = true;
    }
    else if (instrumentId == "NACL") {
        isLroNACL = true;
    }
    else if (instrumentId == "NACR") {
        isLroNACR = true;
    }
//TO DO: UNCOMMENT THIS LINE ONCE HRSC IS WORKING IN SS
//  else if (instrumentId == "HRSC") isHRSC = true;
    else {
        QString msg = "Unsupported instrument: " + instrumentId;
        throw IException(IException::User, msg, _FILEINFO_);
    }

    int ikCode = cam->naifIkCode();

    // Get Focal Length.
    // NOTE:
    //   For MOC Wide Angle, cam->focal_length returns the focal length
    //      in pixels, so we must convert from pixels to mm using the PIXEL_SIZE
    //      of 0.007 mm gotten from $ISIS3DATA/mgs/kernels/ik/moc20.ti.  (The
    //      PIXEL_PITCH value gotten from cam->PixelPitch is 1.0 since the
    //      focal length used by ISIS in this case is in pixels)
    //      For reference: the MOC WA blue filter pixel size needs an adjustment
    //      of 1.000452 (see p_scale in MocWideAngleDistortionMap.cpp), so that
    //      the final blue filter pixel size = (0.007 / 1.000452)
    //
    //   For all other cameras, cam->focal_length returns the focal
    //      length in mm, as needed by Socet Set

    double focal = cam->FocalLength();  // focal length returned in mm

//TO DO: UNCOMMENT THESE LINES ONCE HRSC and MOC IS WORKING IN SS
//  if (isMocWARed)
//    focal = focal * 0.007;  // pixel to mm conversion
//  else if (isHRSC)
//  {
//    switch (ikCode) {
//      case -41219:                   //S1: fwd stereo
//        focal = 184.88;
//        break;
//      case -41218:                   //IR: infra-red
//        focal = 181.57;
//        break;
//      case -41217:                   //P1: fwd photo
//        focal = 179.16;
//        break;
//      case -41216:                   // GREEN
//        focal = 175.31;
//        break;
//      case -41215:                   // NADIR
//        focal = 175.01;
//        break;
//      case -41214:                   // BLUE
//        focal = 175.53;
//        break;
//      case -41213:                   // P2: aft photo
//        focal = 179.19;
//        break;
//      case -41212:                   // RED
//        focal = 181.77;
//        break;
//      case -41211:                   // S2: aft stereo
//        focal = 184.88;
//        break;
//      default:
//        break;
//    }
//  }

    // Get instrument summing modes
    int csum = (int) detectorMap->SampleScaleFactor();
    int dsum = (int) detectorMap->LineScaleFactor();

    if (isLroNACL || isLroNACR || isHRSC)
        dsum = csum;

    // Calculate location of boresight in image space, these are zero-based values
    //
    // Note: For MOC NA, the boresight is at the image center
    //       For MOC WA, MRO HiRISE, MRO CTX, LRO_NACL, LRO_NACR and HRSC the
    //       boresight is not at the detector center, but the boresight is at the
    //       center of a NOPROJ'ED MRO HIRISE image

    // Get line/samp of boresight pixel in detector space (summing == 1)
    focalMap->SetFocalPlane(0.0, 0.0);
    double detectorBoresightSample = focalMap->DetectorSample();
    double detectorBoresightLine = focalMap->DetectorLine();

    // Convert sample of boresight pixel in detector into image space
    // (summing, etc., is accounted for.)
    detectorMap->SetDetector(detectorBoresightSample, detectorBoresightLine);
    double boresightSample = detectorMap->ParentSample();

    // Set Atmospheric correction coefficients to 0
    double atmco[4] = {0.0, 0.0, 0.0, 0.0};

    // Get totalLines, totalSamples and account for summed images
    int totalLines = cube.lineCount();
    int totalSamples = cube.sampleCount();

    // Get the Interval Time in seconds and calculate
    // scan duration in seconds
    double scanDuration = 0.0;
    double intTime = 0.0;

//TO DO: UNCOMMENT THESE LINES ONCE HRSC IS WORKING IN SS
//  int numIntTimes = 0.0;
//  vector<LineRateChange> lineRates;
//  if (isHRSC) {
//    numIntTimes = GetHRSCLineRates(&cube, lineRates, totalLines, HRSCNadirCenterTime);
//    if (numIntTimes == 1) {
//      LineRateChange lrc = lineRates.at(0);
//      intTime = lrc.GetLineScanRate();
//    }
//    if (numIntTimes <= 0) {
//      QString msg = "HRSC: Invalid number of scan times";
//      throw IException(IException::Programmer, msg, _FILEINFO_);
//    }
//    else
//      scanDuration = GetHRSCScanDuration(lineRates, totalLines);
//  }
//  else {
//
//  TO DO: indent the following two lines when HRSC is working in SS
    intTime = detectorMap->LineRate();  //LineRate is in seconds
    scanDuration = intTime * totalLines;
//TO DO: UNCOMMENT THIS LINE ONCE HRSC IS WORKING IN SS
//  }

    // For reference, this is the code if calculating interval time
    // via LineExposureDuration keyword off image labels:
    //
    // if (isMocNA || isMocWARed)
    //   intTime = exposureDuration * (double) dsum / 1000.0;
    // else if (isHiRise)
    //   intTime = exposureDuration * (double) dsum / 1000000.0;

    // Get along and cross scan pixel size for NA and WA sensors.
    // NOTE:
    //     1) The MOC WA pixel size is gotten from moc20.ti and is 7 microns
    //         HRSC pixel size is from the Instrument Addendum file
    //     2) For others, cam->PixelPitch() returns the pixel pitch (size) in mm.
    double alongScanPxSize = 0.0;
    double crossScanPxSize = 0.0;
//TO DO: UNCOMMENT THESE LINES ONCE MOC IS WORKING IN SS
//  if (isMocWARed || isHRSC) {
//    alongScanPxSize = csum * 0.007;
//    crossScanPxSize = dsum * 0.007;
//  }
//  else {
//
//  TO DO: indent the following 24 lines when HRSC is working in SS
    crossScanPxSize = dsum * cam->PixelPitch();

    // Get the ephemeris time, ground position and undistorted focal plane X
    // coordinate at the center line/samp of image
    cam->SetImage(cube.sampleCount() / 2.0, cube.lineCount() / 2.0);

    double tMid = cam->time().Et();

    const double latCenter = cam->UniversalLatitude();
    const double lonCenter = cam->UniversalLongitude();
    const double radiusCenter = cam->LocalRadius().meters();

    double uXCenter = distortionMap->UndistortedFocalPlaneX();

    // from the ground position at the image center, increment the ephemeris
    // time by the line rate and map the ground position into the sensor in
    // undistorted focal plane coordinates

    cam->setTime(iTime(tMid + intTime));
    double uX, uY;
    groundMap->GetXY(latCenter, lonCenter, radiusCenter, &uX, &uY);

    // the along scan pixel size is the difference in focal plane X coordinates
    alongScanPxSize = abs(uXCenter - uX);

//TO DO: UNCOMMENT THIS LINE ONCE MOC and HRSC IS WORKING IN SS
//  }

    // Now that we have totalLines, totalSamples, alongScanPxSize and
    // crossScanPxSize, fill the Interior Orientation Coefficient arrays
    double ioCoefLine[10];
    double ioCoefSample[10];
    for (int i = 0; i <= 9; i++) {
        ioCoefLine[i] = 0.0;
        ioCoefSample[i] = 0.0;
    }

    ioCoefLine[0] = totalLines / 2.0;
    ioCoefLine[1] = 1.0 / alongScanPxSize;

    ioCoefSample[0] = totalSamples / 2.0;
    ioCoefSample[2] = 1.0 / crossScanPxSize;

    // Update the Rectification Terms found in the base sensor class
    double rectificationTerms[6];
    rectificationTerms[0] = totalLines / 2.0;
    rectificationTerms[1] = 0.0;
    rectificationTerms[2] = 1.0;
    rectificationTerms[3] = totalSamples / 2.0;
    rectificationTerms[4] = 1.0;
    rectificationTerms[5] = 0.0;

    // Fill the triangulation parameters array
    double triParams[18];
    for (int i = 0; i <= 17; i++)
        triParams[i] = 0.0;

    triParams[15] = focal;

    // Set the Center Ground Point at the SOCET Set image, in radians
    double centerGp[3];
    double radii[3] = {0.0, 0.0, 0.0};
    Distance Dradii[3];

    cam->radii(Dradii);
    radii[0] = Dradii[0].kilometers();
    radii[1] = Dradii[1].kilometers();
    radii[2] = Dradii[2].kilometers();

    cam->SetImage(boresightSample, totalLines / 2.0);

    centerGp[0] = DEG2RAD *
                  TProjection::ToPlanetographic(cam->UniversalLatitude(), radii[0], radii[2]);
    centerGp[1] = DEG2RAD * TProjection::To180Domain(cam->UniversalLongitude());
    centerGp[2] = 0.0;
    //**** NOTE: in the import_pushbroom SOCET SET program, centerGp[2] will be set to the SS
    //**** project's gp_origin_z

    // Now get keyword values that depend on ephemeris data.

    // First get the ephemeris time and camera Lat Lon at image center line, boresight sample.
    double centerLine = double(totalLines) / 2.0;

    cam->SetImage(boresightSample, centerLine); //set to boresight of image
    double etCenter = cam->time().Et();

    // Get the sensor position at the image center in ographic lat,
    // +E lon domain 180 coordinates, radians, height in meters
    double sensorPosition[3] = {0.0, 0.0, 0.0};
    double ocentricLat, e360Lon;
    cam->subSpacecraftPoint(ocentricLat, e360Lon);
    sensorPosition[0] = DEG2RAD * TProjection::ToPlanetographic(ocentricLat, radii[0], radii[2]);
    sensorPosition[1] = DEG2RAD * TProjection::To180Domain(e360Lon);
    sensorPosition[2] = cam->SpacecraftAltitude() * 1000.0;

    // Build the ephem data.  If the image label contains the InstrumentPosition
    // table, use it as a guide for number and spacing of Ephem points.
    // Otherwise (i.e, for dejittered HiRISE images), the number and spacing of
    // ephem points based on hardcoded dtEphem value

    // Using the InstrumentPosition table as a guide build the ephem data
    QList< QList<double> > ephemPts;
    QList< QList<double> > ephemRates;

    PvlGroup kernels = cube.label()->findGroup("Kernels", Pvl::Traverse);
    QString InstrumentPosition = (QString) kernels["InstrumentPosition"];

    int numEphem = 0;      // number of ephemeris points
    double dtEphem = 0.0;  // delta time of ephemeris points, seconds
    if (InstrumentPosition == "Table") {
        // Labels contain SPK blob
        // set up Ephem pts/rates number and spacing
        Table tablePosition("InstrumentPosition", cubeHeader->fileName());
        numEphem = tablePosition.Records();

        // increase the number of ephem nodes by 20%.  This is somewhat random but
        // generally intended to compensate for having equally time spaced nodes
        // instead of of the potentially more efficient placement used by spiceinit
        numEphem = int(double(numEphem) * 1.2);

        // if numEphem calcutated from SPICE blobs is too sparse for SOCET Set,
        // mulitiply it by a factor of 30
        // (30X was settled upon emperically.  In the future, make this an input parameter)
        if (numEphem <= 10) numEphem = tablePosition.Records() * 30;

        // make the number of nodes odd
        numEphem  = (numEphem % 2) == 1 ? numEphem : numEphem + 1;

        // SOCET has a max number of ephem pts of 10000, and we're going to add twenty...
        if (numEphem > 10000 - 20) numEphem = 9979;

        dtEphem = scanDuration / double(numEphem);

        //build the tables of values
        double et = etCenter - (((numEphem - 1) / 2) * dtEphem);
        for (int i = 0; i < numEphem; i++) {
            cam->setTime(iTime(et));
            SpiceRotation *bodyRot = cam->bodyRotation();
            vector<double> pos = bodyRot->ReferenceVector(cam->instrumentPosition()->Coordinate());
//TO DO: UNCOMMENT THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //vector<double> vel = bodyRot->ReferenceVector(cam->instrumentPosition()->Velocity());

            //Add the ephemeris position and velocity to their respective lists, in meters and meters/sec
            QList<double> ephemPt;
            QList<double> ephemRate;
            ephemPts.append(ephemPt << pos[0] * 1000 << pos[1] * 1000 << pos[2] * 1000);
//TO DO: UNCOMMENT THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //ephemRates.append(ephemRate << vel[0] * 1000 << vel[1] * 1000 << vel[2] * 1000);

            et += dtEphem;
        }

//TO DO: WHEN VELOCITY BLOBS ARE CORRECT IN ISIS, linearlly interpolate 10 nodes rather than 11
//       (need 11 now for computation of velocity at first and last ephemeris point)
        // linearlly interpolate 11 additional nodes before line 1 (SOCET requires this)
        for (int i = 0; i < 11; i++) {
            double vec[3] = {0.0, 0.0, 0.0};
            vec[0] = ephemPts[0][0] + (ephemPts[0][0] - ephemPts[1][0]);
            vec[1] = ephemPts[0][1] + (ephemPts[0][1] - ephemPts[1][1]);
            vec[2] = ephemPts[0][2] + (ephemPts[0][2] - ephemPts[1][2]);
            QList<double> ephemPt;
            ephemPts.prepend (ephemPt << vec[0] << vec[1] << vec[2]);

//TO DO: UNCOMMENT THE FOLLOWING LINES WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //vec[0] = ephemRates[0][0] + (ephemRates[0][0] - ephemRates[1][0]);
            //vec[1] = ephemRates[0][1] + (ephemRates[0][1] - ephemRates[1][1]);
            //vec[2] = ephemRates[0][2] + (ephemRates[0][2] - ephemRates[1][2]);
            //QList<double> ephemRate;
            //ephemRates.prepend (ephemRate << vec[0] << vec[1] << vec[2]);
        }

//TO DO: WHEN VELOCITY BLOBS ARE CORRECT IN ISIS, linearlly interpolate 10 nodes rather than 11
//       (need 11 now for computation of velocity at first and last ephemeris point)
        // linearlly interpolate 11 additional nodes after the last line (SOCET requires this)
        for (int i = 0; i < 11; i++) {
            double vec[3] = {0.0, 0.0, 0.0};
            int index = ephemPts.size() - 1;
            vec[0] = ephemPts[index][0] + (ephemPts[index][0] - ephemPts[index - 1][0]);
            vec[1] = ephemPts[index][1] + (ephemPts[index][1] - ephemPts[index - 1][1]);
            vec[2] = ephemPts[index][2] + (ephemPts[index][2] - ephemPts[index - 1][2]);
            QList<double> ephemPt;
            ephemPts.append(ephemPt << vec[0] << vec[1] << vec[2]);

//TO DO: UNCOMMENT THE FOLLOWING LINES WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //vec[0] = ephemRates[index][0] + (ephemRates[index][0] - ephemRates[index - 1][0]);
            //vec[1] = ephemRates[index][1] + (ephemRates[index][1] - ephemRates[index - 1][1]);
            //vec[2] = ephemRates[index][2] + (ephemRates[index][2] - ephemRates[index - 1][2]);
            //QList<double> ephemRate;
            //ephemRates.append(ephemRate << vec[0] << vec[1] << vec[2]);
        }

        numEphem += 20;

//TO DO: DELETE THE FOLLOWING LINES WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
        // Compute the spacecraft velocity at each ephemeris point
        double deltaTime = 2.0 * dtEphem;
        for (int i = 0; i < numEphem; i++) {
            double vec[3] = {0.0, 0.0, 0.0};
            vec[0] = (ephemPts[i+2][0] - ephemPts[i][0]) / deltaTime;
            vec[1] = (ephemPts[i+2][1] - ephemPts[i][1]) / deltaTime;
            vec[2] = (ephemPts[i+2][2] - ephemPts[i][2]) / deltaTime;
            QList<double> ephemRate;
            ephemRates.append(ephemRate << vec[0] << vec[1] << vec[2]);
        }

    }
    else {
        // Calculate the number of ephemeris points that are needed, based on the
        // value of dtEphem (Delta-Time-Ephemeris).  SOCET SET needs the ephemeris
        // points to exceed the image range for interpolation.  For now, attempt a
        // padding of 10 ephemeris points on either side of the image.

        if (isMocNA || isHiRise || isCTX || isLroNACL || isLroNACR || isHRSC)
            // Try increment of every 300 image lines
            dtEphem = 300 * intTime;  // Make this a user definable increment?
        else // Set increment for WA images to one second
            dtEphem = 1.0;

        // Pad by 10 ephem pts on each side of the image
        numEphem = (int)(scanDuration / dtEphem) + 20;

        // if numEphem is even, make it odd so that the number of ephemeris points
        // is equal on either side of T_CENTER
        if ((numEphem % 2) == 0)
            numEphem++;

//TO DO: DELETE THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
        numEphem = numEphem + 2; // Add two for calcuation of velocity vectors...

        // Find the ephemeris time for the first ephemeris point, and from that, get
        // to_ephem needed by SOCET (to_ephem is relative to etCenter)
        double et = etCenter - (((numEphem - 1) / 2) * dtEphem);
        for (int i = 0; i < numEphem; i++) {
            cam->setTime(iTime(et));
            SpiceRotation *bodyRot = cam->bodyRotation();
            vector<double> pos = bodyRot->ReferenceVector(cam->instrumentPosition()->Coordinate());
//TO DO: UNCOMMENT THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //vector<double> vel = bodyRot->ReferenceVector(cam->instrumentPosition()->Velocity());

            //Add the ephemeris position and velocity to their respective lists, in meters and meters/sec
            QList<double> ephemPt;
            QList<double> ephemRate;
            ephemPts.append(ephemPt << pos[0] * 1000 << pos[1] * 1000 << pos[2] * 1000);
//TO DO: UNCOMMENT THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
            //ephemRates.append(ephemRate << vel[0] * 1000 << vel[1] * 1000 << vel[2] * 1000);

            et += dtEphem;
        }
//TO DO: DELETE THE FOLLOWING LINES WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
        // Compute the spacecraft velocity at each ephemeris point
        // (We must do this when blobs are not attached because the Spice Class
        // stores in memory the same data that would be in a blob...even when reading NAIF kernels)
        double deltaTime = 2.0 * dtEphem;
        numEphem = numEphem - 2; // set numEphem back to the number we need output
        for (int i = 0; i < numEphem; i++) {
            double vec[3] = {0.0, 0.0, 0.0};
            vec[0] = (ephemPts[i+2][0] - ephemPts[i][0]) / deltaTime;
            vec[1] = (ephemPts[i+2][1] - ephemPts[i][1]) / deltaTime;
            vec[2] = (ephemPts[i+2][2] - ephemPts[i][2]) / deltaTime;
            QList<double> ephemRate;
            ephemRates.append(ephemRate << vec[0] << vec[1] << vec[2]);
        }
    }

    //update ephem stats
    double etFirstEphem = etCenter - (((numEphem - 1) / 2) * dtEphem);
    double t0Ephem = etFirstEphem - etCenter;

    // Using the intrumentPointing table as a guide build the quarternions
    // for simplicity sake we'll leave the mountingAngles as identity
    // and store the complete rotation from body fixed to camera in the
    // quarternions

    //set up quaternions number and spacing
    Table tablePointing("InstrumentPointing", cubeHeader->fileName());

    //number of quaternions
    int numQuaternions = tablePointing.Records();

    // increase the number of quaternions nodes by 20%. This is somewhat random but
    // generally intended to compensate for having equally time spaced nodes
    // instead of of the potentially more efficient placement used by spiceinit
    numQuaternions = (int)(numQuaternions * 1.2);

    // if numQuaternions calcutated from SPICE blobs is too sparse for SOCET Set,
    // mulitiply it by a factor of 30
    // (30X was settled upon emperically.  In the future, make this an input parameter)
    if (numQuaternions <= 10) numQuaternions = tablePointing.Records() * 30;

    //make the number of nodes odd
    numQuaternions = (numQuaternions % 2) == 1 ? numQuaternions : numQuaternions + 1;

    // SOCET has a max number of quaternions of 20000, and we're going to add twenty...
    if (numQuaternions > 20000 - 20) numQuaternions = 19179;

    double dtQuat = scanDuration / double(numQuaternions);

    // build the tables of values
    QList< QList<double> > quaternions;
    double et = etCenter - (((numQuaternions - 1) / 2) * dtQuat);

    for (int i = 0; i < numQuaternions; i++) {
        cam->setTime(iTime(et));
        vector<double> j2000ToBodyFixedMatrixVector = cam->bodyRotation()->Matrix();
        vector<double> j2000ToCameraMatrixVector = cam->instrumentRotation()->Matrix();
        double quaternion[4] = {0.0, 0.0, 0.0, 0.0};

        double j2000ToBodyFixedRotationMatrix[3][3], //rotation from J2000 to target (aka body, planet)
               j2000ToCameraRotationMatrix[3][3], //rotation from J2000 to spacecraft
               cameraToBodyFixedRotationMatrix[3][3]; //rotation from camera to target

        // reformat vectors to 3x3 rotation matricies
        for (int j = 0; j < 3; j++) {
            for (int k = 0; k < 3; k++) {
                j2000ToBodyFixedRotationMatrix[j][k] = j2000ToBodyFixedMatrixVector[3 * j + k];
                j2000ToCameraRotationMatrix[j][k] = j2000ToCameraMatrixVector[3 * j + k];
            }
        }

        // get the quaternion
        mxmt_c(j2000ToBodyFixedRotationMatrix, j2000ToCameraRotationMatrix,
               cameraToBodyFixedRotationMatrix);
        m2q_c(cameraToBodyFixedRotationMatrix, quaternion);

        // add the quaternion to the list of quaternions
        QList<double> quat;
        quaternions.append(quat << quaternion[1] << quaternion[2] << quaternion[3] <<
                           quaternion[0]);
        //note also that the order is changed to match socet

        et += dtQuat;
    }

    // linearlly interpolate 10 additional nodes before the first quaternion (SOCET requires this)
    for (int i = 0; i < 10; i++) {
        double vec[4] = {0.0, 0.0, 0.0, 0.0};
        vec[0] = quaternions[0][0] + (quaternions[0][0] - quaternions[1][0]);
        vec[1] = quaternions[0][1] + (quaternions[0][1] - quaternions[1][1]);
        vec[2] = quaternions[0][2] + (quaternions[0][2] - quaternions[1][2]);
        vec[3] = quaternions[0][3] + (quaternions[0][3] - quaternions[1][3]);
        QList<double> quat;
        quaternions.prepend (quat << vec[0] << vec[1] << vec[2] << vec[3]);
    }

    // linearlly interpolate 10 additional nodes after the last quaternion (SOCET requires this)
    for (int i = 0; i < 10; i++) {
        double vec[4] = {0.0, 0.0, 0.0, 0.0};
        int index = quaternions.size() - 1;
        vec[0] = quaternions[index][0] + (quaternions[index][0] - quaternions[index - 1][0]);
        vec[1] = quaternions[index][1] + (quaternions[index][1] - quaternions[index - 1][1]);
        vec[2] = quaternions[index][2] + (quaternions[index][2] - quaternions[index - 1][2]);
        vec[3] = quaternions[index][3] + (quaternions[index][3] - quaternions[index - 1][3]);
        QList<double> quat;
        quaternions.append(quat << vec[0] << vec[1] << vec[2] << vec[3]);
    }

    //update quaternions stats
    numQuaternions += 20;

    //ephemeris time of the first quarternion
    double et0Quat = etCenter - (((numQuaternions - 1) / 2) * dtQuat);

    //quadrtic time of the first quarternion
    double qt0Quat = et0Quat - etCenter;

    //query remaing transformation parameters from Camera Classes
    //transformation to distortionless focal plane
    double zDirection = distortionMap->ZDirection();

    //transformation from DistortionlessFocalPlane to FocalPlane
    vector<double> opticalDistCoefs = distortionMap->OpticalDistortionCoefficients();

    // For instruments with less than 3 distortion coefficients, set the
    // unused ones to 0.0
    opticalDistCoefs.resize(3, 0);

    //transformation from focal plane to detector
    const double *iTransS = focalMap->TransS();
    const double *iTransL = focalMap->TransL();
    double detectorSampleOrigin = focalMap->DetectorSampleOrigin();
    double detectorLineOrigin = focalMap->DetectorLineOrigin();

    //transformation from dectector to cube
    double startingSample = detectorMap->AdjustedStartingSample();
    double startingLine = detectorMap->AdjustedStartingLine();
    double sampleSumming = detectorMap->SampleScaleFactor();
    double etStart = ((LineScanCameraDetectorMap *)detectorMap)->StartTime();
    double lineOffset = focalMap->DetectorLineOffset();

    // We are done with computing keyword values, so output the Line Scanner
    // Keyword file.

    // This is the SOCET SET base sensor class keywords portion of support file:
    toStrm.setf(ios::scientific);
    toStrm << "RECTIFICATION_TERMS" << endl;
    toStrm << "        " << setprecision(14) << rectificationTerms[0] << " " <<
           rectificationTerms[1] << " " << rectificationTerms[2] << endl;
    toStrm << "        " << rectificationTerms[3] << " " << rectificationTerms[4] <<
           " " << rectificationTerms[5] << endl;

    toStrm << "GROUND_ZERO ";
    toStrm << centerGp[0] << " " << centerGp[1] << " " << centerGp[2] << endl;

    toStrm << "LOAD_PT ";
    toStrm << centerGp[0] << " " << centerGp[1] << " " << centerGp[2] << endl;

    toStrm << "COORD_SYSTEM 1" << endl;

    toStrm << "IMAGE_MOTION 0" << endl;

    // This is the line scanner sensor model portion of support file:
    toStrm << "SENSOR_TYPE USGSAstroLineScanner" << endl;
    toStrm << "SENSOR_MODE UNKNOWN" << endl;

    toStrm << "FOCAL " << focal << endl;

    toStrm << "ATMCO";
    for (int i = 0; i < 4; i++) toStrm << " " << atmco[i];
    toStrm << endl;

    toStrm << "IOCOEF_LINE";
    for (int i = 0; i < 10; i++) toStrm << " " << ioCoefLine[i];
    toStrm << endl;

    toStrm << "IOCOEF_SAMPLE";
    for (int i = 0; i < 10; i++) toStrm << " " << ioCoefSample[i];
    toStrm << endl;

    toStrm << "ABERR    0" << endl;
    toStrm << "ATMREF   0" << endl;
    toStrm << "PLATFORM   1" << endl;
    toStrm << "SOURCE_FLAG  1" << endl;
    toStrm << "SINGLE_EPHEMERIDE  0" << endl;

    //Note, for TRI_PARAMETERS, we print the first element separate from the rest so that the array
    //starts in the first column.  Otherwise, SOCET Set will treat the array as a comment
    toStrm << "TRI_PARAMETERS" << endl;
    toStrm << triParams[0];
    for (int i = 1; i < 18; i++) toStrm << " " << triParams[i];
    toStrm << endl;

    toStrm << setprecision(25) << "T_CENTER  ";
    double tCenter = 0.0;
//TO DO: UNCOMMENT THESE LINES ONCE HRSC IS WORKING IN SS
//  if (isHRSC) {
//    tCenter = etCenter - HRSCNadirCenterTime;
//    toStrm << tCenter << endl;
//  }
//  else
    toStrm << tCenter << endl;

    toStrm << "DT_EPHEM  " << dtEphem << endl;

    toStrm << "T0_EPHEM  ";
//TO DO: UNCOMMENT THESE LINES ONCE HRSC IS WORKING IN SS
//  if (isHRSC) {
//    double t = tCenter + t0Ephem;
//    toStrm << t << endl;
//  }
//  else
    toStrm << t0Ephem << endl;

    toStrm << "NUMBER_OF_EPHEM   " << numEphem << endl;

    toStrm << "EPHEM_PTS" << endl;
//TO DO: DELETE THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
    for (int i = 1; i <= numEphem; i++) {
//TO DO: UNCOMMENT THE FOLLOWING LINE WHEN VELOCITY BLOBS ARE CORRECT IN ISIS
        //for (int i = 0; i < numEphem; i++) {
        toStrm << " " << ephemPts[i][0];
        toStrm << " " << ephemPts[i][1];
        toStrm << " " << ephemPts[i][2] << endl;
    }

    toStrm  << "\n\nEPHEM_RATES" << endl;
    for (int i = 0; i < numEphem; i++) {
        toStrm << " " << ephemRates[i][0];
        toStrm << " " << ephemRates[i][1];
        toStrm << " " << ephemRates[i][2] << endl;
    }

    toStrm << "\n\nDT_QUAT " << dtQuat << endl;
    toStrm << "T0_QUAT " << qt0Quat << endl;
    toStrm << "NUMBER_OF_QUATERNIONS  " << numQuaternions << endl;
    toStrm << "QUATERNIONS" << endl;
    for (int i = 0; i < numQuaternions; i++) {
        toStrm << " " << quaternions[i][0];
        toStrm << " " << quaternions[i][1];
        toStrm << " " << quaternions[i][2];
        toStrm << " " << quaternions[i][3] << endl;
    }

    toStrm << "\n\nSCAN_DURATION " << scanDuration << endl;

    //  UNCOMMENT toStrm << "\nNUMBER_OF_INT_TIMES " << numIntTimes << endl;
    //
    //  if (isHRSC) {
    //    toStrm  << "INT_TIMES" << endl;
    //    for (int i = 0; i < numIntTimes; i++) {
    //      LineRateChange lr = lineRates.at(i);
    //      toStrm << " " << lr.GetStartEt();
    //      toStrm << " " << lr.GetLineScanRate();
    //      toStrm << " " << lr.GetStartLine() << endl;
    //    }
    //  }
    //  else
    toStrm << "INT_TIME " << intTime << endl;

    toStrm << "\nALONG_SCAN_PIXEL_SIZE  " << alongScanPxSize << endl;
    toStrm << "CROSS_SCAN_PIXEL_SIZE  " << crossScanPxSize << endl;

    toStrm << "\nCENTER_GP";
    for (int i = 0; i < 3; i++) toStrm << " " << centerGp[i];
    toStrm << endl;

    toStrm << "SENSOR_POSITION";
    for (int i = 0; i < 3; i++) toStrm << " " << sensorPosition[i];
    toStrm << endl;

    toStrm << "MOUNTING_ANGLES";
    double mountingAngles[3] = {0.0, 0.0, 0.0};
    for (int i = 0; i < 3; i++) toStrm << " " << mountingAngles[i];
    toStrm << endl;

    toStrm << "\nTOTAL_LINES " << totalLines << endl;
    toStrm << "TOTAL_SAMPLES " << totalSamples << endl;
    toStrm << "\n\n\n" << endl;

    toStrm << "IKCODE  " << ikCode << endl;
    toStrm << "ISIS_Z_DIRECTION  " << zDirection << endl;

    toStrm << "OPTICAL_DIST_COEF";
    for (int i = 0; i < 3; i++) toStrm << " " << opticalDistCoefs[i];
    toStrm << endl;

    toStrm << "ITRANSS";
    for (int i = 0; i < 3; i++) toStrm << " " << iTransS[i];
    toStrm << endl;

    toStrm << "ITRANSL";
    for (int i = 0; i < 3; i++) toStrm << " " << iTransL[i];
    toStrm << endl;

    toStrm << "DETECTOR_SAMPLE_ORIGIN " << detectorSampleOrigin << endl;
    toStrm << "DETECTOR_LINE_ORIGIN " << detectorLineOrigin << endl;
    toStrm << "DETECTOR_LINE_OFFSET  " << lineOffset << endl;
    toStrm << "DETECTOR_SAMPLE_SUMMING  " << sampleSumming << endl;

    toStrm << "STARTING_SAMPLE " << startingSample << endl;
    toStrm << "STARTING_LINE " << startingLine << endl;
    toStrm << "STARTING_EPHEMERIS_TIME " << setprecision(25) << etStart << endl;
    toStrm << "CENTER_EPHEMERIS_TIME " << etCenter << endl;

} // end main
Example #8
0
/** 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();
}
Example #9
0
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;
}
Example #10
0
void IsisMain(){

  Process p;

  // Reset all the stats objects because they are global
  latStat.Reset();
  lonStat.Reset();
  resStat.Reset();
  sampleResStat.Reset();
  lineResStat.Reset();
  aspectRatioStat.Reset();
  phaseStat.Reset();
  emissionStat.Reset();
  incidenceStat.Reset();
  localSolarTimeStat.Reset();
  localRaduisStat.Reset();
  northAzimuthStat.Reset();

  UserInterface &ui = Application::GetUserInterface();

  Cube *icube = p.SetInputCube("FROM");
  Camera *cam = icube->Camera();

//  Cube cube;
//  cube.Open(ui.GetFilename("FROM"));
//  Camera *cam = cube.Camera();

  int eband = cam->Bands();
  // if the camera is band independent that only run one band
  if (cam->IsBandIndependent()) eband = 1;
  int linc = ui.GetInteger("LINC");
  int sinc = ui.GetInteger("SINC");

  int pTotal = eband * ((cam->Lines()-2) / linc + 2) ;
  Progress progress;
  progress.SetMaximumSteps(pTotal);
  progress.CheckStatus();

  for (int band=1; band<=eband; band++) {
    cam->SetBand(band);
    for (int line=1; line<(int)cam->Lines(); line=line+linc) {
      for (int sample=1; sample< cam->Samples(); sample=sample+sinc) {
        buildStats(cam, sample, line);
      }
      //set the sample value to the last sample and run buildstats
      int sample = cam->Samples();
      buildStats(cam, sample, line);
      progress.CheckStatus();
    }
    //set the line value to the last line and run on all samples(sample + sinc)
    int line = cam->Lines();
    for (int sample=1; sample< cam->Samples(); sample=sample+sinc) {
      buildStats(cam, sample, line);
    }
    //set last sample and run with last line
    int sample = cam->Samples();
    buildStats(cam, sample, line);
    progress.CheckStatus();
  }

  //Set up the Pvl groups and get min, max, avg, and sd for each statstics object  
  PvlGroup pUser("User Parameters");
  pUser += PvlKeyword("Filename",ui.GetFilename("FROM"));
  pUser += PvlKeyword("Linc",ui.GetInteger("LINC"));
  pUser += PvlKeyword("Sinc",ui.GetInteger("SINC"));

  PvlGroup pLat("Latitude");
  pLat += ValidateKey("LatitudeMinimum",latStat.Minimum());
  pLat += ValidateKey("LatitudeMaximum",latStat.Maximum());
  pLat += ValidateKey("LatitudeAverage",latStat.Average());
  pLat += ValidateKey("LatitudeStandardDeviation",latStat.StandardDeviation());

  PvlGroup pLon("Longitude");
  pLon += ValidateKey("LongitudeMinimum",lonStat.Minimum());
  pLon += ValidateKey("LongitudeMaximum",lonStat.Maximum());
  pLon += ValidateKey("LongitudeAverage",lonStat.Average());
  pLon += ValidateKey("LongitudeStandardDeviation",lonStat.StandardDeviation());

  PvlGroup pSampleRes("SampleResolution");
  pSampleRes += ValidateKey("SampleResolutionMinimum",sampleResStat.Minimum(),
                           "meters/pixel");
  pSampleRes += ValidateKey("SampleResolutionMaximum",sampleResStat.Maximum(),
                           "meters/pixel");
  pSampleRes += ValidateKey("SampleResolutionAverage",sampleResStat.Average(),
                           "meters/pixel");
  pSampleRes += ValidateKey("SampleResolutionStandardDeviation",
                           sampleResStat.StandardDeviation(),"meters/pixel");

  PvlGroup pLineRes("LineResolution");
  pLineRes += ValidateKey("LineResolutionMinimum",lineResStat.Minimum(),
                         "meters/pixel");
  pLineRes += ValidateKey("LineResolutionMaximum",lineResStat.Maximum(),
                         "meters/pixel");
  pLineRes += ValidateKey("LineResolutionAverage",lineResStat.Average(),
                         "meters/pixel");
  pLineRes += ValidateKey("LineResolutionStandardDeviation",
                         lineResStat.StandardDeviation(),"meters/pixel");

  PvlGroup pResolution("Resolution");
  pResolution += ValidateKey("ResolutionMinimum",resStat.Minimum(),
                            "meters/pixel");
  pResolution += ValidateKey("ResolutionMaximum",resStat.Maximum(),
                            "meters/pixel");
  pResolution += ValidateKey("ResolutionAverage",resStat.Average(),
                            "meters/pixel");
  pResolution += ValidateKey("ResolutionStandardDeviation",
                            resStat.StandardDeviation(),"meters/pixel");

  PvlGroup pAspectRatio("AspectRatio");
  pAspectRatio += ValidateKey("AspectRatioMinimum",aspectRatioStat.Minimum());
  pAspectRatio += ValidateKey("AspectRatioMaximun",aspectRatioStat.Maximum());
  pAspectRatio += ValidateKey("AspectRatioAverage",aspectRatioStat.Average());
  pAspectRatio += ValidateKey("AspectRatioStandardDeviation",
                             aspectRatioStat.StandardDeviation());

  PvlGroup pPhase("PhaseAngle");
  pPhase += ValidateKey("PhaseMinimum",phaseStat.Minimum());
  pPhase += ValidateKey("PhaseMaximum",phaseStat.Maximum());
  pPhase += ValidateKey("PhaseAverage",phaseStat.Average());
  pPhase += ValidateKey("PhaseStandardDeviation",phaseStat.StandardDeviation());

  PvlGroup pEmission("EmissionAngle");
  pEmission += ValidateKey("EmissionMinimum",emissionStat.Minimum());
  pEmission += ValidateKey("EmissionMaximum",emissionStat.Maximum());
  pEmission += ValidateKey("EmissionAverage",emissionStat.Average());
  pEmission += ValidateKey("EmissionStandardDeviation",
                          emissionStat.StandardDeviation());

  PvlGroup pIncidence("IncidenceAngle");
  pIncidence += ValidateKey("IncidenceMinimum",incidenceStat.Minimum());
  pIncidence += ValidateKey("IncidenceMaximum",incidenceStat.Maximum());
  pIncidence += ValidateKey("IncidenceAverage",incidenceStat.Average());
  pIncidence += ValidateKey("IncidenceStandardDeviation",
                           incidenceStat.StandardDeviation());

  PvlGroup pTime("LocalSolarTime");
  pTime += ValidateKey("LocalSolarTimeMinimum",localSolarTimeStat.Minimum(),
                      "hours");
  pTime += ValidateKey("LocalSolarTimeMaximum",localSolarTimeStat.Maximum(),
                      "hours");
  pTime += ValidateKey("LocalSolarTimeAverage",localSolarTimeStat.Average(),
                      "hours");
  pTime += ValidateKey("LocalSolarTimeStandardDeviation",
                      localSolarTimeStat.StandardDeviation(),"hours");

  PvlGroup pLocalRadius("LocalRadius");
  pLocalRadius += ValidateKey("LocalRadiusMinimum",localRaduisStat.Minimum());
  pLocalRadius += ValidateKey("LocalRadiusMaximum",localRaduisStat.Maximum());
  pLocalRadius += ValidateKey("LocalRadiusAverage",localRaduisStat.Average());
  pLocalRadius += ValidateKey("LocalRadiusStandardDeviation",
                             localRaduisStat.StandardDeviation());

  PvlGroup pNorthAzimuth("NorthAzimuth");
  pNorthAzimuth += ValidateKey("NorthAzimuthMinimum",northAzimuthStat.Minimum());
  pNorthAzimuth += ValidateKey("NorthAzimuthMaximum",northAzimuthStat.Maximum());
  pNorthAzimuth += ValidateKey("NorthAzimuthAverage",northAzimuthStat.Average());
  pNorthAzimuth += ValidateKey("NorthAzimuthStandardDeviation",
                              northAzimuthStat.StandardDeviation());

  // Send the Output to the log area
  Application::Log(pUser);
  Application::Log(pLat);
  Application::Log(pLon);
  Application::Log(pSampleRes);
  Application::Log(pLineRes);
  Application::Log(pResolution);
  Application::Log(pAspectRatio);
  Application::Log(pPhase);
  Application::Log(pEmission);
  Application::Log(pIncidence);
  Application::Log(pTime);
  Application::Log(pLocalRadius);
  Application::Log(pNorthAzimuth);

  if (ui.WasEntered("TO")) {
    string from = ui.GetFilename("FROM");
    string outfile = Filename(ui.GetFilename("TO")).Expanded();
    bool exists = Filename(outfile).Exists();
    bool append = ui.GetBoolean("APPEND");

    //If the user chooses a fromat of PVL then write to the output file ("TO")
    if (ui.GetString("FORMAT") == "PVL") {
      Pvl temp;
      temp.SetTerminator("");
      temp.AddGroup(pUser);
      temp.AddGroup(pLat);
      temp.AddGroup(pLon);
      temp.AddGroup(pSampleRes);
      temp.AddGroup(pLineRes);
      temp.AddGroup(pResolution);
      temp.AddGroup(pAspectRatio);
      temp.AddGroup(pPhase);
      temp.AddGroup(pEmission);
      temp.AddGroup(pIncidence);
      temp.AddGroup(pTime);
      temp.AddGroup(pLocalRadius);
      temp.AddGroup(pNorthAzimuth);

      if (append) {
        temp.Append(outfile);
      }
      else {
        temp.Write(outfile);
      }
    }

    //Create a flatfile of the data with columhn headings 
    // the flatfile is comma delimited and can be imported in to spreadsheets
    else {
      ofstream os;
      bool writeHeader = true;
      if (append) {
        os.open(outfile.c_str(),ios::app);
        if (exists) {
          writeHeader = false;
        }
      }
      else {
        os.open(outfile.c_str(),ios::out);
      }

      // if new file or append and no file exists then write header
      if(writeHeader){
      os << "Filename,"<<
        "LatitudeMinimum,"<<
        "LatitudeMaximum,"<<
        "LatitudeAverage,"<<
        "LatitudeStandardDeviation,"<<
        "LongitudeMinimum,"<<
        "LongitudeMaximum,"<<
        "LongitudeAverage,"<<
        "LongitudeStandardDeviation,"<<
        "SampleResolutionMinimum,"<<
        "SampleResolutionMaximum,"<<
        "SampleResolutionAverage,"<<
        "SampleResolutionStandardDeviation,"<<
        "LineResolutionMinimum,"<<
        "LineResolutionMaximum,"<<
        "LineResolutionAverage,"<<
        "LineResolutionStandardDeviation,"<<
        "ResolutionMinimum,"<<
        "ResolutionMaximum,"<<
        "ResolutionAverage,"<<
        "ResolutionStandardDeviation,"<<
        "AspectRatioMinimum,"<<
        "AspectRatioMaximum,"<<
        "AspectRatioAverage,"<<
        "AspectRatioStandardDeviation,"<<
        "PhaseMinimum,"<<
        "PhaseMaximum,"<<
        "PhaseAverage,"<<
        "PhaseStandardDeviation,"<<
        "EmissionMinimum,"<<
        "EmissionMaximum,"<<
        "EmissionAverage,"<<
        "EmissionStandardDeviation,"<<
        "IncidenceMinimum,"<<
        "IncidenceMaximum,"<<
        "IncidenceAverage,"<<
        "IncidenceStandardDeviation,"<<
        "LocalSolarTimeMinimum,"<<
        "LocalSolarTimeMaximum,"<<
        "LocalSolarTimeAverage,"<<
        "LocalSolarTimeStandardDeviation,"<<
        "LocalRadiusMaximum,"<<
        "LocalRadiusMaximum,"<<
        "LocalRadiusAverage,"<<
        "LocalRadiusStandardDeviation,"<<
        "NorthAzimuthMinimum,"<<
        "NorthAzimuthMaximum,"<<
        "NorthAzimuthAverage,"<<
        "NorthAzimuthStandardDeviation,"<<endl;
      }
      os << Filename(from).Expanded() <<",";
        //call the function to write out the values for each group
        writeFlat(os, latStat);
        writeFlat(os, lonStat);
        writeFlat(os, sampleResStat);
        writeFlat(os, lineResStat);
        writeFlat(os, resStat);
        writeFlat(os, aspectRatioStat);
        writeFlat(os, phaseStat);
        writeFlat(os, emissionStat);
        writeFlat(os, incidenceStat);
        writeFlat(os, localSolarTimeStat);
        writeFlat(os, localRaduisStat);
        writeFlat(os, northAzimuthStat);
        os << endl;
    }
  }

  if( ui.GetBoolean("ATTACH") ) {

    string cam_name = "CameraStatistics";

    //Creates new CameraStatistics Table
    TableField fname( "Name", Isis::TableField::Text, 20 );
    TableField fmin( "Minimum", Isis::TableField::Double );
    TableField fmax( "Maximum", Isis::TableField::Double );
    TableField favg( "Average", Isis::TableField::Double );
    TableField fstd( "StandardDeviation", Isis::TableField::Double );

    TableRecord record;
    record += fname;
    record += fmin;
    record += fmax;
    record += favg;
    record += fstd;

    Table table( cam_name, record );

    vector<PvlGroup> grps;
    grps.push_back( pLat );
    grps.push_back( pLon );
    grps.push_back( pSampleRes );
    grps.push_back( pLineRes );
    grps.push_back( pResolution );
    grps.push_back( pAspectRatio );
    grps.push_back( pPhase );
    grps.push_back( pEmission );
    grps.push_back( pIncidence );
    grps.push_back( pTime );
    grps.push_back( pLocalRadius );
    grps.push_back( pNorthAzimuth );

    for( vector<PvlGroup>::iterator g = grps.begin(); g != grps.end(); g++ ) {
      int i = 0;
      record[i++] = g->Name();
      record[i++] = (double) (*g)[0][0];
      record[i++] = (double) (*g)[1][0];
      record[i++] = (double) (*g)[2][0];
      record[i++] = (double) (*g)[3][0];
      table += record;
    }

    icube->ReOpen( "rw" );
    icube->Write( table );
    p.WriteHistory(*icube);
    icube->Close();

  }

}
Example #11
0
//Helper function to compute input range.
void ComputeInputRange () {
  Process p;
  Cube *latCub = p.SetInputCube("LATCUB");
  Cube *lonCub = p.SetInputCube("LONCUB");

  UserInterface &ui = Application::GetUserInterface();
  Pvl userMap;
  userMap.Read(ui.GetFilename("MAP"));
  PvlGroup &userGrp = userMap.FindGroup("Mapping",Pvl::Traverse);

  Statistics *latStats = latCub->Statistics();
  Statistics *lonStats = lonCub->Statistics();

  double minLat = latStats->Minimum();
  double maxLat = latStats->Maximum();

  int lonDomain = userGrp.HasKeyword("LongitudeDomain") ? (int)userGrp.FindKeyword("LongitudeDomain") : 360;
  double minLon = lonDomain == 360 ? Projection::To360Domain(lonStats->Minimum()) : Projection::To180Domain(lonStats->Minimum());
  double maxLon = lonDomain == 360 ? Projection::To360Domain(lonStats->Maximum()) : Projection::To180Domain(lonStats->Maximum());

  if(userGrp.HasKeyword("LatitudeType")) {
    bool isOcentric = ((std::string)userGrp.FindKeyword("LatitudeType")) == "Planetocentric";

    double equRadius;
    double polRadius;

    //If the user entered the equatorial and polar radii
    if(ui.WasEntered("EQURADIUS") && ui.WasEntered("POLRADIUS")) {
      equRadius = ui.GetDouble("EQURADIUS");
      polRadius = ui.GetDouble("POLRADIUS");
    }
    //Else read them from the pck
    else {
      Filename pckFile("$base/kernels/pck/pck?????.tpc");
      pckFile.HighestVersion();

      string pckFilename = pckFile.Expanded();

      furnsh_c(pckFilename.c_str());

      string target;

      //If user entered target 
      if(ui.WasEntered("TARGET")) {
        target = ui.GetString("TARGET");
      }
      //Else read the target name from the input cube
      else {
        Pvl fromFile;
        fromFile.Read(ui.GetFilename("FROM"));
        target = (string)fromFile.FindKeyword("TargetName", Pvl::Traverse);
      }

      SpiceInt code;
      SpiceBoolean found;

      bodn2c_c (target.c_str(), &code, &found);

      if (!found) {
        string msg = "Could not convert Target [" + target +
                     "] to NAIF code";
        throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
      }

      SpiceInt n;
      SpiceDouble radii[3];

      bodvar_c(code,"RADII",&n,radii);

      equRadius = radii[0] * 1000;
      polRadius = radii[2] * 1000;
    }

    if(isOcentric) {
      if(ui.GetString("LATTYPE") != "PLANETOCENTRIC") {
        minLat = Projection::ToPlanetocentric(minLat, (double)equRadius, (double)polRadius);
        maxLat = Projection::ToPlanetocentric(maxLat, (double)equRadius, (double)polRadius);
      }
    }
    else {
      if(ui.GetString("LATTYPE") == "PLANETOCENTRIC") {
        minLat = Projection::ToPlanetographic(minLat, (double)equRadius, (double)polRadius);
        maxLat = Projection::ToPlanetographic(maxLat, (double)equRadius, (double)polRadius);
      }
    }
  }

  if(userGrp.HasKeyword("LongitudeDirection")) {
    bool isPosEast = ((std::string)userGrp.FindKeyword("LongitudeDirection")) == "PositiveEast";

    if(isPosEast) {
      if(ui.GetString("LONDIR") != "POSITIVEEAST") {
        minLon = Projection::ToPositiveEast(minLon, lonDomain);
        maxLon = Projection::ToPositiveEast(maxLon, lonDomain);

        if(minLon > maxLon) {
          double temp = minLon;
          minLon = maxLon;
          maxLon = temp;
        }
      }
    }
    else {
      if(ui.GetString("LONDIR") == "POSITIVEEAST") {
        minLon = Projection::ToPositiveWest(minLon, lonDomain);
        maxLon = Projection::ToPositiveWest(maxLon, lonDomain);

        if(minLon > maxLon) {
          double temp = minLon;
          minLon = maxLon;
          maxLon = temp;
        }
      }
    }
  }

  // Set ground range parameters in UI
  ui.Clear("MINLAT");
  ui.PutDouble("MINLAT", minLat);
  ui.Clear("MAXLAT");
  ui.PutDouble("MAXLAT", maxLat);
  ui.Clear("MINLON");
  ui.PutDouble("MINLON", minLon);
  ui.Clear("MAXLON");
  ui.PutDouble("MAXLON", maxLon);

  p.EndProcess();

  // Set default ground range param to camera
  ui.Clear("DEFAULTRANGE");
  ui.PutAsString("DEFAULTRANGE","COMPUTE");
}
Example #12
0
void IsisMain() {
  //Create a process to create the input cubes
  Process p;
  //Create the input cubes, matching sample/lines
  Cube *inCube = p.SetInputCube ("FROM");
  Cube *latCube = p.SetInputCube("LATCUB", SpatialMatch);
  Cube *lonCube = p.SetInputCube("LONCUB", SpatialMatch);

  //A 1x1 brick to read in the latitude and longitude DN values from
  //the specified cubes
  Brick latBrick(1,1,1, latCube->PixelType());
  Brick lonBrick(1,1,1, lonCube->PixelType());

  UserInterface &ui = Application::GetUserInterface();

  //Set the sample and line increments
  int sinc = (int)(inCube->Samples() * 0.10);
  if(ui.WasEntered("SINC")) {
    sinc = ui.GetInteger("SINC");
  }

  int linc = (int)(inCube->Lines() * 0.10);
  if(ui.WasEntered("LINC")) {
    linc = ui.GetInteger("LINC");
  }

  //Set the degree of the polynomial to use in our functions
  int degree = ui.GetInteger("DEGREE");

  //We are using a polynomial with two variables
  PolynomialBivariate sampFunct(degree); 
  PolynomialBivariate lineFunct(degree);

  //We will be solving the function using the least squares method
  LeastSquares sampSol(sampFunct);
  LeastSquares lineSol(lineFunct);

  //Setup the variables for solving the stereographic projection
  //x = cos(latitude) * sin(longitude - lon_center)
  //y = cos(lat_center) * sin(latitude) - sin(lat_center) * cos(latitude) * cos(longitude - lon_center)

  //Get the center lat and long from the input cubes
  double lat_center = latCube->Statistics()->Average() * PI/180.0;
  double lon_center = lonCube->Statistics()->Average() * PI/180.0;


  /**
   * Loop through lines and samples projecting the latitude and longitude at those
   * points to stereographic x and y and adding these points to the LeastSquares 
   * matrix. 
   */
  for(int i = 1; i <= inCube->Lines(); i+= linc) {
    for(int j = 1; j <= inCube->Samples(); j+= sinc) {
      latBrick.SetBasePosition(j, i, 1);
      latCube->Read(latBrick);
      if(IsSpecial(latBrick.at(0))) continue;
      double lat = latBrick.at(0) * PI/180.0;
      lonBrick.SetBasePosition(j, i, 1);
      lonCube->Read(lonBrick);
      if(IsSpecial(lonBrick.at(0))) continue;
      double lon = lonBrick.at(0) * PI/180.0;

      //Project lat and lon to x and y using a stereographic projection
      double k = 2/(1 + sin(lat_center) * sin(lat) + cos(lat_center)*cos(lat)*cos(lon - lon_center));
      double x = k * cos(lat) * sin(lon - lon_center);
      double y = k * (cos(lat_center) * sin(lat)) - (sin(lat_center) * cos(lat) * cos(lon - lon_center));

      //Add x and y to the least squares matrix
      vector<double> data;
      data.push_back(x);
      data.push_back(y);
      sampSol.AddKnown(data, j);
      lineSol.AddKnown(data, i);

      //If the sample increment goes past the last sample in the line, we want to
      //always read the last sample..
      if(j != inCube->Samples() && j + sinc > inCube->Samples()) {
        j = inCube->Samples() - sinc;
      }
    }
    //If the line increment goes past the last line in the cube, we want to
    //always read the last line..
    if(i != inCube->Lines() && i + linc > inCube->Lines()) {    
      i = inCube->Lines() - linc;
    }
  }

  //Solve the least squares functions using QR Decomposition
  sampSol.Solve(LeastSquares::QRD);
  lineSol.Solve(LeastSquares::QRD);

  //If the user wants to save the residuals to a file, create a file and write
  //the column titles to it.
  TextFile oFile;
  if(ui.WasEntered("RESIDUALS")) {
    oFile.Open(ui.GetFilename("RESIDUALS"), "overwrite");
    oFile.PutLine("Sample,\tLine,\tX,\tY,\tSample Error,\tLine Error\n");
  }

  //Gather the statistics for the residuals from the least squares solutions
  Statistics sampErr;
  Statistics lineErr;
  vector<double> sampResiduals = sampSol.Residuals();
  vector<double> lineResiduals = lineSol.Residuals();
  for(int i = 0; i < (int)sampResiduals.size(); i++) {
    sampErr.AddData(sampResiduals[i]);
    lineErr.AddData(lineResiduals[i]);
  }

  //If a residuals file was specified, write the previous data, and the errors to the file.
  if(ui.WasEntered("RESIDUALS")) {
    for(int i = 0; i < sampSol.Rows(); i++) {
      vector<double> data = sampSol.GetInput(i);
      iString tmp = "";
      tmp += iString(sampSol.GetExpected(i));
      tmp += ",\t";
      tmp += iString(lineSol.GetExpected(i));
      tmp += ",\t";
      tmp += iString(data[0]);
      tmp += ",\t";
      tmp += iString(data[1]);
      tmp += ",\t";
      tmp += iString(sampResiduals[i]);
      tmp += ",\t";
      tmp += iString(lineResiduals[i]);
      oFile.PutLine(tmp + "\n");
    }
  }
  oFile.Close();

  //Records the error to the log
  PvlGroup error( "Error" );
  error += PvlKeyword( "Degree", degree );
  error += PvlKeyword( "NumberOfPoints", (int)sampResiduals.size() );
  error += PvlKeyword( "SampleMinimumError", sampErr.Minimum() );
  error += PvlKeyword( "SampleAverageError", sampErr.Average() );
  error += PvlKeyword( "SampleMaximumError", sampErr.Maximum() );
  error += PvlKeyword( "SampleStdDeviationError", sampErr.StandardDeviation() );
  error += PvlKeyword( "LineMinimumError", lineErr.Minimum() );
  error += PvlKeyword( "LineAverageError", lineErr.Average() );
  error += PvlKeyword( "LineMaximumError", lineErr.Maximum() );
  error += PvlKeyword( "LineStdDeviationError", lineErr.StandardDeviation() );
  Application::Log( error );

  //Close the input cubes for cleanup
  p.EndProcess();

  //If we want to warp the image, then continue, otherwise return
  if(!ui.GetBoolean("NOWARP")) {
    //Creates the mapping group
    Pvl mapFile;
    mapFile.Read(ui.GetFilename("MAP"));
    PvlGroup &mapGrp = mapFile.FindGroup("Mapping",Pvl::Traverse);

    //Reopen the lat and long cubes
    latCube = new Cube();
    latCube->SetVirtualBands(ui.GetInputAttribute("LATCUB").Bands());
    latCube->Open(ui.GetFilename("LATCUB"));

    lonCube = new Cube();
    lonCube->SetVirtualBands(ui.GetInputAttribute("LONCUB").Bands());
    lonCube->Open(ui.GetFilename("LONCUB"));

    PvlKeyword targetName;

    //If the user entered the target name
    if(ui.WasEntered("TARGET")) {
      targetName = PvlKeyword("TargetName", ui.GetString("TARGET"));
    }
    //Else read the target name from the input cube
    else {
      Pvl fromFile;
      fromFile.Read(ui.GetFilename("FROM"));
      targetName = fromFile.FindKeyword("TargetName", Pvl::Traverse);
    }

    mapGrp.AddKeyword(targetName, Pvl::Replace);

    PvlKeyword equRadius;
    PvlKeyword polRadius;


    //If the user entered the equatorial and polar radii
    if(ui.WasEntered("EQURADIUS") && ui.WasEntered("POLRADIUS")) {
      equRadius = PvlKeyword("EquatorialRadius", ui.GetDouble("EQURADIUS"));
      polRadius = PvlKeyword("PolarRadius", ui.GetDouble("POLRADIUS"));
    }
    //Else read them from the pck
    else {
      Filename pckFile("$base/kernels/pck/pck?????.tpc");
      pckFile.HighestVersion();

      string pckFilename = pckFile.Expanded();

      furnsh_c(pckFilename.c_str());

      string target = targetName[0];
      SpiceInt code;
      SpiceBoolean found;

      bodn2c_c (target.c_str(), &code, &found);

      if (!found) {
        string msg = "Could not convert Target [" + target +
                     "] to NAIF code";
        throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
      }

      SpiceInt n;
      SpiceDouble radii[3];

      bodvar_c(code,"RADII",&n,radii);

      equRadius = PvlKeyword("EquatorialRadius", radii[0] * 1000);
      polRadius = PvlKeyword("PolarRadius", radii[2] * 1000);
    }

    mapGrp.AddKeyword(equRadius, Pvl::Replace);
    mapGrp.AddKeyword(polRadius, Pvl::Replace);


    //If the latitude type is not in the mapping group, copy it from the input
    if(!mapGrp.HasKeyword("LatitudeType")) {
      if(ui.GetString("LATTYPE") == "PLANETOCENTRIC") {
        mapGrp.AddKeyword(PvlKeyword("LatitudeType","Planetocentric"), Pvl::Replace);
      }
      else {
        mapGrp.AddKeyword(PvlKeyword("LatitudeType","Planetographic"), Pvl::Replace);
      }
    }

    //If the longitude direction is not in the mapping group, copy it from the input
    if(!mapGrp.HasKeyword("LongitudeDirection")) {
      if(ui.GetString("LONDIR") == "POSITIVEEAST") {
        mapGrp.AddKeyword(PvlKeyword("LongitudeDirection","PositiveEast"), Pvl::Replace);
      }
      else {
        mapGrp.AddKeyword(PvlKeyword("LongitudeDirection","PositiveWest"), Pvl::Replace);
      }
    }

    //If the longitude domain is not in the mapping group, assume it is 360
    if(!mapGrp.HasKeyword("LongitudeDomain")) {
      mapGrp.AddKeyword(PvlKeyword("LongitudeDomain","360"), Pvl::Replace);
    }

    //If the default range is to be computed, use the input lat/long cubes to determine the range
    if(ui.GetString("DEFAULTRANGE") == "COMPUTE") {
      //NOTE - When computing the min/max longitude this application does not account for the 
      //longitude seam if it exists. Since the min/max are calculated from the statistics of
      //the input longitude cube and then converted to the mapping group's domain they may be
      //invalid for cubes containing the longitude seam. 
    
      Statistics *latStats = latCube->Statistics();
      Statistics *lonStats = lonCube->Statistics();

      double minLat = latStats->Minimum();
      double maxLat = latStats->Maximum();

      bool isOcentric = ((std::string)mapGrp.FindKeyword("LatitudeType")) == "Planetocentric";
 
      if(isOcentric) {
        if(ui.GetString("LATTYPE") != "PLANETOCENTRIC") {
          minLat = Projection::ToPlanetocentric(minLat, (double)equRadius, (double)polRadius);
          maxLat = Projection::ToPlanetocentric(maxLat, (double)equRadius, (double)polRadius);
        }
      }
      else {
        if(ui.GetString("LATTYPE") == "PLANETOCENTRIC") {
          minLat = Projection::ToPlanetographic(minLat, (double)equRadius, (double)polRadius);
          maxLat = Projection::ToPlanetographic(maxLat, (double)equRadius, (double)polRadius);
        }
      }

      int lonDomain = (int)mapGrp.FindKeyword("LongitudeDomain");
      double minLon = lonDomain == 360 ? Projection::To360Domain(lonStats->Minimum()) : Projection::To180Domain(lonStats->Minimum());
      double maxLon = lonDomain == 360 ? Projection::To360Domain(lonStats->Maximum()) : Projection::To180Domain(lonStats->Maximum());

      bool isPosEast = ((std::string)mapGrp.FindKeyword("LongitudeDirection")) == "PositiveEast";
      
      if(isPosEast) {
        if(ui.GetString("LONDIR") != "POSITIVEEAST") {
          minLon = Projection::ToPositiveEast(minLon, lonDomain);
          maxLon = Projection::ToPositiveEast(maxLon, lonDomain);
        }
      }
      else {
        if(ui.GetString("LONDIR") == "POSITIVEEAST") {
          minLon = Projection::ToPositiveWest(minLon, lonDomain);
          maxLon = Projection::ToPositiveWest(maxLon, lonDomain);
        }
      }

      if(minLon > maxLon) {
        double temp = minLon;
        minLon = maxLon;
        maxLon = temp;
      }

      mapGrp.AddKeyword(PvlKeyword("MinimumLatitude", minLat),Pvl::Replace);
      mapGrp.AddKeyword(PvlKeyword("MaximumLatitude", maxLat),Pvl::Replace);
      mapGrp.AddKeyword(PvlKeyword("MinimumLongitude", minLon),Pvl::Replace);
      mapGrp.AddKeyword(PvlKeyword("MaximumLongitude", maxLon),Pvl::Replace);
    }

    //If the user decided to enter a ground range then override
    if (ui.WasEntered("MINLAT")) {
      mapGrp.AddKeyword(PvlKeyword("MinimumLatitude",
                                        ui.GetDouble("MINLAT")),Pvl::Replace);
    }
  
    if (ui.WasEntered("MAXLAT")) {
      mapGrp.AddKeyword(PvlKeyword("MaximumLatitude",
                                        ui.GetDouble("MAXLAT")),Pvl::Replace);
    }

    if (ui.WasEntered("MINLON")) {
      mapGrp.AddKeyword(PvlKeyword("MinimumLongitude",
                                        ui.GetDouble("MINLON")),Pvl::Replace);
    }
  
    if (ui.WasEntered("MAXLON")) {
      mapGrp.AddKeyword(PvlKeyword("MaximumLongitude",
                                        ui.GetDouble("MAXLON")),Pvl::Replace);
    }
  
    //If the pixel resolution is to be computed, compute the pixels/degree from the input
    if (ui.GetString("PIXRES") == "COMPUTE") {
      latBrick.SetBasePosition(1,1,1);
      latCube->Read(latBrick);

      lonBrick.SetBasePosition(1,1,1);
      lonCube->Read(lonBrick);

      //Read the lat and long at the upper left corner
      double a = latBrick.at(0) * PI/180.0;
      double c = lonBrick.at(0) * PI/180.0;
  
      latBrick.SetBasePosition(latCube->Samples(),latCube->Lines(),1);
      latCube->Read(latBrick);

      lonBrick.SetBasePosition(lonCube->Samples(),lonCube->Lines(),1);     
      lonCube->Read(lonBrick);

      //Read the lat and long at the lower right corner
      double b = latBrick.at(0) * PI/180.0;
      double d = lonBrick.at(0) * PI/180.0;

      //Determine the angle between the two points
      double angle = acos(cos(a) * cos(b) * cos(c - d) + sin(a) * sin(b));
      //double angle = acos((cos(a1) * cos(b1) * cos(b2)) + (cos(a1) * sin(b1) * cos(a2) * sin(b2)) + (sin(a1) * sin(a2)));
      angle *= 180/PI;

      //Determine the number of pixels between the two points
      double pixels = sqrt(pow(latCube->Samples() -1.0, 2.0) + pow(latCube->Lines() -1.0, 2.0));

      //Add the scale in pixels/degree to the mapping group
      mapGrp.AddKeyword(PvlKeyword("Scale",
                                        pixels/angle, "pixels/degree"),
                                        Pvl::Replace);
      if (mapGrp.HasKeyword("PixelResolution")) {
        mapGrp.DeleteKeyword("PixelResolution");
      }
    }


    // If the user decided to enter a resolution then override
    if (ui.GetString("PIXRES") == "MPP") {
      mapGrp.AddKeyword(PvlKeyword("PixelResolution",
                                        ui.GetDouble("RESOLUTION"), "meters/pixel"),
                                        Pvl::Replace);
      if (mapGrp.HasKeyword("Scale")) {
        mapGrp.DeleteKeyword("Scale");
      }
    }
    else if (ui.GetString("PIXRES") == "PPD") {
      mapGrp.AddKeyword(PvlKeyword("Scale",
                                        ui.GetDouble("RESOLUTION"), "pixels/degree"),
                                        Pvl::Replace);
      if (mapGrp.HasKeyword("PixelResolution")) {
        mapGrp.DeleteKeyword("PixelResolution");
      }
    }

    //Create a projection using the map file we created
    int samples,lines;
    Projection *outmap = ProjectionFactory::CreateForCube(mapFile,samples,lines,false);

    //Write the map file to the log
    Application::GuiLog(mapGrp);

    //Create a process rubber sheet
    ProcessRubberSheet r;

    //Set the input cube
    inCube = r.SetInputCube("FROM");

    double tolerance = ui.GetDouble("TOLERANCE") * outmap->Resolution();

    //Create a new transform object
    Transform *transform = new nocam2map (sampSol, lineSol, outmap,
                                          latCube, lonCube,
                                          ui.GetString("LATTYPE") == "PLANETOCENTRIC",
                                          ui.GetString("LONDIR") == "POSITIVEEAST",
                                          tolerance, ui.GetInteger("ITERATIONS"),
                                          inCube->Samples(), inCube->Lines(),
                                          samples, lines);
  
    //Allocate the output cube and add the mapping labels
    Cube *oCube = r.SetOutputCube ("TO", transform->OutputSamples(),
                                              transform->OutputLines(),
                                              inCube->Bands());
    oCube->PutGroup(mapGrp);

    //Determine which interpolation to use
    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);
    }
  
    //Warp the cube
    r.StartProcess(*transform, *interp);
    r.EndProcess();

    // add mapping to print.prt
    PvlGroup mapping = outmap->Mapping(); 
    Application::Log(mapping); 

    //Clean up
    delete latCube;
    delete lonCube;

    delete outmap;
    delete transform;
    delete interp;
  }
}
Example #13
0
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;
  }

}
Example #14
0
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;
      }
    }
  }
}
Example #15
0
void IsisMain() {

    // Use a regular Process
    Process p;

    UserInterface &ui = Application::GetUserInterface();
    QString from = ui.GetFileName("FROM");
    QString to = FileName(ui.GetFileName("TO")).expanded();
    QString socetProject = ui.GetString("SS_PROJECT");
    QString socetImageLocation = ui.GetString("SS_IMG_LOC");
    QString socetInputDataPath = ui.GetString("SS_INPUT_PATH");
    QString socetCameraCalibrationPath = ui.GetString("SS_CAM_CALIB_PATH");

    // Open input cube and make sure this is a lev1 image (ie, not map projected)
    Cube cube;
    cube.open(from);

    if (cube.isProjected()) {
        QString msg = QString("You can only create a SOCET Set Framing Camera or FrameOffAxis settings "
                              "file for level 1 images. The input image [%1] is a map projected, level "
                              "2, cube.").arg(from);
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // Initialize the camera
    Cube *input = p.SetInputCube("FROM");
    Camera *cam = input->camera();
    CameraDetectorMap *detectorMap = cam->DetectorMap();
    CameraFocalPlaneMap *focalMap = cam->FocalPlaneMap();

    // Make sure the image contains the SPICE blobs/tables
    PvlGroup test = cube.label()->findGroup("Kernels", Pvl::Traverse);
    QString instrumentPointing = (QString) test["InstrumentPointing"];
    if (instrumentPointing != "Table") {
        QString msg = QString("Input image [%1] does not contain needed SPICE blobs.  Please run "
                              "spiceinit on the image with attach=yes.").arg(from);
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // Set the image at the boresight pixel to get the ephemeris time and SPICE data at that image
    // location
    double detectorSampleOrigin = focalMap->DetectorSampleOrigin();
    double detectorLineOrigin = focalMap->DetectorSampleOrigin();
    cam->SetImage(detectorSampleOrigin, detectorLineOrigin);
    double et = cam->time().Et();

    Spice spice(*input);
    spice.setTime(et);

    // Get required keywords from instrument and band groups
    PvlGroup inst = cube.label()->findGroup("Instrument", Pvl::Traverse);
    QString instrumentId = (QString) inst["InstrumentId"];
    QString spacecraftName = (QString) inst["SpacecraftName"];

    // Compensate for noproj altering cube labels
    if (instrumentId == "IdealCamera") {
        PvlGroup orig = cube.label()->findGroup("OriginalInstrument", Pvl::Traverse);
        instrumentId = (QString) orig["InstrumentId"];
        spacecraftName = (QString) orig["SpacecraftName"];
    }

    // Get sensor position and orientation (opk) angles
    double ographicCamPos[3] = {0.0, 0.0, 0.0};
    double omegaPhiKappa[3] = {0.0, 0.0, 0.0};
    double isisFocalPlane2SocetPlateTranspose[3][3] =
    {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
    getCamPosOPK(spice, spacecraftName, et, cam, ographicCamPos,
                 omegaPhiKappa,isisFocalPlane2SocetPlateTranspose);

    // Determine the SOCET Set camera calibration file
    QString socetCamFile = socetCameraCalibrationPath;

    if (spacecraftName == "VIKING_ORBITER_1") {
        if (instrumentId == "VISUAL_IMAGING_SUBSYSTEM_CAMERA_A") {
            socetCamFile += "VIK1A.cam";
        }
        else {
            socetCamFile += "VIK1B.cam";
        }
    }
    else if (spacecraftName == "VIKING_ORBITER_2") {
        if (instrumentId == "VISUAL_IMAGING_SUBSYSTEM_CAMERA_A") {
            socetCamFile += "VIK2A.cam";
        }
        else {
            socetCamFile += "VIK2B.cam";
        }
    }

    //----------------------------------------.-------------
    //TO DO: Uncomment these lines when MEX SRC is supported
    //----------------------------------------.-------------
    //  // Mars Express
    //  else if (spacecraftName == "MARS_EXPRESS") {
    //    socetCamFile += "SRC.cam";
    //  }
    //-----------------------------------------------------
    //TO DO: Uncomment these lines when Themis is supported
    //-----------------------------------------------------
    //  // THEMIS VIS images (MARS Odyssey)
    //  else if (spacecraftName == "MARS_ODYSSEY") {
    //    socetCamFile += "THEMIS_VIS_F3.cam";
    //  }
    //-----------------------------------------------------
    //TO DO: Uncomment these lines when Apollo is supported
    //-----------------------------------------------------
    //  else if (spacecraftName == "APOLLO 15") {
    //    socetCamFile += "Apollo15_M_ASU.cam";
    //  }
    //  else if (spacecraftName == "APOLLO 16") {
    //    socetCamFile += "Apollo16_M_ASU.cam";
    //  }
    //  else if (spacecraftName == "APOLLO 17") {
    //    socetCamFile += "Apollo17_M_ASU.cam";
    //  }
    else if (spacecraftName == "Galileo Orbiter") {
        //Check if this image was aquired with the cover on or off
        iTime removeCoverDate("1994/04/01 00:00:00");
        iTime imageDate((QString) inst["StartTime"]);

        if (imageDate < removeCoverDate) {
            socetCamFile += "Galileo_SSI_Cover.cam";
        }
        else {
            socetCamFile += "Galileo_SSI.cam";
        }
    }
    else if (spacecraftName == "Cassini-Huygens") {
        // Get the image filter and replace "/" with "_"
        PvlGroup bandBin = cube.label()->findGroup("BandBin", Pvl::Traverse);
        QString filter = (QString) bandBin["FilterName"];
        filter.replace("/", "_");

        socetCamFile += "Cassini_ISSNA_";
        socetCamFile += filter;
        socetCamFile += ".cam";
    }
    else if (spacecraftName == "Messenger") {
        if (instrumentId == "MDIS-NAC") {
            socetCamFile += "MDIS_NAC.cam";
        }
        else {
            socetCamFile += "MDIS_WAC.cam";
        }
    }
    else if (spacecraftName == "CLEMENTINE 1") {
        if (instrumentId == "UVVIS") {
            socetCamFile += "ClemUVVIS.cam";
        }
    }

    // Throw exception for unsupported camera
    else {
        QString msg = QString("The ISIS to SOCET Set translation of input image [%1] is currently "
                              "not supported for instrument [%2].").arg(from).arg(instrumentId);
        throw IException(IException::User, msg, _FILEINFO_);
    }

    // For THEMIS VIS, Galileo SSI, Cassini ISS get the image summation mode
    int summation = 1;
    //-----------------------------------------------------
    //TO DO: Uncomment these lines when Themis is supported
    //-----------------------------------------------------
    //  if (spacecraftName == "MARS_ODYSSEY") {
    //    try {
    //      summation = (int) detectorMap->SampleScaleFactor();
    //    }
    //    catch (IException &e) {
    //      QString msg = "Error reading SpatialSumming from Instrument label";
    //      throw IException(IException::User, msg, _FILEINFO_);
    //    }
    //  }

    if (spacecraftName == "Galileo Orbiter") {
        try {
            summation = (int) detectorMap->SampleScaleFactor();
        }
        catch (IException &e) {
            QString msg = "Error reading Summing from Instrument label";
            throw IException(IException::User, msg, _FILEINFO_);
        }
    }

    if (spacecraftName == "Cassini-Huygens") {
        try {
            summation = (int) detectorMap->SampleScaleFactor();
        }
        catch (IException &e) {
            QString msg = "Error reading Summing from Instrument label";
            throw IException(IException::User, msg, _FILEINFO_);
        }
    }

    // Get NL/NS of image and calculate the size in x/y dimensions, in mm
    // Note: for THEMIS VIS, Galileo SSI and Cassini ISS summed images, calculate the size of the full
    // resolution image because our "isis2socet" scripts will enlarge the summed image for import into
    // Socet Set
    double pixelSize = 1.0 / cam->PixelPitch();
    int numLines = cube.lineCount();
    int numSamples = cube.sampleCount();
    if (summation > 1) {
        // For Themis VIS, Galileo SSI, Cassini ISS:
        numLines *= summation;
        numSamples *= summation;
    }
    double sizeX = numSamples / pixelSize;
    double sizeY = numLines / pixelSize;

    // Make sure the Socet Set project name has the .prj extension
    if (socetProject.endsWith(".prj", Qt::CaseInsensitive) == FALSE)  socetProject += ".prj";

    // Find cube base name w/o extensions & establish the Socet Set support file name
    // Note: I'm using the QFileInfo class because the baseName method in the ISIS
    // FileName class only strips the last extension, and we need the core name
    // of the file without any extensions, or path
    QString baseName = QFileInfo(from).baseName();
    QString socetSupFile = baseName + ".sup";

    //  Open and write to the SOCET Set Framing Camera settings file keywords and values
    //  If this is a Messenger image, add the temperature-dependent focal length so as to overrride
    //  the nominal focal lenghth stored in the SOCET Set camera calibration files
    ofstream toStrm;

    toStrm.open (to.toAscii().data(), ios::trunc);
    if (toStrm.bad()) {
        QString msg = "Unable to open output settings file";
        throw IException(IException::User, msg, _FILEINFO_);
    }

    toStrm << "setting_file                        1.1\n";
    toStrm << "multi_frame.project                 " << socetProject << endl;
    toStrm << "multi_frame.cam_calib_filename      " << socetCamFile << endl;
    toStrm << "multi_frame.create_files            IMAGE_AND_SUPPORT\n";
    toStrm << "multi_frame.atmos_ref               0\n";
    toStrm << "multi_frame.auto_min                YES\n";
    toStrm << "multi_frame.digital_cam             NO\n";
    toStrm << "multi_frame.input_image_filename    " << socetInputDataPath + baseName +
           ".raw" << endl;
    toStrm << "multi_frame.output_format           img_type_vitec\n";
    toStrm << "multi_frame.output_name             " << socetSupFile << endl;
    toStrm << "multi_frame.output_location         " << socetImageLocation << endl;
    toStrm << "multi_frame.cam_loc_ang_sys         OPK\n";
    toStrm << "multi_frame.cam_loc_ang_units       UNIT_DEGREES\n";
    toStrm << "multi_frame.cam_loc_xy_units        UNIT_DEGREES\n";

    if (spacecraftName == "Messenger") {
        // Overide the nominal focal length in the SOCET SET camera calibration file with the
        // Temperature Dependent Focal Length used in ISIS
        double focalLength = cam->FocalLength();
        toStrm << "multi_frame.cam_loc_focal           " << setprecision(17) << focalLength
               << endl;
    }
    toStrm << "multi_frame.cam_loc_y_or_lat        " << setprecision(17) <<
           ographicCamPos[0] << endl;
    toStrm << "multi_frame.cam_loc_x_or_lon        " << ographicCamPos[1] << endl;
    toStrm << "multi_frame.cam_loc_elev            " << ographicCamPos[2] << endl;
    toStrm << "multi_frame.cam_loc_omega           " << omegaPhiKappa[0] << endl;
    toStrm << "multi_frame.cam_loc_phi             " << omegaPhiKappa[1] << endl;
    toStrm << "multi_frame.cam_loc_kappa           " << omegaPhiKappa[2] << endl;
    toStrm << "multi_frame.img_size_lines          " << numLines << endl;
    toStrm << "multi_frame.img_size_samps          " << numSamples << endl;
    toStrm << "multi_frame.sizex                   " << setprecision(6) << sizeX << endl;
    toStrm << "multi_frame.sizey                   " << sizeY << endl;
    toStrm << "multi_frame.orientation             1\n";

    // Furthermore, if this is a Messenger image, get the needed keywords values needed for the
    // USGSAstro FrameOffAxis *support* file, and add them to the output settings file.
    // During frame import in SOCET Set, these values will be ignored, but then later accessed by
    // the USGSAstro import_frame SOCET Set program.
    //
    // Note: Summed Messenger images are handled in the FrameOffAxis sensor model, so no need to
    // account for enlarging Messenger images in the "socet2isis" scripts

    if (spacecraftName == "Messenger") {
        double originalHalfLines = numLines / 2.0;
        double originalHalfSamples = numSamples / 2.0;

        // Set the lens distortion coefficients
        // Note: These values were calculated for SOCET Set by Orrin Thomas in an MSExcel spreadsheet,
        // and are hardcoded here
        QString lenscoX;
        QString lenscoY;
        if (instrumentId == "MDIS-WAC") {
            lenscoX = QString("1.0913499678359500E-06 1.0000181809155400E+00 5.2705094712778700E-06 "
                              "7.3086112844249500E-05 -2.1503011755973800E-06 -3.5311655893430800E-08 "
                              "-5.3312743384716000E-06 -1.4642661005550900E-07 -5.4770856997706100E-06 "
                              "-1.2364567692453900E-07 0.0000000000000000E+00 0.0000000000000000E+00 "
                              "0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00");

            lenscoY = QString("-4.8524316760252900E-08 -5.2704844291112000E-06 1.0000181808487100E+00 "
                              "2.4702140905559800E-09 7.3084305868732200E-05 -2.1478354889239300E-06 "
                              "1.2364567791040000E-07 -5.4663905009059100E-06 1.4516772126792600E-07 "
                              "-5.3419626374895400E-06 0.0000000000000000E+00 0.0000000000000000E+00 "
                              "0.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00");
        }
        else {
            //MDIS-NAC lens distortion coefficients:
            lenscoX = QString("-0.000000000000005 0.997948053760188 0.000000000000000 0.000000000000000 "
                              "0.000542184519158 0.000000000000000 -0.000007008182254 0.000000000000000 "
                              "-0.000006526474815 0.000000000000000 0.000000000000000 0.000000000000000 "
                              "0.000000000000000 0.000000000000000 0.000000000000000");

            lenscoY = QString("-0.000003746900328 0.000000000000000 0.999999575428613 -0.000880501428960 "
                              "0.000000000000000 -0.000332760373453 0.000000000000000 -0.000008067196812 "
                              "0.000000000000000 -0.000007553955548  0.000000000000000  0.000000000000000 "
                              "0.000000000000000  0.000000000000000  0.000000000000000");
        }

        // Get the image summation
        double sampleSumming = (int) detectorMap->SampleScaleFactor();
        double lineSumming = (int) detectorMap->LineScaleFactor();

        // Get the Starting Detector Line/Sample
        double startingSample = detectorMap->AdjustedStartingSample();
        double startingLine = detectorMap->AdjustedStartingLine();

        // Get the image plane corrdinates to pixel coordinates transformation matrices
        const double *iTransS = focalMap->TransS();
        const double *iTransL = focalMap->TransL();

        // Because of the options for applying light-time correction, capture the pertinent
        // ISIS keywords as a record to be stored in the settingsfile
        // Note: these values will not go into the Socet Set support file)
        QString ikCode;
        QString swapObserverTarget;
        QString lightTimeCorrection;
        QString ltSurfaceCorrect;
        PvlObject naifKeywordsObject = cube.label()->findObject("NaifKeywords");
        if (instrumentId == "MDIS-NAC") {
            ikCode = "236820";
            swapObserverTarget = (QString) naifKeywordsObject["INS-236820_SWAP_OBSERVER_TARGET"];
            lightTimeCorrection = (QString) naifKeywordsObject["INS-236820_LIGHTTIME_CORRECTION"];
            ltSurfaceCorrect = (QString) naifKeywordsObject["INS-236820_LT_SURFACE_CORRECT"];
        }
        else {
            ikCode = "236800";
            swapObserverTarget = (QString) naifKeywordsObject["INS-236800_SWAP_OBSERVER_TARGET"];
            lightTimeCorrection = (QString) naifKeywordsObject["INS-236800_LIGHTTIME_CORRECTION"];
            ltSurfaceCorrect = (QString) naifKeywordsObject["INS-236800_LT_SURFACE_CORRECT"];
        }

        toStrm << "\nSENSOR_TYPE FrameOffAxis" << endl;
        toStrm << "USE_LENS_DISTORTION 1" << endl;
        toStrm << "ORIGINAL_HALF_LINES " <<  originalHalfLines << endl;
        toStrm << "ORIGINAL_HALF_SAMPLES " << originalHalfSamples << endl;
        toStrm << "LENSCOX " << lenscoX << endl;
        toStrm << "LENSCOY " << lenscoY << endl;
        toStrm << "SAMPLE_SUMMING  " << sampleSumming << endl;
        toStrm << "LINE_SUMMING  " << lineSumming << endl;
        toStrm << "STARTING_DETECTOR_SAMPLE " << setprecision(17) << startingSample << endl;
        toStrm << "STARTING_DETECTOR_LINE " << startingLine << endl;
        toStrm << "SAMPLE_BORESIGHT " << detectorSampleOrigin << endl;
        toStrm << "LINE_BORESIGHT " << detectorLineOrigin << endl;
        toStrm << "INS_ITRANSS";
        for (int i = 0; i < 3; i++)
            toStrm << " " << setprecision(14) << iTransS[i];
        toStrm << endl;
        toStrm << "INS_ITRANSL";
        for (int i = 0; i < 3; i++)
            toStrm << " " << iTransL[i];
        toStrm << endl;
        toStrm << "M_SOCET2ISIS_FOCALPLANE " << setprecision(2) <<
               isisFocalPlane2SocetPlateTranspose[0][0] << " " <<
               isisFocalPlane2SocetPlateTranspose[0][1] << " " <<
               isisFocalPlane2SocetPlateTranspose[0][2] << endl;
        toStrm << "                         " <<
               isisFocalPlane2SocetPlateTranspose[1][0] << " " <<
               isisFocalPlane2SocetPlateTranspose[1][1] << " " <<
               isisFocalPlane2SocetPlateTranspose[1][2] << endl;
        toStrm << "                         " <<
               isisFocalPlane2SocetPlateTranspose[2][0] << " " <<
               isisFocalPlane2SocetPlateTranspose[2][1] << " " <<
               isisFocalPlane2SocetPlateTranspose[2][2] << endl;
        toStrm << "INS-" << ikCode << "_SWAP_OBSERVER_TARGET = '" << swapObserverTarget << "'\n";
        toStrm << "INS-" << ikCode << "_LIGHTTIME_CORRECTION = '" << lightTimeCorrection << "'\n";
        toStrm << "INS-" << ikCode << "_LT_SURFACE_CORRECT = '" << ltSurfaceCorrect <<"'\n";
    }

} //End IsisMain
Example #16
0
void IsisMain() {
  // Get the list of cubes to mosaic
  FileList imageList;
  UserInterface &ui = Application::GetUserInterface();
  imageList.Read(ui.GetFilename("FROMLIST"));
  if (imageList.size() < 1) {
    std::string msg = "The list file [" + ui.GetFilename("FROMLIST") +
                 "] does not contain any data";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  // Make sure the user enters a "OUTSTATS" file if the CALCULATE option 
  // is selected
  std::string processOpt = ui.GetString("PROCESS");
  if (processOpt == "CALCULATE") {
    if (!ui.WasEntered("OUTSTATS")) {
      std::string msg = "If the CALCULATE option is selected, you must enter";
      msg += " an OUTSTATS file";
      throw iException::Message(iException::User,msg,_FILEINFO_);
    }
  }

  // Make sure number of bands and projection parameters match for all cubes
  for (unsigned int i=0; i<imageList.size(); i++) {
    Cube cube1;
    cube1.Open(imageList[i]);
    g_maxBand = cube1.Bands();

    for (unsigned int j=(i+1); j<imageList.size(); j++) {
      Cube cube2;
      cube2.Open(imageList[j]);

      // Make sure number of bands match
      if (g_maxBand != cube2.Bands()) {
        string msg = "Number of bands do not match between cubes [" +
                     imageList[i] + "] and [" + imageList[j] + "]";
        throw iException::Message(iException::User,msg,_FILEINFO_);
      }

      //Create projection from each cube
      Projection *proj1 = cube1.Projection();
      Projection *proj2 = cube2.Projection();

      // Test to make sure projection parameters match
      if (*proj1 != *proj2) {
        string msg = "Mapping groups do not match between cubes [" +
                     imageList[i] + "] and [" + imageList[j] + "]";
        throw iException::Message(iException::User,msg,_FILEINFO_);
      }
    }
  }

  // Read hold list if one was entered
  std::vector<int> hold;
  if (ui.WasEntered("HOLD")) {
    FileList holdList;
    holdList.Read(ui.GetFilename("HOLD"));

    // Make sure each file in the holdlist matches a file in the fromlist
    for (int i=0; i<(int)holdList.size(); i++) {
      bool matched = false;
      for (int j=0; j<(int)imageList.size(); j++) {
        if (holdList[i] == imageList[j]) {
          matched = true;
          hold.push_back(j);
          break;
        }
      }
      if (!matched) {
        std::string msg = "The hold list file [" + holdList[i] +
                     "] does not match a file in the from list";
        throw iException::Message(iException::User,msg,_FILEINFO_);
      }
    }
  }

  // Read to list if one was entered
  FileList outList;
  if (ui.WasEntered("TOLIST")) {
    outList.Read(ui.GetFilename("TOLIST"));

    // Make sure each file in the tolist matches a file in the fromlist
    if (outList.size() != imageList.size()) {
      std::string msg = "Each input file in the FROM LIST must have a ";
      msg += "corresponding output file in the TO LIST.";
      throw iException::Message(iException::User,msg,_FILEINFO_);
    }

    // Make sure that all output files do not have the same names as their
    // corresponding input files
    for (unsigned i = 0; i < outList.size(); i++) {
      if (outList[i].compare(imageList[i]) == 0) {
        std::string msg = "The to list file [" + outList[i] +
                     "] has the same name as its corresponding from list file.";
        throw iException::Message(iException::User,msg,_FILEINFO_);
      }
    }
  }
  
  // Test to ensure sampling percent in bound
  double sampPercent = ui.GetDouble("PERCENT"); 
  if (sampPercent <= 0.0 || sampPercent > 100.0) {
    string msg = "The sampling percent must be a decimal (0.0, 100.0]";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  int mincnt = ui.GetInteger("MINCOUNT");
  bool wtopt = ui.GetBoolean("WEIGHT");
  if (processOpt != "APPLY") {
    // Loop through all the input cubes, calculating statistics for each cube to use later   
    iString maxCubeStr ((int)imageList.size());
    for (int band=1; band<=g_maxBand; band++) {
      std::vector<Statistics> statsList;
      for (int img=0; img<(int)imageList.size(); img++) {
	Process p;
	const CubeAttributeInput att;
	const std::string inp = imageList[img];
	Cube *icube = p.SetInputCube(inp, att);
	
	// Add a Statistics object to the list for every band of every input cube
	g_imageIndex = img;
	Statistics stats = GatherStatistics(*icube, band, sampPercent, maxCubeStr);
	statsList.push_back(stats);
	p.EndProcess();
      }
  
      // Create a separate OverlapNormalization object for every band
      OverlapNormalization *oNorm = new OverlapNormalization (statsList);
      for (int h=0; h<(int)hold.size(); h++) oNorm->AddHold(hold[h]);
      g_oNormList.push_back(oNorm);
    }

    // A list for keeping track of which input cubes are known to overlap another
    std::vector<bool> doesOverlapList;
    for (unsigned int i=0; i<imageList.size(); i++) doesOverlapList.push_back(false);

    // Find overlapping areas and add them to the set of known overlaps for each
    // band shared amongst cubes
    for (unsigned int i=0; i<imageList.size(); i++){
      Cube cube1;
      cube1.Open(imageList[i]);
  
      for (unsigned int j=(i+1); j<imageList.size(); j++) {
	Cube cube2;
	cube2.Open(imageList[j]);
	iString cubeStr1 ((int)(i+1));
	iString cubeStr2 ((int)(j+1));
	string statMsg = "Gathering Overlap Statisitcs for Cube " +
	  cubeStr1 + " vs " + cubeStr2 + " of " + maxCubeStr;
  
	// Get overlap statistics for cubes
	OverlapStatistics oStats(cube1, cube2, statMsg, sampPercent);
  
	// Only push the stats onto the oList vector if there is an overlap in at
	// least one of the bands
	if (oStats.HasOverlap()) {        
	  oStats.SetMincount(mincnt);
	  g_overlapList.push_back(oStats);
	  for (int band=1; band<=g_maxBand; band++) {
	    // Fill wt vector with 1's if the overlaps are not to be weighted, or
	    // fill the vector with the number of valid pixels in each overlap          
	    int weight = 1;
	    if (wtopt) weight = oStats.GetMStats(band).ValidPixels();
  
	    // Make sure overlap has at least MINCOUNT pixels and add          
	    if (oStats.GetMStats(band).ValidPixels() >= mincnt) {
	      g_oNormList[band-1]->AddOverlap(oStats.GetMStats(band).X(), i,
			       oStats.GetMStats(band).Y(), j, weight);
	      doesOverlapList[i] = true;
	      doesOverlapList[j] = true;
	    }
	  }
	}
      }
    }
  
    // Print an error if one or more of the images does not overlap another
    {
      std::string badFiles = "";
      for (unsigned int img=0; img<imageList.size(); img++) {
	// Print the name of each input cube without an overlap
	if (!doesOverlapList[img]) {
	   badFiles += "[" + imageList[img] + "] ";
	}
      }
      if (badFiles != "") {
	std::string msg = "File(s) " + badFiles;
	msg += " do(es) not overlap any other input images with enough valid pixels";
	throw iException::Message(iException::User,msg,_FILEINFO_);
      }
    }
  
    // Determine whether to calculate gains or offsets
    std::string adjust = ui.GetString("ADJUST");
    OverlapNormalization::SolutionType sType = OverlapNormalization::Both;  
    if (adjust == "CONTRAST")   sType = OverlapNormalization::Gains;
    if (adjust == "BRIGHTNESS") sType = OverlapNormalization::Offsets;
  
    // Loop through each band making all necessary calculations
    for (int band=0; band<g_maxBand; band++) {
      g_oNormList[band]->Solve(sType);
    }
  }

  // Print gathered statistics to the gui and the print file
  int validCnt = 0;
  int invalidCnt = 0;
  if (processOpt != "APPLY") {
    PvlGroup results("Results");

    // Compute the number valid and invalid overlaps
    for (unsigned int o=0; o<g_overlapList.size(); o++) {
      for (int band=1; band<=g_maxBand; band++) {
	if (g_overlapList[o].IsValid(band)) validCnt++;
	else invalidCnt++;
      }
    }

    results += PvlKeyword("TotalOverlaps", validCnt+invalidCnt);
    results += PvlKeyword("ValidOverlaps", validCnt);
    results += PvlKeyword("InvalidOverlaps", invalidCnt);
    std::string weightStr = "false";
    if (wtopt) weightStr = "true";
    results += PvlKeyword("Weighted", weightStr);
    results += PvlKeyword("MinCount", mincnt);

    // Name and band modifiers for each image
    for (unsigned int img=0; img<imageList.size(); img++) {
      results += PvlKeyword("FileName", imageList[img]);
  
      // Band by band statistics
      for (int band=1; band<=g_maxBand; band++) {
	iString mult (g_oNormList[band-1]->Gain(img));
	iString base (g_oNormList[band-1]->Offset(img));        
	iString avg (g_oNormList[band-1]->Average(img));
	iString bandNum (band);
	std::string bandStr = "Band" + bandNum;
	PvlKeyword bandStats(bandStr);
	bandStats += mult;
	bandStats += base;
	bandStats += avg;
	results += bandStats;
      }
    }

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

  // Setup the output text file if the user requested one
  if (ui.WasEntered("OUTSTATS")) {
    PvlObject equ("EqualizationInformation");
    PvlGroup gen("General");
    gen += PvlKeyword("TotalOverlaps", validCnt+invalidCnt);
    gen += PvlKeyword("ValidOverlaps", validCnt);
    gen += PvlKeyword("InvalidOverlaps", invalidCnt);
    std::string weightStr = "false";
    if (wtopt) weightStr = "true";
    gen += PvlKeyword("Weighted", weightStr);
    gen += PvlKeyword("MinCount", mincnt);
    equ.AddGroup(gen);
    for (unsigned int img=0; img<imageList.size(); img++) {
      // Format and name information
      PvlGroup norm("Normalization");
      norm.AddComment("Formula: newDN = (oldDN - AVERAGE) * GAIN + AVERAGE + OFFSET");
      norm.AddComment("BandN = (GAIN, OFFSET, AVERAGE)");
      norm += PvlKeyword("FileName", imageList[img]);
      
      // Band by band statistics
      for (int band=1; band<=g_maxBand; band++) {
        iString mult (g_oNormList[band-1]->Gain(img));
        iString base (g_oNormList[band-1]->Offset(img));        
        iString avg (g_oNormList[band-1]->Average(img));
        iString bandNum (band);
        std::string bandStr = "Band" + bandNum;
        PvlKeyword bandStats(bandStr);
        bandStats += mult;
        bandStats += base;
        bandStats += avg;
        norm += bandStats;
      }
      equ.AddGroup(norm);
    }

    // Write the equalization and overlap statistics to the file
    std::string out = Filename(ui.GetFilename("OUTSTATS")).Expanded();
    std::ofstream os;
    os.open(out.c_str(),std::ios::app);    
    Pvl p;
    p.SetTerminator("");
    p.AddObject(equ);
    os << p << std::endl;
    for (unsigned int i=0; i<g_overlapList.size(); i++) {
      os << g_overlapList[i];
      if (i != g_overlapList.size()-1) os << std::endl;
    }
    os << "End";
  }

  // Check for errors with the input statistics
  if (processOpt == "APPLY") {
    Pvl inStats (ui.GetFilename("INSTATS"));
    PvlObject &equalInfo = inStats.FindObject("EqualizationInformation");

    // Make sure each file in the instats matches a file in the fromlist
    if (imageList.size() > (unsigned)equalInfo.Groups()-1) {
      std::string msg = "Each input file in the FROM LIST must have a ";
      msg += "corresponding input file in the INPUT STATISTICS.";
      throw iException::Message(iException::User,msg,_FILEINFO_);
    }

    // Check that each file in the FROM LIST is present in the INPUT STATISTICS
    for (unsigned i = 0; i < imageList.size(); i++) {
      std::string fromFile = imageList[i];
      bool foundFile = false;
      for (int j = 1; j < equalInfo.Groups(); j++) {
	PvlGroup &normalization = equalInfo.Group(j);
	std::string normFile  = normalization["Filename"][0];
	if (fromFile == normFile) {

	  // Store the index in INPUT STATISTICS file corresponding to the
	  // current FROM LIST file
	  normIndices.push_back(j);
	  foundFile = true;
	}
      }
      if (!foundFile) {
	std::string msg = "The from list file [" + fromFile +
		 "] does not have any corresponding file in the stats list.";
	throw iException::Message(iException::User,msg,_FILEINFO_);
      }
    }
  }

  // Apply the correction to the images if the user wants this done
  if (processOpt != "CALCULATE") {
    iString maxCubeStr ((int)imageList.size());
    for (int img=0; img<(int)imageList.size(); img++) {
      // Set up for progress bar
      ProcessByLine p;
      iString curCubeStr (img+1);
      p.Progress()->SetText("Equalizing Cube " + curCubeStr + " of " + maxCubeStr);

      // Open input cube
      CubeAttributeInput att;
      const std::string inp = imageList[img];
      Cube *icube = p.SetInputCube(inp, att);

      // Establish the output file depending upon whether or not a to list
      // was entered
      std::string out;
      if (ui.WasEntered("TOLIST")) {
	out = outList[img];
      }
      else {
	Filename file = imageList[img];
	out = file.Path() + "/" + file.Basename() + ".equ." + file.Extension();
      }

      // Allocate output cube
      CubeAttributeOutput outAtt;
      p.SetOutputCube(out,outAtt,icube->Samples(),icube->Lines(),icube->Bands());

      // Apply gain/offset to the image
      g_imageIndex = img;
      if (processOpt == "APPLY") {

	// Apply correction based on pre-determined statistics information
	Pvl inStats (ui.GetFilename("INSTATS"));
	PvlObject &equalInfo = inStats.FindObject("EqualizationInformation");
	PvlGroup &normalization = equalInfo.Group(normIndices[g_imageIndex]);
	gains.clear();
	offsets.clear();
	avgs.clear();

	// Get and store the modifiers for each band
	for (int band = 1; band < normalization.Keywords(); band++) {
	  gains.push_back(normalization[band][0]);
	  offsets.push_back(normalization[band][1]);
	  avgs.push_back(normalization[band][2]);
	}
	p.StartProcess(ApplyViaFile); 
      }
      else {

	// Apply correction based on the statistics gathered in this run
	p.StartProcess(ApplyViaObject);
      }
      p.EndProcess();
    }
  }
  
  // Clean-up for batch list runs
  for (unsigned int o=0; o<g_oNormList.size(); o++) delete g_oNormList[o];
  g_oNormList.clear();
  g_overlapList.clear();
  normIndices.clear();
  gains.clear();
  offsets.clear();
  avgs.clear();
}
Example #17
0
void IsisMain() {
  Process p;
  Cube *icube = p.SetInputCube("FROM");

  // Setup the histogram
  UserInterface &ui = Application::GetUserInterface();
  Histogram hist(*icube,1,p.Progress());
  if (ui.WasEntered("MINIMUM")) {
    hist.SetValidRange(ui.GetDouble("MINIMUM"),ui.GetDouble("MAXIMUM"));
  }
  if (ui.WasEntered("NBINS")) {
    hist.SetBins(ui.GetInteger("NBINS"));
  }

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

  if(!ui.IsInteractive() || ui.WasEntered("TO")) {
    // Write the results

    if (!ui.WasEntered("TO")) {
      string msg = "The [TO] parameter must be entered";
      throw iException::Message(iException::User,msg,_FILEINFO_);
    }
    string outfile = ui.GetFilename("TO");
    ofstream fout;
    fout.open (outfile.c_str());
   
    fout << "Cube:           " << ui.GetFilename("FROM") << endl;
    fout << "Band:           " << icube->Bands() << endl;
    fout << "Average:        " << hist.Average() << endl;
    fout << "Std Deviation:  " << hist.StandardDeviation() << endl;
    fout << "Variance:       " << hist.Variance() << endl;
    fout << "Median:         " << hist.Median() << endl;
    fout << "Mode:           " << hist.Mode() << endl;
    fout << "Skew:           " << hist.Skew() << endl;
    fout << "Minimum:        " << hist.Minimum() << endl;
    fout << "Maximum:        " << hist.Maximum() << endl;
    fout << endl;
    fout << "Total Pixels:    " << hist.TotalPixels() << endl;
    fout << "Valid Pixels:    " << hist.ValidPixels() << endl;
    fout << "Null Pixels:     " << hist.NullPixels() << endl;
    fout << "Lis Pixels:      " << hist.LisPixels() << endl;
    fout << "Lrs Pixels:      " << hist.LrsPixels() << endl;
    fout << "His Pixels:      " << hist.HisPixels() << endl;
    fout << "Hrs Pixels:      " << hist.HrsPixels() << endl;
   
    //  Write histogram in tabular format
    fout << endl;
    fout << endl;
    fout << "DN,Pixels,CumulativePixels,Percent,CumulativePercent" << endl;
   
    Isis::BigInt total = 0;
    double cumpct = 0.0;
   
    for (int i=0; i<hist.Bins(); i++) {
      if (hist.BinCount(i) > 0) {
        total += hist.BinCount(i);
        double pct = (double)hist.BinCount(i) / hist.ValidPixels() * 100.;
        cumpct += pct;
   
        fout << hist.BinMiddle(i) << ",";
        fout << hist.BinCount(i) << ",";
        fout << total << ",";
        fout << pct << ",";
        fout << cumpct << endl;
      }
    }
    fout.close();
  }
  // If we are in gui mode, create a histogram plot
  if (ui.IsInteractive()) {
    // Set the title for the dialog
    string title;
    if (ui.WasEntered("TITLE")) {
      title = ui.GetString("TITLE");
    }
    else {
      title = "Histogram Plot for " + Filename(ui.GetAsString("FROM")).Name();
    }

    // Create the QHistogram, set the title & load the Isis::Histogram into it

    Qisis::HistogramToolWindow *plot = new Qisis::HistogramToolWindow(title.c_str(), ui.TheGui());

    // Set the xaxis title if they entered one
    if (ui.WasEntered("XAXIS")) {
      string xaxis(ui.GetString("XAXIS"));
      plot->setAxisLabel(QwtPlot::xBottom,xaxis.c_str());
    }

    // Set the yLeft axis title if they entered one
    if (ui.WasEntered("Y1AXIS")) {
      string yaxis(ui.GetString("Y1AXIS"));
      plot->setAxisLabel(QwtPlot::yLeft,yaxis.c_str());
    }

    // Set the yRight axis title if they entered one
    if (ui.WasEntered("Y2AXIS")) {
      string y2axis(ui.GetString("Y2AXIS"));
      plot->setAxisLabel(QwtPlot::yRight,y2axis.c_str());
    }

    //Transfer data from histogram to the plotcurve
    std::vector<double> xarray,yarray,y2array;
    double cumpct = 0.0;
    for (int i=0; i<hist.Bins(); i++) {
      if (hist.BinCount(i) > 0) {
        xarray.push_back(hist.BinMiddle(i));
        yarray.push_back(hist.BinCount(i));

        double pct = (double)hist.BinCount(i) / hist.ValidPixels() * 100.;
        cumpct += pct;
        y2array.push_back(cumpct);
      }
    }

    Qisis::HistogramItem *histCurve = new Qisis::HistogramItem();
    histCurve->setColor(Qt::darkCyan);
    histCurve->setTitle("Frequency");

    Qisis::PlotToolCurve *cdfCurve = new Qisis::PlotToolCurve();
    cdfCurve->setStyle(QwtPlotCurve::Lines);
    cdfCurve->setTitle("Percentage");

    QPen *pen = new QPen(Qt::red);
    pen->setWidth(2);
    histCurve->setYAxis(QwtPlot::yLeft);
    cdfCurve->setYAxis(QwtPlot::yRight);
    cdfCurve->setPen(*pen);

    //These are all variables needed in the following for loop.
    //----------------------------------------------
    QwtArray<QwtDoubleInterval> intervals(xarray.size());
    QwtArray<double> values(yarray.size());
    double maxYValue = DBL_MIN;
    double minYValue = DBL_MAX;
    // --------------------------------------------- 

    for(unsigned int y = 0; y < yarray.size(); y++) {

      intervals[y] = QwtDoubleInterval(xarray[y], xarray[y] + hist.BinSize());
  
      values[y] = yarray[y];  
      if(values[y] > maxYValue) maxYValue = values[y]; 
      if(values[y] < minYValue) minYValue = values[y];
    }
    
    histCurve->setData(QwtIntervalData(intervals, values));
    cdfCurve->setData(&xarray[0],&y2array[0],xarray.size());

    plot->add(histCurve);
    plot->add(cdfCurve);
    plot->fillTable();

    plot->setScale(QwtPlot::yLeft,0,maxYValue);
    plot->setScale(QwtPlot::xBottom,hist.Minimum(),hist.Maximum());

    QLabel *label = new QLabel("  Average = " + QString::number(hist.Average()) + '\n' +
    "\n  Minimum = " + QString::number(hist.Minimum()) + '\n' +
    "\n  Maximum = " + QString::number(hist.Maximum()) + '\n' +
    "\n  Stand. Dev.= " + QString::number(hist.StandardDeviation()) + '\n' +
    "\n  Variance = " + QString::number(hist.Variance()) + '\n' +
    "\n  Median = " + QString::number(hist.Median()) + '\n' +
    "\n  Mode = " + QString::number(hist.Mode()) +'\n' +
    "\n  Skew = " + QString::number(hist.Skew()), plot);
    plot->getDockWidget()->setWidget(label);
 
    plot->showWindow();
  }
  p.EndProcess();
}
Example #18
0
void IsisMain() {

  // Create a process so we can output the noproj'd labels without overwriting
  Process p;

  // Open the user interface and get the input file and the ideal specs file
  UserInterface &ui = Application::GetUserInterface();
  Cube *mcube, *icube;

  // If a MATCH cube is entered, make sure to SetInputCube it first to get the SPICE blobs
  // from it propagated to the TO labels

  // Until polygon blobs are detached without "/" don't propagate them
  p.PropagatePolygons(false);

  if((ui.WasEntered("MATCH"))) {
    mcube = p.SetInputCube("MATCH");
    icube = p.SetInputCube("FROM");
  }
  else {
    mcube = icube = p.SetInputCube("FROM");
  }

  Camera *incam = mcube->camera();

  // Extract Instrument groups from input labels for the output match and noproj'd cubes
  PvlGroup inst = mcube->group("Instrument");
  PvlGroup fromInst = icube->group("Instrument");
  QString groupName = (QString) inst["SpacecraftName"] + "/";
  groupName += (QString) inst.findKeyword("InstrumentId");

  // Get Ideal camera specifications
  FileName specs;
  if((ui.WasEntered("SPECS"))) {
    specs = ui.GetFileName("SPECS");
  }
  else {
    specs = "$base/applications/noprojInstruments???.pvl";
    specs = specs.highestVersion();
  }
  Pvl idealSpecs(specs.expanded());
  PvlObject obSpecs = idealSpecs.findObject("IdealInstrumentsSpecifications");

  PvlGroup idealGp = obSpecs.findGroup(groupName);
  double transx, transy, transl, transs;
  transx = transy = transl = transs = 0.;
  if(idealGp.hasKeyword("TransX")) transx = idealGp["TransX"];
  if(idealGp.hasKeyword("TransY")) transy = idealGp["TransY"];
  if(idealGp.hasKeyword("ItransL")) transl = idealGp["ItransL"];
  if(idealGp.hasKeyword("ItransS")) transs = idealGp["ItransS"];
  int detectorSamples = mcube->sampleCount();
  if(idealGp.hasKeyword("DetectorSamples")) detectorSamples = idealGp["DetectorSamples"];
  int numberLines = mcube->lineCount();
  int numberBands = mcube->bandCount();

  if(idealGp.hasKeyword("DetectorLines")) numberLines = idealGp["DetectorLines"];

  int xDepend = incam->FocalPlaneMap()->FocalPlaneXDependency();

  // Get output summing mode
  if(ui.GetString("SOURCE") == "FROMMATCH") {
    LoadMatchSummingMode();
  }
  else if(ui.GetString("SOURCE") == "FROMINPUT") {
    LoadInputSummingMode();
  }

  double pixPitch = incam->PixelPitch() * ui.GetDouble("SUMMINGMODE");
  detectorSamples /= (int)(ui.GetDouble("SUMMINGMODE"));
  // Get the user options
  int sampleExpansion = int((ui.GetDouble("SAMPEXP") / 100.) * detectorSamples + .5);
  int lineExpansion = int((ui.GetDouble("LINEEXP") / 100.) * numberLines + .5);
  QString instType;

  // Adjust translations for summing mode
  transl /= ui.GetDouble("SUMMINGMODE");
  transs /= ui.GetDouble("SUMMINGMODE");

  detectorSamples += sampleExpansion;
  numberLines += lineExpansion;

  // Determine whether this ideal camera is a line scan or framing camera and
  // set the instrument id and exposure
  int detectorLines;
  int expandFlag;

  if(incam->DetectorMap()->LineRate() != 0.0) {
    instType = "LINESCAN";
    // Isis3 line rate is always in seconds so convert to milliseconds for the
    // Ideal instrument
    detectorLines = 1;
    expandFlag = 1;
  }
  else {
    instType = "FRAMING";
    detectorLines = numberLines;
    expandFlag = 0;
    // Framing cameras don't need exposure time
  }

  // Adjust focal plane translations with line expansion for scanners since
  // the CCD is only 1 line
  if(expandFlag) {
    transl += lineExpansion / 2;

    if(xDepend == CameraFocalPlaneMap::Line) {
      transx -= lineExpansion / 2.*pixPitch * expandFlag;
    }
    else {
      transy -= lineExpansion / 2.*pixPitch * expandFlag;
    }
  }

  // Get the start time for parent line 1
  AlphaCube alpha(*icube);
  double sample = alpha.BetaSample(.5);
  double line = alpha.BetaLine(.5);
  incam->SetImage(sample, line);
  double et = incam->time().Et();

  // Get the output file name and set its attributes
  CubeAttributeOutput cao;

  // Can we do a regular label? Didn't work on 12-15-2006
  cao.setLabelAttachment(Isis::DetachedLabel);

  // Determine the output image size from
  //   1) the idealInstrument pvl if there or
  //   2) the input size expanded by user specified percentage
  Cube *ocube = p.SetOutputCube("match.cub", cao, 1, 1, 1);

  // Extract the times and the target from the instrument group
  QString startTime = inst["StartTime"];
  QString stopTime;
  if(inst.hasKeyword("StopTime")) stopTime = (QString) inst["StopTime"];

  QString target = inst["TargetName"];

  // rename the instrument groups
  inst.setName("OriginalInstrument");
  fromInst.setName("OriginalInstrument");

  // add it back to the IsisCube object under a new group name
  ocube->putGroup(inst);

  // and remove the version from the IsisCube Object
  ocube->deleteGroup("Instrument");

  // Now rename the group back to the Instrument group and clear out old keywords
  inst.setName("Instrument");
  inst.clear();

  // Add keywords for the "Ideal" instrument
  Isis::PvlKeyword key("SpacecraftName", "IdealSpacecraft");
  inst.addKeyword(key);

  key.setName("InstrumentId");
  key.setValue("IdealCamera");
  inst.addKeyword(key);

  key.setName("TargetName");
  key.setValue(target);
  inst.addKeyword(key);

  key.setName("SampleDetectors");
  key.setValue(Isis::toString(detectorSamples));
  inst.addKeyword(key);

  key.setName("LineDetectors");
  key.setValue(Isis::toString(detectorLines));
  inst.addKeyword(key);

  key.setName("InstrumentType");
  key.setValue(instType);
  inst.addKeyword(key);

  Pvl &ocubeLabel = *ocube->label();
  PvlObject *naifKeywordsObject = NULL;

  if (ocubeLabel.hasObject("NaifKeywords")) {
    naifKeywordsObject = &ocubeLabel.findObject("NaifKeywords");

    // Clean up the naif keywords object... delete everything that isn't a radii
    for (int keyIndex = naifKeywordsObject->keywords() - 1; keyIndex >= 0; keyIndex--) {
      QString keyName = (*naifKeywordsObject)[keyIndex].name();
      
      if (!keyName.contains("RADII")) {
        naifKeywordsObject->deleteKeyword(keyIndex);
      }
    }

    // Clean up the kernels group... delete everything that isn't internalized or the orig frame
    //   code
    PvlGroup &kernelsGroup = ocube->group("Kernels");
    for (int keyIndex = kernelsGroup.keywords() - 1; keyIndex >= 0; keyIndex--) {
      PvlKeyword &kernelsKeyword = kernelsGroup[keyIndex];

      bool isTable = false;
      bool isFrameCode = kernelsKeyword.isNamed("NaifFrameCode") ||
                         kernelsKeyword.isNamed("NaifIkCode");
      bool isShapeModel = kernelsKeyword.isNamed("ShapeModel");

      for (int keyValueIndex = 0; keyValueIndex < kernelsKeyword.size(); keyValueIndex++) {
        if (kernelsKeyword[keyValueIndex] == "Table") {
          isTable = true;
        }
      }

      if (!isTable && !isFrameCode && !isShapeModel) {
        kernelsGroup.deleteKeyword(keyIndex);
      }
    }
  }

  if (naifKeywordsObject) {
    naifKeywordsObject->addKeyword(PvlKeyword("IDEAL_FOCAL_LENGTH", toString(incam->FocalLength())),
                                   Pvl::Replace);
  }
  else {
    inst.addKeyword(PvlKeyword("FocalLength", toString(incam->FocalLength()), "millimeters"));
  }

  double newPixelPitch = incam->PixelPitch() * ui.GetDouble("SUMMINGMODE");
  if (naifKeywordsObject) {
    naifKeywordsObject->addKeyword(PvlKeyword("IDEAL_PIXEL_PITCH", toString(newPixelPitch)),
                                   Pvl::Replace);
  }
  else {
    inst.addKeyword(PvlKeyword("PixelPitch", toString(newPixelPitch), "millimeters"));
  }

  key.setName("EphemerisTime");
  key.setValue(Isis::toString(et), "seconds");
  inst.addKeyword(key);

  key.setName("StartTime");
  key.setValue(startTime);
  inst.addKeyword(key);

  if(stopTime != "") {
    key.setName("StopTime");
    key.setValue(stopTime);
    inst.addKeyword(key);
  }

  key.setName("FocalPlaneXDependency");
  key.setValue(toString((int)incam->FocalPlaneMap()->FocalPlaneXDependency()));
  inst.addKeyword(key);

  int xDependency = incam->FocalPlaneMap()->FocalPlaneXDependency();

  double newInstrumentTransX = incam->FocalPlaneMap()->SignMostSigX();
  inst.addKeyword(PvlKeyword("TransX", toString(newInstrumentTransX)));

  double newInstrumentTransY = incam->FocalPlaneMap()->SignMostSigY();
  inst.addKeyword(PvlKeyword("TransY", toString(newInstrumentTransY)));

  storeSpice(&inst, naifKeywordsObject, "TransX0", "IDEAL_TRANSX", transx,
             newPixelPitch * newInstrumentTransX, (xDependency == CameraFocalPlaneMap::Sample));

  storeSpice(&inst, naifKeywordsObject, "TransY0", "IDEAL_TRANSY", transy,
             newPixelPitch * newInstrumentTransY, (xDependency == CameraFocalPlaneMap::Line));

  double transSXCoefficient = 1.0 / newPixelPitch * newInstrumentTransX;
  double transLXCoefficient = 1.0 / newPixelPitch * newInstrumentTransY;

  if (xDependency == CameraFocalPlaneMap::Line) {
    swap(transSXCoefficient, transLXCoefficient);
  }

  storeSpice(&inst, naifKeywordsObject, "TransS0", "IDEAL_TRANSS",
             transs, transSXCoefficient, (xDependency == CameraFocalPlaneMap::Sample));
  storeSpice(&inst, naifKeywordsObject, "TransL0", "IDEAL_TRANSL",
             transl, transLXCoefficient, (xDependency == CameraFocalPlaneMap::Line));

  if(instType == "LINESCAN") {
    key.setName("ExposureDuration");
    key.setValue(Isis::toString(incam->DetectorMap()->LineRate() * 1000.), "milliseconds");
    inst.addKeyword(key);
  }

  key.setName("MatchedCube");
  key.setValue(mcube->fileName());
  inst.addKeyword(key);

  ocube->putGroup(inst);

  p.EndProcess();

// Now adjust the label to fake the true size of the image to match without
// taking all the space it would require for the image data
  Pvl label;
  label.read("match.lbl");
  PvlGroup &dims = label.findGroup("Dimensions", Pvl::Traverse);
  dims["Lines"] = toString(numberLines);
  dims["Samples"] = toString(detectorSamples);
  dims["Bands"] = toString(numberBands);
  label.write("match.lbl");

// And run cam2cam to apply the transformation
  QString parameters;
  parameters += " FROM= " + ui.GetFileName("FROM");
  parameters += " MATCH= " + QString("match.cub");
  parameters += " TO= " + ui.GetFileName("TO");
  parameters += " INTERP=" + ui.GetString("INTERP");
  ProgramLauncher::RunIsisProgram("cam2cam", parameters);

//  Cleanup by deleting the match files
  remove("match.History.IsisCube");
  remove("match.lbl");
  remove("match.cub");
  remove("match.OriginalLabel.IsisCube");
  remove("match.Table.BodyRotation");
  remove("match.Table.HiRISE Ancillary");
  remove("match.Table.HiRISE Calibration Ancillary");
  remove("match.Table.HiRISE Calibration Image");
  remove("match.Table.InstrumentPointing");
  remove("match.Table.InstrumentPosition");
  remove("match.Table.SunPosition");

// Finally finish by adding the OriginalInstrument group to the TO cube
  Cube toCube;
  toCube.open(ui.GetFileName("TO"), "rw");
// Extract label and create cube object
  Pvl *toLabel = toCube.label();
  PvlObject &o = toLabel->findObject("IsisCube");
  o.deleteGroup("OriginalInstrument");
  o.addGroup(fromInst);
  toCube.close();
}
Example #19
0
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();
  Isis::FileName fromFile = ui.GetFileName("FROM");

  Isis::Cube inputCube;
  inputCube.open(fromFile.expanded());

  //Check to make sure we got the cube properly
  if(!inputCube.isOpen()) {
    QString msg = "Could not open FROM cube" + fromFile.expanded();
    throw IException(IException::User, msg, _FILEINFO_);
  }
  Process p;
  Cube *icube = p.SetInputCube("FROM");

  int totalSamples = icube->sampleCount();
  int totalLines   = icube->lineCount();

  Isis::LineManager lineManager(inputCube);
  lineManager.begin();

  int leftFringe, rightFringe;
  int binningMode = icube->group("Instrument")["Summing"];

  //determine the edges between which no statistics should be gathered
  leftFringe = 48 / binningMode;
  rightFringe = totalSamples - leftFringe;


  int numSections = ui.GetInteger("SECTIONS");
  if(numSections > 9) {
    QString msg = "You may have no more than 9 sections per side";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  int sectionLength = 0;
  if(!ui.WasEntered("LINESIZE")) { //User didn't enter number of lines
    if(numSections == 0) {
      sectionLength = 0;
    }
    else {
      sectionLength = totalLines / numSections;
    }
  }
  else {
    sectionLength = ui.GetInteger("LINESIZE");
    if((sectionLength * numSections > totalLines) || sectionLength < 1) {
      sectionLength = totalLines / numSections;
    }
  }

  Statistics sections[numSections][2];
  Statistics leftTotal, rightTotal;
  int sectionStarts[numSections];
  sectionStarts[0] = 0;
  for(int i = 1 ; i < numSections - 1 ; i ++) {
    sectionStarts[i] = (totalLines / numSections) * i;
  }
  if(numSections > 0) {
    sectionStarts[numSections -1] = totalLines - sectionLength;
  }

  int currentSection = 0;
  Buffer leftFringeBuf(leftFringe, 1, 1, lineManager.PixelType());
  Buffer rightFringeBuf(leftFringe, 1, 1, lineManager.PixelType());

  //Walk down the cube
  for(int lineCount = 0 ; lineCount < totalLines ; lineCount++) {
    inputCube.read(lineManager);
    //Read the edges into the fringe buffers
    for(int i = 0 ; i < leftFringe ; i++) {
      leftFringeBuf[i] = lineManager[i];
    }
    for(int i = rightFringe ; i < totalSamples ; i++) {
      rightFringeBuf[i - rightFringe] = lineManager[i];
    }

    //No matter what, add the fringe buffers to the totals for that side
    leftTotal.AddData(leftFringeBuf.DoubleBuffer(), leftFringeBuf.size());
    rightTotal.AddData(rightFringeBuf.DoubleBuffer(), rightFringeBuf.size());

    if(numSections == 0) {
      continue;
    }
    //Index is not too large for this fringe section
    if(lineCount < sectionStarts[currentSection] + sectionLength) {
      //Index is not too small for this fringe section
      if(lineCount >= sectionStarts[currentSection]) {
        sections[currentSection][0].AddData(leftFringeBuf.DoubleBuffer(),
                                            leftFringeBuf.size());
        sections[currentSection][1].AddData(rightFringeBuf.DoubleBuffer(),
                                            rightFringeBuf.size());
      }
    }
    else {
      currentSection++;
      //Since sections may butt up against each other, it is possible that
      // we have to add this data to the next section.
      if(lineCount >= sectionStarts[currentSection]) {
        sections[currentSection][0].AddData(leftFringeBuf.DoubleBuffer(),
                                            leftFringeBuf.size());
        sections[currentSection][1].AddData(rightFringeBuf.DoubleBuffer(),
                                            rightFringeBuf.size());
      }
    }
  }

  // Write the results to the output file if the user specified one
  PvlObject leftSide("LeftSide"), rightSide("RightSide");
  for(int i = 0 ; i < numSections ; i++) {
    QString sectionName = "Section" + toString(i + 1);
    pvlOut(sections[i][0], //Stats to add to the left Object
           sections[i][1], //Stats to add to the right Object
           sectionName,    //Name for the new groups
           sectionStarts[i], //start line
           sectionStarts[i] + sectionLength, //end line
           &leftSide,      //Object to add left group to
           &rightSide      //Object to add right group to
          );
  }
  pvlOut(leftTotal,   //Stats to add to the left Object
         rightTotal,  //Stats to add to the right Object
         "Total",     //Name for the new groups
         0,           //start line
         totalLines,  //end line
         &leftSide,   //Object to add left group to
         &rightSide   //Object to add right group to
        );
  Pvl outputPvl;
  PvlGroup sourceInfo("SourceInfo");

  sourceInfo += PvlKeyword("From", fromFile.expanded());
  sourceInfo += icube->group("Archive")["ProductId"];
  outputPvl.addGroup(sourceInfo);
  if(numSections > 0) {
    outputPvl.addObject(leftSide);
    outputPvl.addObject(rightSide);
  }
  else {
    PvlGroup leftGroup = leftSide.findGroup("Total");
    PvlGroup rightGroup = rightSide.findGroup("Total");
    leftGroup.setName("LeftSide");
    rightGroup.setName("RightSide");
    outputPvl.addGroup(leftGroup);
    outputPvl.addGroup(rightGroup);
  }
  outputPvl.write(ui.GetFileName("TO"));
}