From 1d31047d8cd343b2d83d49a9c5fb40cc02f8564d Mon Sep 17 00:00:00 2001 From: kledmundson <6842706+kledmundson@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:16:19 -0700 Subject: [PATCH] Photrim has been refactored to be callable; old Makefile tests have been converted to gtests and removed. (#5582) * Photrim has been converted to a callable app. Corresponding Makefile tests have been converted to gtests and removed. Addresses #5581. * Tweaks to FunctionalTestsPhotrim.cpp. Addresses #5581. --- CHANGELOG.md | 1 + isis/src/base/apps/photrim/main.cpp | 95 +----- isis/src/base/apps/photrim/photrim.cpp | 115 +++++++ isis/src/base/apps/photrim/photrim.h | 19 ++ isis/src/base/apps/photrim/photrim.xml | 3 + isis/src/base/apps/photrim/tsts/Makefile | 4 - isis/src/base/apps/photrim/tsts/base/Makefile | 13 - .../base/apps/photrim/tsts/emission/Makefile | 13 - .../base/apps/photrim/tsts/incidence/Makefile | 13 - .../src/base/apps/photrim/tsts/phase/Makefile | 13 - .../base/apps/photrim/tsts/usedem/Makefile | 14 - isis/tests/FunctionalTestsPhotrim.cpp | 314 ++++++++++++++++++ 12 files changed, 463 insertions(+), 154 deletions(-) create mode 100644 isis/src/base/apps/photrim/photrim.cpp create mode 100644 isis/src/base/apps/photrim/photrim.h delete mode 100644 isis/src/base/apps/photrim/tsts/Makefile delete mode 100644 isis/src/base/apps/photrim/tsts/base/Makefile delete mode 100644 isis/src/base/apps/photrim/tsts/emission/Makefile delete mode 100644 isis/src/base/apps/photrim/tsts/incidence/Makefile delete mode 100644 isis/src/base/apps/photrim/tsts/phase/Makefile delete mode 100644 isis/src/base/apps/photrim/tsts/usedem/Makefile create mode 100644 isis/tests/FunctionalTestsPhotrim.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index b6934a7fe0..0fd2d78adc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ release. - Added backplane options for SunIllumination and SurfaceObliqueDetectorResolution to phocube [#5467](https://github.com/DOI-USGS/ISIS3/issues/5467) ### Changed +- Photrim has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5581](https://github.com/USGS-Astrogeology/ISIS3/issues/5581) - Bandtrim has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5571](https://github.com/USGS-Astrogeology/ISIS3/issues/5571) - Modified kaguyasp2isis to work with new (detached) data [#5436](https://github.com/DOI-USGS/ISIS3/issues/5436) - Added jigsaw error message for csminit'd images without csm parameters[#5486](https://github.com/DOI-USGS/ISIS3/issues/5486) diff --git a/isis/src/base/apps/photrim/main.cpp b/isis/src/base/apps/photrim/main.cpp index 12f38766d5..86dcae99a8 100644 --- a/isis/src/base/apps/photrim/main.cpp +++ b/isis/src/base/apps/photrim/main.cpp @@ -1,93 +1,20 @@ -#include "Isis.h" -#include "Camera.h" -#include "ProcessByLine.h" -#include "SpecialPixel.h" +/** This is free and unencumbered software released into the public domain. -using namespace std; -using namespace Isis; +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ -// Global variables -Camera *cam; -Cube *icube; -bool usedem; -double minPhase; -double maxPhase; -double minEmission; -double maxEmission; -double minIncidence; -double maxIncidence; -int lastBand; +/* SPDX-License-Identifier: CC0-1.0 */ -void photrim(Buffer &in, Buffer &out); +#include "Isis.h" -void IsisMain() { - // We will be processing by line - ProcessByLine p; +#include "photrim.h" - // Setup the input and get the camera model - icube = p.SetInputCube("FROM"); - cam = icube->camera(); +#include "Application.h" - // Create the output cube - p.SetOutputCube("TO"); +using namespace Isis; - // Get the trim angles +void IsisMain() { UserInterface &ui = Application::GetUserInterface(); - - minPhase = ui.GetDouble("MINPHASE"); - maxPhase = ui.GetDouble("MAXPHASE"); - minEmission = ui.GetDouble("MINEMISSION"); - maxEmission = ui.GetDouble("MAXEMISSION"); - minIncidence = ui.GetDouble("MININCIDENCE"); - maxIncidence = ui.GetDouble("MAXINCIDENCE"); - - usedem = ui.GetBoolean("USEDEM"); - - if (!usedem) { - cam->IgnoreElevationModel(true); - - } - - // Start the processing - lastBand = 0; - p.StartProcess(photrim); - p.EndProcess(); -} - - -// Line processing routine -void photrim(Buffer &in, Buffer &out) { - // See if there is a change in band which would change the camera model - if (in.Band() != lastBand) { - lastBand = in.Band(); - cam->SetBand(icube->physicalBand(lastBand)); - } - - // Loop for each pixel in the line. - double samp, phase, emission, incidence; - double line = in.Line(); - for (int i = 0; i < in.size(); i++) { - samp = in.Sample(i); - cam->SetImage(samp, line); - if (cam->HasSurfaceIntersection()) { - if (((phase = cam->PhaseAngle()) < minPhase) || (phase > maxPhase)) { - out[i] = Isis::NULL8; - } - else if (((emission = cam->EmissionAngle()) < minEmission) || - (emission > maxEmission)) { - out[i] = Isis::NULL8; - } - else if (((incidence = cam->IncidenceAngle()) < minIncidence) || - (incidence > maxIncidence)) { - out[i] = Isis::NULL8; - } - else { - out[i] = in[i]; - } - } - // Trim outerspace - else { - out[i] = Isis::NULL8; - } - } + photrim(ui); } diff --git a/isis/src/base/apps/photrim/photrim.cpp b/isis/src/base/apps/photrim/photrim.cpp new file mode 100644 index 0000000000..ff95d54ef4 --- /dev/null +++ b/isis/src/base/apps/photrim/photrim.cpp @@ -0,0 +1,115 @@ +/** This is free and unencumbered software released into the public domain. + +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ + +/* SPDX-License-Identifier: CC0-1.0 */ + +#include "photrim.h" + +#include "Camera.h" +#include "ProcessByLine.h" +#include "SpecialPixel.h" + +namespace Isis { + + /* + * The photrim program trims pixels outside of the phase, incidence, + * and emission angles by setting them to "null" within all bands of + * the cube. A user can either trim using the program's default method + * or the USEDEM method. + * + * @param ui UserInterface object containing parameters + */ + void photrim(UserInterface &ui) { + + // open input cube + Cube icube; + icube.open(ui.GetCubeName("FROM")); + + photrim(&icube, ui); + } + + + /* + * The photrim program trims pixels outside of the phase, incidence, + * and emission angles by setting them to "null" within all bands of + * the cube. A user can either trim using the program's default method + * or the USEDEM method. + * + * @param iCube Input cube + * @param ui UserInterface object containing parameters + */ + void photrim(Cube *icube, UserInterface &ui) { + // processing by line + ProcessByLine p; + + // Setup input cube and get the camera model + p.SetInputCube(icube); + + Camera* cam = icube->camera(); + + // Create the output cube + QString fname = ui.GetCubeName("TO"); + CubeAttributeOutput &atts = ui.GetOutputAttribute("TO"); + p.SetOutputCube(fname, atts); + + // Get the trim angles + double minPhase = ui.GetDouble("MINPHASE"); + double maxPhase = ui.GetDouble("MAXPHASE"); + double minEmission = ui.GetDouble("MINEMISSION"); + double maxEmission = ui.GetDouble("MAXEMISSION"); + double minIncidence = ui.GetDouble("MININCIDENCE"); + double maxIncidence = ui.GetDouble("MAXINCIDENCE"); + + bool usedem = ui.GetBoolean("USEDEM"); + + if (!usedem) { + cam->IgnoreElevationModel(true); + } + + // Start the processing + int lastBand = 0; + + // lambda function with captures to process by line + auto photrimLineProcess = [&](Buffer &in, Buffer &out)->void { + // See if there is a change in band which would change the camera model + if (in.Band() != lastBand) { + lastBand = in.Band(); + cam->SetBand(icube->physicalBand(lastBand)); + } + + // Loop for each pixel in the line. + double samp, phase, emission, incidence; + double line = in.Line(); + for (int i = 0; i < in.size(); i++) { + samp = in.Sample(i); + cam->SetImage(samp, line); + if (cam->HasSurfaceIntersection()) { + if (((phase = cam->PhaseAngle()) < minPhase) || (phase > maxPhase)) { + out[i] = Isis::NULL8; + } + else if (((emission = cam->EmissionAngle()) < minEmission) || + (emission > maxEmission)) { + out[i] = Isis::NULL8; + } + else if (((incidence = cam->IncidenceAngle()) < minIncidence) || + (incidence > maxIncidence)) { + out[i] = Isis::NULL8; + } + else { + out[i] = in[i]; + } + } + // Trim outerspace + else { + out[i] = Isis::NULL8; + } + } + }; + + p.StartProcess(photrimLineProcess); + p.EndProcess(); + } +} diff --git a/isis/src/base/apps/photrim/photrim.h b/isis/src/base/apps/photrim/photrim.h new file mode 100644 index 0000000000..8b03e06dbc --- /dev/null +++ b/isis/src/base/apps/photrim/photrim.h @@ -0,0 +1,19 @@ +/** This is free and unencumbered software released into the public domain. + +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ + +/* SPDX-License-Identifier: CC0-1.0 */ + +#ifndef photrim_h +#define photrim_h + +#include "UserInterface.h" + +namespace Isis{ + extern void photrim(UserInterface &ui); + extern void photrim(Cube *icube, UserInterface &ui); +} + +#endif diff --git a/isis/src/base/apps/photrim/photrim.xml b/isis/src/base/apps/photrim/photrim.xml index 33ea366f50..98d44dab50 100644 --- a/isis/src/base/apps/photrim/photrim.xml +++ b/isis/src/base/apps/photrim/photrim.xml @@ -70,6 +70,9 @@ Added the option to use the digital elevation model when trimming the image. Created examples for using the DEM and not using the DEM. Fixes #4181. + + Converted to callable app and converted Makefile tests to gtests. + diff --git a/isis/src/base/apps/photrim/tsts/Makefile b/isis/src/base/apps/photrim/tsts/Makefile deleted file mode 100644 index 46d84c74c2..0000000000 --- a/isis/src/base/apps/photrim/tsts/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -BLANKS = "%-6s" -LENGTH = "%-40s" - -include $(ISISROOT)/make/isismake.tststree diff --git a/isis/src/base/apps/photrim/tsts/base/Makefile b/isis/src/base/apps/photrim/tsts/base/Makefile deleted file mode 100644 index fb2ea8e09a..0000000000 --- a/isis/src/base/apps/photrim/tsts/base/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPNAME = photrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from= $(INPUT)/ab102401.cub \ - to= $(OUTPUT)/PhotrimTruth1.cub \ - minphase=0.0 \ - maxphase=180.0 \ - minemission=0.0 \ - maxemission=90.0 \ - minincidence=0.0 \ - maxincidence=90.0 > /dev/null; diff --git a/isis/src/base/apps/photrim/tsts/emission/Makefile b/isis/src/base/apps/photrim/tsts/emission/Makefile deleted file mode 100644 index 07533bd341..0000000000 --- a/isis/src/base/apps/photrim/tsts/emission/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPNAME = photrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from= $(INPUT)/ab102401.cub \ - to= $(OUTPUT)/PhotrimTruth3.cub \ - minphase=0.0 \ - maxphase=180.0 \ - minemission=22.5 \ - maxemission=67.5 \ - minincidence=0.0 \ - maxincidence=90.0 > /dev/null; diff --git a/isis/src/base/apps/photrim/tsts/incidence/Makefile b/isis/src/base/apps/photrim/tsts/incidence/Makefile deleted file mode 100644 index 1a8d13fc15..0000000000 --- a/isis/src/base/apps/photrim/tsts/incidence/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPNAME = photrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from= $(INPUT)/ab102401.cub \ - to= $(OUTPUT)/PhotrimTruth4.cub \ - minphase=0.0 \ - maxphase=180.0 \ - minemission=0.0 \ - maxemission=90.0 \ - minincidence=22.5 \ - maxincidence=67.5 > /dev/null; diff --git a/isis/src/base/apps/photrim/tsts/phase/Makefile b/isis/src/base/apps/photrim/tsts/phase/Makefile deleted file mode 100644 index f7a1c9a913..0000000000 --- a/isis/src/base/apps/photrim/tsts/phase/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPNAME = photrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from= $(INPUT)/ab102401.cub \ - to= $(OUTPUT)/PhotrimTruth2.cub \ - minphase=45.0 \ - maxphase=135.0 \ - minemission=0.0 \ - maxemission=90.0 \ - minincidence=0.0 \ - maxincidence=90.0 > /dev/null; diff --git a/isis/src/base/apps/photrim/tsts/usedem/Makefile b/isis/src/base/apps/photrim/tsts/usedem/Makefile deleted file mode 100644 index 20a6b9d663..0000000000 --- a/isis/src/base/apps/photrim/tsts/usedem/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -APPNAME = photrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) from= $(INPUT)/AS15-M-1499_msk-L2_1250mpp.cub \ - to= $(OUTPUT)/PhotrimTruth5.cub \ - usedem=true \ - minphase=0.0 \ - maxphase=180.0 \ - minemission=0.0 \ - maxemission=85.0 \ - minincidence=0.0 \ - maxincidence=90.0 > /dev/null; \ No newline at end of file diff --git a/isis/tests/FunctionalTestsPhotrim.cpp b/isis/tests/FunctionalTestsPhotrim.cpp new file mode 100644 index 0000000000..57fa2d58ad --- /dev/null +++ b/isis/tests/FunctionalTestsPhotrim.cpp @@ -0,0 +1,314 @@ + +#include +#include + +#include "CameraFixtures.h" +#include "Histogram.h" + +#include "photrim.h" + +#include "gtest/gtest.h" + +using namespace Isis; + +static QString APP_XML = FileName("$ISISROOT/bin/xml/photrim.xml").expanded(); + +/** + * FunctionalTestsPhotrimBase + * + * PhotrimEmission test given a single 5x5 input cube with 1 band. + * Default values for all parameters are used, resulting in no Null + * pixels. + * + * | 1| 2| 3| 4| 5| Valid Pixels: 25 + * | 6| 7| 8| 9|10| Histogram Sum: 325 + * |11|12|13|14|15| Histogram Avg: 13 + * |16|17|18|19|20| + * |21|22|23|24|25| + * + * The output cube is verified by checking histogram statistics. + * + * INPUT: testCube from DefaultCube fixture resized to 5x5 pixels + * with one band. + minemission=10.852 + maxemission=10.857 + * + * DEFAULTS: usedem=false + * minphase=0.0 + * maxphase=180.0 + * minemission=0.0 + * maxemission=90.0 + * minincidence=0.0 + * maxincidence=90.0 + * + * OUTPUT: photrimEmission.cub + */ + TEST_F(DefaultCube, FunctionalTestsPhotrimBase) { + resizeCube(5,5,1); + + QVector args = {"to=" + tempDir.path() + "/PhotrimBase.cub"}; + + UserInterface ui(APP_XML, args); + + try { + photrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // validate output cube + Cube outCube(tempDir.path() + "/PhotrimBase.cub"); + + // validate histogram statistics for output cube + std::unique_ptr hist (outCube.histogram(1)); + EXPECT_EQ(hist->ValidPixels(), 25); + EXPECT_EQ(hist->Average(), 13); + EXPECT_EQ(hist->Sum(), 325); + + outCube.close(); +} + + +/** + * FunctionalTestsPhotrimEmission + * + * PhotrimEmission test given a single 5x5 input cube with 1 band. + * All pixels outside the range as defined by minemission and + * maxemission are set to Null. Resulting pixel values are as + * shown below. + * + * | N| N| 3| 4| 5| Valid Pixels: 14 + * | 6| 7| 8| 9|10| Histogram Sum: 135 + * |11|12|13|14| N| Histogram Avg: 9.6428571428571423 + * |16|17| N| N| N| + * | N| N| N| N| N| + * + * The output cube is verified by checking histogram statistics. + * + * INPUT: testCube from DefaultCube fixture resized to 5x5 pixels + * with one band. + minemission=10.852 + maxemission=10.857 + * + * DEFAULTS: usedem=false + * minphase=0.0 + * maxphase=180.0 + * minemission=0.0 + * maxemission=90.0 + * minincidence=0.0 + * maxincidence=90.0 + * + * OUTPUT: photrimEmission.cub + */ +TEST_F(DefaultCube, FunctionalTestsPhotrimEmission) { + resizeCube(5,5,1); + + QVector args = {"to=" + tempDir.path() + "/photrimEmission.cub", + "minemission=10.852", + "maxemission=10.857" + }; + + UserInterface ui(APP_XML, args); + + try { + photrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // validate output cube + Cube outCube(tempDir.path() + "/photrimEmission.cub"); + + // validate histogram statistics for output cube + std::unique_ptr hist (outCube.histogram(1)); + EXPECT_EQ(hist->ValidPixels(), 14); + EXPECT_NEAR(hist->Average(), 9.642857, 0.000001); + EXPECT_EQ(hist->Sum(), 135); + + outCube.close(); +} + + +/** + * FunctionalTestsPhotrimPhase + * + * PhotrimPhase test given a single 5x5 input cube with 1 band. + * All pixels outside the range as defined by minphase and + * maxphase are set to Null. Resulting pixel values are as + * shown below. + * + * | N| N| N| N| N| Valid Pixels: 8 + * | N| N| N| N| N| Histogram Sum: 122 + * |11|12|13|14|15| Histogram Avg: 15.25 + * | N| N|18|19|20| + * | N| N| N| N| N| + * + * The output cube is verified by checking histogram statistics. + * + * INPUT: testCube from DefaultCube fixture resized to 5x5 pixels + * with one band. + * minphase=79.77 + * maxphase=79.772 + * + * DEFAULTS: usedem=false + * minphase=0.0 + * maxphase=180.0 + * minemission=0.0 + * maxemission=90.0 + * minincidence=0.0 + * maxincidence=90.0 + * + * OUTPUT: photrimPhase.cub + */ +TEST_F(DefaultCube, FunctionalTestsPhotrimPhase) { + resizeCube(5,5,1); + + QVector args = {"to=" + tempDir.path() + "/photrimPhase.cub", + "minphase=79.77", + "maxphase=79.772" + }; + + UserInterface ui(APP_XML, args); + + try { + photrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // validate output cube + Cube outCube(tempDir.path() + "/photrimPhase.cub"); + + // validate histogram statistics for output cube + std::unique_ptr hist (outCube.histogram(1)); + EXPECT_EQ(hist->ValidPixels(), 8); + EXPECT_EQ(hist->Average(), 15.25); + EXPECT_EQ(hist->Sum(), 122); + + outCube.close(); +} + + +/** + * FunctionalTestsPhotrimIncidence + * + * PhotrimIncidence test given a single 5x5 input cube with 1 band. + * All pixels outside the range as defined by minincidence and + * maxincidence are set to Null. Resulting pixel values are as + * shown below. + * + * | N| N| N| N| N| Valid Pixels: 5 + * | N| N| N| N| N| Histogram Sum: 65 + * |11|12|13|14|15| Histogram Avg: 13 + * | N| N| N| N| N| + * | N| N| N| N| N| + * + * The output cube is verified by checking histogram statistics. + * + * INPUT: testCube from DefaultCube fixture resized to 5x5 pixels + * with one band. + * minincidence=70.248 + * maxincidence=70.2485 + * + * DEFAULTS: usedem=false + * minphase=0.0 + * maxphase=180.0 + * minemission=0.0 + * maxemission=90.0 + * minincidence=0.0 + * maxincidence=90.0 + * + * OUTPUT: photrimIncidence.cub + */ +TEST_F(DefaultCube, FunctionalTestsPhotrimIncidence) { + resizeCube(5,5,1); + + QVector args = {"to=" + tempDir.path() + "/photrimIncidence.cub", + "minincidence=70.248", + "maxincidence=70.2485" + }; + + UserInterface ui(APP_XML, args); + + try { + photrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // validate output cube + Cube outCube(tempDir.path() + "/photrimIncidence.cub"); + + // validate histogram statistics for output cube + std::unique_ptr hist (outCube.histogram(1)); + EXPECT_EQ(hist->ValidPixels(), 5); + EXPECT_EQ(hist->Average(), 13); + EXPECT_EQ(hist->Sum(), 65); +} + + +/** + * FunctionalTestsPhotrimUseDEM + * + * PhotrimIncidence test given a single 5x5 input cube with 1 band. + * The shapemodel set in cube is utilized. All pixels outside the + * range as defined by minemission and maxemission are set to Null. + * Resulting pixel values are as shown below. + * + * | N| N| 3| 4| 5| Valid Pixels: 17 + * | 6| 7| 8| 9|10| Histogram Sum: 189 + * |11|12|13|14|15| Histogram Avg: 11.117647058823529 + * |16|17|18| N| N| + * |21| N| N| N| N| + * + * The output cube is verified by checking histogram statistics. + * + * INPUT: testCube from DefaultCube fixture resized to 5x5 pixels + * with one band. + * usedem=true + * minemission=10.8 + * maxemission=10.805 + * + * DEFAULTS: usedem=false + * minphase=0.0 + * maxphase=180.0 + * minemission=0.0 + * maxemission=90.0 + * minincidence=0.0 + * maxincidence=90.0 + * + * OUTPUT: photrimIncidence.cub + */ +TEST_F(DefaultCube, FunctionalTestsPhotrimUseDEM) { + resizeCube(5,5,1); + + QVector args = {"to=" + tempDir.path() + "/photrimUseDEM.cub", + "usedem=true", + "minemission=10.8", + "maxemission=10.805", + }; + + UserInterface ui(APP_XML, args); + + try { + photrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // validate output cube + Cube outCube(tempDir.path() + "/photrimUseDEM.cub"); + + // validate histogram statistics for output cube + std::unique_ptr hist (outCube.histogram(1)); + EXPECT_EQ(hist->ValidPixels(),17); + EXPECT_NEAR(hist->Average(), 11.117647, 0.000001); + EXPECT_EQ(hist->Sum(), 189); + + outCube.close(); +}