예제 #1
0
파일: cnetadd.cpp 프로젝트: corburn/ISIS
/**
 * Calculates the lat/lon of the ControlNet.
 *
 * @param incubes The filename of the list of cubes in the ControlNet
 * @param cnet    The filename of the ControlNet
 */
void setControlPointLatLon(SerialNumberList &snl, ControlNet &cnet) {
  CubeManager manager;
  manager.SetNumOpenCubes(50);   //Should keep memory usage to around 1GB

  Progress progress;
  progress.SetText("Calculating Lat/Lon");
  progress.SetMaximumSteps(cnet.GetNumPoints());
  progress.CheckStatus();

  for (int cp = 0; cp < cnet.GetNumPoints(); cp++) {
    ControlPoint *point = cnet.GetPoint(cp);
    ControlMeasure *cm = point->GetRefMeasure();

    Cube *cube = manager.OpenCube(snl.FileName(cm->GetCubeSerialNumber()));
    try {
      cube->camera()->SetImage(cm->GetSample(), cm->GetLine());
      g_surfacePoints[point->GetId()] = cube->camera()->GetSurfacePoint();
    }
    catch (IException &e) {
      QString msg = "Unable to create camera for cube file [";
      msg += snl.FileName(cm->GetCubeSerialNumber()) + "]";
      throw IException(e, IException::Unknown, msg, _FILEINFO_);
    }
    cube = NULL; //Do not delete, manager still has ownership

    progress.CheckStatus();
  }

  manager.CleanCubes();
}
예제 #2
0
/**
 * This method performs pass1 on one image. It analyzes each framelet's
 * statistics and populates the necessary global variable.
 *
 * @param progress Progress message
 * @param theCube Current cube that needs processing
 *
 * @return bool True if the file contains a valid framelet
 */
bool CheckFramelets(string progress, Cube &theCube) {
    bool foundValidFramelet = false;
    LineManager mgr(theCube);
    Progress prog;
    prog.SetText(progress);
    prog.SetMaximumSteps(theCube.Lines());
    prog.CheckStatus();

    vector<double> frameletAvgs;
    // We need to store off the framelet information, because if no good
    //   framelets were found then no data should be added to the
    //   global variable for framelets, just files.
    vector< pair<int,double> > excludedFrameletsTmp;
    Statistics frameletStats;

    for(int line = 1; line <= theCube.Lines(); line++) {
        if((line-1) % numFrameLines == 0) {
            frameletStats.Reset();
        }

        mgr.SetLine(line);
        theCube.Read(mgr);
        frameletStats.AddData(mgr.DoubleBuffer(), mgr.size());

        if((line-1) % numFrameLines == numFrameLines-1) {
            if(IsSpecial(frameletStats.StandardDeviation()) ||
                    frameletStats.StandardDeviation() > maxStdev) {
                excludedFrameletsTmp.push_back(
                    pair<int,double>((line-1)/numFrameLines, frameletStats.StandardDeviation())
                );
            }
            else {
                foundValidFramelet = true;
            }

            frameletAvgs.push_back(frameletStats.Average());
        }

        prog.CheckStatus();
    }

    inputFrameletAverages.push_back(frameletAvgs);

    if(foundValidFramelet) {
        for(unsigned int i = 0; i < excludedFrameletsTmp.size(); i++) {
            excludedFramelets.insert(pair< pair<int,int>, double>(
                                         pair<int,int>(currImage, excludedFrameletsTmp[i].first),
                                         excludedFrameletsTmp[i].second
                                     )
                                    );
        }

    }

    return foundValidFramelet;
}
예제 #3
0
/**
 * Finds and writes all input cubes contained within the given Control Network 
 * to the output file list 
 * 
 * @param cnet The Control Network to list the filenames contained within
 * @param sn2file The map for converting the Control Network's serial numbers 
 *                to filenames 
 */
