diff --git a/CHANGELOG.md b/CHANGELOG.md index 81fc6e90e2..2ef0ed0da3 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 +- 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) - Changed `qwt` dependency version to 6.2.0 or below [#5498](https://github.com/DOI-USGS/ISIS3/issues/5498) diff --git a/isis/src/base/apps/bandtrim/bandtrim.cpp b/isis/src/base/apps/bandtrim/bandtrim.cpp new file mode 100644 index 0000000000..07e60d98e3 --- /dev/null +++ b/isis/src/base/apps/bandtrim/bandtrim.cpp @@ -0,0 +1,74 @@ +/** 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 "bandtrim.h" + +#include "Cube.h" +#include "ProcessByBrick.h" +#include "SpecialPixel.h" + +namespace Isis { + + // Process to trim spectral pixels if any are null + void BandTrimSpectral(Buffer &in, Buffer &out); + + /** + * Bandtrim searches for NULL pixels in all bands of a cube. + * When a NULL pixel is found the corresponding pixel is set + * to NULL in all other bands. + * + * @param ui User Interface with application parameters + */ + void bandtrim(UserInterface &ui) { + + // open cube + Cube icube; + icube.open(ui.GetCubeName("FROM")); + + bandtrim(&icube, ui); + } + + + /** + * Bandtrim searches for NULL pixels in all bands of a cube. + * When a NULL pixel is found the corresponding pixel is set + * to NULL in all other bands. + * + * @param icube Input cube + * @param ui User Interface with application parameters + */ + void bandtrim(Cube *icube, UserInterface &ui) { + ProcessByBrick p; + p.SetInputCube(icube); + p.SetBrickSize(1, 1, icube->bandCount()); + + QString fname = ui.GetCubeName("TO"); + CubeAttributeOutput &atts = ui.GetOutputAttribute("TO"); + p.SetOutputCube(fname, atts); + + p.StartProcess(BandTrimSpectral); + p.EndProcess(); + } + + // Process to trim spectral pixels if any are null + void BandTrimSpectral(Buffer &in, Buffer &out) { + // Copy input to output and check to see if we should null + bool nullPixels = false; + for(int i = 0; i < in.size(); i++) { + out[i] = in[i]; + if(in[i] == Isis::Null) nullPixels = true; + } + + // Null all pixels in the spectra if necessary + if(nullPixels) { + for(int i = 0; i < in.size(); i++) { + out[i] = Isis::Null; + } + } + } +} \ No newline at end of file diff --git a/isis/src/base/apps/bandtrim/bandtrim.h b/isis/src/base/apps/bandtrim/bandtrim.h new file mode 100644 index 0000000000..03447a91d8 --- /dev/null +++ b/isis/src/base/apps/bandtrim/bandtrim.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 bandtrim_h +#define bandtrim_h + +#include "UserInterface.h" + +namespace Isis{ + extern void bandtrim(UserInterface &ui); + extern void bandtrim(Cube *iCube, UserInterface &ui); +} + +#endif diff --git a/isis/src/base/apps/bandtrim/bandtrim.xml b/isis/src/base/apps/bandtrim/bandtrim.xml index 525a4e6f19..fd550ac313 100644 --- a/isis/src/base/apps/bandtrim/bandtrim.xml +++ b/isis/src/base/apps/bandtrim/bandtrim.xml @@ -35,6 +35,9 @@ Removed references to CubeInfo + + Converted to callable app and converted Makefile tests to gtests. + diff --git a/isis/src/base/apps/bandtrim/main.cpp b/isis/src/base/apps/bandtrim/main.cpp index d577d27cfe..b163580e1c 100644 --- a/isis/src/base/apps/bandtrim/main.cpp +++ b/isis/src/base/apps/bandtrim/main.cpp @@ -1,34 +1,20 @@ -#include "Isis.h" -#include "ProcessByBrick.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. **/ -void BandTrim(Buffer &in, Buffer &out); +/* SPDX-License-Identifier: CC0-1.0 */ -void IsisMain() { - ProcessByBrick p; - Cube *icube = p.SetInputCube("FROM"); - p.SetBrickSize(1, 1, icube->bandCount()); - p.SetOutputCube("TO"); - p.StartProcess(BandTrim); - p.EndProcess(); -} +#include "Isis.h" -// Trim spectral pixels if anyone of them is null -void BandTrim(Buffer &in, Buffer &out) { - // Copy input to output and check to see if we should null - bool nullPixels = false; - for(int i = 0; i < in.size(); i++) { - out[i] = in[i]; - if(in[i] == Isis::Null) nullPixels = true; - } +#include "bandtrim.h" - // Null all pixels in the spectra if necessary - if(nullPixels) { - for(int i = 0; i < in.size(); i++) { - out[i] = Isis::Null; - } - } +#include "Application.h" + +using namespace Isis; + +void IsisMain() { + UserInterface &ui = Application::GetUserInterface(); + bandtrim(ui); } diff --git a/isis/src/base/apps/bandtrim/tsts/Makefile b/isis/src/base/apps/bandtrim/tsts/Makefile deleted file mode 100644 index 46d84c74c2..0000000000 --- a/isis/src/base/apps/bandtrim/tsts/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -BLANKS = "%-6s" -LENGTH = "%-40s" - -include $(ISISROOT)/make/isismake.tststree diff --git a/isis/src/base/apps/bandtrim/tsts/default/Makefile b/isis/src/base/apps/bandtrim/tsts/default/Makefile deleted file mode 100644 index 4360b7671b..0000000000 --- a/isis/src/base/apps/bandtrim/tsts/default/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -APPNAME = bandtrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) FROM=$(INPUT)/input.cub TO=$(OUTPUT)/truth.cub > /dev/null; diff --git a/isis/src/base/apps/bandtrim/tsts/oneband/Makefile b/isis/src/base/apps/bandtrim/tsts/oneband/Makefile deleted file mode 100644 index 4360b7671b..0000000000 --- a/isis/src/base/apps/bandtrim/tsts/oneband/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -APPNAME = bandtrim - -include $(ISISROOT)/make/isismake.tsts - -commands: - $(APPNAME) FROM=$(INPUT)/input.cub TO=$(OUTPUT)/truth.cub > /dev/null; diff --git a/isis/tests/FunctionalTestsBandtrim.cpp b/isis/tests/FunctionalTestsBandtrim.cpp new file mode 100644 index 0000000000..71f39029e5 --- /dev/null +++ b/isis/tests/FunctionalTestsBandtrim.cpp @@ -0,0 +1,192 @@ + +#include +#include + +#include "Brick.h" +#include "CameraFixtures.h" +#include "Histogram.h" +#include "bandtrim.h" + +#include "gtest/gtest.h" + +using namespace Isis; + +static QString APP_XML = FileName("$ISISROOT/bin/xml/bandtrim.xml").expanded(); + +/** + * BandtrimDefault Test + * + * BandtrimDefault test given a single 5x5 input cube with 7 bands. + * One pixel in each band is set to Isis::Null as below. + * N implies a Null pixel, N1 is band 1, N2 is band 2, etc. + * All Null pixels should be duplicated across each band in the + * output Cube. + * + * The output cube is verified by checking the histogram statistics + * for each band. + * + * | |N1| |N2| | + * | | | | | | + * |N3| |N4| |N5| + * | | | | | | + * | |N6| |N7| | + * + * INPUT: testCube from DefaultCube fixture modified as above. + * + * OUTPUT: bandtrimDefaultOut.cub + * + */ +TEST_F(DefaultCube, FunctionalTestBandtrimDefault) { + + // reduce test cube size, create seven bands + resizeCube(5, 5, 7); + + // set one pixel in each of the seven bands to Isis::Null + // following the pattern in the comment block above + + Brick b(1, 1, 1, testCube->pixelType()); // create buffer of size 1 pixel + + b.SetBasePosition(2, 1, 1); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(4, 1, 2); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(1, 3, 3); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(3, 3, 4); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(5, 3, 5); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(2, 5, 6); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(4, 5, 7); + b[0] = Isis::Null; + testCube->write(b); + + // run bandtrim + QVector args = {"to=" + tempDir.path() + "/bandtrimDefaultOut.cub"}; + UserInterface ui(APP_XML, args); + + try { + bandtrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // Open output cube + Cube outCube(tempDir.path() + "/bandtrimDefaultOut.cub"); + + // validate histogram statistics for each band in output cube + std::unique_ptr band1Hist (outCube.histogram(1)); + std::unique_ptr band2Hist (outCube.histogram(2)); + std::unique_ptr band3Hist (outCube.histogram(3)); + std::unique_ptr band4Hist (outCube.histogram(4)); + std::unique_ptr band5Hist (outCube.histogram(5)); + std::unique_ptr band6Hist (outCube.histogram(6)); + std::unique_ptr band7Hist (outCube.histogram(7)); + + EXPECT_EQ(band1Hist->ValidPixels(), 18); + EXPECT_EQ(band1Hist->Average(), 13); + EXPECT_EQ(band1Hist->Sum(), 234); + EXPECT_EQ(band2Hist->ValidPixels(), 18); + EXPECT_EQ(band2Hist->Average(), 38); + EXPECT_EQ(band2Hist->Sum(), 684); + EXPECT_EQ(band3Hist->ValidPixels(), 18); + EXPECT_EQ(band3Hist->Average(), 63); + EXPECT_EQ(band3Hist->Sum(), 1134); + EXPECT_EQ(band4Hist->ValidPixels(), 18); + EXPECT_EQ(band4Hist->Average(), 88); + EXPECT_EQ(band4Hist->Sum(), 1584); + EXPECT_EQ(band5Hist->ValidPixels(), 18); + EXPECT_EQ(band5Hist->Average(), 113); + EXPECT_EQ(band5Hist->Sum(), 2034); + EXPECT_EQ(band6Hist->ValidPixels(), 18); + EXPECT_EQ(band6Hist->Average(), 138); + EXPECT_EQ(band6Hist->Sum(), 2484); + EXPECT_EQ(band7Hist->ValidPixels(), 18); + EXPECT_EQ(band7Hist->Average(), 163); + EXPECT_EQ(band7Hist->Sum(), 2934); + + outCube.close(); +} + + +/** + * BandtrimOneBand Test + * + * BandtrimOneBand test given a single 5x5 input cube with 1 band. + * The four pixels in the upper left corner are set to Isis::Null + * as below. N implies a Null pixel. + * + * The output cube is verified by checking histogram statistics. + * + * |N|N| | | | + * |N|N| | | | + * | | | | | | + * | | | | | | + * | | | | | | + * + * INPUT: testCube from DefaultCube fixture + * + * OUTPUT: bandtrimOneBandOut.cub + */ +TEST_F(DefaultCube, FunctionalTestBandtrimOneBand) { + + // reduce test cube size + resizeCube(5, 5, 1); + + // set 4 pixel block in upper left corner to Isis::Null + Brick b(1, 1, 1, testCube->pixelType()); // create buffer of size 1 pixels + b.SetBasePosition(1, 1, 1); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(2, 1, 1); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(1, 2, 1); + b[0] = Isis::Null; + testCube->write(b); + + b.SetBasePosition(2, 2, 1); + b[0] = Isis::Null; + testCube->write(b); + + // run bandtrim + QVector args = {"to=" + tempDir.path() + "/bandtrimOneBandOut.cub"}; + + UserInterface ui(APP_XML, args); + + try { + bandtrim(testCube, ui); + } + catch(IException &e) { + FAIL() << e.toString().toStdString().c_str() << std::endl; + } + + // Open output cube + Cube outCube(tempDir.path() + "/bandtrimOneBandOut.cub"); + + // validate histogram statistics for each band in output cube + std::unique_ptr band1Hist (outCube.histogram(1)); + + EXPECT_EQ(band1Hist->ValidPixels(), 21); + EXPECT_EQ(band1Hist->Average(), 14.714285714285714); + EXPECT_EQ(band1Hist->Sum(), 309); + + outCube.close(); +} +