From ea46702809861c88bdd8076980268bbc78a2a004 Mon Sep 17 00:00:00 2001
From: Kristin <kberry@usgs.gov>
Date: Tue, 28 Apr 2020 07:56:29 -0700
Subject: [PATCH] Added the look direction to SAR sensor model (#283)

* Non-compiling rough-draft of groundToImage and helper functions

* Merge with upstream changesa and add compiling version of groundtoimage

* Incremental improvements. Moved secant function back into previous function because two return values

* Compiles and some cleanup

* I might regret this, but pushed dopplerShiftFrequency calculation to a lambda fn and made secantRoot a function

* Clean up and move secantRoot to utilities. Add test. Update brentsMethod to take a lambda and update other code accordingly

* remove ooo

* Move bounds checking into secantRoot function and move exceptions around

* Replace placeholders with member variables.

* Add getRangeCoefficients function

* Update to include wavelength, add tests for functions, and fix broken functions based on tests

* Update g->i test with real line, samp image values and fix accidental copy-paste errors

* Tweaked ground to image

* Updated format and associated parsing of range coefficients and times

* Oops, missed some files last commit

* Add 0.5 offset to line calculation needed and update tests to add an Isis comparison test

* Updated Test SAR ISD

* Removed ISIS test and fixed ISD parsing test failure

* Add look direction to SAR

* Updated sar look direction to use an enum

Co-authored-by: Jesse Mapel <jmapel@usgs.gov>
---
 include/usgscsm/UsgsAstroSarSensorModel.h |  5 +++++
 include/usgscsm/Utilities.h               |  1 +
 src/UsgsAstroSarSensorModel.cpp           | 27 +++++++++++++++++++++++
 src/Utilities.cpp                         | 17 ++++++++++++++
 tests/data/orbitalSar.json                |  1 +
 5 files changed, 51 insertions(+)

diff --git a/include/usgscsm/UsgsAstroSarSensorModel.h b/include/usgscsm/UsgsAstroSarSensorModel.h
index f7cba8d..3855911 100644
--- a/include/usgscsm/UsgsAstroSarSensorModel.h
+++ b/include/usgscsm/UsgsAstroSarSensorModel.h
@@ -9,6 +9,10 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab
 {
 
   public:
+    enum LookDirection {
+      LEFT  = 0,
+      RIGHT = 1
+    };
 
     UsgsAstroSarSensorModel();
     ~UsgsAstroSarSensorModel() {}
@@ -249,6 +253,7 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab
     std::vector<double> m_sunPosition;
     std::vector<double> m_sunVelocity;
     double m_wavelength;
+    LookDirection m_lookDirection;
 };
 
 #endif
diff --git a/include/usgscsm/Utilities.h b/include/usgscsm/Utilities.h
index 9765b26..51fb78d 100644
--- a/include/usgscsm/Utilities.h
+++ b/include/usgscsm/Utilities.h
@@ -102,6 +102,7 @@ std::vector<double> getIntegrationStartTimes(nlohmann::json isd, csm::WarningLis
 std::vector<double> getIntegrationTimes(nlohmann::json isd, csm::WarningList *list=nullptr);
 double getExposureDuration(nlohmann::json isd, csm::WarningList *list=nullptr);
 double getScaledPixelWidth(nlohmann::json isd, csm::WarningList *list=nullptr);
+std::string getLookDirection(nlohmann::json isd, csm::WarningList *list=nullptr);
 std::vector<double> getScaleConversionCoefficients(nlohmann::json isd, csm::WarningList *list=nullptr);
 std::vector<double> getScaleConversionTimes(nlohmann::json isd, csm::WarningList *list=nullptr);
 int getSampleSumming(nlohmann::json isd, csm::WarningList *list=nullptr);
diff --git a/src/UsgsAstroSarSensorModel.cpp b/src/UsgsAstroSarSensorModel.cpp
index b2782cf..8f44b94 100644
--- a/src/UsgsAstroSarSensorModel.cpp
+++ b/src/UsgsAstroSarSensorModel.cpp
@@ -116,6 +116,7 @@ string UsgsAstroSarSensorModel::constructStateFromIsd(
   state["m_scaleConversionCoefficients"] = getScaleConversionCoefficients(isd, parsingWarnings);
   state["m_scaleConversionTimes"] = getScaleConversionTimes(isd, parsingWarnings);
   state["m_wavelength"] = getWavelength(isd, parsingWarnings);
+  state["m_lookDirection"] = getLookDirection(isd, parsingWarnings);
 
   // Default to identity covariance
   state["m_covariance"] =
@@ -188,6 +189,7 @@ void UsgsAstroSarSensorModel::reset()
   m_nSamples = 0;
   m_exposureDuration = 0;
   m_scaledPixelWidth = 0;
+  m_lookDirection = LookDirection::LEFT;
   m_startingEphemerisTime = 0;
   m_centerEphemerisTime = 0;
   m_endingEphemerisTime = 0;
@@ -229,6 +231,19 @@ void UsgsAstroSarSensorModel::replaceModelState(const string& argState)
   m_nSamples = stateJson["m_nSamples"];
   m_exposureDuration = stateJson["m_exposureDuration"];
   m_scaledPixelWidth = stateJson["m_scaledPixelWidth"];
+  std::string lookStr = stateJson["m_lookDirection"]; 
+  if (lookStr.compare("right") == 0 ) {
+    m_lookDirection = UsgsAstroSarSensorModel::RIGHT; 
+  }
+  else if (lookStr.compare("left") == 0) {
+    m_lookDirection = UsgsAstroSarSensorModel::LEFT; 
+  }
+  else {
+    std::string message = "Could not determine look direction from state";
+    throw csm::Error(csm::Error::INVALID_SENSOR_MODEL_STATE,
+                     message,
+                     "UsgsAstroSarSensorModel::replaceModelState");
+  }
   m_wavelength = stateJson["m_wavelength"];
   m_startingEphemerisTime = stateJson["m_startingEphemerisTime"];
   m_centerEphemerisTime = stateJson["m_centerEphemerisTime"];
@@ -287,6 +302,18 @@ string UsgsAstroSarSensorModel::getModelState() const
   state["m_minElevation"] = m_minElevation;
   state["m_maxElevation"] = m_maxElevation;
   state["m_scaledPixelWidth"] = m_scaledPixelWidth;
+  if (m_lookDirection == 0) {
+    state["m_lookDirection"] = "left";
+  }
+  else if (m_lookDirection == 1) {
+    state["m_lookDirection"] = "right";
+  }
+  else {
+    std::string message = "Could not parse look direction from json state.";
+    throw csm::Error(csm::Error::INVALID_SENSOR_MODEL_STATE,
+                     message,
+                     "UsgsAstroSarSensorModel::getModelState");
+  }
   state["m_wavelength"] = m_wavelength;
   state["m_scaleConversionCoefficients"] = m_scaleConversionCoefficients;
   state["m_scaleConversionTimes"] = m_scaleConversionTimes;
diff --git a/src/Utilities.cpp b/src/Utilities.cpp
index a532b8b..08101a8 100644
--- a/src/Utilities.cpp
+++ b/src/Utilities.cpp
@@ -1215,6 +1215,23 @@ double getScaledPixelWidth(nlohmann::json isd, csm::WarningList *list) {
   return width;
 }
 
+std::string getLookDirection(nlohmann::json isd, csm::WarningList *list) {
+  std::string lookDirection = "";
+  try {
+    lookDirection = isd.at("look_direction");
+  }
+  catch (...) {
+    if (list) {
+      list->push_back(
+        csm::Warning(
+          csm::Warning::DATA_NOT_AVAILABLE,
+          "Could not parse the scaled pixel width.",
+          "Utilities::getScaledPixelWidth()"));
+    }
+  }
+  return lookDirection;
+}
+
 std::vector<double> getScaleConversionTimes(nlohmann::json isd, csm::WarningList *list) {
   std::vector<double> time;
   try {
diff --git a/tests/data/orbitalSar.json b/tests/data/orbitalSar.json
index 95e1a9f..57aa104 100644
--- a/tests/data/orbitalSar.json
+++ b/tests/data/orbitalSar.json
@@ -18,6 +18,7 @@
   "scaled_pixel_width" : 7.5,
   "t0_ephemeris": -0.0025,
   "dt_ephemeris": 0.25,
+  "look_direction": "right",
   "sensor_position": {
     "positions":
       [[3737400.0, 0.0, -0.0],
-- 
GitLab