Unverified Commit 1528aedd authored by Kaitlyn Lee's avatar Kaitlyn Lee Committed by GitHub
Browse files

Added the ability to skip special pixels in phocube (#3897)

* Added ignore special pixels parameter and new test

* Forgot to include change to xml file

* Changed process function to lambda function to get rid of global variables

* Response to comments
parent 4c7d776f
Loading
Loading
Loading
Loading
+245 −285
Original line number Diff line number Diff line
@@ -16,44 +16,6 @@
using namespace std;
using namespace Isis;

// Global variables
Camera *cam;
TProjection *proj;
int nbands;
bool noCamera;

bool dn;
bool phase;
bool emission;
bool incidence;
bool localEmission;
bool localIncidence;
bool latitude;
bool longitude;
bool pixelResolution;
bool lineResolution;
bool sampleResolution;
bool detectorResolution;
bool obliqueDetectorResolution;
bool northAzimuth;
bool sunAzimuth;
bool spacecraftAzimuth;
bool offnadirAngle;
bool subSpacecraftGroundAzimuth;
bool subSolarGroundAzimuth;
bool morphologyRank;
bool albedoRank;
bool ra;
bool declination;
bool bodyFixedX;
bool bodyFixedY;
bool bodyFixedZ;

int raBandNum;

void phocubeDN(Buffer &in, Buffer &out);
void phocube(Buffer &out);


// Function to create a keyword with same values of a specified count
template <typename T> PvlKeyword makeKey(const QString &name,
@@ -73,8 +35,6 @@ MosData *getMosaicIndicies(Camera &camera, MosData &md);
void UpdateBandKey(const QString &keyname, PvlGroup &bb, const int &nvals,
                   const QString &default_value = "Null");



void IsisMain() {
  UserInterface &ui = Application::GetUserInterface();

@@ -82,6 +42,8 @@ void IsisMain() {
  // projection information
  Process p1;
  Cube *icube = p1.SetInputCube("FROM", OneBand);

  bool noCamera;
  if (ui.GetString("SOURCE") == "CAMERA") {
    noCamera = false;
  }
@@ -89,6 +51,8 @@ void IsisMain() {
    noCamera = true;
  }

  Camera *cam;
  TProjection *proj;
  if(noCamera) {
    try {
      proj = (TProjection *) icube->projection();
@@ -113,30 +77,30 @@ void IsisMain() {
  ProcessByBrick p;

  // Find out which bands are to be created
  nbands = 0;
  phase = false;
  emission = false;
  incidence = false;
  localEmission = false;
  localIncidence = false;
  lineResolution = false;
  sampleResolution = false;
  detectorResolution = false;
  obliqueDetectorResolution = false;
  sunAzimuth = false;
  spacecraftAzimuth = false;
  offnadirAngle = false;
  subSpacecraftGroundAzimuth = false;
  subSolarGroundAzimuth = false;
  morphologyRank = false;
  albedoRank = false;
  northAzimuth = false;
  ra = false;
  declination = false;
  bodyFixedX = false;
  bodyFixedY = false;
  bodyFixedZ = false;
  raBandNum = 0;  // 0 based, if RA is 5th band, raBandNum will be 4
  int nbands = 0;
  bool phase = false;
  bool emission = false;
  bool incidence = false;
  bool localEmission = false;
  bool localIncidence = false;
  bool lineResolution = false;
  bool sampleResolution = false;
  bool detectorResolution = false;
  bool obliqueDetectorResolution = false;
  bool sunAzimuth = false;
  bool spacecraftAzimuth = false;
  bool offnadirAngle = false;
  bool subSpacecraftGroundAzimuth = false;
  bool subSolarGroundAzimuth = false;
  bool morphologyRank = false;
  bool albedoRank = false;
  bool northAzimuth = false;
  bool ra = false;
  bool declination = false;
  bool bodyFixedX = false;
  bool bodyFixedY = false;
  bool bodyFixedZ = false;
  int raBandNum = 0;  // 0 based, if RA is 5th band, raBandNum will be 4

  if (!noCamera) {
    if ((phase = ui.GetBoolean("PHASE"))) nbands++;
@@ -162,9 +126,17 @@ void IsisMain() {
    if ((bodyFixedY = ui.GetBoolean("BODYFIXED"))) nbands++;
    if ((bodyFixedZ = ui.GetBoolean("BODYFIXED"))) nbands++;
  }

  bool dn;
  if ((dn = ui.GetBoolean("DN"))) nbands++;

  bool latitude;
  if ((latitude = ui.GetBoolean("LATITUDE"))) nbands++;

  bool longitude;
  if ((longitude = ui.GetBoolean("LONGITUDE"))) nbands++;

  bool pixelResolution;
  if ((pixelResolution = ui.GetBoolean("PIXELRESOLUTION"))) nbands++;

  if (nbands < 1) {
@@ -288,87 +260,43 @@ void IsisMain() {
    name += "Body Fixed Z";
  }

  // Create the output cube.  Note we add the input cube to expedite propagation
  // of input cube elements (label, blobs, etc...).  It will be cleared
  // prior to systematic processing only if the DN option is not selected.
  // If DN is chosen by the user, then we propagate the input buffer with a
  // different function - one that accepts both input and output buffers.
  (void) p.SetInputCube("FROM", OneBand);
  Cube *ocube = p.SetOutputCube("TO", icube->sampleCount(),
                                icube->lineCount(), nbands);
  p.SetBrickSize(64, 64, nbands);
  bool specialPixels = ui.GetBoolean("SPECIALPIXELS");

  if (dn) {
    // Process with input and output buffers
    p.StartProcess(phocubeDN);
  }
  else {
    // Toss the input file as stated above
    p.ClearInputCubes();

    // Start the processing
    p.StartProcess(phocube);
  }

  // Add the bandbin group to the output label.  If a BandBin group already
  // exists, remove all existing keywords and add the keywords for this app.
  // Otherwise, just put the group in.
  PvlObject &cobj = ocube->label()->findObject("IsisCube");
  if (!cobj.hasGroup("BandBin")) {
    cobj.addGroup(PvlGroup("BandBin"));
  }
  /**
   * Computes all the geometric properties for the output buffer. Certain
   * knowledge of the buffers size is assumed below, so ensure the buffer
   * is still of the expected size.
   * 
   * @param in  The input cube buffer.
   * @param out The output cube buffer.
   */
  auto phocube = [&](Buffer &in, Buffer &out)->void {
    for (int i = 0; i < 64; i++) {
      for (int j = 0; j < 64; j++) {

  PvlGroup &bb = cobj.findGroup("BandBin");
  bb.addKeyword(name, PvlContainer::Replace);
  int nvals = name.size();
  UpdateBandKey("Center", bb, nvals, "1.0");
        MosData mosd, *p_mosd(0);  // For special mosaic angles

  if ( bb.hasKeyword("OriginalBand") ) {
    UpdateBandKey("OriginalBand", bb, nvals, "1.0");
  }
        int index = i * 64 + j;
        int inIndex = index;

  if ( bb.hasKeyword("Number") ) {
    UpdateBandKey("Number", bb, nvals, "1.0");
        if (dn) {
          out[index] = in[index];
          index += 64 * 64;
        }

  UpdateBandKey("Width", bb, nvals, "1.0");



  p.EndProcess();
        // If dn is true, make sure to not overwrite the original pixels with NULL for the dn band
        if (!specialPixels && IsSpecial(in[inIndex])) {
          for (int band = (dn) ? 1 : 0; band < nbands; band++) {
            out[index] = Isis::Null;
            index += 64 * 64;
          }


//  This propagates the input plane to the output plane, then passes it off to
//  the general routine
void phocubeDN(Buffer &in, Buffer &out) {
  for (int i = 0 ; i < in.size() ; i++) {
    out[i] = in[i];
  }
  phocube(out);
          continue;
        }


//  Computes all the geometric properties for the output buffer.  Certain
//  knowledge of the buffers size is assumed below, so ensure the buffer
//  is still of the expected size.
void phocube(Buffer &out) {


  // If the DN option is selected, it is already added by the phocubeDN
  // function.  We must compute the offset to start at the second band.
  int skipDN = (dn) ? 64 * 64   :  0;

  for (int i = 0; i < 64; i++) {
    for (int j = 0; j < 64; j++) {

      MosData mosd, *p_mosd(0);  // For special mosaic angles

      int index = i * 64 + j + skipDN;
        // Checks to see if the point is off the body
        double samp = out.Sample(index);
        double line = out.Line(index);

      // Checks to see if the point is in outer space
        bool isGood = false;
        if (noCamera) {
          isGood = proj->SetWorld(samp, line);
@@ -532,21 +460,53 @@ void phocube(Buffer &out) {

        // Trim outer space except RA and dec bands
        else {
        for (int b = (skipDN) ? 1 : 0; b < nbands; b++) {
          if(ra && b == raBandNum) {
          for (int band = (dn) ? 1 : 0; band < nbands; band++) {
            if(ra && band == raBandNum) {
              out[index] = cam->RightAscension();
            }
          else if (declination && b == raBandNum + 1) {
            else if (declination && band == raBandNum + 1) {
              out[index] = cam->Declination();
            }
            else {
            out[index] = Isis::NULL8;
              out[index] = Isis::Null;
            }
            index += 64 * 64;
          }
        }
      }
    }
  };

  (void) p.SetInputCube("FROM", OneBand);
  Cube *ocube = p.SetOutputCube("TO", icube->sampleCount(),
                                icube->lineCount(), nbands);
  p.SetBrickSize(64, 64, nbands);
  p.StartProcess(phocube);

  // Add the bandbin group to the output label.  If a BandBin group already
  // exists, remove all existing keywords and add the keywords for this app.
  // Otherwise, just put the group in.
  PvlObject &cobj = ocube->label()->findObject("IsisCube");
  if (!cobj.hasGroup("BandBin")) {
    cobj.addGroup(PvlGroup("BandBin"));
  }

  PvlGroup &bb = cobj.findGroup("BandBin");
  bb.addKeyword(name, PvlContainer::Replace);
  int nvals = name.size();
  UpdateBandKey("Center", bb, nvals, "1.0");

  if ( bb.hasKeyword("OriginalBand") ) {
    UpdateBandKey("OriginalBand", bb, nvals, "1.0");
  }

  if ( bb.hasKeyword("Number") ) {
    UpdateBandKey("Number", bb, nvals, "1.0");
  }

  UpdateBandKey("Width", bb, nvals, "1.0");

  p.EndProcess();
}


+16 −0
Original line number Diff line number Diff line
@@ -305,6 +305,13 @@ xsi:noNamespaceSchemaLocation=
    <change name="Kaitlyn Lee" date="2019-02-15">
      Allowed RA and DEC to be exported regardless if the pixel is off body. Fixes #4446.
    </change>
    <change name="Kaitlyn Lee" date="2020-06-04">
      Added SPECIALPIXELS parameter to allow users to skip calculations on special pixels, excluding
      RA and DEC. This changed merged the two process functions, which were created to speed up 
      the application when copying over DN values. After a few time tests, it doesn't look like the 
      merge causes the application to run longer. Changed the process function to be a lambda function
      to get rid of global variables.
    </change>
  </history>

  <category>
@@ -403,6 +410,15 @@ xsi:noNamespaceSchemaLocation=
    </group>

    <group name="Photometry">
      <parameter name="SPECIALPIXELS">
        <type>boolean</type>
        <default><item>TRUE</item></default>
        <brief>Include special pixels in the ouptut image</brief>
        <description>
          If this parameter is true, calculations will be done on special pixels.
          If this parameter is false, special pixels will be skipped and set to NULL in the output image for all bands selected.
        </description>
      </parameter>
      <parameter name="DN">
        <type>boolean</type>
        <default><item>FALSE</item></default>
+13 −0
Original line number Diff line number Diff line
# Tests that special pixels in the input are set to null for all bands.
APPNAME = phocube

include $(ISISROOT)/make/isismake.tsts

commands:
	$(APPNAME) from=$(INPUT)/ab102401.cropped.lvl2.cub \
	  to=$(OUTPUT)/output.cub \
	  specialpixels=false \
	  dn=true \
	  radec=true > /dev/null; 
	catlab from=$(OUTPUT)/output.cub \
	  to=$(OUTPUT)/output.pvl > /dev/null;