Commit aa275da5 authored by Kaitlyn Lee's avatar Kaitlyn Lee Committed by Adam Paquette
Browse files

Added the ability to convert to radiance and reflectance and cleaned up code (#3957)



* Added logging for testing

* Added couts to test code

* Cleaned up calibration function to match JAXA paper

* Added history comment

* Better comment for why we create a temp file

* Added DN -> Radiance -> Reflectance conversions

* Some format changes

* Grabbed the solar distance from the instrument group

* Removed unused functions

* Fixed conflicts

* Moved special pixel check

Co-authored-by: default avatarStuart Sides <ssides@usgs.gov>
parent 34adbaaa
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -99,17 +99,6 @@ xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Applica
      process FIT files using the old keywords.  Also set TARGET=RYUGU in the event the user
      does not specify a target, and the target in the fit label is set to SKY.
    </change>
    <change name="Kaitlyn Lee" date="2020-07-21">
      Updated calibration method to match JAXAs calibration by:
      1. moving linearity correction to after smear correction,
      2. commenting out dark current and linearity correction,
      3. changing an addition to subtraction in the g_bias calculation,
      4. refactoring the smear correction to be before the main loop to speed up the program
         and to be dependent on the bit-corrected input image DNs instead of the already corrected
         output image DNs,
      5. and removing `*g_sensitivity*g_texp` in the flat-field correction so that the output
         aligns with l2b data.
    </change>
  </history>

  <category>
+324 −325
Original line number Diff line number Diff line
@@ -102,10 +102,11 @@ static double g_timeRatio(1.0);
static int binning(1);         //!< The number of samples/lines which are binned
static double g_compfactor(1.0);  // Default if OutputMode = LOSS-LESS; 16.0 for LOSSY

static QString g_iofCorrection("IOF");  //!< Is I/F correction to be applied?
static QString g_calStep("IOF");  //!< Which calibrations step should we stop at?
static double g_calibrationScale = 1.0; //!< Radiance or I/F conversion factor

// I/F variables
//static double g_iof(1.0);
static double g_solarDist(1.0);
static double g_iofScale(1.0);
static double g_solarFlux(1.0);  //!< The solar flux (used to calculate g_iof).
static double g_sensitivity(1.0);
@@ -228,16 +229,15 @@ void Calibrate(vector<Buffer *>& in, vector<Buffer *>& out) {

    // Iterate over the line space
    for (int i = 0; i < imageIn.size(); i++) {
    imageOut[i] = imageIn[i] * pow(2.0, 12 - g_bitDepth);

      // Check for special pixel in input image and pass through
    if ( IsSpecial(imageOut[i]) ) {
      imageOut[i] = imageIn[i];
      if ( IsSpecial(imageIn[i]) ) {
        imageOut[i] = Isis::Null;
        continue;
      }

    // Apply compression factor here to raise LOSSY dns to proper response
      imageOut[i] = imageIn[i] * pow(2.0, 12 - g_bitDepth);

      // Apply compression factor here to raise LOSSY dns to proper response

      // BIAS Removal - Only needed if not on-board corrected
      if (!g_onBoardSmearCorrection) {
@@ -271,9 +271,8 @@ void Calibrate(vector<Buffer *>& in, vector<Buffer *>& out) {

      // FLATFIELD correction
      // Check for any special pixels in the flat field (unlikely)
    // Note that our current flat-fields to not have special pixel values.
    if (IsSpecial(flatField[i]) || IsSpecial(imageOut[i]))
    {
      // If we have only one input cube, that means that we do not have a flat-field (W1/W2).
      if (IsSpecial(flatField[i]) || IsSpecial(imageOut[i])) {
        imageOut[i] = Isis::Null;
        continue;
      }
@@ -282,6 +281,10 @@ void Calibrate(vector<Buffer *>& in, vector<Buffer *>& out) {
          imageOut[i] /= (flatField[i]);
        }
      }

      // I/F or Radiance Conversion (or g_calibrationScale might = 1, 
      // in which case the output will be in DNs)
      imageOut[i] *= g_calibrationScale;
    }
    return;
  }
@@ -358,7 +361,6 @@ void mat2isis(Mat *matrix, QString cubeName) {
   *
   * @param cubeName The name of the ISIS::Cube that is being created.
   */

  void translate(Cube *flatField,double *transform, QString fname) {
    Mat *originalMat = isis2mat(flatField);
    double scale = transform[0];
@@ -424,6 +426,7 @@ FileName DetermineFlatFieldFile(const QString &filter) {
  }



  /**
  * @brief Loads the calibration variables into the program.
  * @param config QString Name of the calibration file to load.
@@ -445,7 +448,6 @@ QString loadCalibrationVariables(const QString &config) {
    PvlGroup &sensitivity = g_configFile.findGroup("SENSITIVITYFACTOR");
    PvlGroup & effectiveBW = g_configFile.findGroup("EFFECTIVEBW");
    PvlGroup &linearity = g_configFile.findGroup("Linearity");
  // PvlGroup &iof = g_configFile.findGroup("RAD");

    // Load Smear Removal Variables
    g_Tvct = Smear["Tvct"];
@@ -495,11 +497,8 @@ QString loadCalibrationVariables(const QString &config) {
    g_L[1] = linearity["L"][1].toDouble();
    g_L[2] = linearity["L"][2].toDouble();


    return calibFile.original();
  }


}

#endif
+30 −27
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ using namespace std;
namespace Isis {

  void hyb2onccal(UserInterface &ui) {
    // g_iofCorrection = ui.GetString("UNITS");
    g_calStep = ui.GetString("UNITS");

    const QString hyb2cal_program = "hyb2onccal";
    const QString hyb2cal_version = "1.1";
@@ -164,6 +164,17 @@ namespace Isis {
      throw IException(e, IException::Io, msg, _FILEINFO_);
    }

    try {
      // Convert from KM to AU
      QString solarDistance = inst["SolarDistance"][0].replace('D', 'e');
      g_solarDist = solarDistance.toDouble() * (1.0 / 49598073.0);
    }
    catch(IException &e) {
      QString msg = "Unable to read [SolarDistance] keyword in the Instrument group "
                    "from input file [" + icube->fileName() + "]";
      throw IException(e, IException::Io, msg, _FILEINFO_);
    }

    QString smearCorrection;
    try {
      smearCorrection = inst["SmearCorrection"][0];
@@ -261,27 +272,20 @@ namespace Isis {
    QString calfile = loadCalibrationVariables(ui.GetAsString("CONFIG"));
    g_timeRatio = g_Tvct/(g_texp + g_Tvct);

    QString g_units = "DN";
    // if ( "radiance" == g_iofCorrection.toLower() ) {
    //   // Units of RADIANCE
    //   g_iof = g_iof * g_iofScale;
    //   g_units = "W / (m**2 micrometer sr)";
    // }
    //
    // if ( !sunDistanceAU(startTime, target, g_solarDist) ) {
    //    throw IException(IException::Programmer, "Cannot calculate distance to sun!",
    //                      _FILEINFO_);
    // }
    //
    // if ( "iof" == g_iofCorrection.toLower() ) {
    //   // Units of I/F
    //   // TODO: Note, we do not have a correct g_iofScale (== 1 right now). This was provided for
    //   // Hayabusa AMICA's v-band and all other bands were normalized according to this value. We do
    //   // not have this value for Hayabusa2 ONC. Need to correct this value.
    //   g_iof = pi_c() * (g_solarDist * g_solarDist) *
    //           g_iofScale / g_solarFlux / g_texp;
    //   g_units = "I over F";
    // }
    QString units = "DN";
    if (g_calStep == "RADIANCE") {
      // Units of RADIANCE
      g_calibrationScale = 1.0 / (g_texp * g_sensitivity);
      units = "W / (m**2 micrometer sr)";
    }

    else if (g_calStep == "IOF") {
      // Units of I/F
      // Included this line because we need to convert to radiance before I/F.
      g_calibrationScale = 1.0 / (g_texp * g_sensitivity);
      g_calibrationScale *= (Isis::PI * (g_solarDist * g_solarDist)) / g_solarFlux;
      units = "I over F";
    }

    // Calibrate!
    try {
@@ -340,12 +344,11 @@ namespace Isis {
    calibrationLog.addKeyword(PvlKeyword("Smear_Tvct", toString(g_Tvct, 16)));
    calibrationLog.addKeyword(PvlKeyword("Smear_texp", toString(g_texp, 16)));

    calibrationLog.addKeyword(PvlKeyword("CalibrationUnits", g_iofCorrection));
    calibrationLog.addKeyword(PvlKeyword("CalibrationUnits", g_calStep));

    calibrationLog.addKeyword(PvlKeyword("RadianceScaleFactor", toString(g_iofScale, 16)));
    calibrationLog.addKeyword(PvlKeyword("SolarFlux", toString(g_solarFlux, 16)));  
    calibrationLog.addKeyword(PvlKeyword("Units", g_units));

    calibrationLog.addKeyword(PvlKeyword("Units", units));
    PvlKeyword linearityCoefs("LinearityCoefficients");
    linearityCoefs.addValue(toString(g_L[0], 16));
    linearityCoefs.addValue(toString(g_L[1], 16));
+13 −8
Original line number Diff line number Diff line
@@ -119,6 +119,18 @@ xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Applica
    <change name="Tyler Wilson" date="2019-02-12">
      Modified version to handle the updated calibration values/formulas.
    </change>
    <change name="Kaitlyn Lee" date="2020-07-21">
      Updated calibration method to match JAXAs calibration by:
      1. moving linearity correction to after smear correction,
      2. commenting out dark current and linearity correction,
      3. changing an addition to subtraction in the g_bias calculation,
      4. refactoring the smear correction to be before the main loop to speed up the program
         and to be dependent on the bit-corrected input image DNs instead of the already corrected
         output image DNs,
      5. removing `*g_sensitivity*g_texp` in the flat-field correction so that the output
         aligns with l2b data,
      6. and adding the units parameter and the ability to convert to radiance and reflectance.
    </change>
  </history>

  <groups>
@@ -164,18 +176,11 @@ xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Applica
           the parameters as needed.
        </description>
        <filter>*.trn</filter>
         <!-->
        <default><item>/scratch/isis3data/hayabusa2/calibration/onc/hyb2oncCalibration????.trn</item></default>
        -->

        <default><item>/usgs/cpkgs/isis3/datalocal/hayabusa2/calibration/onc/hyb2oncCalibration????.trn</item></default>

      </parameter>
      
    </group>

    <!-- Recall no radiance values have been provided for the filters, so radiance and i/f cannot be
    correctly computed.
    <group name="Options">

      <parameter name = "UNITS">
@@ -214,6 +219,6 @@ xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Applica
        </list>
      </parameter>
    </group>
  -->
 
  </groups>
</application>