/** * FindCnetRef traverses all the control points and measures in the network and checks for * valid Measure which passes the Emission Incidence Angle, DN value tests and chooses the * measure with the best Resolution criteria as the reference. Creates a new control network * with these adjustments. * * @author Sharmila Prasad (5/25/2010) * @history 2010-10-04 Sharmila Prasad - Modified for Binary CNet (Edit Lock) * * @param pNewNet - Modified output Control Net * */ void CnetRefByResolution::FindCnetRef(ControlNet &pNewNet) { // Process each existing control point in the network int iPointsModified = 0; int iMeasuresModified = 0; int iRefChanged = 0; //Status Report mStatus.SetText("Choosing Reference by Resolution..."); mStatus.SetMaximumSteps(pNewNet.GetNumPoints()); mStatus.CheckStatus(); //mPvlLog += GetStdOptions(); for (int point = 0; point < pNewNet.GetNumPoints(); ++point) { ControlPoint *newPnt = pNewNet.GetPoint(point); bool bError = false; // Create a copy of original control point const ControlPoint origPnt(*newPnt); mdResVector.clear(); // Logging PvlObject pvlPointObj("PointDetails"); pvlPointObj += Isis::PvlKeyword("PointId", newPnt->GetId()); // Edit Lock Option bool bPntEditLock = newPnt->IsEditLocked(); if (!bPntEditLock) { newPnt->SetDateTime(Application::DateTime()); } else { pvlPointObj += Isis::PvlKeyword("Reference", "No Change, PointEditLock"); } int iNumMeasuresLocked = newPnt->GetNumLockedMeasures(); bool bRefLocked = newPnt->GetRefMeasure()->IsEditLocked(); int numMeasures = newPnt->GetNumMeasures(); int iRefIndex = -1; if (newPnt->IsReferenceExplicit()) iRefIndex = newPnt->IndexOfRefMeasure(); QString istrTemp; std::vector <PvlGroup> pvlGrpVector; int iBestIndex = 0; // Only perform the interest operation on points of type "Free" and // Points having atleast 1 measure and Point is not Ignored // Check for EditLock in the Measures and also verfify that // only a Reference Measure can be Locked else error if (!newPnt->IsIgnored() && newPnt->GetType() == ControlPoint::Free && numMeasures > 0 && (iNumMeasuresLocked == 0 || (iNumMeasuresLocked > 0 && bRefLocked))) { int iNumIgnore = 0; QString istrTemp; for (int measure = 0; measure < newPnt->GetNumMeasures(); ++measure) { ControlMeasure *newMsr = newPnt->GetMeasure(measure); bool bMeasureLocked = newMsr->IsEditLocked(); double dSample = newMsr->GetSample(); double dLine = newMsr->GetLine(); QString sn = newMsr->GetCubeSerialNumber(); if (!bPntEditLock && !bMeasureLocked) { newMsr->SetDateTime(Application::DateTime()); newMsr->SetChooserName("Application cnetref(Resolution)"); } // Log PvlGroup pvlMeasureGrp("MeasureDetails"); pvlMeasureGrp += Isis::PvlKeyword("SerialNum", sn); pvlMeasureGrp += Isis::PvlKeyword("OriginalLocation", LocationString(dSample, dLine)); if (bMeasureLocked) pvlMeasureGrp += Isis::PvlKeyword("EditLock", "True"); if (!newMsr->IsIgnored()) { Cube *measureCube = mCubeMgr.OpenCube(mSerialNumbers.FileName(sn)); MeasureValidationResults results = ValidStandardOptions(newMsr, measureCube, &pvlMeasureGrp); if (!results.isValid()) { if (bPntEditLock) { pvlMeasureGrp += Isis::PvlKeyword("UnIgnored", "Failed Validation Test but not Ignored as Point EditLock is True"); } else if (bMeasureLocked) { pvlMeasureGrp += Isis::PvlKeyword("UnIgnored", "Failed Validation Test but not Ignored as Measure EditLock is True"); } else { pvlMeasureGrp += Isis::PvlKeyword("Ignored", "Failed Validation Test"); newMsr->SetIgnored(true); iNumIgnore++; } } // valid measure else { if (!bPntEditLock && !bRefLocked) { newMsr->SetType(ControlMeasure::Candidate); newMsr->SetIgnored(false); mdResVector.push_back(mdResolution); } } } // Ignore == false else { pvlMeasureGrp += Isis::PvlKeyword("Ignored", "Originally Ignored"); iNumIgnore++; } if (newMsr != origPnt.GetMeasure(measure)) { iMeasuresModified++; } //newPnt.UpdateMeasure(newMsr); // Redesign fixed this pvlGrpVector.push_back(pvlMeasureGrp); }// end Measure if ((newPnt->GetNumMeasures() - iNumIgnore) < 2) { if (bPntEditLock) { pvlPointObj += Isis::PvlKeyword("UnIgnored", "Good Measures less than 2 but not Ignored as Point EditLock is True"); } else { newPnt->SetIgnored(true); pvlPointObj += Isis::PvlKeyword("Ignored", "Good Measures less than 2"); } } // Set the Reference if the Point is unlocked and Reference measure is unlocked if (!newPnt->IsIgnored() && !bPntEditLock && !bRefLocked) { iBestIndex = GetReferenceByResolution(newPnt); if (iBestIndex >= 0 && !newPnt->GetMeasure(iBestIndex)->IsIgnored()) { newPnt->SetRefMeasure(iBestIndex); //newPnt.UpdateMeasure(cm); // Redesign fixed this pvlGrpVector[iBestIndex] += Isis::PvlKeyword("Reference", "true"); } else { if (iBestIndex < 0 && meType == Range) { pvlPointObj += Isis::PvlKeyword("NOTE", "No Valid Measures within the Resolution Range. Reference defaulted to the first Measure"); } iBestIndex = 0; newPnt->SetRefMeasure(iBestIndex); //newPnt.UpdateMeasure(cm); // Redesign fixed this // Log info, if Point not locked, apriori source == Reference and a new reference if (iRefIndex != iBestIndex && newPnt->GetAprioriSurfacePointSource() == ControlPoint::SurfacePointSource::Reference) { pvlGrpVector[iBestIndex] += Isis::PvlKeyword("AprioriSource", "Reference is the source and has changed"); } } } for (int i = 0; i < newPnt->GetNumMeasures(); i++) { pvlPointObj += pvlGrpVector[i]; } } // end Free else { int iComment = 0; if (numMeasures == 0) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "No Measures in the Point"); } if (newPnt->IsIgnored()) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Point was originally Ignored"); } if (newPnt->GetType() == ControlPoint::Fixed) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Fixed Point"); } else if (newPnt->GetType() == ControlPoint::Constrained) { QString sComment = "Comment"; sComment += QString(++iComment); pvlPointObj += Isis::PvlKeyword(sComment, "Constrained Point"); } if (iNumMeasuresLocked > 0 && !bRefLocked) { pvlPointObj += Isis::PvlKeyword("Error", "Point has a Measure with EditLock set to true " "but the Reference is not Locked"); bError = true; } else { for (int measure = 0; measure < newPnt->GetNumMeasures(); measure++) { ControlMeasure *cm = newPnt->GetMeasure(iBestIndex); cm->SetDateTime(Application::DateTime()); cm->SetChooserName("Application cnetref(Resolution)"); //newPnt.UpdateMeasure(cm); // Redesign fixed this } } } if (*newPnt != origPnt) { iPointsModified++; } if (!bError && !newPnt->IsIgnored() && newPnt->IsReferenceExplicit() && iBestIndex != iRefIndex && !bPntEditLock && !bRefLocked) { iRefChanged++; PvlGroup pvlRefChangeGrp("ReferenceChangeDetails"); if (iRefIndex >= 0) { pvlRefChangeGrp += Isis::PvlKeyword("PrevSerialNumber", origPnt.GetMeasure(iRefIndex)->GetCubeSerialNumber()); pvlRefChangeGrp += Isis::PvlKeyword("PrevResolution", toString(mdResVector[iRefIndex])); istrTemp = QString((int)origPnt.GetMeasure(iRefIndex)->GetSample()); istrTemp += ","; istrTemp += QString((int)origPnt.GetMeasure(iRefIndex)->GetLine()); pvlRefChangeGrp += Isis::PvlKeyword("PrevLocation", istrTemp); } else { pvlRefChangeGrp += Isis::PvlKeyword("PrevReference", "Not Set"); } pvlRefChangeGrp += Isis::PvlKeyword("NewSerialNumber", newPnt->GetMeasure(iBestIndex)->GetCubeSerialNumber()); QString sKeyName = "NewHighestResolution"; if (meType == Low) { sKeyName = "NewLeastResolution"; } else if (meType == Mean) { pvlRefChangeGrp += Isis::PvlKeyword("MeanResolution", toString(GetMeanResolution())); sKeyName = "NewResolutionNeartoMean"; } else if (meType == Nearest) { sKeyName = "NewResolutionNeartoValue"; } else if (meType == Range) { sKeyName = "NewResolutionInRange"; } pvlRefChangeGrp += Isis::PvlKeyword(sKeyName, toString(mdResVector[iBestIndex])); istrTemp = QString((int)newPnt->GetMeasure(iBestIndex)->GetSample()); istrTemp += ","; istrTemp += QString((int)newPnt->GetMeasure(iBestIndex)->GetLine()); pvlRefChangeGrp += Isis::PvlKeyword("NewLocation", istrTemp); pvlPointObj += pvlRefChangeGrp; } else { pvlPointObj += Isis::PvlKeyword("Reference", "No Change"); } //pNewNet.UpdatePoint(newPnt); // Redesign fixed this mPvlLog += pvlPointObj; mStatus.CheckStatus(); }// end Point // CnetRef Change Statistics mStatisticsGrp += Isis::PvlKeyword("PointsModified", toString(iPointsModified)); mStatisticsGrp += Isis::PvlKeyword("ReferenceChanged", toString(iRefChanged)); mStatisticsGrp += Isis::PvlKeyword("MeasuresModified", toString(iMeasuresModified)); mPvlLog += mStatisticsGrp; }
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(); 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; }