void WriteCubeOutList( ControlNet cnet, map<iString,iString> sn2file ) {
  UserInterface &ui = Application::GetUserInterface();

  if( ui.WasEntered("TOLIST") ) {

    Progress p;
    p.SetText("Writing Cube List");
    try {
      p.SetMaximumSteps(cnet.Size());
      p.CheckStatus();
    } catch( iException &e ) {
      e.Clear();
      string msg = "The provided filters have resulted in an empty Control Network.";
      throw Isis::iException::Message(Isis::iException::User,msg, _FILEINFO_);
    }

    set<iString> outputsn;
    for( int cp = 0; cp < cnet.Size(); cp ++ ) {
      for( int cm = 0; cm < cnet[cp].Size(); cm ++ ) {
        outputsn.insert( cnet[cp][cm].CubeSerialNumber() );
      }
      p.CheckStatus();
    }

    std::string toList = ui.GetFilename("TOLIST");
    ofstream out_stream;
    out_stream.open(toList.c_str(), std::ios::out);
    out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file

    for( set<iString>::iterator sn = outputsn.begin(); sn != outputsn.end(); sn ++ ) {
      if( !sn2file[(*sn)].empty() ) {
        out_stream << sn2file[(*sn)] << endl;
      }
    }

    out_stream.close();
  }
}
예제 #4
0
파일: hijitreg.cpp 프로젝트: assutech/isis3
void IsisMain() {

  // Get user interface
  UserInterface &ui = Application::GetUserInterface();

//  Open the shift definitions file
  Pvl shiftdef;
  if (ui.WasEntered("SHIFTDEF")) {
    shiftdef.Read(ui.GetFilename("SHIFTDEF"));
  }
  else {
    shiftdef.AddObject(PvlObject("Hiccdstitch"));
  }

  PvlObject &stitch = shiftdef.FindObject("Hiccdstitch", Pvl::Traverse);


  // Open the first cube.  It will be matched to the second input cube.
  HiJitCube trans;
  CubeAttributeInput &attTrans = ui.GetInputAttribute("FROM");
  vector<string> bandTrans = attTrans.Bands();
  trans.SetVirtualBands(bandTrans);
  trans.OpenCube(ui.GetFilename("FROM"), stitch);

 
  // Open the second cube, it is held in place.  We will be matching the
  // first to this one by attempting to compute a sample/line translation
  HiJitCube match;
  CubeAttributeInput &attMatch = ui.GetInputAttribute("MATCH");
  vector<string> bandMatch = attMatch.Bands();
  match.SetVirtualBands(bandMatch);
  match.OpenCube(ui.GetFilename("MATCH"), stitch);

//  Ensure only one band
  if ((trans.Bands() != 1) || (match.Bands() != 1)) {
    string msg = "Input Cubes must have only one band!";
    throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
  }

//  Now test compatability (basically summing)
  trans.Compatable(match);

//  Determine intersection
  if (!trans.intersects(match)) {
    string msg = "Input Cubes do not overlap!";
    throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
  }

//  Get overlapping regions of each cube
  HiJitCube::Corners fcorns, mcorns;
  trans.overlap(match, fcorns);
  match.overlap(trans, mcorns);

#if defined(ISIS_DEBUG)
  cout << "FROM Poly:  " << trans.PolyToString() << std::endl;
  cout << "MATCH Poly: " << match.PolyToString() << std::endl;
  cout << "From Overlap:  (" << fcorns.topLeft.sample << ","
                             << fcorns.topLeft.line   << "), ("
                             << fcorns.lowerRight.sample << "," 
                             << fcorns.lowerRight.line << ")\n" ;
  cout << "Match Overlap: (" << mcorns.topLeft.sample << ","
                             << mcorns.topLeft.line   << "), ("
                             << mcorns.lowerRight.sample << "," 
                             << mcorns.lowerRight.line << ")\n" ;
#endif


  // We need to get a user definition of how to auto correlate around each
  // of the grid points.
  Pvl regdef;
  Filename regFile(ui.GetFilename("REGDEF"));
  regdef.Read(regFile.Expanded());
  AutoReg *ar = AutoRegFactory::Create(regdef);


  double flines(fcorns.lowerRight.line - fcorns.topLeft.line + 1.0);
  double fsamps(fcorns.lowerRight.sample - fcorns.topLeft.sample + 1.0);

  // We want to create a grid of control points that is N rows by M columns.
  // Get row and column variables, if not entered, default to 1% of the input
  // image size
  int rows(1), cols(1);
  if (ui.WasEntered("ROWS")) {
    rows = ui.GetInteger("ROWS");
  }
  else {
    rows = (int)(((flines - 1.0) / ar->SearchChip()->Lines()) + 1);
  }

  cols = ui.GetInteger("COLUMNS");
  if (cols == 0) {
    cols = (int)(((fsamps - 1.0) / ar->SearchChip()->Samples()) + 1);
  }

  // Calculate spacing for the grid of points
  double lSpacing = floor(flines / rows);
  double sSpacing = floor(fsamps / cols);

#if defined(ISIS_DEBUG)
  cout << "# Samples in Overlap: " << fsamps << endl;
  cout << "# Lines in Overlap  : " << flines << endl;
  cout << "# Rows:    " << rows << endl;
  cout << "# Columns: " << cols << endl;
  cout << "Line Spacing:   " << lSpacing << endl;
  cout << "Sample Spacing: " << sSpacing << endl;
#endif

  // Display the progress...10% 20% etc.
  Progress prog;
  prog.SetMaximumSteps(rows * cols);
  prog.CheckStatus();

  // Initialize control point network
  ControlNet cn;
  cn.SetType(ControlNet::ImageToImage);
  cn.SetUserName(Application::UserName());
  cn.SetCreatedDate(iTime::CurrentLocalTime());

  //  Get serial numbers for input cubes
  string transSN = SerialNumber::Compose(trans, true);
  string matchSN = SerialNumber::Compose(match, true);

  cn.SetTarget(transSN);
  cn.SetDescription("Records s/c jitter between two adjacent HiRISE images");

//  Set up results parameter saves
  JitterParms jparms;
  jparms.fromCorns = fcorns;
  jparms.fromJit = trans.GetInfo();
  jparms.matchCorns = mcorns;
  jparms.matchJit = match.GetInfo();
  jparms.regFile =  regFile.Expanded();
  jparms.cols = cols;
  jparms.rows = rows;
  jparms.lSpacing = lSpacing;
  jparms.sSpacing = sSpacing;
  jparms.nSuspects = 0;

  // Loop through grid of points and get statistics to compute
  // translation values
  RegList reglist;
  double fline0(fcorns.topLeft.line-1.0), fsamp0(fcorns.topLeft.sample-1.0);
  double mline0(mcorns.topLeft.line-1.0), msamp0(mcorns.topLeft.sample-1.0);

  for (int r=0; r<rows; r++) {
    int line = (int)(lSpacing / 2.0 + lSpacing * r + 0.5);
    for (int c=0; c<cols; c++) {
      int samp = (int)(sSpacing / 2.0 + sSpacing * c + 0.5);

      ar->PatternChip()->TackCube(msamp0+samp, mline0+line);
      ar->PatternChip()->Load(match);
      ar->SearchChip()->TackCube(fsamp0+samp, fline0+line);
      ar->SearchChip()->Load(trans);

     // Set up ControlMeasure for cube to translate
      ControlMeasure cmTrans;
      cmTrans.SetCubeSerialNumber(transSN);
      cmTrans.SetCoordinate(msamp0+samp, mline0+line, 
                            ControlMeasure::Unmeasured);
      cmTrans.SetChooserName("hijitreg");
      cmTrans.SetReference(false);

      // Set up ControlMeasure for the pattern/Match cube 
      ControlMeasure cmMatch;
      cmMatch.SetCubeSerialNumber(matchSN);
      cmMatch.SetCoordinate(fsamp0+samp, fline0+line, 
                            ControlMeasure::Automatic);
      cmMatch.SetChooserName("hijitreg");
      cmMatch.SetReference(true);


      // Match found
      if (ar->Register()==AutoReg::Success) {
        RegData reg;
        reg.fLine = fline0 + line;
        reg.fSamp = fsamp0 + samp;
        reg.fLTime = trans.getLineTime(reg.fLine);
        reg.mLine = mline0 + line;
        reg.mSamp = msamp0 + samp;
        reg.mLTime = match.getLineTime(reg.mLine);
        reg.regLine = ar->CubeLine();
        reg.regSamp = ar->CubeSample();
        reg.regCorr = ar->GoodnessOfFit();


        if (fabs(reg.regCorr) > 1.0) jparms.nSuspects++;

        double sDiff = reg.fSamp - reg.regSamp;
        double lDiff = reg.fLine - reg.regLine;
        jparms.sStats.AddData(&sDiff,(unsigned int)1);
        jparms.lStats.AddData(&lDiff,(unsigned int)1);

//  Record the translation in the control point
        cmTrans.SetCoordinate(ar->CubeSample(), ar->CubeLine(), 
                              ControlMeasure::Automatic);
        cmTrans.SetError(sDiff, lDiff);
        cmTrans.SetGoodnessOfFit(ar->GoodnessOfFit());

//  Reread the chip location centering the offset and compute
//  linear regression statistics
        try {
          Chip &pchip(*ar->PatternChip());
          Chip fchip(pchip.Samples(), pchip.Lines());
          fchip.TackCube(ar->CubeSample(), ar->CubeLine());
          fchip.Load(trans);

//  Writes correlated chips to files for visual inspection
#if defined(ISIS_DEBUG)
          ostringstream tstr;
          tstr << "R" << r << "C" << c << "_chip.cub";
          string fcname("from"  + tstr.str());
          string mcname("match" + tstr.str());

          pchip.Write(mcname);
          fchip.Write(fcname);
#endif

          MultivariateStatistics mstats;
          for (int line = 1 ; line <= fchip.Lines() ; line++) {
            for(int sample = 1; sample < fchip.Samples(); sample++) {
              double fchipValue = fchip.GetValue(sample,line);
              double pchipValue = pchip.GetValue(sample,line);
              mstats.AddData(&fchipValue, &pchipValue, 1);
            }
          }

//  Get regression and correlation values
          mstats.LinearRegression(reg.B0, reg.B1);
          reg.Bcorr = mstats.Correlation();
          if (IsSpecial(reg.B0)) throw 1;
          if (IsSpecial(reg.B1)) throw 2;
          if (IsSpecial(reg.Bcorr)) throw 3;
        } 
        catch (...) {
//  If fails, flag this condition
          reg.B0 = 0.0;
          reg.B1= 0.0;
          reg.Bcorr = 0.0;
        }

        reglist.push_back(reg);
      }

      // Add the measures to a control point
      string str = "Row " + iString(r) + " Column " + iString(c);
      ControlPoint cp(str);
      cp.SetType(ControlPoint::Tie);
      cp.Add(cmTrans);
      cp.Add(cmMatch);
      if (!cmTrans.IsMeasured()) cp.SetIgnore(true);
      cn.Add(cp);
      prog.CheckStatus();
    }
  }

  // If flatfile was entered, create the flatfile
  // The flatfile is comma seperated and can be imported into an excel
  // spreadsheet
  if (ui.WasEntered("FLATFILE")) {
    string fFile = ui.GetFilename("FLATFILE");
    ofstream os;
    string fFileExpanded = Filename(fFile).Expanded();
    os.open(fFileExpanded.c_str(),ios::out);
    dumpResults(os, reglist, jparms, *ar);
  }

  // If a cnet file was entered, write the ControlNet pvl to the file
  if (ui.WasEntered("CNETFILE")) {
    cn.Write(ui.GetFilename("CNETFILE"));
  }

  // Don't need the cubes opened anymore
  trans.Close();
  match.Close();


  // Write translation to log
  PvlGroup results("AverageTranslation");
  if (jparms.sStats.ValidPixels() > 0) {
    double sTrans = (int)(jparms.sStats.Average() * 100.0) / 100.0;
    double lTrans = (int)(jparms.lStats.Average() * 100.0) / 100.0;
    results += PvlKeyword ("Sample",sTrans);
    results += PvlKeyword ("Line",lTrans);
    results += PvlKeyword ("NSuspects",jparms.nSuspects);
  }
  else {
    results += PvlKeyword ("Sample","NULL");
    results += PvlKeyword ("Line","NULL");
  }

  Application::Log(results);

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

  return;
}
예제 #5
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();
}
예제 #6
0
파일: cnetadd.cpp 프로젝트: corburn/ISIS
void IsisMain() {

  UserInterface &ui = Application::GetUserInterface();

  FileList addList(ui.GetFileName("ADDLIST"));

  bool log = false;
  FileName logFile;
  if (ui.WasEntered("LOG")) {
    log = true;
    logFile = ui.GetFileName("LOG");
  }
  Pvl results;
  results.setName("cnetadd_Results");
  PvlKeyword added("FilesAdded");
  PvlKeyword omitted("FilesOmitted");
  PvlKeyword pointsModified("PointsModified");

  bool checkMeasureValidity = ui.WasEntered("DEFFILE");
  ControlNetValidMeasure validator;
  if (checkMeasureValidity) {
    Pvl deffile(ui.GetFileName("DEFFILE"));
    validator = ControlNetValidMeasure(deffile);
  }

  SerialNumberList *fromSerials = ui.WasEntered("FROMLIST") ?
    new SerialNumberList(ui.GetFileName("FROMLIST")) : new SerialNumberList();

  ControlNet inNet = ControlNet(ui.GetFileName("CNET"));
  inNet.SetUserName(Application::UserName());
  inNet.SetModifiedDate(iTime::CurrentLocalTime()); //This should be done in ControlNet's Write fn

  QString retrievalOpt = ui.GetString("RETRIEVAL");
  PvlKeyword duplicates("DupSerialNumbers");
  if (retrievalOpt == "REFERENCE") {
    FileList list1(ui.GetFileName("FROMLIST"));
    SerialNumberList addSerials(ui.GetFileName("ADDLIST"));

    //Check for duplicate files in the lists by serial number
    for (int i = 0; i < addSerials.Size(); i++) {

      // Check for duplicate SNs accross the lists
      if (fromSerials->HasSerialNumber(addSerials.SerialNumber(i))) {
        duplicates.addValue(addSerials.FileName(i));
      }

      // Check for duplicate SNs within the addlist
      for (int j = i + 1; j < addSerials.Size(); j++) {
        if (addSerials.SerialNumber(i) == addSerials.SerialNumber(j)) {
          QString msg = "Add list files [" + addSerials.FileName(i) + "] and [";
          msg += addSerials.FileName(j) + "] share the same serial number.";
          throw IException(IException::User, msg, _FILEINFO_);
        }
      }
    }

    // Get the lat/long coords from the existing reference measure
    setControlPointLatLon(*fromSerials, inNet);
  }
  else {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      // Get the surface point from the current control point
      ControlPoint *point = inNet.GetPoint(cp);
      SurfacePoint surfacePoint = point->GetBestSurfacePoint();

      if (!surfacePoint.Valid()) {
        QString msg = "Unable to retreive lat/lon from Control Point [";
        msg += point->GetId() + "]. RETREIVAL=POINT cannot be used unless ";
        msg += "all Control Points have Latitude/Longitude keywords.";
        throw IException(IException::User, msg, _FILEINFO_);
      }

      g_surfacePoints[point->GetId()] = surfacePoint;
    }
  }

  FileName outNetFile(ui.GetFileName("ONET"));

  Progress progress;
  progress.SetText("Adding Images");
  progress.SetMaximumSteps(addList.size());
  progress.CheckStatus();

  STRtree coordTree;
  QList<ControlPoint *> pointList;
  bool usePolygon = ui.GetBoolean("POLYGON");
  if (usePolygon) {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      ControlPoint *point = inNet.GetPoint(cp);
      SurfacePoint surfacePoint = g_surfacePoints[point->GetId()];

      Longitude lon = surfacePoint.GetLongitude();
      Latitude lat = surfacePoint.GetLatitude();

      Coordinate *coord = new Coordinate(lon.degrees(), lat.degrees());
      Envelope *envelope = new Envelope(*coord);
      coordTree.insert(envelope, point);
    }
  }
  else {
    for (int cp = 0; cp < inNet.GetNumPoints(); cp++) {
      pointList.append(inNet.GetPoint(cp));
    }
  }

  // Loop through all the images
  for (int img = 0; img < addList.size(); img++) {
    Cube cube;
    cube.open(addList[img].toString());
    Pvl *cubepvl = cube.label();
    QString sn = SerialNumber::Compose(*cubepvl);
    Camera *cam = cube.camera();

    // Loop through all the control points
    QList<ControlPoint *> validPoints = usePolygon ?
        getValidPoints(cube, coordTree) : pointList;

    bool imageAdded = false;
    for (int cp = 0; cp < validPoints.size(); cp++) {
      ControlPoint *point = validPoints[cp];

      // If the point is locked and Apriori source is "AverageOfMeasures"
      // then do not add the measures.
      if (point->IsEditLocked() &&
          point->GetAprioriSurfacePointSource() ==
              ControlPoint::SurfacePointSource::AverageOfMeasures) {
        continue;
      }

      if (point->HasSerialNumber(sn)) continue;

      // Only use the surface point's latitude and longitude, rely on the DEM
      // for computing the radius.  We do this because otherwise we will receive
      // inconsistent results from successive runs of this program if the
      // different DEMs are used, or the point X, Y, Z was generated from the
      // ellipsoid.
      SurfacePoint surfacePoint = g_surfacePoints[point->GetId()];
      if (cam->SetGround(
              surfacePoint.GetLatitude(), surfacePoint.GetLongitude())) {

        // Make sure the samp & line are inside the image
        if (cam->InCube()) {
          ControlMeasure *newCm = new ControlMeasure();
          newCm->SetCoordinate(cam->Sample(), cam->Line(), ControlMeasure::Candidate);
          newCm->SetAprioriSample(cam->Sample());
          newCm->SetAprioriLine(cam->Line());
          newCm->SetCubeSerialNumber(sn);
          newCm->SetDateTime();
          newCm->SetChooserName("Application cnetadd");

          // Check the measure for DEFFILE validity
          if (checkMeasureValidity) {
            if (!validator.ValidEmissionAngle(cam->EmissionAngle())) {
              //TODO: log that it was Emission Angle that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.ValidIncidenceAngle(cam->IncidenceAngle())) {
              //TODO: log that it was Incidence Angle that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.ValidResolution(cam->resolution())) {
              //TODO: log that it was Resolution that failed the check
              newCm->SetIgnored(true);
            }
            else if (!validator.PixelsFromEdge((int)cam->Sample(), (int)cam->Line(), &cube)) {
              //TODO: log that it was Pixels from Edge that failed the check
              newCm->SetIgnored(true);
            }
            else {
              Portal portal(1, 1, cube.pixelType());
              portal.SetPosition(cam->Sample(), cam->Line(), 1);
              cube.read(portal);
              if (!validator.ValidDnValue(portal[0])) {
                //TODO: log that it was DN that failed the check
                newCm->SetIgnored(true);
              }
            }
          }

          point->Add(newCm); // Point takes ownership

          // Record the modified Point and Measure
          g_modifications[point->GetId()].insert(newCm->GetCubeSerialNumber());
          newCm = NULL; // Do not delete because the point has ownership

          if (retrievalOpt == "POINT" && point->GetNumMeasures() == 1)
            point->SetIgnored(false);

          imageAdded = true;
        }
      }
    }

    cubepvl = NULL;
    cam = NULL;

    if (log) {
      PvlKeyword &logKeyword = (imageAdded) ? added : omitted;
      logKeyword.addValue(addList[img].baseName());
    }

    progress.CheckStatus();
  }

  if (log) {
    // Add the list of modified points to the output log file
    QList<QString> modifiedPointsList = g_modifications.keys();
    for (int i = 0; i < modifiedPointsList.size(); i++)
      pointsModified += modifiedPointsList[i];

    results.addKeyword(added);
    results.addKeyword(omitted);
    results.addKeyword(pointsModified);
    if (duplicates.size() > 0) {
      results.addKeyword(duplicates);
    }

    results.write(logFile.expanded());
  }

  // List the modified points
  if (ui.WasEntered("MODIFIEDPOINTS")) {
    FileName pointList(ui.GetFileName("MODIFIEDPOINTS"));

    // Set up the output file for writing
    std::ofstream out_stream;
    out_stream.open(pointList.expanded().toAscii().data(), std::ios::out);
    out_stream.seekp(0, std::ios::beg);   //Start writing from beginning of file

    QList<QString> modifiedPointsList = g_modifications.keys();
    for (int i = 0; i < modifiedPointsList.size(); i++)
      out_stream << modifiedPointsList[i].toStdString() << std::endl;

    out_stream.close();
  }

  // Modify the inNet to only have modified points/measures
  if (ui.GetString("EXTRACT") == "MODIFIED") {
    for (int cp = inNet.GetNumPoints() - 1; cp >= 0; cp--) {
      ControlPoint *point = inNet.GetPoint(cp);

      // If the point was not modified, delete
      // Even get rid of edit locked points in this case
      if (!g_modifications.contains(point->GetId())) {
        point->SetEditLock(false);
        inNet.DeletePoint(cp);
      }
      // Else, remove the unwanted measures from the modified point
      else {
        for (int cm = point->GetNumMeasures() - 1; cm >= 0; cm--) {
          ControlMeasure *measure = point->GetMeasure(cm);

          // Even get rid of edit locked measures in this case
          if (point->GetRefMeasure() != measure &&
              !g_modifications[point->GetId()].contains(
                  measure->GetCubeSerialNumber())) {
            measure->SetEditLock(false);
            point->Delete(cm);
          }
        }
      }
    }
  }

  // Generate the TOLIST if wanted
  if (ui.WasEntered("TOLIST")) {
    SerialNumberList toList;

    SerialNumberList addSerials(ui.GetFileName("ADDLIST"));

    const QList<QString> snList = inNet.GetCubeSerials();
    for (int i = 0; i < snList.size(); i++) {
      QString sn = snList[i];

      if (addSerials.HasSerialNumber(sn))
        toList.Add(addSerials.FileName(sn));
      else if (fromSerials->HasSerialNumber(sn))
        toList.Add(fromSerials->FileName(sn));
    }

    IString name(ui.GetFileName("TOLIST"));
    std::fstream out_stream;
    out_stream.open(name.c_str(), std::ios::out);
    out_stream.seekp(0, std::ios::beg); //Start writing from beginning of file

    for (int f = 0; f < (int) toList.Size(); f++)
      out_stream << toList.FileName(f) << std::endl;

    out_stream.close();
  }

  inNet.Write(outNetFile.expanded());

  delete fromSerials;
}
예제 #7
0
파일: mapgrid.cpp 프로젝트: jlaura/isis3
void IsisMain() {
    // Get user interface
    UserInterface &ui = Application::GetUserInterface();

    // Get necessary variables from the user
    double latStart = ui.GetDouble("STARTLAT");
    double lonStart = ui.GetDouble("STARTLON");
    double latEnd = ui.GetDouble("ENDLAT");
    double lonEnd = ui.GetDouble("ENDLON");
    double latSpacing = ui.GetDouble("LATSPACING");
    double lonSpacing = ui.GetDouble("LONSPACING");
    double latInc = ui.GetDouble("LATINCREMENT");
    double lonInc = ui.GetDouble("LONINCREMENT");

    // Get mapfile, add values for range and create projection
    QString mapFile = ui.GetFileName("MAPFILE");
    Pvl p(mapFile);
    PvlGroup &mapping = p.findGroup("Mapping", Pvl::Traverse);

    if(mapping.hasKeyword("MinimumLatitude")) {
        mapping.deleteKeyword("MinimumLatitude");
    }

    if(mapping.hasKeyword("MaximumLatitude")) {
        mapping.deleteKeyword("MaximumLatitude");
    }

    if(mapping.hasKeyword("MinimumLongitude")) {
        mapping.deleteKeyword("MinimumLongitude");
    }

    if(mapping.hasKeyword("MaximumLongitude")) {
        mapping.deleteKeyword("MaximumLongitude");
    }

    mapping += PvlKeyword("MinimumLatitude", toString(latStart));
    mapping += PvlKeyword("MaximumLatitude", toString(latEnd));
    mapping += PvlKeyword("MinimumLongitude", toString(lonStart));
    mapping += PvlKeyword("MaximumLongitude", toString(lonEnd));

    TProjection *proj;
    try {
        proj = (TProjection *) ProjectionFactory::Create(p);
    }
    catch(IException &e) {
        QString msg = "Cannot create grid - MapFile [" + mapFile +
                      "] does not contain necessary information to create a projection";
        throw IException(e, IException::User, msg, _FILEINFO_);
    }


    // Write grid to well known text output
    QString out = FileName(ui.GetFileName("TO")).expanded();
    std::ofstream os;
    os.open(out.toAscii().data(), std::ios::out);

    // Display the progress...10% 20% etc.
    Progress prog;
    int steps = (int)(abs((latEnd - latStart) / latSpacing) +
                      abs((lonEnd - lonStart) / lonSpacing) + 0.5) + 3;
    prog.SetMaximumSteps(steps);
    prog.CheckStatus();

    /**
     * Initialize document. GML is XML-based, so we need the necessary XML headers. These
     * are necessary for the GML file to be recognized.
     */
    os << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" << endl;
    os << "<ogr:FeatureCollection " << endl <<
       "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << endl <<
       "xsi:schemaLocation=\"http://org.maptools.org/\"" << endl <<
       "xmlns:ogr=\"http://org.maptools.org/\"" << endl <<
       "xmlns:gml=\"http://www.opengis.net/gml\">" << endl;

    /**
     * Draw the interior longitude lines by looping through the longitude
     * range and drawing across each latitude line using the longitude increment. The first
     * and last line will be skipped for now.
     */
    for(double j = lonStart + lonSpacing; j < lonEnd; j += lonSpacing) {
        StartNewLine(os);
        for(double k = latStart; k <= latEnd; k += lonInc) {
            proj->SetGround(k, j);
            AddPointToLine(os, proj->XCoord(), proj->YCoord());
        }

        EndLine(os);
        prog.CheckStatus();
    }

    /**
     * Draw the exterior longitude boundary lines. This happens by drawing just the first and
     * last longitude lines.
     */
    for(double r = lonStart; r <= lonEnd; r += (lonEnd - lonStart)) {
        StartNewLine(os);
        for(double s = latStart; s <= latEnd; s += lonInc) {
            proj->SetGround(s, r);
            AddPointToLine(os, proj->XCoord(), proj->YCoord());
        }
        EndLine(os);
        prog.CheckStatus();
    }

    /**
     * Draw the interior latitude lines by looping through the latitude
     * range and drawing across each longitude line using the latitude increment. The first
     * and last line will be skipped for now.
     */
    for(double i = latStart + latSpacing; i < latEnd; i += latSpacing) {

        // Get Latitude Line
        StartNewLine(os);
        for(double l = lonStart; l <= lonEnd; l += latInc) {
            proj->SetGround(i, l);
            AddPointToLine(os, proj->XCoord(), proj->YCoord());
        }
        EndLine(os);
        prog.CheckStatus();
    }

    /**
     * Draw the exterior latitude boundary lines. This happens by drawing just the first and
     * last longitude lines.
     */
    for(double m = latStart; m <= latEnd; m += (latEnd - latStart)) {
        StartNewLine(os);

        for(double n = lonStart; n <= lonEnd; n += latInc) {
            proj->SetGround(m, n);
            AddPointToLine(os, proj->XCoord(), proj->YCoord());
        }

        EndLine(os);
        prog.CheckStatus();
    }

    /**
     * Draw the bounding box using a series of lines.
     */
    if(ui.GetBoolean("BOUNDED")) {
        double minX, maxX, minY, maxY;
        proj->XYRange(minX, maxX, minY, maxY);

        StartNewLine(os);
        AddPointToLine(os, minX, minY);
        AddPointToLine(os, minX, maxY);
        EndLine(os);

        StartNewLine(os);
        AddPointToLine(os, minX, maxY);
        AddPointToLine(os, maxX, maxY);
        EndLine(os);

        StartNewLine(os);
        AddPointToLine(os, maxX, minY);
        AddPointToLine(os, maxX, maxY);
        EndLine(os);

        StartNewLine(os);
        AddPointToLine(os, minX, minY);
        AddPointToLine(os, maxX, minY);
        EndLine(os);
    }

    os << "</ogr:FeatureCollection>" << endl;

    // add mapping to print.prt
    PvlGroup projMapping = proj->Mapping();
    Application::Log(projMapping);
}
예제 #8
0
/**
 * Constructs an OverlapStatistics object.  Compares the two input cubes and
 * finds where they overlap.
 *
 * @param x The first input cube
 * @param y The second input cube
 * @param progressMsg (Default value of "Gathering Overlap Statistics") Text
 *         for indicating progress during statistic gathering
 * @param sampPercent (Default value of 100.0) Sampling percent, or the percentage
 *       of lines to consider during the statistic gathering procedure
 *
 * @throws Isis::iException::User - All images must have the same number of
 *                                  bands
 */
