void IsisMain() { // Create a serial number list UserInterface &ui = Application::GetUserInterface(); QString filename = ui.GetFileName("FROM"); SerialNumberList serialNumberList; serialNumberList.Add(filename); // Get the coordinate for updating the camera pointing // We will want to make the camera pointing match the lat/lon at this // line sample double samp1 = ui.GetDouble("SAMP1"); double line1 = ui.GetDouble("LINE1"); Latitude lat1(ui.GetDouble("LAT1"), Angle::Degrees); Longitude lon1(ui.GetDouble("LON1"), Angle::Degrees); Distance rad1; if(ui.WasEntered("RAD1")) { rad1 = Distance(ui.GetDouble("RAD1"), Distance::Meters); } else { rad1 = GetRadius(ui.GetFileName("FROM"), lat1, lon1); } // In order to use the bundle adjustment class we will need a control // network ControlMeasure * m = new ControlMeasure; m->SetCubeSerialNumber(serialNumberList.SerialNumber(0)); m->SetCoordinate(samp1, line1); // m->SetType(ControlMeasure::Manual); m->SetType(ControlMeasure::RegisteredPixel); ControlPoint * p = new ControlPoint; p->SetAprioriSurfacePoint(SurfacePoint(lat1, lon1, rad1)); p->SetId("Point1"); p->SetType(ControlPoint::Fixed); p->Add(m); ControlNet cnet; // cnet.SetType(ControlNet::ImageToGround); cnet.AddPoint(p); // We need the target body Cube c; c.open(filename, "rw"); //check for target name if(c.label()->hasKeyword("TargetName", PvlObject::Traverse)) { // c.Label()->findKeyword("TargetName"); PvlGroup inst = c.label()->findGroup("Instrument", PvlObject::Traverse); QString targetName = inst["TargetName"]; cnet.SetTarget(targetName); } c.close(); // See if they wanted to solve for twist if(ui.GetBoolean("TWIST")) { double samp2 = ui.GetDouble("SAMP2"); double line2 = ui.GetDouble("LINE2"); Latitude lat2(ui.GetDouble("LAT2"), Angle::Degrees); Longitude lon2(ui.GetDouble("LON2"), Angle::Degrees); Distance rad2; if(ui.WasEntered("RAD2")) { rad2 = Distance(ui.GetDouble("RAD2"), Distance::Meters); } else { rad2 = GetRadius(ui.GetFileName("FROM"), lat2, lon2); } ControlMeasure * m = new ControlMeasure; m->SetCubeSerialNumber(serialNumberList.SerialNumber(0)); m->SetCoordinate(samp2, line2); m->SetType(ControlMeasure::Manual); ControlPoint * p = new ControlPoint; p->SetAprioriSurfacePoint(SurfacePoint(lat2, lon2, rad2)); p->SetId("Point2"); p->SetType(ControlPoint::Fixed); p->Add(m); cnet.AddPoint(p); } // Bundle adjust to solve for new pointing try { BundleAdjust b(cnet, serialNumberList); b.SetSolveTwist(ui.GetBoolean("TWIST")); // double tol = ui.GetDouble("TOL"); //int maxIterations = ui.GetInteger("MAXITS"); //b.Solve(tol, maxIterations); b.SetSolveCmatrix(BundleAdjust::AnglesOnly); b.SetSolveSpacecraftPosition(BundleAdjust::Nothing); b.SetErrorPropagation(false); b.SetOutlierRejection(false); b.SetSolutionMethod("SPECIALK"); b.SetStandardOutput(true); b.SetCSVOutput(false); b.SetResidualOutput(true); b.SetConvergenceThreshold(ui.GetDouble("SIGMA0")); b.SetMaxIterations(ui.GetInteger("MAXITS")); b.SetDecompositionMethod(BundleAdjust::SPECIALK); b.SolveCholesky(); Cube c; c.open(filename, "rw"); //check for existing polygon, if exists delete it if(c.label()->hasObject("Polygon")) { c.label()->deleteObject("Polygon"); } Table cmatrix = b.Cmatrix(0); // Write out a description in the spice table QString deltackComment = "deltackAdjusted = " + Isis::iTime::CurrentLocalTime(); cmatrix.Label().addComment(deltackComment); //PvlKeyword description("Description"); //description = "Camera pointing updated via deltack application"; //cmatrix.Label().findObject("Table",Pvl::Traverse).addKeyword(description); // Update the cube history c.write(cmatrix); History h("IsisCube"); c.read(h); h.AddEntry(); c.write(h); c.close(); PvlGroup gp("DeltackResults"); gp += PvlKeyword("Status", "Camera pointing updated"); Application::Log(gp); } catch(IException &e) { QString msg = "Unable to update camera pointing for [" + filename + "]"; throw IException(e, IException::Unknown, msg, _FILEINFO_); } }
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; }
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; }