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() { // 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; }