Skip to content

Commit

Permalink
Added phocube options to create SUNILLUMINATIONMASK and SURFACEOBLIQU…
Browse files Browse the repository at this point in the history
…EDETECTORRESOLUTION backplanes. Added gtests for these options. Updated documentation and added an example. Addresses DOI-USGS#5467.
  • Loading branch information
kledmundson committed Apr 19, 2024
1 parent ef4a54b commit 28907f4
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 20 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions isis/src/base/apps/phocube/phocube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ namespace Isis {
bool bodyFixedZ = false;
bool localSolarTime = false;
bool sunilluminationmask = false;
bool surfaceobliquedetectorresolution = false;
int raBandNum = 0; // 0 based, if RA is 5th band, raBandNum will be 4

if (!noCamera) {
Expand Down Expand Up @@ -152,6 +153,7 @@ namespace Isis {
if ((bodyFixedZ = ui.GetBoolean("BODYFIXED"))) nbands++;
if ((localSolarTime = ui.GetBoolean("LOCALTIME"))) nbands++;
if ((sunilluminationmask = ui.GetBoolean("SUNILLUMINATIONMASK"))) nbands++;
if ((surfaceobliquedetectorresolution = ui.GetBoolean("SURFACEOBLIQUEDETECTORRESOLUTION"))) nbands++;
}

// ALLDN includes DN so if both are set ignore DN
Expand Down Expand Up @@ -341,6 +343,9 @@ namespace Isis {
if (sunilluminationmask) {
name += "Sun Illumination Mask";
}
if (surfaceobliquedetectorresolution) {
name += "Surface Oblique Detector Resolution";
}
bool specialPixels = ui.GetBoolean("SPECIALPIXELS");

/**
Expand Down Expand Up @@ -591,6 +596,7 @@ namespace Isis {
out[index] = pB[0];
index += 64 * 64;
}

if (bodyFixedY) {
out[index] = pB[1];
index += 64 * 64;
Expand Down
8 changes: 8 additions & 0 deletions isis/src/base/apps/phocube/phocube.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/** 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 phocube_h
#define phocube_h

Expand Down
112 changes: 94 additions & 18 deletions isis/src/base/apps/phocube/phocube.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ xsi:noNamespaceSchemaLocation=
<li>RADEC (<def link="Right Ascension">Right Ascension</def>, <def link="Declination">Declination</def> )</li>
<li><def link="Local Solar Time">LOCALTIME</def></li>
<li>SUNILLUMINATIONMASK</li>
<li>SURFACEOBLIQUEDETECTORRESOLUTION</li>
</ul>
The following options are available for Level2 images:
<ul>
Expand Down Expand Up @@ -326,15 +327,15 @@ xsi:noNamespaceSchemaLocation=
<change name="Adam Paquette" date="2020-08-23">
Added initial slope and backplane options for the local normal and the
ellipsoid normal.
<change name="UA/OSIRIS-REx IPWG Team" date="2024-04-09">
Added solar illumination mask backplane (SUNILLUMINATIONMASK).
Originally added to UofA 2018-01-25.
</change>
<change name="UA/OSIRIS-REx IPWG Team" date="2019-03-14">
Added SurfaceObliqueDetectorResoluton plane. This one is in addition to the
existing ObliqueDetectorResolution. The difference is ObliqueDetectorResolution
uses the local emission angle and SurfaceObliqueDetectorResolution uses the
emission angle calculated from the ellipsoid.
<change name="Ken Edmundson" date="2024-04-17">
Added Sunilluminationmask and SurfaceObliqueDetectorResolution backplanes.
SurfaceObliqueDetectorResolution is in addition to the existing
ObliqueDetectorResolution. The difference is that ObliqueDetectorResolution
uses the local emission angle while SurfaceObliqueDetectorResolution uses
the emission angle calculated from the ellipsoid. Sunilluminationmask and
SurfaceObliqueDetectorResolution were added to the U. of Arizona code base
by the UA/OSIRIS-REx IPWG Team on 2018-09-19 and 2019-03-29 respectively.
</change>
</history>

Expand Down Expand Up @@ -440,13 +441,13 @@ xsi:noNamespaceSchemaLocation=
<parameter name="SPECIALPIXELS">
<type>boolean</type>
<default><item>TRUE</item></default>
<brief>Include special pixels in the ouptut image</brief>
<brief>Include special pixels in the output image</brief>
<description>
Controls the output of the values phocube calculates based on the DN from the first band.
If this parameter is true, phocube will always attempt to calculate values for the requested bands.
If this parameter is false, and the DN is a special pixel value, phocube will not
calculate values, and will instead place ISIS Null values in all requested photometry bands.
The DN bands, if requested, will be transfered to the output cube regardless of this setting.
The DN bands, if requested, will be transferred to the output cube regardless of this setting.
</description>
</parameter>
<parameter name="DN">
Expand All @@ -473,14 +474,14 @@ xsi:noNamespaceSchemaLocation=
Calculations for the other bands that require a sensor model (e.g., phase) will be
based on the first band, again subject to the cube attribute.
This doesn't affect the values calculated for those bands when the
input image bands are spatially allinged,
input image bands are spatially aligned,
but it is very import when the bands of the input image are not
spatially alligned (e.g., Level 1, Odyssey, Themis IR).
spatially aligned (e.g., Level 1, Odyssey, Themis IR).
Use the input cube attribute to select the band used to calculate
the other phocube values (e.g., ThemisIR.cub+9,1-5).
The geometry of the first band or the first band in the input attribute,
will be used to calculate the phocube values.
NOTE: If the DN parameter is also set then ALLDNS will take presidence,
NOTE: If the DN parameter is also set then ALLDNS will take precedence,
and DN will be ignored.
</p>
</description>
Expand Down Expand Up @@ -712,7 +713,7 @@ xsi:noNamespaceSchemaLocation=
three bands (X, Y, Z) in the output cube. Meaning if your cube has an
ellipsoid shapemodel rather than a DEM, the local normal and the
ellipsoid normal will look the same. The output cube labels will contain
three "Local Normal (coord)" keywordsin the BandBin group, in band
three "Local Normal (coord)" keywords in the BandBin group, in band
sequence of the output file.

<p>
Expand Down Expand Up @@ -869,7 +870,7 @@ xsi:noNamespaceSchemaLocation=
or shadow mask, will be determined for every pixel. This option is mainly
useful for small irregular bodies, such as comets, where terrain is
occluded from solar illumination at the surface intersection point at
a given pixel. This information cannot be provided soley by incidence
a given pixel. This information cannot be provided solely by incidence
or local incidence angles because the occlusion occurs due to
foreground terrain, such as lobes in comets, at much larger distances
than the proximity of the initial surface point of intersection.
Expand All @@ -880,7 +881,7 @@ xsi:noNamespaceSchemaLocation=
spacecraft (camera) pixel intercept location on the surface. If the solar
intercept point on the surface is not the same point as seen from the
spacecraft/camera perspective, it is deemed occluded (shadowed).
For tesselated plate shape models, which are often used to represent
For tessellated plate shape models, which are often used to represent
the shape of irregular bodies, both camera and solar surface
intercept points must occur on the same triangle at approximately
the same location.
Expand All @@ -894,7 +895,7 @@ xsi:noNamespaceSchemaLocation=
the <b>local</b> incidence backplane where the angles are greater
than 90 degrees.
</p>
</description>
</description>
</parameter>
<parameter name="SURFACEOBLIQUEDETECTORRESOLUTION">
<type>boolean</type>
Expand Down Expand Up @@ -962,7 +963,7 @@ xsi:noNamespaceSchemaLocation=
FROM
</parameterName>
</image>
</inputImages>
</inputImages>S
<outputImages>
<image src="assets/images/phocube_lat_band.png" width="496" height="496">
<brief>Output file band 1 (Latitude)</brief>
Expand Down Expand Up @@ -992,5 +993,80 @@ xsi:noNamespaceSchemaLocation=
</image>
</outputImages>
</example>
<example>
<brief>Create "sun illumination mask" and "surface oblique detector resolution" backplane bands</brief>
<description>
In this example, <i>phocube</i> creates an output cube file with a
sun illumination backplane and a surface oblique detector resolution
backplane. These backplanes are shown below as separate snapshots
under "Output Images." The input image file shown below under "Input
Image" was not propagated to the <i>phocube</i> output file because DN
is set to false. The "DN" parameter must be set to "true" if the output
product is expected to contain the input image.
</description>
<terminalInterface>
<commandLine>
from=20190425T211232S312_map_iofL2pan.cub to=20190425T211232S312_map_iofL2pan.pho.cub specialpixels=no
phase=no emission=no incidence=no latitude=no longitude=no sunilluminationmask=yes
surfaceobliquedetectorresolution=yes
</commandLine>
<description>Run <i>phocube</i> to create sunilluminationmask and surfaceobliquedetectorresolution bands.</description>
</terminalInterface>
<guiInterfaces>
<guiInterface>
<image src="assets/images/phocube_gui_example2.jpg" width="458" height="764">
<brief>Example GUI</brief>
<description>
Screenshot of GUI version of the application.<br /> For this example,
only "SUNILLUMINATIONMASK" and "SURFACEOBLIQUEDETECTORRESOLUTION" are selected. The pre-selected
options "PHASE," "EMISSION," "INCIDENCE," "LATITUDE," and "LONGITUDE" are
deselected to avoid creating these unwanted backplanes.
</description>
<thumbnail src="assets/thumbs/thumb_phocube_gui_example2.jpg" caption="phocube GUI" width="147" height="245"/>
</image>
</guiInterface>
</guiInterfaces>
<inputImages>
<image src="assets/images/20190425T211232S312_map_iofL2pan.png" width="496" height="522">
<brief>Input file </brief>
<description>
Screenshot of the input cube file.
</description>
<thumbnail src="assets/thumbs/20190425T211232S312_map_iofL2pan_thumb.png" caption="Input image" width="200" height="210"/>
<parameterName>
FROM
</parameterName>
</image>
</inputImages>
<outputImages>
<image src="assets/images/phocube_sun_illumination_band.png" width="496" height="522">
<brief>Output file band 1 (SunIlluminationMask)</brief>
<description>
Screenshot of the first band in the output file. This band contains
sun illumination information. Occluded and illuminated pixel values
are 0 and 1 respectively.
</description>
<thumbnail src="assets/thumbs/thumb_phocube_sun_illumination_band.png" caption="Output image band 1 (Sun Illumination Mask)" width="200" height="210"/>
<parameterName>
TO
</parameterName>
</image>
<image src="assets/images/phocube_surface_oblique_detector_resolution_band.png" width="496" height="496">
<brief>Output file band 2 (SurfaceObliqueDetectorResolution)</brief>
<description>
Screenshot of the second band in the output file containing
Surface Oblique Detector Resolution information computed using the
emission angle determined from the ellipsoid. This produces a
smoother data plane compared to that created with the Oblique
Detector Resolution option, which is computed using the local
emission angle from the shape model.
</description>
<thumbnail src="assets/thumbs/thumb_phocube_surface_oblique_detector_resolution_band.png" caption="Output image band 2 (Surface Oblique Detector Resolution)" width="200" height="200"/>
<parameterName>
TO
</parameterName>
</image>
</outputImages>
</example>
</examples>
</application>
110 changes: 108 additions & 2 deletions isis/tests/FunctionalTestsPhocube.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "phocube.h"

#include <QTemporaryFile>
#include <QTemporaryDir>
#include <QTextStream>
#include <QStringList>

Expand Down Expand Up @@ -57,8 +58,7 @@ TEST_F(DefaultCube, FunctionalTestPhocubeDefault) {


TEST_F(DefaultCube, FunctionalTestPhocubeAllBands) {
// QString cubeFileName = tempDir.path() + "/phocubeTEMP.cub";
QString cubeFileName = "phocubeTEMP.cub";
QString cubeFileName = tempDir.path() + "/phocubeTEMP.cub";
QVector<QString> args = {"to=" + cubeFileName, "dn=true", "phase=true", "emission=true",
"incidence=true", "localemission=true", "localincidence=true",
"latitude=true", "longitude=true", "pixelresolution=true",
Expand Down Expand Up @@ -451,3 +451,109 @@ TEST_F(DefaultCube, FunctionalTestPhocubeAllDnBands) {
cube.close();
}


/**
* FunctionalTestPhocubeSunIlluminationMask
*
* phocube test of sunilluminationmask backplane.
* Input ...
* 1) Cropped OSIRIS-REx MapCam cube
* (data/phocube/20190425T211232S312_map_iofL2pan-crop.cub)
* 2) phase, emission, incidence, latitude, longitude = no
* 3) sunilluminationmask = yes
*
* Output ...
* cube with sunilluminationmask backplane
*/
TEST(Phocube, FunctionalTestPhocubeSunIlluminationMask) {
QTemporaryDir tempDir;

// instantiate test cube
Cube testCube("data/phocube/20190425T211232S312_map_iofL2pan-crop.cub");

QString outCubeFileName = tempDir.path() + "/phocubeTEMP.cub";
QVector<QString> args = {"to=" + outCubeFileName, "phase=no", "emission=no",
"incidence=no", "latitude=no", "longitude=no",
"sunilluminationmask=yes"};
UserInterface options(APP_XML, args);
phocube(&testCube, options);

// open output cube and retrieve label
Cube cube(outCubeFileName);
Pvl *isisLabel = cube.label();

ASSERT_EQ(cube.sampleCount(), testCube.sampleCount());
ASSERT_EQ(cube.lineCount(), testCube.lineCount());
ASSERT_EQ(cube.bandCount(), 1);

PvlGroup bandBin = isisLabel->findGroup("BandBin", Pvl::Traverse);
EXPECT_PRED_FORMAT2(AssertQStringsEqual, bandBin.findKeyword("Name")[0],
"Sun Illumination Mask");

for (int i = 0; i < cube.bandCount(); i++) {
EXPECT_DOUBLE_EQ(bandBin.findKeyword("Center")[i].toDouble(), 650.0);
EXPECT_DOUBLE_EQ(bandBin.findKeyword("Width")[i].toDouble(), 1.0);
}

// verify statistics of SunIlluminationMask band
std::unique_ptr<Histogram> hist (cube.histogram(1));
EXPECT_NEAR(hist->Average(), 0.44588570919140591, .000001);
EXPECT_NEAR(hist->Sum(), 30009, .000001);
EXPECT_EQ(hist->ValidPixels(), 67302);
EXPECT_NEAR(hist->StandardDeviation(), 0.49706671048663414, .000001);

cube.close();
}


/**
* FunctionalTestPhocubeSurfaceObliqueDetectorResolution
*
* phocube test of surfaceobliquedetectorresolution backplane.
* Input ...
* 1) Cropped OSIRIS-REx MapCam cube
* (data/phocube/20190425T211232S312_map_iofL2pan-crop.cub)
* 2) phase, emission, incidence, latitude, longitude = no
* 3) surfaceobliquedetectorresolution = yes
*
* Output ...
* cube with surfaceobliquedetectorresolution backplane
*/
TEST(Phocube, FunctionalTestPhocubeSurfaceObliqueDetectorResolution) {
QTemporaryDir tempDir;

// instantiate test cube
Cube testCube("data/phocube/20190425T211232S312_map_iofL2pan-crop.cub");

QString outCubeFileName = tempDir.path() + "/phocubeTEMP.cub";
QVector<QString> args = {"to=" + outCubeFileName, "phase=no", "emission=no",
"incidence=no", "latitude=no", "longitude=no",
"surfaceobliquedetectorresolution=yes"};
UserInterface options(APP_XML, args);
phocube(&testCube, options);

// open output cube and retrieve label
Cube cube(outCubeFileName);
Pvl *isisLabel = cube.label();

ASSERT_EQ(cube.sampleCount(), testCube.sampleCount());
ASSERT_EQ(cube.lineCount(), testCube.lineCount());
ASSERT_EQ(cube.bandCount(), 1);

PvlGroup bandBin = isisLabel->findGroup("BandBin", Pvl::Traverse);
EXPECT_PRED_FORMAT2(AssertQStringsEqual, bandBin.findKeyword("Name")[0], "Surface Oblique Detector Resolution");

for (int i = 0; i < cube.bandCount(); i++) {
EXPECT_DOUBLE_EQ(bandBin.findKeyword("Center")[i].toDouble(), 650.0);
EXPECT_DOUBLE_EQ(bandBin.findKeyword("Width")[i].toDouble(), 1.0);
}

// verify statistics of SunIlluminationMask band
std::unique_ptr<Histogram> hist (cube.histogram(1));
EXPECT_NEAR(hist->Average(), 1.9283095245704811, .000001);
EXPECT_NEAR(hist->Sum(), 129779.08762264252, .000001);
EXPECT_EQ(hist->ValidPixels(), 67302);
EXPECT_NEAR(hist->StandardDeviation(), 67.195033751062496, .000001);

cube.close();
}

0 comments on commit 28907f4

Please sign in to comment.