OverlapStatistics::OverlapStatistics(Isis::Cube &x, Isis::Cube &y,
                                     std::string progressMsg, double sampPercent) {
    // Test to ensure sampling percent in bound
    if (sampPercent <= 0.0 || sampPercent > 100.0) {
        string msg = "The sampling percent must be a decimal (0.0, 100.0]";
        throw iException::Message(iException::Programmer,msg,_FILEINFO_);
    }

    p_sampPercent = sampPercent;

    // Extract filenames and band number from cubes
    p_xFile = x.Filename();
    p_yFile = y.Filename();

    // Make sure number of bands match
    if (x.Bands() != y.Bands()) {
        string msg = "Number of bands do not match between cubes [" +
                     p_xFile.Name() + "] and [" + p_yFile.Name() + "]";
        throw iException::Message(iException::User,msg,_FILEINFO_);
    }
    p_bands = x.Bands();
    p_stats.resize(p_bands);

    //Create projection from each cube
    Projection *projX = x.Projection();
    Projection *projY = y.Projection();

    // Test to make sure projection parameters match
    if (*projX != *projY) {
        string msg = "Mapping groups do not match between cubes [" +
                     p_xFile.Name() + "] and [" + p_yFile.Name() + "]";
        throw iException::Message(iException::Programmer,msg,_FILEINFO_);
    }

    // Figure out the x/y range for both images to find the overlap
    double Xmin1 = projX->ToProjectionX(0.5);
    double Ymax1 = projX->ToProjectionY(0.5);
    double Xmax1 = projX->ToProjectionX(x.Samples()+0.5);
    double Ymin1 = projX->ToProjectionY(x.Lines()+0.5);

    double Xmin2 = projY->ToProjectionX(0.5);
    double Ymax2 = projY->ToProjectionY(0.5);
    double Xmax2 = projY->ToProjectionX(y.Samples()+0.5);
    double Ymin2 = projY->ToProjectionY(y.Lines()+0.5);

    // Find overlap
    if ((Xmin1<Xmax2) && (Xmax1>Xmin2) && (Ymin1<Ymax2) && (Ymax1>Ymin2)) {
        double minX = Xmin1 > Xmin2 ? Xmin1 : Xmin2;
        double minY = Ymin1 > Ymin2 ? Ymin1 : Ymin2;
        double maxX = Xmax1 < Xmax2 ? Xmax1 : Xmax2;
        double maxY = Ymax1 < Ymax2 ? Ymax1 : Ymax2;

        // Find Sample range of the overlap
        p_minSampX = (int)(projX->ToWorldX(minX) + 0.5);
        p_maxSampX = (int)(projX->ToWorldX(maxX) + 0.5);
        p_minSampY = (int)(projY->ToWorldX(minX) + 0.5);
        p_maxSampY = (int)(projY->ToWorldX(maxX) + 0.5);
        p_sampRange = p_maxSampX - p_minSampX + 1;

        // Test to see if there was only sub-pixel overlap
        if (p_sampRange <= 0) return;

        // Find Line range of overlap
        p_minLineX = (int)(projX->ToWorldY(maxY) + 0.5);
        p_maxLineX = (int)(projX->ToWorldY(minY) + 0.5);
        p_minLineY = (int)(projY->ToWorldY(maxY) + 0.5);
        p_maxLineY = (int)(projY->ToWorldY(minY) + 0.5);
        p_lineRange = p_maxLineX - p_minLineX + 1;

        // Print percent processed
        Progress progress;
        progress.SetText(progressMsg);

        int linc = (int)(100.0 / sampPercent + 0.5); // Calculate our line increment

        // Define the maximum number of steps to be our line range divided by the
        // line increment, but if they do not divide evenly, then because of
        // rounding, we need to do an additional step for each band
        int maxSteps = (int)(p_lineRange / linc + 0.5);

        if (p_lineRange % linc != 0) maxSteps += 1;
        maxSteps *= p_bands;


        progress.SetMaximumSteps(maxSteps);
        progress.CheckStatus();

        // Collect and store off the overlap statistics
        for (int band=1; band<=p_bands; band++) {
            Brick b1(p_sampRange,1,1,x.PixelType());
            Brick b2(p_sampRange,1,1,y.PixelType());

            int i=0;
            while (i<p_lineRange) {
                b1.SetBasePosition(p_minSampX,(i+p_minLineX),band);
                b2.SetBasePosition(p_minSampY,(i+p_minLineY),band);
                x.Read(b1);
                y.Read(b2);
                p_stats[band-1].AddData(b1.DoubleBuffer(), b2.DoubleBuffer(), p_sampRange);

                // Make sure we consider the last line
                if (i+linc > p_lineRange-1 && i != p_lineRange-1) {
                    i = p_lineRange-1;
                    progress.AddSteps(1);
                }
                else i+=linc; // Increment the current line by our incrementer

                progress.CheckStatus();
            }
        }
    }
}
예제 #9
0
파일: camstats.cpp 프로젝트: assutech/isis3
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();

  }

}
예제 #10
0
/**
 * This is the main method. Makeflat runs in three steps:
 *
 * 1) Calculate statistics
 *   - For all cameras, this checks for one band and matching
 *       sample counts.
 *   - For framing cameras, this checks the standard deviation of
 *       the images and records the averages of each image
 *   - For push frame cameras, this calls CheckFramelets for each
 *       image.
 *
 * 2) Create the temporary file, collect more detailed statistics
 *   - For all cameras, this generates the temporary file and calculates
 *       the final exclusion list
 *   - For framing/push frame cameras, the temporary file is
 *       2 bands, where the first is a sum of DNs from each image/framelet
 *       and the second band is a count of valid DNs that went into each sum
 *
 *  3) Create the final flat field file
 *   - For all cameras, this processes the temporary file to create the final flat
 *       field file.
 */
void IsisMain() {
    // Initialize variables
    ResetGlobals();

    UserInterface &ui = Application::GetUserInterface();
    maxStdev = ui.GetDouble("STDEVTOL");

    if(ui.GetString("IMAGETYPE") == "FRAMING") {
        cameraType = Framing;

        // framing cameras need to figure this out automatically
        //   during step 1
        numFrameLines = -1;
    }
    else if(ui.GetString("IMAGETYPE") == "LINESCAN") {
        cameraType = LineScan;
        numFrameLines = ui.GetInteger("NUMLINES");
    }
    else {
        cameraType = PushFrame;
        numFrameLines = ui.GetInteger("FRAMELETHEIGHT");
    }

    FileList inList(ui.GetFilename("FROMLIST"));
    Progress progress;

    tempFileLength = 0;
    numOutputSamples = 0;

    /**
     * Line scan progress is based on the input list, whereas
     * the other cameras take much longer and are based on the
     * images themselves. Prepare the progress if we're doing
     * line scan.
     */
    if(cameraType == LineScan) {
        progress.SetText("Calculating Number of Image Lines");
        progress.SetMaximumSteps(inList.size());
        progress.CheckStatus();
    }

    /**
     *  For a push frame camera, the temp file is one framelet.
     *   Technically this is the same for the framing, but we
     *   don't know the height of a framelet yet.
     */
    if(cameraType == PushFrame) {
        tempFileLength = numFrameLines;
    }

    /**
     * Start pass 1, use global currImage so that methods called
     *   know the image we're processing.
     */
    for(currImage = 0; currImage < inList.size(); currImage++) {
        /**
         * Read the current cube into memory
         */
        Cube tmp;
        tmp.Open(Filename(inList[currImage]).Expanded());

        /**
         * If we haven't determined how many samples the output
         *   should have, we can do so now
         */
        if(numOutputSamples == 0 && tmp.Bands() == 1) {
            numOutputSamples = tmp.Samples();
        }

        /**
         * Try and validate the image, quick tests first!
         *
         * (imageValid &= means imageValid = imageValid && ...)
         */
        bool imageValid = true;

        // Only single band images are acceptable
        imageValid &= (tmp.Bands() == 1);

        // Sample sizes must always match
        imageValid &= (numOutputSamples == tmp.Samples());

        // For push frame cameras, there must be valid all framelets
        if(cameraType == PushFrame) {
            imageValid &=  (tmp.Lines() % numFrameLines == 0);
        }

        // For framing cameras, we need to figure out the size...
        //    setTempFileLength is used to revert if the file
        //    is decided to be invalid
        bool setTempFileLength = false;
        if(cameraType == Framing) {
            if(tempFileLength == 0 && imageValid) {
                tempFileLength = tmp.Lines();
                numFrameLines = tempFileLength;
                setTempFileLength = true;
            }

            imageValid &= (tempFileLength == tmp.Lines());
        }

        // Statistics are necessary at this point for push frame and framing cameras
        //   because the framing camera standard deviation tolerance is based on
        //   entire images, and push frame framelet exclusion stats can not be collected
        //   during pass 2 cleanly
        if((cameraType == Framing || cameraType == PushFrame) && imageValid) {
            string prog = "Calculating Standard Deviation " + iString((int)currImage+1) + "/";
            prog += iString((int)inList.size()) + " (" + Filename(inList[currImage]).Name() + ")";

            if(cameraType == Framing) {
                Statistics *stats = tmp.Statistics(1, prog);
                imageValid &= !IsSpecial(stats->StandardDeviation());
                imageValid &= !IsSpecial(stats->Average());
                imageValid &= stats->StandardDeviation() <= maxStdev;

                vector<double> fileStats;
                fileStats.push_back(stats->Average());
                inputFrameletAverages.push_back(fileStats);

                delete stats;
            }
            else if(cameraType == PushFrame) {
                imageValid &= CheckFramelets(prog, tmp);
            }

            if(setTempFileLength && !imageValid) {
                tempFileLength = 0;
            }
        }

        // The line scan camera needs to actually count the number of lines in each image to know
        //   how many total frames there are before beginning pass 2.
        if(imageValid && (cameraType == LineScan)) {
            int lines = (tmp.Lines() / numFrameLines);

            // partial frame?
            if(tmp.Lines() % numFrameLines != 0) {
                lines ++;
            }

            tempFileLength += lines;
        }
        else if(!imageValid) {
            excludedFiles.insert(pair<int, bool>(currImage, true));
        }

        tmp.Close();

        if(cameraType == LineScan) {
            progress.CheckStatus();
        }
    }

    /**
     * If the number of output samples could not be determined, we never
     *   found a legitimate cube.
     */
    if(numOutputSamples <= 0) {
        string msg = "No valid input cubes were found";
        throw iException::Message(iException::User,msg,_FILEINFO_);
    }

    /**
     * If theres no temp file length, which is based off of valid data in
     *   the input cubes, then we havent found any valid data.
     */
    if(tempFileLength <= 0) {
        string msg = "No valid input data was found";
        throw iException::Message(iException::User,msg,_FILEINFO_);
    }

    /**
     * ocube is now the temporary file (for pass 2).
     */
    ocube = new Cube();
    ocube->SetDimensions(numOutputSamples, tempFileLength, 2);
    PvlGroup &prefs = Preference::Preferences().FindGroup("DataDirectory", Pvl::Traverse);
    iString outTmpName = (string)prefs["Temporary"][0] + "/";
    outTmpName += Filename(ui.GetFilename("TO")).Basename() + ".tmp.cub";
    ocube->Create(outTmpName);
    oLineMgr = new LineManager(*ocube);
    oLineMgr->SetLine(1);

    ProcessByBrick p;
    int excludedCnt = 0;

    if(cameraType == LineScan) {
        outputTmpAverages.resize(numOutputSamples);
        outputTmpCounts.resize(numOutputSamples);
        numInputDns.resize(numOutputSamples);
    }

    cubeInitialized = false;
    for(currImage = 0; currImage < inList.size(); currImage++) {
        if(Excluded(currImage)) {
            excludedCnt ++;
            continue;
        }

        PvlObject currFile("Exclusions");
        currFile += PvlKeyword("Filename", inList[currImage]);
        currFile += PvlKeyword("Tolerance", maxStdev);

        if(cameraType == LineScan) {
            currFile += PvlKeyword("FrameLines", numFrameLines);
        }
        else if(cameraType == PushFrame) {
            currFile += PvlKeyword("FrameletLines", numFrameLines);
        }

        excludedDetails.push_back(currFile);

        CubeAttributeInput inAtt;

        // This needs to be set constantly because ClearInputCubes
        //   seems to be removing the input brick size.
        if(cameraType == LineScan) {
            p.SetBrickSize(1, numFrameLines, 1);
        }
        else if(cameraType == Framing || cameraType == PushFrame) {
            p.SetBrickSize(numOutputSamples, 1, 1);
        }

        p.SetInputCube(inList[currImage], inAtt);
        iString progText = "Calculating Averages " + iString((int)currImage+1);
        progText += "/" + iString((int)inList.size());
        progText += " (" + Filename(inList[currImage]).Name() + ")";
        p.Progress()->SetText(progText);

        p.StartProcess(CreateTemporaryData);
        p.EndProcess();
        p.ClearInputCubes();

        if(excludedDetails[excludedDetails.size()-1].Groups() == 0) {
            excludedDetails.resize(excludedDetails.size()-1);
        }
    }

    /**
     * Pass 2 completed. The processing methods were responsible for writing
     * the entire temporary cube.
     */
    if(oLineMgr) {
        delete oLineMgr;
        oLineMgr = NULL;
    }

    if(ocube) {
        ocube->Close();
        delete ocube;
    }

    /**
     * ocube is now the final output
     */
    ocube = new Cube();

    if(cameraType == LineScan) {
        ocube->SetDimensions(numOutputSamples, 1, 1);
    }
    else if(cameraType == Framing || cameraType == PushFrame) {
        ocube->SetDimensions(numOutputSamples, tempFileLength, 1);
    }

    ocube->Create(Filename(ui.GetFilename("TO")).Expanded());
    oLineMgr = new LineManager(*ocube);
    oLineMgr->SetLine(1);

    // We now have the necessary temp file, let's go ahead and combine it into
    //   the final output!
    p.SetInputBrickSize(numOutputSamples, 1, 2);
    p.SetOutputBrickSize(numOutputSamples, 1, 1);

    cubeInitialized = false;
    CubeAttributeInput inAtt;
    p.Progress()->SetText("Calculating Final Flat Field");
    p.SetInputCube(outTmpName, inAtt);
    p.StartProcess(ProcessTemporaryData);
    p.EndProcess();

    if(cameraType == LineScan) {
        ocube->Write(*oLineMgr);
    }

    if(oLineMgr) {
        delete oLineMgr;
        oLineMgr = NULL;
    }

    if(ocube) {
        ocube->Close();
        delete ocube;
        ocube = NULL;
    }

    /**
     * Build a list of excluded files
     */
    PvlGroup excludedFiles("ExcludedFiles");
    for(currImage = 0; currImage < inList.size(); currImage++) {
        if(Excluded(currImage)) {
            excludedFiles += PvlKeyword("File", inList[currImage]);
        }
    }

    // log the results
    Application::Log(excludedFiles);

    if(ui.WasEntered("EXCLUDE")) {
        Pvl excludeFile;

        // Find excluded files
        excludeFile.AddGroup(excludedFiles);

        for(unsigned int i = 0; i < excludedDetails.size(); i++) {
            excludeFile.AddObject(excludedDetails[i]);
        }

        excludeFile.Write(Filename(ui.GetFilename("EXCLUDE")).Expanded());
    }

    remove(outTmpName.c_str());

    // Clean up settings
    ResetGlobals();
}
예제 #11
0
파일: caminfo.cpp 프로젝트: corburn/ISIS
void IsisMain() {
  const QString caminfo_program  = "caminfo";
  UserInterface &ui = Application::GetUserInterface();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}
