diff --git a/isis/tests/Fixtures.cpp b/isis/tests/Fixtures.cpp index 839dfb8885..14364a371f 100644 --- a/isis/tests/Fixtures.cpp +++ b/isis/tests/Fixtures.cpp @@ -307,9 +307,9 @@ namespace Isis { cubeListFile = tempDir.path() + "/cubes.lis"; cubeList->write(cubeListFile); - ControlNet inputNet("data/apolloNetwork/apolloNet.pvl"); + network = new ControlNet("data/apolloNetwork/apolloNet.pvl"); controlNetPath = tempDir.path() + "/apolloNet.net"; - inputNet.Write(controlNetPath); + network->Write(controlNetPath); } void ApolloNetwork::TearDown() { diff --git a/isis/tests/Fixtures.h b/isis/tests/Fixtures.h index 4b79ae59ae..cc570bdde8 100644 --- a/isis/tests/Fixtures.h +++ b/isis/tests/Fixtures.h @@ -120,21 +120,7 @@ namespace Isis { void SetUp() override; void TearDown() override; }; - - class ApolloNetwork: public TempTestingFiles { - protected: - Cube *cube1, *cube2, *cube3, *cube4, *cube5, *cube6, *cube7; - FileName *isdFile1, *isdFile2, *isdFile3, *isdFile4, *isdFile5, *isdFile6, *isdFile7, - *cubeLabel, *label1, *label2, *label3, *label4, *label5, *label6, *label7; - - FileList *cubeList; - QString cubeListFile; - QString controlNetPath; - - void SetUp() override; - void TearDown() override; - }; - + class ObservationPair : public TempTestingFiles { protected: @@ -152,6 +138,22 @@ namespace Isis { ControlNet *network; QString cnetPath; + + void SetUp() override; + void TearDown() override; + }; + + class ApolloNetwork: public TempTestingFiles { + protected: + Cube *cube1, *cube2, *cube3, *cube4, *cube5, *cube6, *cube7; + FileName *isdFile1, *isdFile2, *isdFile3, *isdFile4, *isdFile5, *isdFile6, *isdFile7, + *cubeLabel, *label1, *label2, *label3, *label4, *label5, *label6, *label7; + + FileList *cubeList; + QString cubeListFile; + + ControlNet *network; + QString controlNetPath; void SetUp() override; void TearDown() override; diff --git a/isis/tests/FunctionalTestsJigsaw.cpp b/isis/tests/FunctionalTestsJigsaw.cpp index 056d872da2..e0adb4db59 100644 --- a/isis/tests/FunctionalTestsJigsaw.cpp +++ b/isis/tests/FunctionalTestsJigsaw.cpp @@ -1,28 +1,14 @@ -#include +#include #include -#include -#include -#include -#include -#include -#include "jigsaw.h" -#include "Angle.h" -#include "ControlNet.h" -#include "ControlPoint.h" -#include "ControlMeasure.h" -#include "Distance.h" -#include "FileName.h" -#include "Latitude.h" -#include "Longitude.h" -#include "SurfacePoint.h" -#include "gmock/gmock.h" -#include "UserInterface.h" -#include "CSVReader.h" #include "Pvl.h" #include "PvlGroup.h" #include "Statistics.h" +#include "CSVReader.h" +#include "Latitude.h" +#include "Longitude.h" +#include "ControlPoint.h" #include "jigsaw.h" @@ -211,7 +197,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) { for (int i=0; i < inputPoints.length(); i++) { ControlPoint* inputPoint = inputPoints[i]; - ControlPoint* outputPoint; + ControlPoint* outputPoint = nullptr; EXPECT_NO_THROW({ outputPoint = outputNet.GetPoint(inputPoint->GetId()); } @@ -354,16 +340,151 @@ TEST_F(ObservationPair, FunctionalTestJigsawCamSolveAll) { EXPECT_NEAR(elems.at(56).toDouble(), 0.365717165, 0.00001); } -TEST_F(ObservationPair, FunctionalTestJigsawErrorNoSolve) { + +TEST_F(ApolloNetwork, FunctionalTestJigsawHeldList) { QTemporaryDir prefix; + + QString heldlistpath = prefix.path() + "/heldlist.lis"; + FileList heldList; + heldList.append(cube6->fileName()); + heldList.write(heldlistpath); + QString outCnetFileName = prefix.path() + "/outTemp.net"; - QVector args = {"fromlist="+cubeListFile, "cnet="+cnetPath, "onet="+outCnetFileName, - "camsolve=None", "spsolve=None"}; + QVector args = {"fromlist="+cubeListFile, "cnet="+controlNetPath, "onet="+outCnetFileName, "heldlist="+heldlistpath, + "radius=yes", "errorpropagation=yes", "spsolve=position", "Spacecraft_position_sigma=1000", + "Residuals_csv=off", "Camsolve=angles", "Twist=yes", "Camera_angles_sigma=2", + "Output_csv=off", "imagescsv=on", "file_prefix="+prefix.path()+"/"}; UserInterface options(APP_XML, args); Pvl log; + try { + jigsaw(options, &log); + } + catch (IException &e) { + FAIL() << "Unable to bundle: " << e.what() << std::endl; + } + + CSVReader::CSVAxis csvLine; + CSVReader header = CSVReader(prefix.path()+"/bundleout_images.csv", + false, 0, ',', false, true); + + csvLine = header.getRow(7); + + // assert corrections are very small + // X Correction + EXPECT_LE(std::abs(csvLine[5].toDouble()), 1e-10); + // Y Correction + EXPECT_LE(std::abs(csvLine[10].toDouble()), 1e-10); + // Z Correction + EXPECT_LE(std::abs(csvLine[15].toDouble()), 1e-10); + // RA Correction + EXPECT_LE(std::abs(csvLine[20].toDouble()), 1e-10); + // DEC Correction + EXPECT_LE(std::abs(csvLine[25].toDouble()), 1e-10); + // TWIST Correction + EXPECT_LE(std::abs(csvLine[30].toDouble()), 1e-10); +} + + +TEST_F(ApolloNetwork, FunctionalTestJigsawMEstimator) { + QTemporaryDir prefix; + QString newNetworkPath = prefix.path()+"/badMeasures.net"; + + QVector pid = {"AS15_000031985", + "AS15_000033079", + "AS15_SocetPAN_03", + "AS15_Tie03"}; + + QVector mid = {"APOLLO15/METRIC/1971-07-31T14:01:40.346", + "APOLLO15/METRIC/1971-07-31T14:02:27.179", + "APOLLO15/METRIC/1971-07-31T14:02:03.751", + "APOLLO15/METRIC/1971-07-31T14:00:53.547"}; + + for (int i = 0; i < pid.size(); i++) { + // grab random points and add error to a single measure + ControlPoint *point = network->GetPoint(pid[i]); + ControlMeasure *measure = point->GetMeasure(mid[i]); + measure->SetCoordinate(measure->GetLine()+50, measure->GetLine()+50); + } + + network->Write(newNetworkPath); + + QString outCnetFileName = prefix.path() + "/outTemp.net"; + QVector args = {"fromlist="+cubeListFile, "cnet="+newNetworkPath, "onet="+outCnetFileName, + "Radius=yes", "Errorpropagation=yes", "Spsolve=position","Spacecraft_position_sigma=1000.0", + "Camsolve=angles", "twist=yes", "Camera_angles_sigma=2", + "Model1=huber", "Max_model1_c_quantile=0.6", "Model2=chen", "Max_model2_c_quantile=0.98", "Sigma0=1e-3", + "bundleout_txt=yes", "Output_csv=on", "imagescsv=on", "file_prefix="+prefix.path()+"/"}; + + UserInterface options(APP_XML, args); + + Pvl log; + try { + jigsaw(options, &log); + } + catch (IException &e) { + FAIL() << "Unable to bundle: " << e.what() << std::endl; + } + + CSVReader::CSVAxis csvLine; + CSVReader header = CSVReader(prefix.path()+"/bundleout_images.csv", + false, 0, ',', false, true); + + ControlNet onet; + onet.ReadControl(outCnetFileName); + + QVector presiduals = {}; + QVector> mresiduals = {{1.27975, 1.54281, 1.8778, 1.30159}, + {2.25115, 2.33559, 0.547574, 3.16777}, + {1.15396, 0.69243, 1.03005, 0.848934}, + {2.24641, 4.39168, 0.560941, 2.844}}; + + for (int i = 0; i < pid.size(); i++) { + ControlPoint *point = network->GetPoint(pid[i]); + QList measures = point->getMeasures(); + for (int j = 0; j < measures.size(); j++ ) { + EXPECT_NEAR(measures.at(j)->GetResidualMagnitude(), mresiduals[i][j], 0.0001); + } + } + + QFile bo(prefix.path()+"/bundleout.txt"); + QString contents; + if (bo.open(QIODevice::ReadOnly)) { + contents = bo.read(bo.size()); + } + else { + FAIL() << "Failed to open bundleout.txt" << std::endl; + } + + QStringList lines = contents.split("\n"); + + EXPECT_THAT(lines[31].toStdString(), HasSubstr("Tier 0 Enabled: TRUE")); + EXPECT_THAT(lines[32].toStdString(), HasSubstr("Maximum Likelihood Model: Huber")); + EXPECT_THAT(lines[33].toStdString(), HasSubstr("Quantile used for tweaking constant: 0.6")); + EXPECT_THAT(lines[34].toStdString(), HasSubstr("Quantile weighted R^2 Residual value: 0.207")); + EXPECT_THAT(lines[35].toStdString(), HasSubstr("Approx. weighted Residual cutoff: N/A")); + + EXPECT_THAT(lines[37].toStdString(), HasSubstr("Tier 1 Enabled: TRUE")); + EXPECT_THAT(lines[38].toStdString(), HasSubstr("Maximum Likelihood Model: Chen")); + EXPECT_THAT(lines[39].toStdString(), HasSubstr("Quantile used for tweaking constant: 0.98")); + EXPECT_THAT(lines[40].toStdString(), HasSubstr("Quantile weighted R^2 Residual value: 1.0")); + EXPECT_THAT(lines[41].toStdString(), HasSubstr("Approx. weighted Residual cutoff: 1.0")); + + EXPECT_THAT(lines[43].toStdString(), HasSubstr(" Tier 2 Enabled: FALSE")); +} + + + TEST_F(ObservationPair, FunctionalTestJigsawErrorNoSolve) { + QTemporaryDir prefix; + QString outCnetFileName = prefix.path() + "/outTemp.net"; + QVector args = {"fromlist="+cubeListFile, "cnet="+cnetPath, "onet="+outCnetFileName, + "camsolve=None", "spsolve=None"}; + + UserInterface options(APP_XML, args); + Pvl log; + try { jigsaw(options, &log); FAIL() << "Should throw" << std::endl;