Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bandtrim has been refactored to be callable; old Makefile tests have been converted to gtests. #5572

Merged
merged 3 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
74 changes: 74 additions & 0 deletions isis/src/base/apps/bandtrim/bandtrim.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
19 changes: 19 additions & 0 deletions isis/src/base/apps/bandtrim/bandtrim.h
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions isis/src/base/apps/bandtrim/bandtrim.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
<change name="Steven Lambright" date="2008-05-12">
Removed references to CubeInfo
</change>
<change name="Ken Edmundson" date="2024-07-31">
Converted to callable app and converted Makefile tests to gtests.
</change>
</history>

<groups>
Expand Down
42 changes: 14 additions & 28 deletions isis/src/base/apps/bandtrim/main.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
4 changes: 0 additions & 4 deletions isis/src/base/apps/bandtrim/tsts/Makefile

This file was deleted.

6 changes: 0 additions & 6 deletions isis/src/base/apps/bandtrim/tsts/default/Makefile

This file was deleted.

6 changes: 0 additions & 6 deletions isis/src/base/apps/bandtrim/tsts/oneband/Makefile

This file was deleted.

192 changes: 192 additions & 0 deletions isis/tests/FunctionalTestsBandtrim.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@

#include <QString>
#include <QVector>

#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<QString> 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<Histogram> band1Hist (outCube.histogram(1));
std::unique_ptr<Histogram> band2Hist (outCube.histogram(2));
std::unique_ptr<Histogram> band3Hist (outCube.histogram(3));
std::unique_ptr<Histogram> band4Hist (outCube.histogram(4));
std::unique_ptr<Histogram> band5Hist (outCube.histogram(5));
std::unique_ptr<Histogram> band6Hist (outCube.histogram(6));
std::unique_ptr<Histogram> 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<QString> 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<Histogram> band1Hist (outCube.histogram(1));

EXPECT_EQ(band1Hist->ValidPixels(), 21);
EXPECT_EQ(band1Hist->Average(), 14.714285714285714);
EXPECT_EQ(band1Hist->Sum(), 309);

outCube.close();
}