예제 #12
0
파일: pointreg.cpp 프로젝트: assutech/isis3
void IsisMain() {
  // Get user interface
  UserInterface &ui = Application::GetUserInterface();

  bool register_ignored = ui.GetBoolean("REGISTERIGNOREDONLY");

  // Open the files list in a SerialNumberList for
  // reference by SerialNumber
  SerialNumberList files(ui.GetFilename("FILES"));

  // Create a ControlNet from the input file
  ControlNet inNet(ui.GetFilename("CNET"));

  // Create an AutoReg from the template file
  Pvl pvl(ui.GetFilename("TEMPLATE"));
  AutoReg *ar = AutoRegFactory::Create(pvl);

  // Create the output ControlNet
  ControlNet outNet;
  outNet.SetType(inNet.Type());
  outNet.SetUserName(Application::UserName());
  outNet.SetDescription(inNet.Description());
  outNet.SetCreatedDate(iTime::CurrentLocalTime());
  outNet.SetTarget(inNet.Target());
  outNet.SetNetworkId(inNet.NetworkId());

  Progress progress;
  progress.SetMaximumSteps(inNet.Size());
  progress.CheckStatus();

  int ignored=0, unmeasured=0, registered=0, unregistered=0, validated=0;

  CubeManager cubeMgr;
  cubeMgr.SetNumOpenCubes(50);

  // Register the points and create a new
  // ControlNet containing the refined measurements
  for (int i=0; i<inNet.Size(); i++) {
    ControlPoint &inPoint = inNet[i];

    ControlPoint outPoint;
    outPoint.SetType(inPoint.Type());
    outPoint.SetId(inPoint.Id());
    outPoint.SetUniversalGround(inPoint.UniversalLatitude(), inPoint.UniversalLongitude(), inPoint.Radius());
    outPoint.SetHeld(inPoint.Held());
    outPoint.SetIgnore(inPoint.Ignore());

    // CHECK TO SEE IF THE CONTROL POINT SHOULD BE REGISTERED

    // "Ignore" point and we are not registering ignored
    if (inPoint.Ignore() && !register_ignored){
      ignored++;
      // add "Ignored" to network only if indicated
      if (ui.GetBoolean("OUTPUTIGNORED")) {
        // only include appropriate control measures
        for (int j = 0; j < inPoint.Size(); j++) {
          if (inPoint[j].IsMeasured()){
            outPoint.Add(inPoint[j]); 
          } 
          else{
            unmeasured++;
            if (ui.GetBoolean("OUTPUTUNMEASURED")){
              outPoint.Add(inPoint[j]); 
            } 
          }
        }
        // only add this point if OUTPUTIGNORED
        outNet.Add(outPoint);
      }
      // go to next control point
      continue;
    }
    // Not "Ignore" point (i.e. "valid") and we are only registering "Ignored"
    else if (!inPoint.Ignore() && register_ignored) {
      // add all "valid" points to network
      // only include appropriate control measures
      for (int j = 0; j < inPoint.Size(); j++) {
        if (inPoint[j].IsMeasured()){
          outPoint.Add(inPoint[j]); 
        } 
        else{
          unmeasured++;
          if (ui.GetBoolean("OUTPUTUNMEASURED")) {
            outPoint.Add(inPoint[j]);
          } 
        }
      }
      // add this point since it is not ignored
      outNet.Add(outPoint);
      // go to next control point
      continue;
    }
    // "Ignore" point or "valid" point to be registered
    else { // if ( (inPoint.Ignore() && register_ignored) || (!inPoint.Ignore() && !register_ignored ) ) {
      if (inPoint.Ignore()) { outPoint.SetIgnore(false); }
      
      ControlMeasure &patternCM = inPoint[inPoint.ReferenceIndex()];
      Cube &patternCube = *cubeMgr.OpenCube(files.Filename(patternCM.CubeSerialNumber()));
      
      ar->PatternChip()->TackCube(patternCM.Sample(), patternCM.Line());
      ar->PatternChip()->Load(patternCube);
      
      if (patternCM.IsValidated()) validated++;
      if (!patternCM.IsMeasured()) continue;
      if(!patternCM.IsReference()) {
        patternCM.SetReference(true);
        patternCM.SetChooserName("Application pointreg");
        patternCM.SetDateTime();
      }
      outPoint.Add(patternCM);
      
      // reset goodMeasureCount for this point before looping measures
      int goodMeasureCount = 0; 
      // Register all the unvalidated measurements
      for (int j = 0; j < inPoint.Size(); j++) {
        // don't register the reference, go to next measure
        if (j == inPoint.ReferenceIndex()){
          if (!inPoint[j].Ignore()) goodMeasureCount++;
          continue;
        }
        // if the measurement is valid, keep it as is and go to next measure
        if (inPoint[j].IsValidated()) {
          validated++;
          outPoint.Add(inPoint[j]);
          if (!inPoint[j].Ignore()) goodMeasureCount++;
          continue;
        }
        // if the point is unmeasured, add to output only if necessary and go to next measure
        if (!inPoint[j].IsMeasured()) {
          unmeasured++;
          if (ui.GetBoolean("OUTPUTUNMEASURED")) {
            outPoint.Add(inPoint[j]);
          }
          continue;
        }
      
        ControlMeasure searchCM = inPoint[j];
      
        // refresh pattern cube pointer to ensure it stays valid
        Cube &patternCube = *cubeMgr.OpenCube(files.Filename(patternCM.CubeSerialNumber()));
        Cube &searchCube = *cubeMgr.OpenCube(files.Filename(searchCM.CubeSerialNumber()));

        ar->SearchChip()->TackCube(searchCM.Sample(), searchCM.Line());
      
        try {
          ar->SearchChip()->Load(searchCube,*(ar->PatternChip()),patternCube);
      
          // If the measurements were correctly registered
          // Write them to the new ControlNet
          AutoReg::RegisterStatus res = ar->Register();
      
          double score1, score2;
          ar->ZScores(score1, score2);
          searchCM.SetZScores(score1, score2);
      
          if(res == AutoReg::Success) {
            registered++;
            searchCM.SetType(ControlMeasure::Automatic);
            searchCM.SetError(searchCM.Sample() - ar->CubeSample(), searchCM.Line() - ar->CubeLine());
            searchCM.SetCoordinate(ar->CubeSample(),ar->CubeLine());
            searchCM.SetGoodnessOfFit(ar->GoodnessOfFit());
            searchCM.SetChooserName("Application pointreg");
            searchCM.SetDateTime();
            searchCM.SetIgnore(false);
            outPoint.Add(searchCM);
            goodMeasureCount++;
          }
          // Else use the original marked as "Estimated"
          else {
            unregistered++;
            searchCM.SetType(ControlMeasure::Estimated);
      
            if(res == AutoReg::FitChipToleranceNotMet) {
              searchCM.SetError(inPoint[j].Sample() - ar->CubeSample(), inPoint[j].Line() - ar->CubeLine());
              searchCM.SetGoodnessOfFit(ar->GoodnessOfFit());
            }
            searchCM.SetChooserName("Application pointreg");
            searchCM.SetDateTime();
            searchCM.SetIgnore(true);
            outPoint.Add(searchCM);
          }
        } catch (iException &e) {
          e.Clear();
          unregistered++;
          searchCM.SetType(ControlMeasure::Estimated);
          searchCM.SetChooserName("Application pointreg");
          searchCM.SetDateTime();
          searchCM.SetIgnore(true);
          outPoint.Add(searchCM);
        }
      }

      // Jeff Anderson put in this test (Dec 2, 2008) to allow for control 
      // points to be good so long as at least two measure could be 
      // registered. When a measure can't be registered to the reference then
      // that measure is set to be ignored where in the past the whole point
      // was ignored
      if (goodMeasureCount < 2) {
        if (!outPoint.Held() && outPoint.Type() != ControlPoint::Ground) {
          outPoint.SetIgnore(true);
        }
      }
      // Otherwise, ignore=false. This is already set at the beginning of the registration process

      // Check to see if the control point has now been assigned
      // to "ignore".  If not, add it to the network. If so, only 
      // add it to the output if the OUTPUTIGNORED parameter is selected
      // 2008-11-14 Jeannie Walldren
      if (!outPoint.Ignore()) {                             
        outNet.Add(outPoint);
      }
      else{                                              
        ignored++;                                   
        if (ui.GetBoolean("OUTPUTIGNORED")) outNet.Add(outPoint);
      }
    }
    progress.CheckStatus();
  }

  // If flatfile was entered, create the flatfile
  // The flatfile is comma seperated and can be imported into an excel
  // spreadsheet
  if (ui.WasEntered("FLATFILE")) {
    string fFile = Filename(ui.GetFilename("FLATFILE")).Expanded();
    ofstream os;
    os.open(fFile.c_str(),ios::out);
    os << "PointId,OriginalMeasurementSample,OriginalMeasurementLine," <<
      "RegisteredMeasurementSample,RegisteredMeasurementLine,SampleDifference," <<
      "LineDifference,ZScoreMin,ZScoreMax,GoodnessOfFit" << endl;
    os << NULL8 << endl;
    for (int i=0; i<outNet.Size(); i++) {
      // get point from output control net and its
      // corresponding point from input control net
      ControlPoint outPoint = outNet[i];
      ControlPoint *inPoint = inNet.Find(outPoint.Id());
      if (outPoint.Ignore()) continue;
      for (int i = 0; i<outPoint.Size();i++) {
        // get measure and find its corresponding measure from input net
        ControlMeasure cmTrans = outPoint[i];
        ControlMeasure cmOrig = (*inPoint)[cmTrans.CubeSerialNumber()];
        double inSamp = cmOrig.Sample();
        double inLine = cmOrig.Line();
        double outSamp = cmTrans.Sample();
        double outLine = cmTrans.Line();
        double sampErr = cmTrans.SampleError();
        double lineErr = cmTrans.LineError();
        double zScoreMin = cmTrans.GetZScoreMin();
        if (fabs(zScoreMin) <= DBL_EPSILON || zScoreMin == NULL8) zScoreMin = 0;
        double zScoreMax = cmTrans.GetZScoreMax();
        if (fabs(zScoreMax) <= DBL_EPSILON || zScoreMax == NULL8) zScoreMax = 0;
        double goodnessOfFit = cmTrans.GoodnessOfFit();
        if (fabs(goodnessOfFit) <= DBL_EPSILON || goodnessOfFit == NULL8) goodnessOfFit = 0;
        string pointId = outPoint.Id();
        
        os << pointId << "," << inSamp << ","
           << inLine << "," << outSamp << ","
           << outLine << "," << sampErr << "," 
           << lineErr << "," << zScoreMin << ","
           << zScoreMax << "," << goodnessOfFit << endl;
      }
    }
  }

  PvlGroup pLog("Points");
  pLog+=PvlKeyword("Ignored", ignored);
  Application::Log(pLog);

  PvlGroup mLog("Measures");
  mLog+=PvlKeyword("Validated", validated);
  mLog+=PvlKeyword("Registered", registered);
  mLog+=PvlKeyword("Unregistered", unregistered);
  mLog+=PvlKeyword("Unmeasured", unmeasured);
  Application::Log(mLog);

  // Log Registration Statistics
  Pvl arPvl = ar->RegistrationStatistics();

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

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

  outNet.Write(ui.GetFilename("TO"));

  delete ar;
}
예제 #13
0
파일: smtk.cpp 프로젝트: corburn/ISIS
/** The ISIS smtk main application */
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();

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

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

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

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

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

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

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

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

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

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

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

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

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

    gstack.reserve(cnet.GetNumPoints());

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  }

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

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

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

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

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

    SmtkQStackIter cstack = matcher.FindSmallestEV(gstack);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      prog.CheckStatus();
    }

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

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

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


    p.EndProcess();
  }

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

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

  Application::Log(totalPointsPvl);

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

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

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

  // Don't need the cubes opened anymore
  lhImage.close();
  rhImage.close();
}
예제 #14
0
// Main program
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();

  if( !ui.WasEntered("FROMLIST") && ui.WasEntered("TOLIST") ) {
    std::string msg = "To create a [TOLIST] the [FROMLIST] parameter must be provided.";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  // Gets the input parameters
  ControlNet outNet( ui.GetFilename("CNET") );
  FileList inList;
  if( ui.WasEntered("FROMLIST") ) {
    inList = ui.GetFilename("FROMLIST");
  }

  bool noIgnore          = ui.GetBoolean("NOIGNORE");
  bool noHeld            = ui.GetBoolean("NOHELD");
  bool noSingleMeasure   = ui.GetBoolean("NOSINGLEMEASURES");
  bool noMeasureless     = ui.GetBoolean("NOMEASURELESS");
  bool noTolerancePoints = ui.GetBoolean("TOLERANCE");
  bool reference         = ui.GetBoolean("REFERENCE");
  bool ground            = ui.GetBoolean("GROUND");
  bool cubePoints        = ui.WasEntered("CUBEPOINTS");
  bool cubeMeasures      = ui.GetBoolean("CUBEMEASURES");
  bool pointsEntered     = ui.WasEntered("POINTLIST");
  bool latLon            = ui.GetBoolean("LATLON");

  if( !(noIgnore || noHeld || noSingleMeasure || noMeasureless || noTolerancePoints ||
        reference || ground || cubePoints || pointsEntered || latLon) ) {
    std::string msg = "At least one filter must be selected [";
    msg += "NOIGNORE,NOHELD,NOSINGLEMEASURE,TOLERANCE,REFERENCE,GROUND,CUBEPOINTS,";
    msg += "CUBEMEASURES,POINTLIST,LATLON]";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }
  else if( cubeMeasures  &&  !cubePoints ) {
    std::string msg = "When CUBEMEASURES is selected, CUBEPOINTS must be given";
    msg += " a list of cubes.";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  // Set up the Serial Number to Filename mapping
  map<iString,iString> sn2filename;
  for( int cubeIndex=0; cubeIndex < (int)inList.size(); cubeIndex ++ ) {
    iString sn = SerialNumber::Compose( inList[cubeIndex] );
    sn2filename[sn] = inList[cubeIndex];
  }


  Progress progress;
  progress.SetMaximumSteps(outNet.Size());
  progress.CheckStatus();

  // Set up verctor records of how points/measures are removed
  PvlKeyword ignoredPoints( "IgnoredPoints" );
  PvlKeyword ignoredMeasures( "IgnoredMeasures" );
  PvlKeyword heldPoints( "HeldPoints" );
  PvlKeyword singleMeasurePoints( "SingleMeasurePoints" );
  PvlKeyword measurelessPoints( "MeasurelessPoints" );
  PvlKeyword tolerancePoints( "TolerancePoints" );
  PvlKeyword nonReferenceMeasures( "NonReferenseMeasures" );
  PvlKeyword nonGroundPoints( "NonGroundPoints" );
  PvlKeyword nonCubePoints( "NonCubePoints" );
  PvlKeyword nonCubeMeasures( "NonCubeMeasures" );
  PvlKeyword noMeasurePoints( "NoMeasurePoints" );
  PvlKeyword nonListedPoints( "NonListedPoints" );
  PvlKeyword nonLatLonPoints( "LatLonOutOfRangePoints" );
  PvlKeyword cannotGenerateLatLonPoints( "NoLatLonPoints" );

  // Set up comparison data
  vector<iString> serialNumbers;
  if( cubePoints ) {
    FileList cubeList( ui.GetFilename("CUBEPOINTS") );
    for( int cubeIndex=0; cubeIndex < (int)cubeList.size(); cubeIndex ++ ) {
      iString sn = SerialNumber::Compose( cubeList[cubeIndex] );
      serialNumbers.push_back( sn );
    }
  }

  double tolerance = 0.0;
  if( noTolerancePoints ) {
    tolerance = ui.GetDouble("PIXELTOLERANCE");
  }

  // Set up extracted network values
  if( ui.WasEntered("NETWORKID") )
    outNet.SetNetworkId( ui.GetString("NETWORKID") );

  outNet.SetUserName( Isis::Application::UserName() );
  outNet.SetDescription( ui.GetString("DESCRIPTION") );


  for(int cp=outNet.Size()-1; cp >= 0; cp --) {
    progress.CheckStatus();

    // Do preliminary exclusion checks
    if( noIgnore && outNet[cp].Ignore() ) {
      ignoredPoints += outNet[cp].Id();
      outNet.Delete(cp);
      continue;
    }
    if( noHeld && outNet[cp].Held() ) {
      heldPoints += outNet[cp].Id();
      outNet.Delete(cp);
      continue;
    }
    if( ground && !(outNet[cp].Type() == ControlPoint::Ground) ) {
      nonGroundPoints += outNet[cp].Id();
      outNet.Delete(cp);
      continue;
    }

    if( noSingleMeasure ) {
      bool invalidPoint = false;
      invalidPoint |= noIgnore && (outNet[cp].NumValidMeasures() < 2);
      invalidPoint |= outNet[cp].Size() < 2 && (outNet[cp].Type() != ControlPoint::Ground);

      if( invalidPoint ) {
        singleMeasurePoints += outNet[cp].Id();
        outNet.Delete(cp);
        continue;
      }
    }

    // Change the current point into a new point by manipulation of its control measures
    ControlPoint & newPoint = outNet[cp];

    for( int cm = newPoint.Size()-1; cm >= 0; cm --) {
      if(noIgnore && newPoint[cm].Ignore()) {
        ignoredMeasures += "(" + newPoint.Id() + "," + newPoint[cm].CubeSerialNumber() + ")";
        newPoint.Delete( cm );
      }
      else if( reference && !newPoint[cm].IsReference() ) {
        nonReferenceMeasures += "(" + newPoint.Id() + "," + newPoint[cm].CubeSerialNumber() + ")";
        newPoint.Delete( cm );
      }
      else if( cubeMeasures ) {
        bool hasSerialNumber = false;

        for( unsigned int sn = 0; sn < serialNumbers.size() && !hasSerialNumber; sn ++) {
          if(serialNumbers[sn] == newPoint[cm].CubeSerialNumber()) hasSerialNumber = true;
        }

        if( !hasSerialNumber ) { 
          nonCubeMeasures += "(" + newPoint.Id() + "," + newPoint[cm].CubeSerialNumber() + ")";
          newPoint.Delete( cm );
        }
      }
    }

    // Check for line/sample errors above provided tolerance
    if( noTolerancePoints ) {
      bool hasLowTolerance = true;

      for( int cm = 0; cm < newPoint.Size() && hasLowTolerance; cm ++ ) {
        if( newPoint[cm].SampleError() >= tolerance ||
            newPoint[cm].LineError() >= tolerance ) {
          hasLowTolerance = false;
        }
      }

      if( hasLowTolerance ) {
        tolerancePoints += newPoint.Id();
        outNet.Delete(cp);
        continue;
      }
    }

    // Do not add outPoint if it has too few measures
    if( noSingleMeasure ) {
      bool invalidPoint = false;
      invalidPoint |= noIgnore && (newPoint.NumValidMeasures() < 2);
      invalidPoint |= newPoint.Size() < 2 && newPoint.Type() != ControlPoint::Ground;

      if( invalidPoint ) {
        singleMeasurePoints += outNet[cp].Id();
        outNet.Delete(cp);
        continue;
      }
    }

    // Do not add outPoint if it does not have a cube in CUBEPOINTS as asked
    if( cubePoints && !cubeMeasures ) {
      bool hasSerialNumber = false;

      for( int cm = 0; cm < newPoint.Size() && !hasSerialNumber; cm ++) {
        for( unsigned int sn = 0; sn < serialNumbers.size() && !hasSerialNumber; sn ++) {
          if(serialNumbers[sn] == newPoint[cm].CubeSerialNumber()) hasSerialNumber = true;
        }
      }

      if( !hasSerialNumber ) {
        nonCubePoints += newPoint.Id();
        outNet.Delete(cp);
        continue;
      }
    }

    if( noMeasureless && newPoint.Size() == 0 ) {
      noMeasurePoints += newPoint.Id();
      outNet.Delete(cp);
      continue;
    }
  } //! Finished with simple comparisons


  /**
   * Use another pass to check for Ids
   */
  if( pointsEntered ) {
    ExtractPointList( outNet, nonListedPoints );
  }


  /** 
   *  Use another pass on outNet, because this is by far the most time consuming
   *  process, and time could be saved by using the reduced size of outNet
   */
  if( latLon ) {
    ExtractLatLonRange( outNet, nonLatLonPoints, cannotGenerateLatLonPoints, sn2filename );
  }


  // Write the filenames associated with outNet
  WriteCubeOutList( outNet, sn2filename );

  Progress outProgress;
  outProgress.SetText("Writing Control Network");
  outProgress.SetMaximumSteps( 5 );
  outProgress.CheckStatus();

  // Create the points included file
  PvlGroup included("NewControlNet");
  included.AddKeyword( PvlKeyword( "Size", outNet.Size() ) );
  PvlKeyword newPoints( "Points" );
  for( int cp = 0; cp < outNet.Size(); cp ++ ) {
    newPoints.AddValue( outNet[cp].Id() );
  }
  included.AddKeyword( newPoints );

  outProgress.CheckStatus();

  // Write the extracted Control Network
  outNet.Write( ui.GetFilename("OUTNET") );

  outProgress.CheckStatus();

  // Adds the remove history to the summary and results group
  PvlGroup summary("ResultSummary");
  PvlGroup results("Results");

  if( noIgnore ) {
    summary.AddKeyword( PvlKeyword( "IgnoredPoints", ignoredPoints.Size() ) ); 
    results.AddKeyword( ignoredPoints );
    summary.AddKeyword( PvlKeyword( "IgnoredMeasures", ignoredMeasures.Size() ) ); 
    results.AddKeyword( ignoredMeasures );
  }
  if( noHeld ) {
    summary.AddKeyword( PvlKeyword( "HeldPoints", heldPoints.Size() ) ); 
    results.AddKeyword( heldPoints );
  }
  if( noSingleMeasure ) {
    summary.AddKeyword( PvlKeyword( "SingleMeasurePoints", singleMeasurePoints.Size() ) ); 
    results.AddKeyword( singleMeasurePoints );
  }
  if( noMeasureless ) {
    summary.AddKeyword( PvlKeyword( "MeasurelessPoints", measurelessPoints.Size() ) ); 
    results.AddKeyword( measurelessPoints );
  }
  if( noTolerancePoints ) {
    summary.AddKeyword( PvlKeyword( "TolerancePoints", tolerancePoints.Size() ) ); 
    results.AddKeyword( tolerancePoints );
  }
  if( reference ) {
    summary.AddKeyword( PvlKeyword( "NonReferenceMeasures", nonReferenceMeasures.Size() ) ); 
    results.AddKeyword( nonReferenceMeasures );
  }
  if( ground ) {
    summary.AddKeyword( PvlKeyword( "NonGroundPoints", nonGroundPoints.Size() ) ); 
    results.AddKeyword( nonGroundPoints );
  }
  if( cubePoints ) {
    summary.AddKeyword( PvlKeyword( "NonCubePoints", nonCubePoints.Size() ) ); 
    results.AddKeyword( nonCubePoints );
  }
  if( noMeasurePoints.Size() != 0 ) {
    summary.AddKeyword( PvlKeyword( "NonCubeMeasure", noMeasurePoints.Size() ) ); 
    results.AddKeyword( noMeasurePoints );
  }
  if( cubeMeasures ) {
    summary.AddKeyword( PvlKeyword( "NoMeasurePoints", nonCubeMeasures.Size() ) ); 
    results.AddKeyword( nonCubeMeasures );
  }
  if( pointsEntered ) {
    summary.AddKeyword( PvlKeyword( "NonListedPoints", nonListedPoints.Size() ) ); 
    results.AddKeyword( nonListedPoints );
  }
  if( latLon ) {
    summary.AddKeyword( PvlKeyword( "LatLonOutOfRange", nonLatLonPoints.Size() ) ); 
    results.AddKeyword( nonLatLonPoints );
    summary.AddKeyword( PvlKeyword( "NoLatLonPoints", cannotGenerateLatLonPoints.Size() ) ); 
    results.AddKeyword( cannotGenerateLatLonPoints );
  }

  outProgress.CheckStatus();
  
  // Log Control Net results
  Application::Log(included);
  Application::Log(summary);
  results.AddComment( "Each keyword represents a filter parameter used." \
                      " Check the documentation for specific keyword descriptions." );
  Application::Log(results);

  outProgress.CheckStatus();
}
예제 #15
0
파일: mosrange.cpp 프로젝트: assutech/isis3
void IsisMain() {
  Process p;

  // Get the list of names of input CCD cubes to stitch together
  FileList flist;
  UserInterface &ui = Application::GetUserInterface();
  flist.Read(ui.GetFilename("FROMLIST"));
  if (flist.size() < 1) {
    string msg = "The list file[" + ui.GetFilename("FROMLIST") +
    " does not contain any filenames";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  string projection("Equirectangular");
  if(ui.WasEntered("MAP")) {
      Pvl mapfile(ui.GetFilename("MAP"));
      projection = (string) mapfile.FindGroup("Mapping")["ProjectionName"];
  }

  if(ui.WasEntered("PROJECTION")) {
      projection = ui.GetString("PROJECTION");
  }

  // Gather other user inputs to projection
  string lattype = ui.GetString("LATTYPE");
  string londir  = ui.GetString("LONDIR");
  string londom  = ui.GetString("LONDOM");
  int digits = ui.GetInteger("PRECISION");

  // Fix them for mapping group
  lattype = (lattype == "PLANETOCENTRIC") ? "Planetocentric" : "Planetographic";
  londir = (londir == "POSITIVEEAST") ? "PositiveEast" : "PositiveWest";

  Progress prog;
  prog.SetMaximumSteps(flist.size());
  prog.CheckStatus();

  Statistics scaleStat;
  Statistics longitudeStat;
  Statistics latitudeStat;
  Statistics equiRadStat;
  Statistics poleRadStat;
  PvlObject fileset("FileSet");

  // Save major equitorial and polar radii for last occuring
  double eqRad; 
  double eq2Rad; 
  double poleRad;

  string target("Unknown");
  for (unsigned int i = 0 ; i < flist.size() ; i++) {
    // Set the input image, get the camera model, and a basic mapping
    // group
    Cube cube;
    cube.Open(flist[i]);

    int lines = cube.Lines();
    int samples = cube.Samples();


    PvlObject fmap("File");
    fmap += PvlKeyword("Name",flist[i]);
    fmap += PvlKeyword("Lines", lines);
    fmap += PvlKeyword("Samples", samples);

    Camera *cam = cube.Camera();
    Pvl mapping;
    cam->BasicMapping(mapping);
    PvlGroup &mapgrp = mapping.FindGroup("Mapping");
    mapgrp.AddKeyword(PvlKeyword("ProjectionName",projection),Pvl::Replace);    
    mapgrp.AddKeyword(PvlKeyword("LatitudeType",lattype),Pvl::Replace);    
    mapgrp.AddKeyword(PvlKeyword("LongitudeDirection",londir),Pvl::Replace);    
    mapgrp.AddKeyword(PvlKeyword("LongitudeDomain",londom),Pvl::Replace);    

    // Get the radii
    double radii[3];
    cam->Radii(radii);

    eqRad   = radii[0] * 1000.0;
    eq2Rad  = radii[1] * 1000.0;
    poleRad = radii[2] * 1000.0;

    target = cam->Target();
    equiRadStat.AddData(&eqRad, 1);
    poleRadStat.AddData(&poleRad, 1);

    // Get resolution
    double lowres = cam->LowestImageResolution();
    double hires = cam->HighestImageResolution();
    scaleStat.AddData(&lowres, 1);
    scaleStat.AddData(&hires, 1);

    double pixres = (lowres+hires)/2.0;
    double scale = Scale(pixres, poleRad, eqRad);
    mapgrp.AddKeyword(PvlKeyword("PixelResolution",pixres),Pvl::Replace);
    mapgrp.AddKeyword(PvlKeyword("Scale",scale,"pixels/degree"),Pvl::Replace);
    mapgrp += PvlKeyword("MinPixelResolution",lowres,"meters");
    mapgrp += PvlKeyword("MaxPixelResolution",hires,"meters");

    // Get the universal ground range
    double minlat,maxlat,minlon,maxlon;
    cam->GroundRange(minlat,maxlat,minlon,maxlon,mapping);
    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);

    fmap.AddGroup(mapgrp);
    fileset.AddObject(fmap);

    longitudeStat.AddData(&minlon, 1);
    longitudeStat.AddData(&maxlon, 1);
    latitudeStat.AddData(&minlat, 1);
    latitudeStat.AddData(&maxlat, 1);

    p.ClearInputCubes();
    prog.CheckStatus();
  }

//  Construct the output mapping group with statistics
  PvlGroup mapping("Mapping");
  double avgPixRes((scaleStat.Minimum()+scaleStat.Maximum())/2.0);
  double avgLat((latitudeStat.Minimum()+latitudeStat.Maximum())/2.0);
  double avgLon((longitudeStat.Minimum()+longitudeStat.Maximum())/2.0);
  double avgEqRad((equiRadStat.Minimum()+equiRadStat.Maximum())/2.0);
  double avgPoleRad((poleRadStat.Minimum()+poleRadStat.Maximum())/2.0);
  double scale  = Scale(avgPixRes, avgPoleRad, avgEqRad);

  mapping += PvlKeyword("ProjectionName",projection);
  mapping += PvlKeyword("TargetName", target);
  mapping += PvlKeyword("EquatorialRadius",eqRad,"meters");
  mapping += PvlKeyword("PolarRadius",poleRad,"meters");
  mapping += PvlKeyword("LatitudeType",lattype);
  mapping += PvlKeyword("LongitudeDirection",londir);
  mapping += PvlKeyword("LongitudeDomain",londom);
  mapping += PvlKeyword("PixelResolution", SetRound(avgPixRes, digits), "meters/pixel");
  mapping += PvlKeyword("Scale", SetRound(scale, digits), "pixels/degree");
  mapping += PvlKeyword("MinPixelResolution",scaleStat.Minimum(),"meters");
  mapping += PvlKeyword("MaxPixelResolution",scaleStat.Maximum(),"meters");
  mapping += PvlKeyword("CenterLongitude", SetRound(avgLon,digits));
  mapping += PvlKeyword("CenterLatitude",  SetRound(avgLat,digits));
  mapping += PvlKeyword("MinimumLatitude", MAX(SetFloor(latitudeStat.Minimum(),digits), -90.0));
  mapping += PvlKeyword("MaximumLatitude", MIN(SetCeil(latitudeStat.Maximum(),digits), 90.0));
  mapping += PvlKeyword("MinimumLongitude",MAX(SetFloor(longitudeStat.Minimum(),digits), -180.0));
  mapping += PvlKeyword("MaximumLongitude",MIN(SetCeil(longitudeStat.Maximum(),digits), 360.0));

  PvlKeyword clat("PreciseCenterLongitude", avgLon);
  clat.AddComment("Actual Parameters without precision applied");
  mapping += clat;
  mapping += PvlKeyword("PreciseCenterLatitude",  avgLat);
  mapping += PvlKeyword("PreciseMinimumLatitude", latitudeStat.Minimum());
  mapping += PvlKeyword("PreciseMaximumLatitude", latitudeStat.Maximum());
  mapping += PvlKeyword("PreciseMinimumLongitude",longitudeStat.Minimum());
  mapping += PvlKeyword("PreciseMaximumLongitude",longitudeStat.Maximum());

  
  Application::GuiLog(mapping);

  // Write the output file if requested
  if (ui.WasEntered("TO")) {
    Pvl temp;
    temp.AddGroup(mapping);
    temp.Write(ui.GetFilename("TO","map"));
  }

  if (ui.WasEntered("LOG")) {
    Pvl temp;
    temp.AddObject(fileset);
    temp.Write(ui.GetFilename("LOG","log"));
  }

  p.EndProcess();
}
예제 #16
0
/**
 * Removes control points not in the lat/lon range provided in the unput 
 * parameters. 
 * 
 * @param outNet The output control net being removed from
 * @param noLanLonPoint The keyword recording all of the control points removed
 *                      due to the provided lat/lon range
 * @param noLanLonPoint The keyword recording all of the control points removed
 *                      due to the inability to calculate the lat/lon for that
 *                      point
 */
void ExtractLatLonRange( ControlNet & outNet, PvlKeyword & nonLatLonPoints,
                         PvlKeyword & cannotGenerateLatLonPoints,  map<iString,iString> sn2filename ) {
  if( outNet.Size() == 0 ) { return; }

  UserInterface &ui = Application::GetUserInterface();

  // Get the lat/lon and fix the range for the internal 0/360
  double minlat = ui.GetDouble("MINLAT");
  double maxlat = ui.GetDouble("MAXLAT");
  double minlon = ui.GetDouble("MINLON");
  if( minlon < 0.0 ) { minlon += 360; }
  double maxlon = ui.GetDouble("MAXLON");
  if( maxlon < 0.0 ) { minlon += 360; }

  bool useNetwork = ui.GetBoolean("USENETWORK");

  Progress progress;
  progress.SetText("Calculating lat/lon");
  progress.SetMaximumSteps(outNet.Size());
  progress.CheckStatus();

  CubeManager manager;
  manager.SetNumOpenCubes( 50 ); //Should keep memory usage to around 1GB

  for( int cp = outNet.Size()-1; cp >= 0; cp --) {
    progress.CheckStatus();

    // If the Contorl Network takes priority, use it
    double pointLat = outNet[cp].UniversalLatitude();
    double pointLon = outNet[cp].UniversalLongitude();
    bool useControlNet = useNetwork && pointLat > -1000 && pointLon > -1000;
    if( outNet[cp].Type() == Isis::ControlPoint::Ground || useControlNet ) {
      if( NotInLatLonRange( outNet[cp].UniversalLatitude(),
                            outNet[cp].UniversalLongitude(),
                            minlat, maxlat, minlon, maxlon ) ) {
        nonLatLonPoints += outNet[cp].Id();
        outNet.Delete( cp );
      }
    }

    /** 
     * If the lat/lon cannot be determined from the point, then we need to calculate
     * lat/lon on our own 
     */
    else if( ui.WasEntered("FROMLIST") ) {

      // Find a cube in the Control Point to get the lat/lon from
      int cm = 0;
      iString sn = "";
      double lat = 0.0;
      double lon = 0.0;
      double radius = 0.0;

      // First check the reference Measure
      if( outNet[cp].HasReference() ) {
        cm = outNet[cp].ReferenceIndex();
        if( !sn2filename[outNet[cp][cm].CubeSerialNumber()].empty() ) {
          sn = outNet[cp][cm].CubeSerialNumber();
        }
      }

      // Search for other Control Measures if needed
      if( sn.empty() ) {
        // Find the Serial Number if it exists
        for( int cm = 0; (cm < outNet[cp].Size()) && sn.empty(); cm ++ ) {
          if( !sn2filename[outNet[cp][cm].CubeSerialNumber()].empty() ) {
            sn = outNet[cp][cm].CubeSerialNumber();
          }
        }
      }

      // Connot fine a cube to get the lat/lon from
      if( sn.empty() ) {
        cannotGenerateLatLonPoints += outNet[cp].Id();
        outNet.Delete( cp );
      }

      // Calculate the lat/lon and check for validity
      else {
        bool remove = false;

        Cube *cube = manager.OpenCube( sn2filename[sn] );
        Camera *camera = cube->Camera();

        if (camera == NULL) {
          try {
            Projection *projection = ProjectionFactory::Create( (*(cube->Label())) );

            if(!projection->SetCoordinate(outNet[cp][cm].Sample(),outNet[cp][cm].Line())) {
              nonLatLonPoints += outNet[cp].Id();
              remove = true;
            }

            lat = projection->Latitude();
            lon = projection->Longitude();
            radius = projection->LocalRadius();

            delete projection;
            projection = NULL;
          } catch ( iException &e ) {
            remove = true;
            e.Clear();
          }
        }
        else {
          if(!camera->SetImage(outNet[cp][cm].Sample(),outNet[cp][cm].Line())) {
            nonLatLonPoints += outNet[cp].Id();
            remove = true;
          }

          lat = camera->UniversalLatitude();
          lon = camera->UniversalLongitude();
          radius = camera->LocalRadius();

          camera = NULL;
        }

        cube = NULL;

        if( remove  ||  NotInLatLonRange( lat, lon, minlat, maxlat, minlon, maxlon ) ) {
          nonLatLonPoints += outNet[cp].Id();
          outNet.Delete( cp );
        }
        else { // Add the reference lat/lon/radius to the Control Point
          outNet[cp].SetUniversalGround( lat, lon, radius );
        }
      }
    }
    else {
      cannotGenerateLatLonPoints += outNet[cp].Id();
      outNet.Delete( cp );
    }

  }

  manager.CleanCubes();
}
예제 #17
0
파일: mdisddr.cpp 프로젝트: corburn/ISIS
void IsisMain() {
  const QString mdisddr_program = "mdisddr";
  const QString mdisddr_version = "1.0";
  const QString mdisddr_revision = "$Revision: 5086 $";
  const QString mdisddr_runtime = Application::DateTime();
  const QString dataSetID = "MESS-E/V/H-MDIS-6-DDR-GEOMDATA-V1.0";

  UserInterface &ui = Application::GetUserInterface();
  FileName input(ui.GetFileName("FROM"));
  QString to("");
  bool toEntered = ui.WasEntered("TO");
  if(toEntered) {
    to = ui.GetAsString("TO");
  }

  QString opath(".");    // Set default to local directory
  if(ui.WasEntered("OPATH")) {
    opath = ui.GetString("OPATH");
  }
  else {
    ui.PutAsString("OPATH", opath);
  }

  //  Generate the image cube that phocube produces for the DDR data
  FileName phoFile = FileName::createTempFile("$TEMPORARY/" + input.baseName() + "_phocube.cub");
  QString pfile = phoFile.expanded();
  QString parameters = "FROM=" + input.expanded() + " TO=" + pfile +
                      " LATITUDE=TRUE LONGITUDE=TRUE PHASE=TRUE EMISSION=TRUE INCIDENCE=TRUE";
  ProgramLauncher::RunIsisProgram("phocube", parameters);

  //  Wrap a try clause so that if anything goes wrong below, we can remove
  //  the phocube file.
  try {
    Pvl phoLabel(pfile);
    BandMap bandmap;
    PvlKeyword bn = phoLabel.findGroup("BandBin", Pvl::Traverse)["Name"];
    for(int i = 0 ; i < bn.size() ; i++) {
      bandmap.add(bn[i], i + 1);
    }

    // Set up the export.  Note that the attributes selects 5 bands from the
    // output of the phocube run.  It doesn't matter at this time which 5
    // bands it is, just so that we have this established so the right labels
    // and file size is created.
    ProcessExportPds processPds;
    (void) processPds.SetInputCube(pfile, CubeAttributeInput("+1-5"));

    //  Due to the nature of the phocube file, we cannot compute a histogram
    //  of the data (it includes lots of data we don't need).  So we will
    //  fix the range to the expected well defined angle ranges.
    double minmin = 0.0;
    double maxmax = 0.0;
    if(ui.GetString("TYPE").compare("AUTOMATIC") == 0) {
      minmin = -360.0;
      maxmax = 360.0;
    }
    else {
      minmin = ui.GetDouble("MIN");
      maxmax = ui.GetDouble("MAX");
    }

    processPds.SetOutputEndian(Isis::Msb);
    processPds.SetExportType(ProcessExportPds::Fixed);
    processPds.SetInputRange(minmin, maxmax);

    // Set the output pixel type and the special pixel values
    processPds.SetOutputType(Real);
    processPds.SetOutputRange(minmin, maxmax);
    processPds.SetOutputNull(NULL4);
    processPds.SetOutputLrs(LOW_REPR_SAT4);
    processPds.SetOutputLis(LOW_INSTR_SAT4);
    processPds.SetOutputHrs(HIGH_REPR_SAT4);
    processPds.SetOutputHis(HIGH_INSTR_SAT4);

    Progress p;
    p.SetText("Modifying Keywords");
    p.SetMaximumSteps(6);
    p.CheckStatus();

    // Get the PDS label from the process
    Pvl &pdsLabel = processPds.StandardPdsLabel(ProcessExportPds::Image);

    // Translate the keywords from the original EDR PDS label that go in
    // this DDR PDS label.  Note that we have to open the original (FROM)
    // cube as the phocube output goes into the specification of the
    // output PDS file (required for 5 band IMAGE object).
    Cube from;
    from.open(input.expanded());
    OriginalLabel origBlob;
    from.read(origBlob);
    Pvl origLabel;
    PvlObject origLabelObj = origBlob.ReturnLabels();
    origLabelObj.setName("OriginalLabelObject");
    origLabel.addObject(origLabelObj);
    p.CheckStatus();

    // Translates the ISIS labels along with the original EDR labels
    origLabel.addObject(*from.label());
    PvlTranslationManager labels(origLabel,
                                 "$messenger/translations/mdisDDRLabel.trn");
    labels.Auto(pdsLabel);
    p.CheckStatus();

    //  Add any new keywords
    QString lnote = "2007-12-20, S. Murchie (JHU/APL); "
                   "2008-01-02, S. Murchie (JHU/APL); "
                   "2008-01-11, J. Ward (GEO)";
    pdsLabel += PvlKeyword("LABEL_REVISION_NOTE", lnote);
    pdsLabel += PvlKeyword("SPACECRAFT_NAME", Quote("MESSENGER"));

    // Fixes bad keywords
    PvlKeyword &data_set_id = pdsLabel.findKeyword("DATA_SET_ID", Pvl::Traverse);
    data_set_id.setValue(dataSetID);
    QString prodid(input.baseName());
    PvlKeyword &product_id = pdsLabel.findKeyword("PRODUCT_ID", Pvl::Traverse);
    if((product_id.size() == 0) || ((product_id.size() > 0) && (product_id[0] == "N/A"))) {
      product_id.setValue(prodid);
    }
    else {
      QString pid = product_id[0];
      pid[0] = 'D';
      pid.remove(QRegExp("_.*"));
      pid.append("_DE_0");
      product_id.setValue(pid);
      prodid = pid;
    }

    // Now we have enough to establish output file name
    if(!toEntered) to = opath + "/" + prodid;
    FileName output(to);
    output = output.addExtension("IMG");
    if(!toEntered) ui.PutFileName("TO", output.expanded());

    PvlKeyword &product_creation_time = pdsLabel.findKeyword("PRODUCT_CREATION_TIME", Pvl::Traverse);
    product_creation_time.setValue(mdisddr_runtime);

    PvlKeyword &software_name = pdsLabel.findKeyword("SOFTWARE_NAME", Pvl::Traverse);
    software_name.setValue(mdisddr_program);

    PvlKeyword &software_version_id = pdsLabel.findKeyword("SOFTWARE_VERSION_ID", Pvl::Traverse);
    software_version_id.setValue(Quote(mdisddr_version));

    PvlKeyword &filter_number = pdsLabel.findKeyword("FILTER_NUMBER", Pvl::Traverse);
    if((filter_number.size() > 0)) {
      filter_number.setValue(Quote(filter_number[0]));
    }


    // Add quotes
    PvlKeyword &data_quality_id = pdsLabel.findKeyword("DATA_QUALITY_ID", Pvl::Traverse);
    data_quality_id.setValue(Quote(data_quality_id));
    PvlKeyword &sequence_name = pdsLabel.findKeyword("SEQUENCE_NAME", Pvl::Traverse);
    sequence_name.setValue(Quote(sequence_name));
    PvlKeyword &start_count = pdsLabel.findKeyword("SPACECRAFT_CLOCK_START_COUNT", Pvl::Traverse);
    start_count.setValue(Quote(start_count));
    PvlKeyword &stop_count = pdsLabel.findKeyword("SPACECRAFT_CLOCK_STOP_COUNT", Pvl::Traverse);
    stop_count.setValue(Quote(stop_count));

    //  For DDRs, the SOURCE_PRODUCT_ID is made up of SPICE kernels.  I need to
    //  go get em.
    Kernels kernels(from);
    QStringList kfiles = kernels.getKernelList();
    PvlKeyword &source_product_id = pdsLabel.findKeyword("SOURCE_PRODUCT_ID", Pvl::Traverse);
    source_product_id.clear();
    for(int i = 0; i < kfiles.size(); i++) {
      FileName kfile(kfiles[i]);
      source_product_id.addValue(Quote(kfile.name()));
    }

    //  Enforce parentheses for scalars
    if(source_product_id.size() == 1)
      source_product_id.setValue('(' + source_product_id[0] + ')');

    // Removes keywords
    PvlObject imageObject(pdsLabel.findObject("IMAGE"));
    if(imageObject.hasKeyword("CENTER_FILTER_WAVELENGTH")) imageObject.deleteKeyword("CENTER_FILTER_WAVELENGTH");
    if(imageObject.hasKeyword("BANDWIDTH")) imageObject.deleteKeyword("BANDWIDTH");
    if(imageObject.hasKeyword("UNIT")) imageObject.deleteKeyword("UNIT");
    if(imageObject.hasKeyword("DARK_STRIP_MEAN")) imageObject.deleteKeyword("DARK_STRIP_MEAN");
    if(imageObject.hasKeyword("OFFSET")) imageObject.deleteKeyword("OFFSET");
    if(imageObject.hasKeyword("SCALING_FACTOR")) imageObject.deleteKeyword("SCALING_FACTOR");
    if(imageObject.hasKeyword("SAMPLE_BIT_MASK")) imageObject.deleteKeyword("SAMPLE_BIT_MASK");

    // Add band names to image object
    PvlKeyword &bandNames = imageObject.findKeyword("FILTER_NAME");
    bandNames.setName("BAND_NAME");
    bandNames.clear();
    bandNames.addValue("Latitude, planetocentric, deg N");
    bandNames.addValue("Longitude, planetocentric, deg E");
    bandNames.addValue("Incidence angle at equipotential surface, deg");
    bandNames.addValue("Emission angle at equipotential surface, deg");
    bandNames.addValue("Phase angle at equipotential surface, deg");
    pdsLabel.deleteObject("IMAGE");
    pdsLabel.addObject(imageObject);

    p.CheckStatus();

    //  Fix all the hosed units upon ingest.  They are illformed.
    FixUnit(pdsLabel, "RETICLE_POINT_RA", "DEG");
    FixUnit(pdsLabel, "RETICLE_POINT_DECLINATION", "DEG");
    FixUnit(pdsLabel, "RETICLE_POINT_LATITUDE", "DEG");
    FixUnit(pdsLabel, "RETICLE_POINT_LONGITUDE", "DEG");

    //  Now address nested keywords in SUBFRAME groups
    for(int i = 1 ; i <= 5 ; i++) {
      QString n(toString(i));
      QString group = "SUBFRAME" + n + "_PARAMETERS";
      if(pdsLabel.hasGroup(group)) {
        PvlGroup &grp = pdsLabel.findGroup(group);
        ValidateUnit(grp.findKeyword("RETICLE_POINT_LATITUDE"), "DEG");
        ValidateUnit(grp.findKeyword("RETICLE_POINT_LONGITUDE"), "DEG");
      }
    }
    p.CheckStatus();


    //  Finally, fix keywords by Quoting missing N/A values
    FixLabels(pdsLabel);
    p.CheckStatus();

    // All done...write result.
    pdsLabel.setFormatTemplate("$messenger/templates/labels/mdisPdsDDR.pft");
    QString ofile(output.expanded());
    ofstream outstream(ofile.toAscii().data());
    processPds.OutputLabel(outstream);

    // Writing out the 5 bands is a bit tricky for this product.  The bands
    // must be ordered in a specific order, but phocube orders them in a
    // different order.  To make this approach work, determine the proper band
    // as ordered in the phocube output and select the desired bands one at a
    // time setting the input cube to the desired band and writing it out by
    // stream.

    //  Write latitude, longitude, incidence, emission, phase bands
    WriteBand(processPds, outstream, pfile, bandmap.get("Latitude"));
    WriteBand(processPds, outstream, pfile, bandmap.get("Longitude"));
    WriteBand(processPds, outstream, pfile, bandmap.get("Incidence Angle"));
    WriteBand(processPds, outstream, pfile, bandmap.get("Emission Angle"));
    WriteBand(processPds, outstream, pfile, bandmap.get("Phase Angle"));
    outstream.close();
    processPds.EndProcess();
    remove(pfile.toAscii().data());
  }
  catch(IException &) {
    remove(pfile.toAscii().data());
    throw;
  }
  catch(...) {
    remove(pfile.toAscii().data());
    throw IException(IException::Unknown, "Unexpected exception caught!",
                     _FILEINFO_);
  }

}
예제 #18
0
// Construct a BLOb to contain the Hirise main line suffix and prefix data
void SaveHiriseAncillaryData (ProcessImportPds &process, Cube *ocube) {

  vector<int> ConvertCalibrationPixels (int samples,
                                        Isis::PixelType pixelType,
                                        unsigned char *data);


  // Setup a Table to hold the main image prefix/suffix data
  TableField gap("GapFlag", TableField::Integer);
  TableField line("LineNumber", TableField::Integer);
  TableField buffer("BufferPixels", TableField::Integer, 12);
  TableField dark("DarkPixels", TableField::Integer, 16);

  TableRecord rec;
  rec += gap;
  rec += line;
  rec += buffer;
  rec += dark;

  Table table("HiRISE Ancillary", rec);
  table.SetAssociation (Table::Lines);

  // Loop through all the prefix and suffix data and construct the table records
  // In the case of HiRISE there is only one band so the outside vector
  // only contains one entry. The inside vector contains nl entries.
  vector<vector<char *> > pre = process.DataPrefix();
  vector<vector<char *> > suf = process.DataSuffix();
  vector<char *> prefix = pre.at(0);
  vector<char *> suffix = suf.at(0);

  Progress progress;
  progress.SetText("Saving ancillary data");
  progress.SetMaximumSteps(prefix.size());
  progress.CheckStatus();

  for (unsigned int l=0; l<prefix.size(); l++) {

    unsigned char *linePrefix = (unsigned char *)(prefix[l]);

    // Pull out the gap byte (in byte 0)
    rec[0] = (int)(linePrefix[0]);

    // Pull out the line number (bytes 3-5 3=MSB, 5=LSB)
    int lineCounter = 0;
    lineCounter += ((int)(linePrefix[3])) << 16;
    lineCounter += ((int)(linePrefix[4])) << 8;
    lineCounter += ((int)(linePrefix[5]));
    rec[1] = lineCounter;

    // Pull the 12 buffer pixels (same type as image data)
    // from the image prefix area
    linePrefix += 6;
    section = 3;
    rec[2] = ConvertCalibrationPixels (12, process.PixelType(),linePrefix);
    linePrefix += 12 * SizeOf(process.PixelType());

    // Pull the 16 dark pixels (same type as image data)
    // from the image suffix area
    unsigned char *lineSuffix = (unsigned char *)(suffix[l]);
    section = 5;
    rec[3] = ConvertCalibrationPixels (16, process.PixelType(),lineSuffix);
    lineSuffix += 16 * SizeOf(process.PixelType());

    // Add this record to the table
    table += rec;

    // Report the progress
    progress.CheckStatus();
  }

  // Add the table to the output cube
  ocube->Write(table);
}
예제 #19
0
void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();
  double  time0,//start time
          time1,//end time
          alti,  //altitude of the spacecraftmore
          fmc,  //forward motion compensation rad/sec
          horV,  //horizontal velocity km/sec
          radV,  //radial velocity km/sec
          rollV,//roll speed in rad/sec
          led;  //line exposure duration in seconds

  Cube  panCube;
  iTime  isisTime;
  QString iStrTEMP;

  int i,j,k,scFrameCode,insCode;

  QString mission;

  SpicePosition *spPos;
  SpiceRotation *spRot;

  //int nlines,nsamples,nbands;

  double deg2rad = acos(-1.0)/180.0;

  ProcessImport jp;
  FileName transFile("$apollo15/translations/apollopantranstable.trn");
  PvlTranslationTable transTable(transFile);
  PvlGroup kernels_pvlG;

  //scFrameCode and insCode from user input
  mission = ui.GetString("MISSION");
  if (mission == "APOLLO12") scFrameCode = -912000;
  if (mission == "APOLLO14") scFrameCode = -914000;
  if (mission == "APOLLO15") scFrameCode = -915000;
  if (mission == "APOLLO16") scFrameCode = -916000;
  if (mission == "APOLLO17") scFrameCode = -917000;

  insCode = scFrameCode - 230;

  try {
    panCube.open(ui.GetFileName("FROM"),"rw");
  }
  catch (IException &e) {
    throw IException(IException::User,
                     "Unable to open the file [" + ui.GetFileName("FROM") + "] as a cube.",
                     _FILEINFO_);
  }

  ////////////////////////////////////////////build the cube header instrament group
  PvlGroup inst_pvlG("Instrument");

  PvlKeyword keyword;

  //four that are the same for every panaramic mission
  keyword.setName("SpacecraftName");
  keyword.setValue(mission);
  inst_pvlG.addKeyword(keyword);

  keyword.setName("InstrumentName");
  keyword.setValue(transTable.Translate("InstrumentName","whatever"));
  inst_pvlG.addKeyword(keyword);

  keyword.setName("InstrumentId");
  keyword.setValue(transTable.Translate("InstrumentId","whatever"));
  inst_pvlG.addKeyword(keyword);

  keyword.setName("TargetName");
  keyword.setValue(transTable.Translate("TargetName","whatever"));
  inst_pvlG.addKeyword(keyword);

  //three that need to be calculated from input values
  horV = ui.GetDouble("VEL_HORIZ");
  radV = ui.GetDouble("VEL_RADIAL");
  alti = ui.GetDouble("CRAFT_ALTITUDE");

  //caculate the LineExposureDuration (led)
  if( ui.WasEntered("V/H_OVERRIDE") )
    fmc = ui.GetDouble("V/H_OVERRIDE")/1000.0;
  else
    //forward motion compensation is directly equivalent to V/H
    fmc = sqrt(horV*horV + radV*radV)/alti;  
  rollV = fmc*ROLLC;  //roll angular velcoity is equal to  V/H * constant    (units rad/sec)
  //led = rad/mm * sec/rad = radians(2.5)/FIDL / rollV    (final units: sec/mm)
  led = (2.5*acos(-1.0)/180.0)/rollV/FIDL;  

  //use led and the number of mm to determine the start and stop times
  isisTime = ui.GetString("GMT");

  //calculate starting and stoping times
  time0 = isisTime.Et() - led*FIDL*21.5;
  time1 = time0 + led*FIDL*43;

  isisTime = time0;
  keyword.setName("StartTime");
  keyword.setValue(iStrTEMP=isisTime.UTC());
  inst_pvlG.addKeyword(keyword);

  isisTime = time1;
  keyword.setName("StopTime");
  keyword.setValue(iStrTEMP=isisTime.UTC());
  inst_pvlG.addKeyword(keyword);

  keyword.setName("LineExposureDuration");
  //converted led to msec/mm--negative sign to account for the anti-parallel time and line axes
  keyword.setValue(iStrTEMP=toString(-led),"sec/mm");  
  inst_pvlG.addKeyword(keyword);

  panCube.putGroup(inst_pvlG);

  ///////////////////////////////////The kernals group
  kernels_pvlG.setName("Kernels");
  kernels_pvlG.clear();

  keyword.setName("NaifFrameCode");
  keyword.setValue(toString(insCode));
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("LeapSecond");
  keyword.setValue( transTable.Translate("LeapSecond","File1") );
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("TargetAttitudeShape");
  keyword.setValue( transTable.Translate("TargetAttitudeShape", "File1") );
  keyword.addValue( transTable.Translate("TargetAttitudeShape", "File2") );
  keyword.addValue( transTable.Translate("TargetAttitudeShape", "File3") );
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("TargetPosition");
  keyword.setValue("Table");
  keyword.addValue( transTable.Translate("TargetPosition", "File1") );
  keyword.addValue( transTable.Translate("TargetPosition", "File2") );
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("ShapeModel");
  keyword.setValue( transTable.Translate("ShapeModel", "File1") );
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("InstrumentPointing");
  keyword.setValue("Table");
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("InstrumentPosition");
  keyword.setValue("Table");
  kernels_pvlG.addKeyword(keyword);

  keyword.setName("InstrumentAddendum");
  keyword.setValue( transTable.Translate("InstrumentAddendum",mission));
  kernels_pvlG.addKeyword(keyword);

  panCube.putGroup(kernels_pvlG);

  //Load all the kernals
  Load_Kernel(kernels_pvlG["TargetPosition"]);
  Load_Kernel(kernels_pvlG["TargetAttitudeShape"]);
  Load_Kernel(kernels_pvlG["LeapSecond"]);

  //////////////////////////////////////////attach a target rotation table
  char frameName[32];
  SpiceInt frameCode;
  SpiceBoolean found;
  //get the framecode from the body code (301=MOON)
  cidfrm_c(301, sizeof(frameName), &frameCode, frameName, &found);  
  if(!found) {
    QString naifTarget = QString("IAU_MOOM");
    namfrm_c(naifTarget.toAscii().data(), &frameCode);
    if(frameCode == 0) {
      QString msg = "Can not find NAIF code for [" + naifTarget + "]";
      throw IException(IException::Io, msg, _FILEINFO_);
    }
  }
  spRot = new SpiceRotation(frameCode);
  //create a table from starttime to endtime (streched by 3%) with NODES entries
  spRot->LoadCache(time0-0.015*(time1-time0), time1+0.015*(time1-time0), NODES);  
  Table tableTargetRot = spRot->Cache("BodyRotation");
  tableTargetRot.Label() += PvlKeyword("Description", "Created by apollopaninit");
  panCube.write(tableTargetRot);


  //////////////////////////////////////////////////attach a sun position table
  spPos = new SpicePosition(10,301);  //Position of the sun (10) WRT to the MOON (301)
  //create a table from starttime to endtime (stretched by 3%) with NODES entries
  spPos->LoadCache(time0-0.015*(time1-time0), time1+0.015*(time1-time0), NODES);  
  Table tableSunPos = spPos->Cache("SunPosition");
  tableSunPos.Label() += PvlKeyword("SpkTableStartTime", toString(time0-0.015*(time1-time0)));
  tableSunPos.Label() += PvlKeyword("SpkTablleEndTime", toString(time1+0.015*(time1-time0)));
  tableSunPos.Label() += PvlKeyword("Description", "Created by apollopaninit");
  panCube.write(tableSunPos);  //attach the table to the cube


  /////////////Finding the principal scan line position and orientation
  //get the radii of the MOON
  SpiceInt tempRadii = 0;
  bodvcd_c(301,"RADII",3,&tempRadii,R_MOON);  //units are km
  double  omega,phi,kappa;

  std::vector<double>  posSel;  //Seleno centric position
  std::vector<double> sunPos;  //sunPosition used to transform to J2000
  std::vector<double> posJ20;  //camera position in J2000
  posSel.resize(3);
  sunPos.resize(3);
  posJ20.resize(3);

  double  temp,
          vel[3] = { 0.0, 0.0, 0.0 },  //the total velocity vector (combined Horizonatal and normal components) 
                   //  in km/sec
          M[3][3] = { { 0.0, 0.0, 0.0 },
                      { 0.0, 0.0, 0.0 },
                      { 0.0, 0.0, 0.0 } },    //rotation matrix
          zDir[] = { 0.0, 0.0, 1.0 },  //selenographic Z axis
          northPN[3]  = { 0.0, 0.0, 0.0 }, //normal to the plane containing all the north/south directions, 
                      //  that is plane containing 
                      //  the origin, the z axis, and the primary point of intersection
          northL[3] = { 0.0, 0.0, 0.0 },    //north direction vector in local horizontal plane
          azm[3] = { 0.0, 0.0, 0.0 },   //azm direction of the veclocity vector in selenographic coordinates
          azmP[3] = { 0.0, 0.0, 0.0 },  //azm rotated (partially) and projected into the image plane
          norm[3] = { 0.0, 0.0, 0.0 },  //normal to the local horizontal plane
          look[3] = { 0.0, 0.0, 0.0 };  //unit direction vector in the pincipal cameral look direction, 
                    //  parallel to the vector from the center of the moon through the spacecraft

  double  pos0[3] = { 0.0, 0.0, 0.0 },  //coordinate of the camera position
          pInt[3] = { 0.0, 0.0, 0.0 };  //coordinate of the principle intersection point

  /////////////////calculating the camera position for the center (principal scan line)
  pos0[1] = ui.GetDouble("LON_NADIR")*deg2rad;
  pos0[0] = ui.GetDouble("LAT_NADIR")*deg2rad;
  pos0[2] = ui.GetDouble("CRAFT_ALTITUDE");  //units are km
  Geographic2GeocentricLunar(pos0,pos0);    //function is written so the input can also be the 
                                            //  output

  /////////////////////calculating the camera orientation for the center (principal) scan line
  pInt[1] = ui.GetDouble("LON_INT")*deg2rad;
  pInt[0] = ui.GetDouble("LAT_INT")*deg2rad;
  pInt[2] = 0.0;
  Geographic2GeocentricLunar(pInt,pInt); //function is written so the input can also be the output
  //calculate the unit look direction vector in object space
  look[0] = -pos0[0] + pInt[0];
  look[1] = -pos0[1] + pInt[1];
  look[2] = -pos0[2] + pInt[2];
  temp = sqrt(look[0]*look[0] + look[1]*look[1] + look[2]*look[2]);
  look[0] /= temp;
  look[1] /= temp;
  look[2] /= temp;
  //the local normal vector is equal to pInt0/|pInt0|
  temp = sqrt(pInt[0]*pInt[0] + pInt[1]*pInt[1] + pInt[2]*pInt[2]);
  norm[0] = pInt[0]/temp;
  norm[1] = pInt[1]/temp;
  norm[2] = pInt[2]/temp;
  //omega and phi are defined so that M(phi)M(omega)look = [0 0 -1]  leaving only the roation 
  //  around z axis to be found
  omega = -atan2(look[1], look[2]);  //omega rotation to zero look[1]
  phi   = atan2(-look[0], sin(omega)*look[1] - cos(omega)*look[2]);  //phi rotation to zero look[0]
  //use the horizontal velocity vector direction to solve for the last rotation; we will make the 
  //  image x axis parallel to the in-image-plane projection of the horizontal direction of flight.
  //  The local normal cross the selenogrpahic z gives northPN (normal to the plane containing all 
  //  the north/south directions), that is, the plane containing the origin, the z axis, and the 
  //  primary point of intersection.
  crossp(northPN,norm,northL);   
  //The normal to the plane containing all the north/south directions cross the local normal 
  //  direction gives the local north/south direction in the local normal plane
  crossp(norm, zDir, northPN); 
  if (northL[2] < 0) {  //if by chance we got the south direction change the signs
    northL[0] = -northL[0];
    northL[1] = -northL[1];
    northL[2] = -northL[2];
  }
  //define the rotation matrix to convert northL to the azimuth of flight.
  //  A left handed rotation of "VEL_AZM" around the positive normal direction will convert northL 
  //  to azm
  MfromVecLeftAngle(M,norm,ui.GetDouble("VEL_AZM")*deg2rad);    
  azm[0] = M[0][0]*northL[0] + M[0][1]*northL[1] + M[0][2]*northL[2];
  azm[1] = M[1][0]*northL[0] + M[1][1]*northL[1] + M[1][2]*northL[2];
  azm[2] = M[2][0]*northL[0] + M[2][1]*northL[1] + M[2][2]*northL[2];
  //apply the two rotations we already know
  MfromLeftEulers(M,omega,phi,0.0);
  azmP[0] = M[0][0]*azm[0] + M[0][1]*azm[1] + M[0][2]*azm[2];
  azmP[1] = M[1][0]*azm[1] + M[1][1]*azm[1] + M[1][2]*azm[2];
  azmP[2] = M[2][0]*azm[2] + M[2][1]*azm[1] + M[2][2]*azm[2];
  //subtract that portion of the azm that is perpindicular to the image plane (also the portion 
  //  which is parallel to look) making azm a vector parrallel to the image plane
  //  Further, since we're now rotated into some coordinate system that differs from 
  //  the image coordinate system by only a kappa rotation making the vector parrallel to the 
  //  image plan is as simple as zeroing the z component (and as pointless to further calculations 
  //  as a nat's fart in hurricane) nevertheless it completes the logical transition
  azmP[2] = 0.0;  

  //finally the kappa rotation that will make azmP parallel (including sign) to the camera x axis                  
  kappa = -atan2(-azmP[1], azmP[0]);  


  ////////////////////Add an instrument position table
  //Define the table records
  TableRecord recordPos;  // reacord to be added to table
  // add x,y,z position labels and ephemeris time et to record
  TableField x("J2000X", TableField::Double);  
  TableField y("J2000Y", TableField::Double);
  TableField z("J2000Z", TableField::Double);
  TableField t("ET", TableField::Double);
  recordPos += x;
  recordPos += y;
  recordPos += z;
  recordPos += t;
  Table tablePos("InstrumentPosition", recordPos);
  //now that the azm and norm vectors are defined 
  //  the total velocity vector can be calcualted (km/sec)
  vel[0] = horV*azm[0] + radV * norm[0];
  vel[1] = horV*azm[1] + radV * norm[1];
  vel[2] = horV*azm[2] + radV * norm[2];
  //we'll provide a two ellement table (more is redundant because the motion is modeled as linear 
  //  at this point)  we'll extend the nodes 3% beyond the edges of the images to be sure 
  //  rounding errors don't cause problems
  temp = 0.515*(time1-time0);  //3% extension
  posSel[0] = pos0[0] - temp*vel[0];    //selenocentric coordinate calculation
  posSel[1] = pos0[1] - temp*vel[1];
  posSel[2] = pos0[2] - temp*vel[2];
  //converting to J2000
  temp = time0 - 0.005*(time1-time0);  //et just before the first scan line
  spPos->SetEphemerisTime(temp);
  spRot->SetEphemerisTime(temp);
  //Despite being labeled as J2000, the coordinates for the instrument position are in fact in 
  //  target centric coordinated rotated to a system centered at the target with aces parallel 
  //  to J2000, whatever that means
  posJ20 = spRot->J2000Vector(posSel); //J2000Vector calls rotates the position vector into J2000,
                                       //  completing the transformation
  recordPos[0] = posJ20[0];
  recordPos[1] = posJ20[1];
  recordPos[2] = posJ20[2];
  recordPos[3] = temp;  //temp = et (right now anyway)
  tablePos += recordPos;
  tablePos.Label() += PvlKeyword("SpkTableStartTime",toString(temp));
  //now the other node
  temp = 0.515*(time1-time0);      //3% extension
  posSel[0] = pos0[0] + temp*vel[0];    //selenocentric coordinate calculation
  posSel[1] = pos0[1] + temp*vel[1];
  posSel[2] = pos0[2] + temp*vel[2];
  //converting to J2000
  temp = time1 + 0.015*(time1-time0);  //et just after the last scan line
  spPos->SetEphemerisTime(temp);
  spRot->SetEphemerisTime(temp);
  //Despite being labeled as J2000, the coordinates for the instrument position are in fact 
  //  in target centric coordinated rotated to a system centered at the target with aces 
  //  parallel to J2000, whatever that means
  posJ20 = spRot->J2000Vector(posSel); //J2000Vector calls rotates the position vector into J2000,
                                       //  completing the transformation
  recordPos[0] = posJ20[0];
  recordPos[1] = posJ20[1];
  recordPos[2] = posJ20[2];
  recordPos[3] = temp;  //temp = et (right now anyway)
  tablePos += recordPos;
  tablePos.Label() += PvlKeyword("SpkTableEndTime",toString(temp));
  tablePos.Label() += PvlKeyword("CacheType","Linear");
  tablePos.Label() += PvlKeyword("Description","Created by apollopaninit");
  panCube.write(tablePos);  //now attach it to the table

  /////////////////////////////attach a camera pointing table
  double  cacheSlope,  //time between epoches in the table
          rollComb,  //magnitude of roll relative to the center in the middle of the epoch
          relT,  //relative time at the center of each epoch
          Q[NODES][5],  //NODES four ellement unit quarternions and et (to be calculated).
          gimVec[3],  //the direction of the gimbal rotation vector (to the cameras persepective 
                      //  this is always changing because the camera is mounted to the roll frame 
                      //  assembly which is mounted to the gimbal)
          M0[3][3],  //rotation matrix of the previous epoch
          Mtemp1[3][3],  //intermediate step in the multiplication of rotation matricies
          Mtemp2[3][3],  //intermediate step in the multiplication of rotation matricies
          Mdg[3][3],  //incremental rotation due the the gimbal motion in the camera frame
          Mdr[3][3];  //the contribution of the roll motion in the camera frame during time 
                      //  cacheSlope
  std::vector <double> M_J2toT;  //rotation matrix from J2000 to the target frame
  M_J2toT.resize(9);
  //Table Definition
  TableField q0("J2000Q0", TableField::Double);
  TableField q1("J2000Q1", TableField::Double);
  TableField q2("J2000Q2", TableField::Double);
  TableField q3("J2000Q3", TableField::Double);
  TableField et("ET", TableField::Double);
  TableRecord recordRot;
  recordRot += q0;
  recordRot += q1;
  recordRot += q2;
  recordRot += q3;
  recordRot += et;
  Table tableRot("InstrumentPointing",recordRot);
  //From the cameras perspective the gimbal motion is around a constantly changing axis, 
  //  this is handled by combining a series of incremental rotations
  MfromLeftEulers(M0, omega, phi, kappa);  //rotation matrix in the center Q[(NOPDES-1)/2]
  spRot->SetEphemerisTime(isisTime.Et());
  M_J2toT = spRot->Matrix();   //this actually gives the rotation from J2000 to target centric
  for(j=0; j<3; j++)    //reformating M_J2toT to a 3x3
    for(k=0; k<3; k++)
      Mtemp1[j][k] = M_J2toT[3*j+k];
  mxm_c(M0, Mtemp1, Mtemp2);
  M2Q(Mtemp2, Q[(NODES-1)/2]);  //save the middle scan line quarternion

  Q[(NODES-1)/2][4] = (time1 + time0)/2.0;  //time in the center of the image
  //the total time is scaled up slightly so that nodes will extend just beyond the edge of the image
  cacheSlope = 1.03*(time1 - time0)/(NODES-1);    
  //Mdr is constant for all the forward time computations
  MfromLeftEulers(Mdr,cacheSlope*rollV,0.0,0.0);  
  for (i=(NODES-1)/2+1; i<NODES; i++) {    //moving foward in time first
    Q[i][4] = Q[i-1][4] + cacheSlope;    //new time epoch
    //epoch center time relative to the center line
    relT = double(i - (NODES-1)/2 - 0.5)*cacheSlope;  
    rollComb = relT*rollV;
    gimVec[0] = 0.0;      //gimbal rotation vector direction in the middle of the epoch
    gimVec[1] =  cos(rollComb);
    gimVec[2] = -sin(rollComb);
    //incremental rotation due to the gimbal (forward motion compensation)
    MfromVecLeftAngle(Mdg, gimVec, fmc*cacheSlope);    
    //the new rotation matrix is Transpose(Mdr)*Transpose(Mdg)*M0--NOTE the order swap and 
    //  transposes are needed because both Mdr and Mdg were caculated in image space and need to be 
    //  transposed to apply to object space
    mtxm_c(Mdg, M0, Mtemp1);  
    //M0 is now what would typically be considered the rotation matrix of an image.  It rotates a 
    //  vector from the target centric space into camera space.  However, what is standard to 
    //  include in the cube labels is a rotation from camera space to J2000.  M0 is therefore the 
    //  transpose of the first part of this rotation.  Transpose(M0) is the rotation from camera 
    //  space to target centric space
    mtxm_c(Mdr, Mtemp1, M0);  
    //now adding the rotation from the target frame to J2000
    spRot->SetEphemerisTime(Q[i][4]);
    //this actually gives the rotation from J2000 to target centric--hence the mxmt_c function being 
    //  used later
    M_J2toT = spRot->Matrix();   
    for(j=0; j<3; j++)  //reformating M_J2toT to a 3x3
      for(k=0; k<3; k++)
        Mtemp1[j][k] = M_J2toT[3*j+k];
    mxm_c(M0, Mtemp1, Mtemp2);
    M2Q(Mtemp2, Q[i]);    //convert to a quarterion
  }

  MfromLeftEulers(M0, omega, phi, kappa);  //rotation matrix in the center Q[(NOPDES-1)/2]
  //Mdr is constant for all the backward time computations
  MfromLeftEulers(Mdr, -cacheSlope*rollV, 0.0, 0.0);    
  for (i=(NODES-1)/2-1; i>=0; i--) {  //moving backward in time
    Q[i][4] = Q[i+1][4] - cacheSlope;  //new time epoch
    //epoch center time relative to the center line
    relT = double(i  - (NODES-1)/2 + 0.5)*cacheSlope;  
    rollComb = relT*rollV;
    gimVec[0] = 0.0;      //gimbal rotation vector direction in the middle of the epoch
    gimVec[1] =  cos(rollComb);
    gimVec[2] = -sin(rollComb);
    //incremental rotation due to the gimbal (forward motion compensation)
    MfromVecLeftAngle(Mdg, gimVec, -fmc*cacheSlope);    
    //the new rotation matrix is Transpose(Mdr)*Transpose(Mdg)*M0    NOTE the order swap and 
    //  transposes are needed because both Mdr and Mdg were caculated in image space and need to be
    //  transposed to apply to object space
    mtxm_c(Mdg, M0, Mtemp1);  
    //M0 is now what would typically be considered the rotation matrix of an image.  It rotates a 
    //  vector from the target centric space into camera space.  However, what is standard to 
    //  include in the cube labels is a rotation from camera space to J2000.  M0 is therefore the 
    //  transpose of the first part of this rotation.  Transpose(M0) is the rotation from camera 
    //  space to target centric space
    mtxm_c(Mdr, Mtemp1, M0);  
    //now adding the rotation from the target frame to J2000
    spRot->SetEphemerisTime(Q[i][4]);
    M_J2toT = spRot->Matrix();
    for(j=0; j<3; j++)  //reformating M_J2toT to a 3x3
      for(k=0; k<3; k++)
        Mtemp1[j][k] = M_J2toT[3*j+k];
    mxm_c(M0, Mtemp1, Mtemp2);
    M2Q(Mtemp2, Q[i]);    //convert to a quarterion
  }
  //fill in the table
  for (i=0; i<NODES; i++) {
    recordRot[0] = Q[i][0];
    recordRot[1] = Q[i][1];
    recordRot[2] = Q[i][2];
    recordRot[3] = Q[i][3];
    recordRot[4] = Q[i][4];
    tableRot += recordRot;
  }
  tableRot.Label() += PvlKeyword("CkTableStartTime", toString(Q[0][4]));
  tableRot.Label() += PvlKeyword("CkTableEndTime", toString(Q[NODES-1][4]));
  tableRot.Label() += PvlKeyword("Description", "Created by appollopan2isis");

  keyword.setName("TimeDependentFrames");
  keyword.setValue(toString(scFrameCode));
  keyword.addValue("1");
  tableRot.Label() += keyword;

  keyword.setName("ConstantFrames");
  keyword.setValue(toString(insCode));
  keyword.addValue(toString(scFrameCode));
  tableRot.Label() += keyword;

  keyword.setName("ConstantRotation");
  keyword.setValue("1");
  for (i=1;i<9;i++)
    if (i%4 == 0) keyword.addValue("1");
    else keyword.addValue("0");
  tableRot.Label() += keyword;
  panCube.write(tableRot);


  /////////////////////////Attach a table with all the measurements of the fiducial mark locations.
  Chip patternS,searchS;   //scaled pattern and search chips
  Cube  fidC;  //Fiducial image

  //line and sample coordinates for looping through the panCube
  double l=1,s=1,sample,line,sampleInitial=1,lineInitial=1,play;  

  int  regStatus,
       fidn,
       panS,
       refL,  //number of lines in the patternS
       refS;  //number of samples in the patternS
  Pvl pvl;

  bool foundFirst=false;

  QString fileName;

  panS = panCube.sampleCount();

  //Table definition
  TableRecord recordFid;
  TableField indexFid("FID_INEX",TableField::Integer);
  TableField xFid("X_COORD",TableField::Double);
  TableField yFid("Y_COORD",TableField::Double);
  recordFid += indexFid;
  recordFid += xFid;
  recordFid += yFid;
  Table tableFid("Fiducial Measurement",recordFid);

  //read the image resolutions and scale the constants acordingly
  double  resolution = ui.GetDouble("MICRONS"),    //pixel size in microns
          scale            = SCALE  *5.0/resolution,  //reduction scale for fast autoregistrations
          searchHeight     = SEARCHh*5.0/resolution,  //number of lines (in 5-micron-pixels) in 
                                                      //  search space for the first fiducial
          searchCellSize   = SEARCHc*5.0/resolution,  //height/width of search chips block
          averageSamples   = AVERs  *5.0/resolution,  //scaled smaples between fiducials
          averageLines     = AVERl  *5.0/resolution;  //scaled average distance between the top and 
                                                      //bottom fiducials

  if( 15.0/resolution < 1.5) play=1.5;
  else play = 15.0/resolution; 

  //copy the patternS chip (the entire ApolloPanFiducialMark.cub)
  FileName fiducialFileName("$apollo15/calibration/ApolloPanFiducialMark.cub");
  fidC.open(fiducialFileName.expanded(),"r");
  if( !fidC.isOpen() ) {
    QString msg = "Unable to open the fiducial patternS cube: ApolloPanFiducialMark.cub\n";
    throw IException(IException::User, msg, _FILEINFO_);
  }
  refL = fidC.lineCount();
  refS = fidC.sampleCount();
  //scaled pattern chip for fast matching
  patternS.SetSize(int((refS-2)/SCALE), int((refL-2)/SCALE));  
  patternS.TackCube((refS-1)/2, (refL-1)/2);
  patternS.Load(fidC, 0, SCALE);

  //parameters for maximum correlation autoregestration  
  // see:  file:///usgs/pkgs/isis3nightly2011-09-21/isis/doc/documents/patternSMatch/patternSMatch.html#DistanceTolerance
  FileName fiducialPvl("$apollo15/templates/apolloPanFiducialFinder.pvl");
  pvl.read(fiducialPvl.expanded());  //read in the autoreg parameters
  AutoReg *arS = AutoRegFactory::Create(pvl);

  *arS->PatternChip()   = patternS;  //patternS chip is constant

  //set up a centroid measurer
  CentroidApolloPan centroid(resolution);
  Chip inputChip,selectionChip;
  inputChip.SetSize(int(ceil(200*5.0/resolution)), int(ceil(200*5.0/resolution)));
  fileName = ui.GetFileName("FROM");
  if( panCube.pixelType() == 1)  //UnsignedByte
    centroid.setDNRange(12, 1e99);  //8 bit bright target
  else
    centroid.setDNRange(3500, 1e99);  //16 bit bright target

  Progress progress;
  progress.SetText("Locating Fiducials");
  progress.SetMaximumSteps(91);

  //Search for the first fiducial, search sizes are constanst
  searchS.SetSize(int(searchCellSize/scale),int(searchCellSize/scale));  
  //now start searching along a horizontal line for the first fiducial mark
  for(l = searchCellSize/2;
      l<searchHeight+searchCellSize/2.0 && !foundFirst;
      l+=searchCellSize-125*5.0/resolution) {
    for (s = searchCellSize/2;
         s < averageSamples + searchCellSize/2.0 && !foundFirst;
         s += searchCellSize-125*5.0/resolution) {
      searchS.TackCube(s, l);
      searchS.Load(panCube, 0, scale);
      *arS->SearchChip() = searchS;
      regStatus = arS->Register();
      if (regStatus == AutoReg::SuccessPixel) {
        inputChip.TackCube(arS->CubeSample(), arS->CubeLine());
        inputChip.Load(panCube, 0, 1);
        inputChip.SetCubePosition(arS->CubeSample(), arS->CubeLine());
        //continuous dynamic range selection
        centroid.selectAdaptive(&inputChip, &selectionChip);    
        //elliptical trimming/smoothing
        if (centroid.elipticalReduction(&selectionChip, 95, play, 2000)) {  
          //center of mass to reduce selection to a single measure
          centroid.centerOfMass(&selectionChip, &sample, &line);    
          inputChip.SetChipPosition(sample, line);
          sampleInitial = inputChip.CubeSample();
          lineInitial   = inputChip.CubeLine();
          foundFirst = true;  //once the first fiducial is found stop
        }
      }
    }
  }
  if(s>=averageLines+searchCellSize/2.0) {
     QString msg = "Unable to locate a fiducial mark in the input cube [" + fileName + 
                  "].  Check FROM and MICRONS parameters.";
     throw IException(IException::Io, msg, _FILEINFO_);
     return;
  }
  progress.CheckStatus();

  //record first fiducial measurement in the table
  recordFid[0] = 0;
  recordFid[1] = sampleInitial;
  recordFid[2] = lineInitial;
  tableFid += recordFid;
  for (s= sampleInitial, l=lineInitial, fidn=0;  s<panS;  s+=averageSamples, fidn++) {
     //corrections for half spacing of center fiducials
     if (fidn == 22) s -= averageSamples/2.0;
     if (fidn == 23) s -= averageSamples/2.0;

     //look for the bottom fiducial
     searchS.TackCube(s,l+averageLines);
     searchS.Load(panCube, 0, scale);
     *arS->SearchChip()   = searchS;
     regStatus = arS->Register();
     if (regStatus == AutoReg::SuccessPixel) {
       inputChip.TackCube(arS->CubeSample(), arS->CubeLine());
       inputChip.Load(panCube,0,1);
       inputChip.SetCubePosition(arS->CubeSample(), arS->CubeLine());
     }
     else {  //if autoreg is unsuccessful, a larger window will be used
       inputChip.TackCube(s, l+averageLines);
       inputChip.Load(panCube, 0, 1);
       inputChip.SetCubePosition(s, l+averageLines);
     }
     centroid.selectAdaptive(&inputChip, &selectionChip);  //continuous dynamic range selection
     //elliptical trimming/smoothing... if this fails move on
     if (centroid.elipticalReduction(&selectionChip, 95, play, 2000) != 0 ) {      
       //center of mass to reduce selection to a single measure
       centroid.centerOfMass(&selectionChip, &sample, &line);      
       inputChip.SetChipPosition(sample, line);
       sample = inputChip.CubeSample();
       line   = inputChip.CubeLine();
       recordFid[0] = fidn*2+1;
       recordFid[1] = sample;
       recordFid[2] = line;
       tableFid += recordFid;
     }
     progress.CheckStatus();

     //look for the top fiducial
     if (s == sampleInitial) //first time through the loop?
       continue;  //then the top fiducial was already found
     searchS.TackCube(s, l);
     searchS.Load(panCube, 0, scale);
     *arS->SearchChip()   = searchS;
     regStatus = arS->Register();
     if (regStatus == AutoReg::SuccessPixel) {
       inputChip.TackCube(arS->CubeSample(), arS->CubeLine());
       inputChip.Load(panCube, 0, 1);
       inputChip.SetCubePosition(arS->CubeSample(), arS->CubeLine());
     }
     else {  //if autoreg is unsuccessful, a larger window will be used
       inputChip.TackCube(s, l);
       inputChip.Load(panCube, 0, 1);
       inputChip.SetCubePosition(s, l);
     }
     centroid.selectAdaptive(&inputChip, &selectionChip);//continuous dynamic range selection
     //inputChip.Write("inputTemp.cub");//debug
     //selectionChip.Write("selectionTemp.cub");//debug
     //elliptical trimming/smoothing... if this fails move on
     if (centroid.elipticalReduction(&selectionChip, 95, play, 2000) !=0) {    
       //center of mass to reduce selection to a single measure
       centroid.centerOfMass(&selectionChip, &sample, &line);  
       inputChip.SetChipPosition(sample, line);
       //when finding the top fiducial both s and l are refined for a successful measurement, 
       //  this will help follow trends in the scaned image
       s = inputChip.CubeSample(); 
       l = inputChip.CubeLine();
       recordFid[0] = fidn*2;
       recordFid[1] = s;
       recordFid[2] = l;
       tableFid += recordFid;
     }
     progress.CheckStatus();
  }

  panCube.write(tableFid);
  //close the new cube
  panCube.close(false);
  panCube.open(ui.GetFileName("FROM"),"rw");
 
  delete spPos;
  delete spRot;

  //now instantiate a camera to make sure all of this is working
  ApolloPanoramicCamera* cam = (ApolloPanoramicCamera*)(panCube.camera());
  //log the residual report from interior orientation 
  PvlGroup residualStats("InteriorOrientationStats");
  residualStats += PvlKeyword("FiducialsFound",  toString(tableFid.Records()));
  residualStats += PvlKeyword("ResidualMax",  toString(cam->intOriResidualMax()),"pixels");
  residualStats += PvlKeyword("ResidualMean", toString(cam->intOriResidualMean()),"pixels");
  residualStats += PvlKeyword("ResidualStdev", toString(cam->intOriResidualStdev()),"pixels");

  Application::Log( residualStats ); 


  return;
}