From 0a48527b3615f904d44e18d01cfea08a2457b6ec Mon Sep 17 00:00:00 2001 From: victoronline Date: Mon, 18 Apr 2022 18:24:11 -0700 Subject: [PATCH] squashing last 3 commits --- isis/src/lro/apps/lronacpho/LROCEmpirical.cpp | 80 ++++--- isis/src/lro/apps/lronacpho/LROCEmpirical.h | 30 ++- isis/src/lro/apps/lronacpho/lronacpho.cpp | 217 ++++++++++++++++++ isis/src/lro/apps/lronacpho/lronacpho.h | 28 +++ isis/src/lro/apps/lronacpho/lronacpho.xml | 111 +++++---- isis/src/lro/apps/lronacpho/main.cpp | 189 +-------------- isis/src/lro/apps/lronacpho/old.main.cpp | 213 +++++++++++++++++ 7 files changed, 599 insertions(+), 269 deletions(-) create mode 100644 isis/src/lro/apps/lronacpho/lronacpho.cpp create mode 100644 isis/src/lro/apps/lronacpho/lronacpho.h create mode 100644 isis/src/lro/apps/lronacpho/old.main.cpp diff --git a/isis/src/lro/apps/lronacpho/LROCEmpirical.cpp b/isis/src/lro/apps/lronacpho/LROCEmpirical.cpp index 8e512f68a3..dfeb5bf2ff 100644 --- a/isis/src/lro/apps/lronacpho/LROCEmpirical.cpp +++ b/isis/src/lro/apps/lronacpho/LROCEmpirical.cpp @@ -173,7 +173,8 @@ namespace Isis { * @internal * @history 2016-08-15 Victor Silva - Adapted code from lrowacpho application * written by Kris Becker - * + * @history 2021-03-12 Victor Silva - Added b parameters for 2019 version of + * LROC Empirical algorithm */ double LROCEmpirical::photometry( const Parameters &parms, double i, double e, double g ) const { // Ensure problematic values are adjusted @@ -193,7 +194,16 @@ namespace Isis { double mu = cos(e); double mu0 = cos(i); double alpha = g; - double rcal = exp(parms.a0 + parms.a1 * alpha + parms.a2 * mu + parms.a3 * mu0); + double rcal; + + if (parms.algoVersion == 2014 || parms.algoVersion == 0) + rcal = exp(parms.aTerms[0] + parms.aTerms[1] * alpha + parms.aTerms[2] * mu + parms.aTerms[3] * mu0); + else if (parms.algoVersion == 2019) + rcal = mu0 / (mu + mu0) * exp(parms.bTerms[0] + parms.bTerms[1] * (alpha * alpha) + parms.bTerms[2] * alpha + parms.bTerms[3] * sqrt(alpha) + parms.bTerms[4] * mu + parms.bTerms[5] * mu0 + parms.bTerms[6] * (mu0 * mu0) ); + else { + std::string mess = "Algorithm version in PVL file not recognized [" + IString(parms.algoVersion) + "]. Supported versions are [0, 2014, 2019]."; + throw IException(IException::Programmer, mess, _FILEINFO_); + } return (rcal); } @@ -212,6 +222,8 @@ namespace Isis { * @internal * @history 2016-08-15 Victor Silva - Adapted code from lrowacpho application * written by Kris Becker + * @history 2021-03-12 Victor Silva - Added b parameters for 2019 version of + * LROC Empirical algorithm */ void LROCEmpirical::report( PvlContainer &pvl ) { @@ -219,16 +231,18 @@ namespace Isis { pvl.addComment(" where:"); pvl.addComment(" mu0 = cos(incidence)"); pvl.addComment(" mu = cos(emission)"); - pvl.addComment(" F(mu, mu0, phase) = exp(A0 + A1 * phase + A2 * mu + A3 * mu0 "); + + if (m_bandpho[0].algoVersion == 2019 ) + pvl.addComment(" F(mu, mu0, phase) = mu0 / (mu + mu0) * exp(B0 + B1 * (alpha * alpha) + B2 * alpha + B3 * sqrt(alpha) + B4 * mu + B5 * mu0 + B6 * (mu0 * mu0) )"); + else if (m_bandpho[0].algoVersion == 2014 || m_bandpho[0].algoVersion == 0) + pvl.addComment(" F(mu, mu0, phase) = exp (A0 + A1 * phase + A2 * mu + A3 * mu0 "); + else { + std::string mess = "Could not file the correction algorithm name."; + throw IException(IException::Programmer, mess, _FILEINFO_); + } pvl += PvlKeyword("Algorithm", "LROC_Empirical"); - pvl += PvlKeyword("IncRef", toString(m_iRef), "degrees"); - pvl += PvlKeyword("EmaRef", toString(m_eRef), "degrees"); - pvl += PvlKeyword("Algorithm", "LROC_Empirical"); - pvl += PvlKeyword("IncRef", toString(m_iRef), "degrees"); - pvl += PvlKeyword("EmaRef", toString(m_eRef), "degrees"); - pvl += PvlKeyword("EmaRef", toString(m_eRef), "degrees"); - pvl += PvlKeyword("Algorithm", "LROC_Empirical"); + pvl += PvlKeyword("AlgorithmVersion", toString(m_bandpho[0].algoVersion), "" ); pvl += PvlKeyword("IncRef", toString(m_iRef), "degrees"); pvl += PvlKeyword("EmaRef", toString(m_eRef), "degrees"); pvl += PvlKeyword("PhaRef", toString(m_gRef), "degrees"); @@ -238,10 +252,13 @@ namespace Isis { PvlKeyword bbc("BandBinCenter"); PvlKeyword bbct("BandBinCenterTolerance"); PvlKeyword bbn("BandNumber"); - PvlKeyword a0("A0"); - PvlKeyword a1("A1"); - PvlKeyword a2("A2"); - PvlKeyword a3("A3"); + + std::vector aTermKeywords; + std::vector bTermKeywords; + for (unsigned int i = 0; i < m_bandpho[0].aTerms.size(); i++) + aTermKeywords.push_back(PvlKeyword("A" + toString((int) i))); + for (unsigned int i = 0; i < m_bandpho[0].bTerms.size(); i++) + bTermKeywords.push_back(PvlKeyword("B" + toString((int) i))); for (unsigned int i = 0; i < m_bandpho.size(); i++) { Parameters &p = m_bandpho[i]; @@ -250,10 +267,10 @@ namespace Isis { bbc.addValue(toString(p.wavelength)); bbct.addValue(toString(p.tolerance)); bbn.addValue(toString(p.band)); - a0.addValue(toString(p.a0)); - a1.addValue(toString(p.a1)); - a2.addValue(toString(p.a2)); - a3.addValue(toString(p.a3)); + for (unsigned int j = 0; j < aTermKeywords.size(); j++) + aTermKeywords[j].addValue(toString(p.aTerms[j])); + for (unsigned int j = 0; j < bTermKeywords.size(); j++) + bTermKeywords[j].addValue(toString(p.bTerms[j])); } pvl += units; @@ -261,10 +278,11 @@ namespace Isis { pvl += bbc; pvl += bbct; pvl += bbn; - pvl += a0; - pvl += a1; - pvl += a2; - pvl += a3; + + for (unsigned int i = 0; i < aTermKeywords.size(); i++) + pvl += aTermKeywords[i]; + for (unsigned int i = 0; i < bTermKeywords.size(); i++) + pvl += bTermKeywords[i]; return; } @@ -277,7 +295,7 @@ namespace Isis { * use for a given wavelength. It iterates through all band profiles * as read from the PVL file and computes the difference between * wavelength parameter and the BandBinCenter keyword. The absolute - * value of this value is checke against the BandBinCenterTolerance + * value of this value is check against the BandBinCenterTolerance * parameter and if it is less than or equal to it, a Parameter * container is returned. * @@ -333,18 +351,26 @@ namespace Isis { * * @internal * @history 2016-08-15 Victor Silva - Adapted from the lrowacpho application - written by Kris Becker. + * written by Kris Becker. + * + * @history 2021-03-12 Victor Silva - Added b parameters for 2019 version of + * LROC Empirical algorithm + * */ LROCEmpirical::Parameters LROCEmpirical::extract( const DbProfile &profile) const { Parameters pars; - pars.a1 = toDouble(ConfKey(profile, "A1", toString(0.0))); - pars.a2 = toDouble(ConfKey(profile, "A2", toString(0.0))); - pars.a3 = toDouble(ConfKey(profile, "A3", toString(0.0))); + + for (int i=0; i<4; i++) + pars.aTerms.push_back(toDouble(ConfKey(profile, "A" + toString(i), "0.0"))); + for (int i=0; i<7; i++) + pars.bTerms.push_back(toDouble(ConfKey(profile, "B" + toString(i), "0.0"))); + pars.wavelength = toDouble(ConfKey(profile, "BandBinCenter", toString(Null))); pars.tolerance = toDouble(ConfKey(profile, "BandBinCenterTolerance", toString(Null))); // Determine equation units - defaults to Radians pars.units = ConfKey(profile, "Units", QString("Radians")); pars.phaUnit = (pars.units.toLower() == "degrees") ? 1.0 : rpd_c(); + pars.algoVersion = toInt(ConfKey(profile, "AlgorithmVersion", "0")); return (pars); } diff --git a/isis/src/lro/apps/lronacpho/LROCEmpirical.h b/isis/src/lro/apps/lronacpho/LROCEmpirical.h index 5ace4c69f0..8e9aed1a46 100644 --- a/isis/src/lro/apps/lronacpho/LROCEmpirical.h +++ b/isis/src/lro/apps/lronacpho/LROCEmpirical.h @@ -35,6 +35,8 @@ namespace Isis { * * @internal * @history 2016-08-15 - Code adapted from lrowacpho written by Kris Becker + * @history 2021-03-12 Victor Silva - Added b parameters for 2019 version of + * LROC Empirical algorithm * */ class LROCEmpirical : public PhotometricFunction { @@ -53,23 +55,29 @@ namespace Isis { * * @internal * @history 2016-08-05 - Code adapted from lrowacpho written by Kris Becker + * @history 2021-03-12 Victor Silva - Added b parameters for 2019 version of + * LROC Empirical algorithm */ struct Parameters { - Parameters() : a0(0.0), a1(0.0), a2(0.0), a3(0.0), + Parameters() : aTerms(), bTerms(), wavelength(0.0), tolerance(0.0), units("Degrees"), phaUnit(1.0), band(0), phoStd(0.0), + algoVersion(2019), iProfile(-1) { } ~Parameters() { } - bool IsValid() const { return (iProfile != -1);} - double a0, a1, a2, a3; // aTerms; // bTerms; //open(ui.getCubeName("FROM")); + return lronacpho(iCube, ui); + } + + /** + * @brief Photometric application for the LRO NAC cameras + * + * This application provides features that allow multiband cubes for LRO NAC cameras + * to be photometrically corrected + * @author 2016-09-16 Victor Silva + * + * @internal + * @history 2016-09-19 Victor Silva - Adapted from lrowacpho written by Kris Becker + * @history 2021-03-12 Victor Silva - Updates include ability to run with default values + * Added new values for 2019 version of LROC Empirical function. + * @history 2022-04-18 Victor Silva - Refactored to make callable for GTest framework + * + * @param iCube The input cube to be photometrically corrected. + * @param ui The user interfact to parse the parameters from. + */ + void lronacpho(Cube iCube, UserInterface &ui){ + // forward declare helper functions + void phoCal (Buffer &in, Buffer &out); + void phoCalWithBackplane (std::vector &in, std::vector &out ); + + // globals + static bool g_useDEM; + PhotometricFunction *g_phoFunction; + + ProcessByLine p; + // Set up input cube and get camera info + //Cube *iCube = p.SetInputCube("FROM"); + + // set up input cube + QString from = ui.GetAsString("FROM"); + CubeAttributeInput inAtt(from); + cube = new Cube(); + from = ui.getCubeName("FROM"); + cube->open(from); + p.SetInputCube(ui.GetCubeName("FROM"), inputAtt); + + Cube *oCube = p.SetOutputCube("TO"); + + // Backplane option + bool useBackplane = false; + if (ui.WasEntered("BACKPLANE")) { + CubeAttributeInput backplaneCai = ui.GetInputAttribute("BACKPLANE"); + + Cube bpCube; + bpCube.open(ui.GetFileName("BACKPLANE")); + int bpBands = bpCube.bandCount(); + bpCube.close(); + + int bpCaiBands = backplaneCai.bands().size(); + if (bpBands < 3 || (bpCaiBands != 3 && bpBands > 3)) { + string msg = "Invalid Backplane: The backplane must be exactly 3 bands"; + throw IException(IException::User, msg, _FILEINFO_); + } + + if (iCube->bandCount() != 1) { + string msg = "Invalid Image: The backplane option can only be used with a single image band at a time."; + throw IException(IException::User, msg, _FILEINFO_); + } + + CubeAttributeInput cai; + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[0]) : cai.setAttributes("+1" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[1]) : cai.setAttributes("+2" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[2]) : cai.setAttributes("+3" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + + useBackplane = true; + } + + // Get name of parameters file + QString algoName = ""; + QString algoFile = ui.GetAsString("PHOPAR"); + + FileName algoFileName(algoFile); + + if(algoFileName.isVersioned()) + algoFileName = algoFileName.highestVersion(); + + if(!algoFileName.fileExists()) { + QString msg = algoFile + " does not exist."; + throw IException(IException::User, msg, _FILEINFO_); + } + + Pvl params(algoFileName.expanded()); + + algoName = PhotometricFunction::algorithmName(params); + algoName = algoName.toUpper(); + + // Set NAC algorithm + if (algoName == "LROC_EMPIRICAL") { + g_phoFunction = new LROCEmpirical(params, *iCube, !useBackplane); + } + else { + QString msg = " Algorithm Name [" + algoName + "] not recognized. "; + msg += "Compatible Algorithms are:\n LROC_Empirical\n"; + throw IException(IException::User, msg, _FILEINFO_); + } + + // Set user selected max and mins + g_phoFunction->setMinimumPhaseAngle(ui.GetDouble("MINPHASE")); + g_phoFunction->setMaximumPhaseAngle(ui.GetDouble("MAXPHASE")); + g_phoFunction->setMinimumEmissionAngle(ui.GetDouble("MINEMISSION")); + g_phoFunction->setMaximumEmissionAngle(ui.GetDouble("MAXEMISSION")); + g_phoFunction->setMinimumIncidenceAngle(ui.GetDouble("MININCIDENCE")); + g_phoFunction->setMaximumIncidenceAngle(ui.GetDouble("MAXINCIDENCE")); + + // Set use of DEM to calculate photometric angles + g_useDEM = ui.GetBoolean("USEDEM"); + + // Begin processing by line + if(useBackplane) { + p.StartProcess(phoCalWithBackplane); + } + else { + p.StartProcess(phoCal); + } + // Start all the PVL + PvlGroup photo("Photometry"); + g_phoFunction->report(photo); + oCube->putGroup(photo); + Application::Log(photo); + p.EndProcess(); + p.ClearInputCubes(); + delete g_phoFunction; + } + /** + * @brief Apply LROC Empirical photometric correction with backplane + * + * Short function dispatched for each line to apply the LROC Empirical photometric + * correction function. + * + * @author 2016-09-19 Victor Silva + * + * @internal + * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker + * @history 2022-04-18 Victor Silva - Refactored to make callable for GTest framework + * + * @param in Buffer containing input data + * @param out Buffer of photometrically corrected data + */ + auto phoCal = [&](Buffer &in, Buffer &out)->void{ + // Iterate through pixels + for(int i = 0; i < in.size(); i++){ + // Ignore special pixels + if(IsSpecial(in[i])){ + out[i] = in[i]; + } + else{ + // Get correction and test for validity + double ph = g_pho->compute(in.Line(i), in.Sample(i), in.Band(i), g_useDEM); + out[i] = ( IsSpecial(ph) ? Null : (in[i] * ph) ); + } + } + return; + }//end phoCal + + /** + * @brief Apply LROC Empirical photometric correction with backplane + * + * Short function dispatched for each line to apply the LROC Empirical photometrc + * correction function. + * + * @author 2016-09-19 Victor Silva + * + * @internal + * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker + * @history 2022-04-18 Victor Silva - Refactored to make callable for GTest framework + * + * @param in Buffer containing input data + * @param out Buffer of photometrically corrected data + */ + auto phoCalWithBackplane [&]( std::vector &in, std::vector &out )->void { + + Buffer &image = *in[0]; + Buffer &phase = *in[1]; + Buffer &emission = *in[2]; + Buffer &incidence = *in[3]; + Buffer &calibrated = *out[0]; + + for (int i = 0; i < image.size(); i++) { + // Don't correct special pixels + if (IsSpecial(image[i])) { + calibrated[i] = image[i]; + } + else { + // Get correction and test for validity + double ph = g_pho->photometry(incidence[i], emission[i], phase[i], image.Band(i)); + calibrated[i] = (IsSpecial(ph) ? Null : image[i] * ph); + } + } + return; + } +} + diff --git a/isis/src/lro/apps/lronacpho/lronacpho.h b/isis/src/lro/apps/lronacpho/lronacpho.h new file mode 100644 index 0000000000..aea081603b --- /dev/null +++ b/isis/src/lro/apps/lronacpho/lronacpho.h @@ -0,0 +1,28 @@ + + +#ifndef lronacpho_h +#define lronacpho_h + +#include "Isis.h" +#include "Cube.h" +#include "IException.h" +#include "ProcessByLine.h" +#include "Pvl.h" +#include "PvlGroup.h" +#include "SpecialPixel.h" +#include "UserInterface.h" + +#include "lronacpho.h" +#include "LROCEmpirical.h" +#include "PhotometricFunction.h" +#include "UserInterface.h" +#include +#include +#include + +namespace Isis{ + extern PvlGroup lronacpho(Cube* iCube, UserInterface &ui); + extern PvlGroup lronacpho(UserInterface &ui); +} + +#endif \ No newline at end of file diff --git a/isis/src/lro/apps/lronacpho/lronacpho.xml b/isis/src/lro/apps/lronacpho/lronacpho.xml index 4f1b951b23..19eec13f62 100644 --- a/isis/src/lro/apps/lronacpho/lronacpho.xml +++ b/isis/src/lro/apps/lronacpho/lronacpho.xml @@ -8,18 +8,24 @@

- LROC Empirical implements a photometric correction + LROC Empirical implements a photometric correction

       I/F = F(mu, mu0,phase)
               where
                   mu0 = cos(incidence)
                   mu = cos(emission)
-                  F(mu, mu0, phase) = e(A0 + A1 * phase + A2 * mu + A3 * mu0) 
+                  (2014 version)
+                    F(mu, mu0, phase) = e(A0 + A1 * phase + A2 * mu + A3 * mu0)
+                  (2019 version)
+                    F(mu, mu0, phase) = mu0 / (mu + mu0) * exp(B0 +
+                     B1 * (alpha * alpha) + B2 * alpha +
+                     B3 * sqrt(alpha) + B4 * mu + B5 * mu0 +
+                     B6 * (mu0 * mu0) );
     

- The equation described accounts for scattering dependance on incidence, - emission, and phase angles. Lunar Reflectance approximately follows this function + The equation described accounts for scattering dependance on incidence, + emission, and phase angles. Lunar Reflectance approximately follows this function and has been tested with repeat coverage at different illumination geometries. The exponential equation has been derived from over 760,000 NAC image tiles. More information can be found at: @@ -28,11 +34,11 @@ http://www.hou.usra.edu/meetings/lpsc2014/pdf/2826.pdf

- This application provides features that allow LROC NAC image cubes to be - photometrically corrected with a properly formatted PVL input file much - like that of the ISIS program photomet. This application restricts - much of the options available to the more sophisticated photomet - application. Below is an example input parameter file for this + This application provides features that allow LROC NAC image cubes to be + photometrically corrected with a properly formatted PVL input file much + like that of the ISIS program photomet. This application restricts + much of the options available to the more sophisticated photomet + application. Below is an example input parameter file for this application:

@@ -52,57 +58,64 @@
           Name = LROC_Empirical
           FilterName = "Broadband"
           BandBinCenter = 600.0
-          A0 = -2.9811422
-          A1 = -0.0112862
-          A2 = -0.8084603
-          A3 = 1.3248888
+          A0 = -2.9811422 (2014 version)
+          A1 = -0.0112862 (2014 version)
+          A2 = -0.8084603 (2014 version)
+          A3 = 1.3248888 (2014 version)
+          B0 = -1.479654495
+          B1 = -0.000083528
+          B2 =  0.012964707
+          B3 = -0.237774774
+          B4 =  0.556075496
+          B5 =  0.663671460
+          B6 = -0.439918609
         EndGroup
       EndObject
   

The Normalization object is the PhotometricModel evaluated at the given Incref, - Emaref and Pharef angles. The value of the Name parameter is ignored here. - The Incref, Emaref, and Pharef are the incidence, emission and phase angles - to be used as the photometric standard. It will be used to normalize the photometric - correction parameter to these angles. The equation used to create the + Emaref and Pharef angles. The value of the Name parameter is ignored here. + The Incref, Emaref, and Pharef are the incidence, emission and phase angles + to be used as the photometric standard. It will be used to normalize the photometric + correction parameter to these angles. The equation used to create the photometrically corrected I/F dn is:

           odn = idn * (phostd  / ph)
-         
-              where phostd is the photometry model evaluated at the given Incref, 
-              Emaref and Pharef angles. ph is the photometric correction for the 
+
+              where phostd is the photometry model evaluated at the given Incref,
+              Emaref and Pharef angles. ph is the photometric correction for the
               incidence, emission and phase at each pixel
       

- The "Center" parameter in the above equality comes from the Center keyword - in the BandBin group of the input cube file specified in the FROM - parameter. This keyword must exist in the input cube or an error is - generated and the program aborts. BandBinCenter and - BandBinCenterTolerance are contained in each Algorithm group. Only - BandBinCenter is required. If BandBinCenterTolerance is not present in an - Algorithm group a value of 1.0E-6 is used. All input bands in the FROM - file must be matched to at least one of the Algorithm parameters otherwise + The "Center" parameter in the above equality comes from the Center keyword + in the BandBin group of the input cube file specified in the FROM + parameter. This keyword must exist in the input cube or an error is + generated and the program aborts. BandBinCenter and + BandBinCenterTolerance are contained in each Algorithm group. Only + BandBinCenter is required. If BandBinCenterTolerance is not present in an + Algorithm group a value of 1.0E-6 is used. All input bands in the FROM + file must be matched to at least one of the Algorithm parameters otherwise an error is generated and the application is aborted.

- The parameter Units is provided to specify if the phase angle is in - units of degrees or radians. It does not have to exist in any group or - even in the top Object section. If it does not exist, "Radians" is the + The parameter Units is provided to specify if the phase angle is in + units of degrees or radians. It does not have to exist in any group or + even in the top Object section. If it does not exist, "Radians" is the default.

- An additional feature of the PVL structure is that any keyword that exists - in the Object section of the PhotometricModel Object is propagated to each - Algorithm group when it is read in unless the keyword already exists in - the Algorithm group. If a keyword exists in both the PhotometricModel - object and an Algorithm group, the keyword in the Algorithm group has + An additional feature of the PVL structure is that any keyword that exists + in the Object section of the PhotometricModel Object is propagated to each + Algorithm group when it is read in unless the keyword already exists in + the Algorithm group. If a keyword exists in both the PhotometricModel + object and an Algorithm group, the keyword in the Algorithm group has precedence.

- Additional consequences of the photometric correction processing is any - incidence angle greater than 90 degrees is set to the ISIS special Null - pixel value. And, of course, any ISIS special pixel encountered on input + Additional consequences of the photometric correction processing is any + incidence angle greater than 90 degrees is set to the ISIS special Null + pixel value. And, of course, any ISIS special pixel encountered on input is propagated to the output TO file without modification. Function is only valid for phase angles between 15 and 65 degrees.

@@ -112,6 +125,10 @@ Version adapted from Kris Becker's LROWACPHO application from 2010 + + Included ability to run with default pvl values + Added new values for 2019 version of LROC Empirical function + @@ -142,7 +159,7 @@ Output cube - This file will contain the photometrically corrected image data after + This file will contain the photometrically corrected image data after being corrected by with LROC_Empirical algorithm. @@ -166,12 +183,14 @@ filename input + $lro/calibration + $lro/calibration/NAC_PHO_LROC_Empirical.????.pvl - PVL file + PVL file containing parameters for photometric calibration - This file will contain the parameters A0-A3 to use when - applying the LROC Empirical photometric correction. See the main program + This file will contain a set of parameters A or B to use when + applying the LROC Empirical photometric correction. See the main program documentation for a full description. *.pvl @@ -217,7 +236,7 @@ MAXEMISSION - 90.0 + 85.0 double Maximum emission angle to trim @@ -243,7 +262,7 @@ double - 90.0 + 85.0 Maximum incidence angle to trim Pixels which have a incidence angle greater than this value will be @@ -254,7 +273,7 @@ MININCIDENCE - + boolean diff --git a/isis/src/lro/apps/lronacpho/main.cpp b/isis/src/lro/apps/lronacpho/main.cpp index ed3e5d27e2..75d1ce00bf 100644 --- a/isis/src/lro/apps/lronacpho/main.cpp +++ b/isis/src/lro/apps/lronacpho/main.cpp @@ -1,192 +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 */ - #include "Isis.h" - -#include - -#include "Cube.h" -#include "IException.h" -#include "LROCEmpirical.h" -#include "PhotometricFunction.h" -#include "ProcessByLine.h" -#include "Pvl.h" -#include "PvlGroup.h" - +#include "lronacpho.h" using namespace std; using namespace Isis; -PhotometricFunction *g_pho; -static bool g_useDEM; - -void phoCal (Buffer &in, Buffer &out); -void phoCalWithBackplane (std::vector &in, std::vector &out ); -/** - * - * @brief Photometric application for the LRO NAC cameras - * - * This application provides featurs that allow multiband cubes for LRO NAC cameras - * to be photometrically corrected - * - * @author 2016-09-16 Victor Silva - * - * @internal - * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker - * - */ -void IsisMain (){ - // Isis Processing by line - ProcessByLine p; - // Set up input cube and get camera info - Cube *iCube = p.SetInputCube("FROM"); - // Set up output cube - Cube *oCube = p.SetOutputCube("TO"); - // Set up the user interface +void IsisMain() { UserInterface &ui = Application::GetUserInterface(); - // Backplane option - bool useBackplane = false; - - if (ui.WasEntered("BACKPLANE")) { - CubeAttributeInput backplaneCai = ui.GetInputAttribute("BACKPLANE"); - - Cube bpCube; - bpCube.open(ui.GetFileName("BACKPLANE")); - int bpBands = bpCube.bandCount(); - bpCube.close(); - - int bpCaiBands = backplaneCai.bands().size(); - - if (bpBands < 3 || (bpCaiBands != 3 && bpBands > 3)) { - string msg = "Invalid Backplane: The backplane must be exactly 3 bands"; - throw IException(IException::User, msg, _FILEINFO_); - } - - if (iCube->bandCount() != 1) { - string msg = "Invalid Image: The backplane option can only be used with a single image band at a time."; - throw IException(IException::User, msg, _FILEINFO_); - } - - CubeAttributeInput cai; - bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[0]) : cai.setAttributes("+1" ) ; - p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); - bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[1]) : cai.setAttributes("+2" ) ; - p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); - bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[2]) : cai.setAttributes("+3" ) ; - p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); - - useBackplane = true; - } - - // Get parameters file - Pvl params(ui.GetFileName("PHOPAR")); - IString algoName = PhotometricFunction::algorithmName(params); - algoName.UpCase(); - - // Use generic NAC algorithm - if (algoName == "LROC_EMPIRICAL") { - g_pho = new LROCEmpirical(params, *iCube, !useBackplane); - } - else { - string msg = " Algorithm Name [" + algoName + "] not recognized. "; - msg += "Compatible Algorithms are:\n LROC_Empirical"; - throw IException(IException::User, msg, _FILEINFO_); - } - - // Set user selected max and mins - g_pho->setMinimumPhaseAngle(ui.GetDouble("MINPHASE")); - g_pho->setMaximumPhaseAngle(ui.GetDouble("MAXPHASE")); - g_pho->setMinimumEmissionAngle(ui.GetDouble("MINEMISSION")); - g_pho->setMaximumEmissionAngle(ui.GetDouble("MAXEMISSION")); - g_pho->setMinimumIncidenceAngle(ui.GetDouble("MININCIDENCE")); - g_pho->setMaximumIncidenceAngle(ui.GetDouble("MAXINCIDENCE")); - - // Set use of DEM to calculate photometric angles - g_useDEM = ui.GetBoolean("USEDEM"); - - // Begin processing by line - if(useBackplane) { - p.StartProcess(phoCalWithBackplane); - } - else { - p.StartProcess(phoCal); - } - // Start all the PVL - PvlGroup photo("Photometry"); - g_pho->report(photo); - oCube->putGroup(photo); + PvlGroup photo = lronacpho(ui); Application::Log(photo); - p.EndProcess(); - delete g_pho; -}//end IsisMain - -/** - * @brief Apply LROC Empirical photometric correction - * - * Process function dispatched for each line to apply the LROC Empirical photometric - * correction function. - * - * @author 2016-09-19 Victor Silva - * - * @internal - * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker - * - * @param in Buffer containing input data - * @param out Buffer of photometrically corrected data - */ -void phoCal(Buffer &in, Buffer &out){ - // Iterate through pixels - for(int i = 0; i < in.size(); i++){ - // Ignore special pixels - if(IsSpecial(in[i])){ - out[i] = in[i]; - } - else{ - // Get correction and test for validity - double ph = g_pho->compute(in.Line(i), in.Sample(i), in.Band(i), g_useDEM); - out[i] = ( IsSpecial(ph) ? Null : (in[i] * ph) ); - } - } - return; -}//end phoCal - -/** - * @brief Apply LROC Empirical photometric correction with backplane - * - * Short function dispatched for each line to apply the LROC Empirical photometric - * correction function. - * - * @author 2016-09-19 Victor Silva - * - * @internal - * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker - * - * @param in Buffer containing input data - * @param out Buffer of photometrically corrected data - */ -void phoCalWithBackplane ( std::vector &in, std::vector &out ) { - - Buffer &image = *in[0]; - Buffer &phase = *in[1]; - Buffer &emission = *in[2]; - Buffer &incidence = *in[3]; - Buffer &calibrated = *out[0]; - - for (int i = 0; i < image.size(); i++) { - // Don't correct special pixels - if (IsSpecial(image[i])) { - calibrated[i] = image[i]; - } - else { - // Get correction and test for validity - double ph = g_pho->photometry(incidence[i], emission[i], phase[i], image.Band(i)); - calibrated[i] = (IsSpecial(ph) ? Null : image[i] * ph); - } - } - return; -} +} \ No newline at end of file diff --git a/isis/src/lro/apps/lronacpho/old.main.cpp b/isis/src/lro/apps/lronacpho/old.main.cpp new file mode 100644 index 0000000000..b0623cc8f0 --- /dev/null +++ b/isis/src/lro/apps/lronacpho/old.main.cpp @@ -0,0 +1,213 @@ +/** 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 "Isis.h" + +#include +#include +#include + +#include "Cube.h" +#include "IException.h" +#include "LROCEmpirical.h" +#include "PhotometricFunction.h" +#include "ProcessByLine.h" +#include "Pvl.h" +#include "PvlGroup.h" +#include "SpecialPixel.h" + +using namespace std; +using namespace Isis; + +PhotometricFunction *g_pho; +static bool g_useDEM; + +void phoCal (Buffer &in, Buffer &out); +void phoCalWithBackplane (std::vector &in, std::vector &out ); + +/** + * + * @brief Photometric application for the LRO NAC cameras + * + * This application provides features that allow multiband cubes for LRO NAC cameras + * to be photometrically corrected + * + * @author 2016-09-16 Victor Silva + * + * @internal + * @history 2016-09-19 Victor Silva - Adapted from lrowacpho written by Kris Becker + * @history 2021-03-12 Victor Silva - Updates include ability to run with default values + * Added new values for 2019 version of LROC Empirical function. + */ +void IsisMain (){ + // Isis Processing by line + ProcessByLine p; + // Set up input cube and get camera info + Cube *iCube = p.SetInputCube("FROM"); + // Set up output cube + Cube *oCube = p.SetOutputCube("TO"); + // Set up the user interface + UserInterface &ui = Application::GetUserInterface(); + // Backplane option + bool useBackplane = false; + + if (ui.WasEntered("BACKPLANE")) { + CubeAttributeInput backplaneCai = ui.GetInputAttribute("BACKPLANE"); + + Cube bpCube; + bpCube.open(ui.GetFileName("BACKPLANE")); + int bpBands = bpCube.bandCount(); + bpCube.close(); + + int bpCaiBands = backplaneCai.bands().size(); + + if (bpBands < 3 || (bpCaiBands != 3 && bpBands > 3)) { + string msg = "Invalid Backplane: The backplane must be exactly 3 bands"; + throw IException(IException::User, msg, _FILEINFO_); + } + + if (iCube->bandCount() != 1) { + string msg = "Invalid Image: The backplane option can only be used with a single image band at a time."; + throw IException(IException::User, msg, _FILEINFO_); + } + + CubeAttributeInput cai; + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[0]) : cai.setAttributes("+1" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[1]) : cai.setAttributes("+2" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + bpCaiBands == 3 ? cai.setAttributes("+" + backplaneCai.bands()[2]) : cai.setAttributes("+3" ) ; + p.SetInputCube(ui.GetFileName("BACKPLANE"), cai); + + useBackplane = true; + } + + // Get name of parameters file + QString algoName = ""; + QString algoFile = ui.GetAsString("PHOPAR"); + + FileName algoFileName(algoFile); + + if(algoFileName.isVersioned()) + algoFileName = algoFileName.highestVersion(); + + if(!algoFileName.fileExists()) { + QString msg = algoFile + " does not exist."; + throw IException(IException::User, msg, _FILEINFO_); + } + + Pvl params(algoFileName.expanded()); + + + + algoName = PhotometricFunction::algorithmName(params); + algoName = algoName.toUpper(); + + // Set NAC algorithm + if (algoName == "LROC_EMPIRICAL") { + g_pho = new LROCEmpirical(params, *iCube, !useBackplane); + } + else { + QString msg = " Algorithm Name [" + algoName + "] not recognized. "; + msg += "Compatible Algorithms are:\n LROC_Empirical\n"; + throw IException(IException::User, msg, _FILEINFO_); + } + + // Set user selected max and mins + g_pho->setMinimumPhaseAngle(ui.GetDouble("MINPHASE")); + g_pho->setMaximumPhaseAngle(ui.GetDouble("MAXPHASE")); + g_pho->setMinimumEmissionAngle(ui.GetDouble("MINEMISSION")); + g_pho->setMaximumEmissionAngle(ui.GetDouble("MAXEMISSION")); + g_pho->setMinimumIncidenceAngle(ui.GetDouble("MININCIDENCE")); + g_pho->setMaximumIncidenceAngle(ui.GetDouble("MAXINCIDENCE")); + + // Set use of DEM to calculate photometric angles + g_useDEM = ui.GetBoolean("USEDEM"); + + // Begin processing by line + if(useBackplane) { + p.StartProcess(phoCalWithBackplane); + } + else { + p.StartProcess(phoCal); + } + // Start all the PVL + PvlGroup photo("Photometry"); + g_pho->report(photo); + oCube->putGroup(photo); + Application::Log(photo); + p.EndProcess(); + delete g_pho; +}//end IsisMain + +/** + * @brief Apply LROC Empirical photometric correction with backplane + * + * Short function dispatched for each line to apply the LROC Empirical photometric + * correction function. + * + * @author 2016-09-19 Victor Silva + * + * @internal + * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker + * + * @param in Buffer containing input data + * @param out Buffer of photometrically corrected data + */ + void phoCal(Buffer &in, Buffer &out){ + // Iterate through pixels + for(int i = 0; i < in.size(); i++){ + // Ignore special pixels + if(IsSpecial(in[i])){ + out[i] = in[i]; + } + else{ + // Get correction and test for validity + double ph = g_pho->compute(in.Line(i), in.Sample(i), in.Band(i), g_useDEM); + out[i] = ( IsSpecial(ph) ? Null : (in[i] * ph) ); + } + } + return; + }//end phoCal + + /** + * @brief Apply LROC Empirical photometric correction with backplane + * + * Short function dispatched for each line to apply the LROC Empirical photometrc + * correction function. + * + * @author 2016-09-19 Victor Silva + * + * @internal + * @history 2016-09-19 Victor silva - Adapted from lrowacpho written by Kris Becker + * + * @param in Buffer containing input data + * @param out Buffer of photometrically corrected data + */ + void phoCalWithBackplane ( std::vector &in, std::vector &out ) { + + Buffer &image = *in[0]; + Buffer &phase = *in[1]; + Buffer &emission = *in[2]; + Buffer &incidence = *in[3]; + Buffer &calibrated = *out[0]; + + for (int i = 0; i < image.size(); i++) { + // Don't correct special pixels + if (IsSpecial(image[i])) { + calibrated[i] = image[i]; + } + else { + // Get correction and test for validity + double ph = g_pho->photometry(incidence[i], emission[i], phase[i], image.Band(i)); + calibrated[i] = (IsSpecial(ph) ? Null : image[i] * ph); + } + } + return; + } +}