From 1e981d2c7a29e5e913968db86c49b5730c2ace9a Mon Sep 17 00:00:00 2001
From: jlaura <jlaura@usgs.gov>
Date: Wed, 19 Dec 2018 11:33:23 -0700
Subject: [PATCH] Merging dev into master for release (#158)

* Updated ISD and tests  (#87)

* updated tests + RIP TestyMcTestFace

* keys updated

* Probably should not hard code .cpps in the CMakeLists.txt for GTest

* updated specs to mimic synthetic json

* appveyor assumed broken from standup, disabling until fixed

* eulers are now quats

* merge from jay's changes

* merge markers

* renamed quats as per Jessie's reccomendation

* only appends sensor_orientation to missing params

* stupid markers

* updated test ISD

* changes as per some comments

* updated as per comments

* defaults are all 0

* #pragma once to C style header guard

* stragler change

* missed some params

* missed another

* moving things around

* patched segfault error + added detector center as defined in json schema (#94)

* patched segfault error + added detector center as defined in the swagger schema

* verbose travi

* Fixed optical distortion and pixel to focal transforms. (#115)

* Update to use quaternions in test to match new ISD

* Fixes #121

* Fix 1 remaining failing omega rotation test

* Updates token to be in quotes

* Still trying to get the builds working.

* Updates to force upload

* Adds newline

* Update for formatting

* Trying to force travis to deploy with labels

I am editing this on the repo in order to get Travis to do its thing - I can not do this via a PR.

* Update .travis.yml

* Update meta.yaml

to try and force a dev tag on the builds to get labels to work.

* Update meta.yaml

* Update .travis.yml

* test x scaling for reset model state

* test FL500 conversion

* test FL500 conversion

* Add tests to include

* commit to force run of tests on mac with debug output

* switch to using tolerances from dev

* 0.5 pixel offset

* try moving set of filename into setup

* initialize differently test

* more debug output

* Add matrix to debug output

* Even more debug output from matrix calculation

* Add missing quaternion component to state string

* cleanup debug output now that problem is fixed

* fix added spacing

* Adds in check for PR for upload

* echo to check travis env

* fixes equality check for PR

* Clean up some spacing (non-functional) in UsgsAstroFrameModel

* Fixed canModelBeConstructedFromISD throwing an exception when the metadata file doesn't exist. (#134)

* fixed can be converted error

* Added not constructible test for frame plugin

* Removed old LS ISD header (#137)

* Update some of the tests that set a new state value to use a function in the fixture, rather than repeating code

* Windows Build (#139)

* adds win build

* Windows build

* Updates submodules

* Refactoring to move to one plugin and removed unused classes.  (#138)

* merge

* changed varrs

* reset test

* First iteration

* it compiles, although renaming this is still neccessary

* added source

* cleaned up, tests still need to pass

* post merge clean up

* validation updated, validation tests are now passing

* Addressed comments from Jesse

* last Jesse comment, convertISDToModelState doesn't check if pointer is invalid anymore as the sensor model should except

* model_name -> m_modelName for frame getState

* copy paste error in FrameSensorModel

* Resolve merge conflicts with FrameIsdTest vs. SimpleFrameIsdTest names

* Fix hopefully last merge problem

* Conda build on win (#143)

* Conda build on win

* Trying a straight build first

* Unneeded csmapi

* Now trying to upload build

* Trying a build and upload

* Trying syntax change

* trying ps

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update meta.yaml

* Update bld.bat

This is a test to see where appveyor is failing.

* Update bld.bat

* Update bld.bat

* Update meta.yaml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Update .appveyor.yml

* Adds if/else into appveyor (#146)

* Adds if/else into appveyor

* Update .appveyor.yml

* Updates to use gcc7

* Update .travis.yml

* Update .appveyor.yml

* Fixed Line Scan construction and condensed plugin tests (#145)

* First pass at test LS ISD

* Initial LS plugin test base

* fixed a test in frame plugin tests

* Initial LS plugin test suite

* Moved to single plugin test file

* Added some new plugin tests

* Fixed LS construction

* Re-updated submodules

* Reverted gtest

* removed debuf prints left in and made getModelName functional (#148)

* Changed line scan sensor model to new ISD spec (#149)

* Changed line scan sensor model to new ISD spec

* Updated LS to the proper spec

* Changed model_name to name_model

* Updated tests to use new name_ format in ISD

* Updated LS test data to new spec

* Fixed typo in ls test ISD

* Moved framer to new ISD format. Added bad debug statements.

* Updated LS to new spec

* Fixed focal length epsilon name

* Added model state test for framer (#152)

* fixed nan issue (#153)

* fixed nan issue

* left in for loop

* Removed switch statement for ls distortion: (#150)
---
 .appveyor.yml                                 |   44 +-
 .travis.yml                                   |   11 +-
 CMakeLists.txt                                |   23 +-
 csm                                           |    2 +-
 gtest                                         |    2 +-
 include/usgscsm/UsgsAstroFrameSensorModel.h   |   57 +-
 include/usgscsm/UsgsAstroLsISD.h              |  154 ---
 include/usgscsm/UsgsAstroLsPlugin.h           |  219 ----
 include/usgscsm/UsgsAstroLsSensorModel.h      |  119 +-
 include/usgscsm/UsgsAstroLsStateData.h        |  208 ----
 ...gsAstroFramePlugin.h => UsgsAstroPlugin.h} |   23 +-
 recipe/bld.bat                                |    7 +
 recipe/meta.yaml                              |   12 +-
 src/UsgsAstroFramePlugin.cpp                  |  620 ----------
 src/UsgsAstroFrameSensorModel.cpp             |  778 +++++++-----
 src/UsgsAstroLsPlugin.cpp                     |  534 ---------
 src/UsgsAstroLsSensorModel.cpp                | 1039 ++++++++++++-----
 src/UsgsAstroLsStateData.cpp                  |  538 ---------
 src/UsgsAstroPlugin.cpp                       |  284 +++++
 tests/CMakeLists.txt                          |   12 +-
 tests/Fixtures.h                              |  144 +++
 tests/FrameCameraTests.cpp                    |  324 ++---
 tests/PluginTests.cpp                         |  190 +++
 tests/TestyMcTestFace.cpp                     |  124 --
 tests/data/constVelocityLineScan.json         |   93 ++
 tests/data/simpleFramerISD.json               |  143 +--
 26 files changed, 2341 insertions(+), 3363 deletions(-)
 delete mode 100644 include/usgscsm/UsgsAstroLsISD.h
 delete mode 100644 include/usgscsm/UsgsAstroLsPlugin.h
 delete mode 100644 include/usgscsm/UsgsAstroLsStateData.h
 rename include/usgscsm/{UsgsAstroFramePlugin.h => UsgsAstroPlugin.h} (82%)
 create mode 100644 recipe/bld.bat
 delete mode 100644 src/UsgsAstroFramePlugin.cpp
 delete mode 100644 src/UsgsAstroLsPlugin.cpp
 delete mode 100644 src/UsgsAstroLsStateData.cpp
 create mode 100644 src/UsgsAstroPlugin.cpp
 create mode 100644 tests/Fixtures.h
 create mode 100644 tests/PluginTests.cpp
 delete mode 100644 tests/TestyMcTestFace.cpp
 create mode 100644 tests/data/constVelocityLineScan.json

diff --git a/.appveyor.yml b/.appveyor.yml
index 43ad8f2..cfdf80e 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -7,17 +7,41 @@ platform:
 
 configuration:
   - Release
-  - Debug
-
-environment:
-  CSM_LIBRARY_PATH: C:\\Miniconda36-x64\lib
-  CSM_INCLUDE_PATH: C:\\Miniconda36-x64\include
 
 install:
   - git submodule update --init --recursive
-  # This pulls csm from conda
-  - cmd: call C:\\Miniconda36-x64\Scripts\activate.bat
-  - cmd: conda install -y -c usgs-astrogeology libcsm
-  - cmake .
+  - call C:\\Miniconda36-x64\Scripts\activate.bat
+  - conda config --set always_yes yes --set changeps1 no
+  - conda update -q conda
+  - conda install conda-build anaconda-client
+  - conda config --add channels usgs-astrogeology
+
+before_build:
+  - mkdir build
+  - cd build
+  
 build_script:
-  - cmake --build . -- %MSBUILD_ARGS%
+  - cmake -G "Visual Studio 15 2017 Win64" -DBUILD_TESTS=OFF ..
+  - cmake --build . --target ALL_BUILD --config Release
+
+artifacts:
+  - path: build\Release\usgscsm.dll
+    name: usgscsm.dll
+
+on_success:
+- cd ../
+- conda build -q recipe/
+- ps:
+    if ($env:APPVEYOR_PULL_REQUEST_NUMBER -eq "") {
+      $tar_glob = conda build recipe --output;
+      Write-Host "tar_glob $tar_glob";
+      if ($env:APPVEYOR_REPO_BRANCH -eq "dev") {
+        $anaconda_label = "dev"
+      } else {
+        $anaconda_label = "main"
+      };
+      Write-Host "anaconda_label $anaconda_label";
+      $parameters = '-t', "$env:CONDA_UPLOAD_TOKEN", 'upload', "$tar_glob", '-l',
+                    "$anaconda_label", '--force', '--no-progress';
+      & cmd /c 'anaconda 2>&1' $parameters;
+    };
diff --git a/.travis.yml b/.travis.yml
index 52c16c3..c0a3508 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,15 +14,16 @@ matrix:
           sources:
             - ubuntu-toolchain-r-test
           packages:
-            - g++-6
+            - g++-7
       env:
-        - MATRIX_EVAL="CXX=g++-6 && CC=gcc-6"
+        - MATRIX_EVAL="CXX=g++-7 && CC=gcc-7"
     - os: osx
       osx_image: xcode9.4
       env:
         - MATRIX_EVAL="CXX=clang++ && CC=clang"
 
 before_install:
+  - echo "$TRAVIS_PULL_REQUEST"
   - eval "${MATRIX_EVAL}"
   - |
     if [ "$TRAVIS_OS_NAME" == "linux" ]; then
@@ -58,8 +59,8 @@ after_success:
   - builddir=(`conda build recipe --output`)
   # Label based on the branch and upload to anaconda.org
   - |
-    if [ "$TRAVIS_BRANCH" == "master" ]; then
+    if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
       anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir;
-    elif [ "$TRAVIS_BRANCH" == "dev" ]; then
-      anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir --label dev;
+    elif [ "$TRAVIS_BRANCH" == "dev" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+      anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir --label dev --force;
     fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cee474e..76ab4a6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,17 +15,18 @@ if(BUILD_CSM)
   set(CSM_LIBRARY csmapi)
 else()
   find_path(CSM_INCLUDE_DIR NAMES "csm.h"
-			    PATH_SUFFIXES "csm" 
+			    PATH_SUFFIXES "csm"
 			    PATHS $ENV{CONDA_PREFIX}/include/)
   find_library(CSM_LIBRARY csmapi PATHS $ENV{CONDA_PREFIX}/lib)
+  
+  message("--Found CSM Library: ${CSM_LIBRARY}")
+  message("--Found CSM Include Directory: ${CSM_INCLUDE_DIR}")
 endif(BUILD_CSM)
 
 add_library(usgscsm SHARED
-            src/UsgsAstroFramePlugin.cpp
+            src/UsgsAstroPlugin.cpp
             src/UsgsAstroFrameSensorModel.cpp
-            src/UsgsAstroLsPlugin.cpp
-            src/UsgsAstroLsSensorModel.cpp
-            src/UsgsAstroLsStateData.cpp)
+            src/UsgsAstroLsSensorModel.cpp)
 
 set_target_properties(usgscsm PROPERTIES
     VERSION ${PROJECT_VERSION}
@@ -42,7 +43,6 @@ target_include_directories(usgscsm
 )
 
 # Setup for GoogleTest
-
 find_package (Threads)
 
 target_link_libraries(usgscsm
@@ -50,16 +50,11 @@ target_link_libraries(usgscsm
                       gtest ${CMAKE_THREAD_LIBS_INIT})
 
 if(WIN32)
-  option(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON)
-  option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
-  install(TARGETS usgscsm
-    RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})
-    install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+  install(TARGETS usgscsm RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})
 else()
-  install(TARGETS usgscsm
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-    install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+  install(TARGETS usgscsm LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
 endif()
+install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 
 
 # Optional build or link against CSM
diff --git a/csm b/csm
index ea22180..c78dbba 160000
--- a/csm
+++ b/csm
@@ -1 +1 @@
-Subproject commit ea22180f46f86f4c95ade84ab81eb4477bdd8dd6
+Subproject commit c78dbba3731432249a75db9fdd7415b292d46715
diff --git a/gtest b/gtest
index e5e2ef7..2fe3bd9 160000
--- a/gtest
+++ b/gtest
@@ -1 +1 @@
-Subproject commit e5e2ef7cd27cc089c1d8302a11970ef870554294
+Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2
diff --git a/include/usgscsm/UsgsAstroFrameSensorModel.h b/include/usgscsm/UsgsAstroFrameSensorModel.h
index c82d1d8..7da5473 100644
--- a/include/usgscsm/UsgsAstroFrameSensorModel.h
+++ b/include/usgscsm/UsgsAstroFrameSensorModel.h
@@ -9,6 +9,10 @@
 #include "RasterGM.h"
 #include "CorrelationModel.h"
 
+#include <json.hpp>
+using json = nlohmann::json;
+
+
 class UsgsAstroFrameSensorModel : public csm::RasterGM {
   // UsgsAstroFramePlugin needs to access private members
   friend class UsgsAstroFramePlugin;
@@ -17,11 +21,19 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM {
     UsgsAstroFrameSensorModel();
     ~UsgsAstroFrameSensorModel();
 
+
+    bool isValidModelState(const std::string& stringState, csm::WarningList *warnings);
+    bool isValidIsd(const std::string& stringIsd, csm::WarningList *warnings);
+
     virtual csm::ImageCoord groundToImage(const csm::EcefCoord &groundPt,
                                      double desiredPrecision=0.001,
                                      double *achievedPrecision=NULL,
                                      csm::WarningList *warnings=NULL) const;
 
+
+    std::string constructStateFromIsd(const std::string& jsonIsd, csm::WarningList *warnings);
+    void reset();
+
     virtual csm::ImageCoordCovar groundToImage(const csm::EcefCoordCovar &groundPt,
                                           double desiredPrecision=0.001,
                                           double *achievedPrecision=NULL,
@@ -301,12 +313,12 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM {
 protected:
 
     FRIEND_TEST(FramerParameterizedTest,JacobianTest);
-    FRIEND_TEST(FrameIsdTest, setFocalPlane1);
-    FRIEND_TEST(FrameIsdTest, Jacobian1);
-    FRIEND_TEST(FrameIsdTest, setFocalPlane_AllCoefficientsOne);
-    FRIEND_TEST(FrameIsdTest, distortMe_AllCoefficientsOne);
-    FRIEND_TEST(FrameIsdTest, setFocalPlane_AlternatingOnes);
-    FRIEND_TEST(FrameIsdTest, distortMe_AlternatingOnes);
+    FRIEND_TEST(FrameSensorModel, setFocalPlane1);
+    FRIEND_TEST(FrameSensorModel, Jacobian1);
+    FRIEND_TEST(FrameSensorModel, setFocalPlane_AllCoefficientsOne);
+    FRIEND_TEST(FrameSensorModel, distortMe_AllCoefficientsOne);
+    FRIEND_TEST(FrameSensorModel, setFocalPlane_AlternatingOnes);
+    FRIEND_TEST(FrameSensorModel, distortMe_AlternatingOnes);
 
     virtual bool setFocalPlane(double dx,double dy,double &undistortedX,double &undistortedY) const;
     virtual void distortionFunction(double ux, double uy, double &dx, double &dy) const;
@@ -316,7 +328,6 @@ protected:
 
 
   private:
-
     // Input parameters
     static const int m_numParameters;
     static const std::string m_parameterName[];
@@ -326,40 +337,43 @@ protected:
     std::vector<double> m_noAdjustments;
     std::vector<double> m_odtX;
     std::vector<double> m_odtY;
-
-    static const int         _NUM_STATE_KEYWORDS;
-    static const std::string _STATE_KEYWORD[];
-
-    double m_transX[3];
-    double m_transY[3];
+    std::vector<double> m_transX;
+    std::vector<double> m_transY;
+    std::vector<double> m_spacecraftVelocity;
+    std::vector<double> m_sunPosition;
+    std::vector<double> m_ccdCenter;
+    std::vector<double> m_iTransS;
+    std::vector<double> m_iTransL;
+    std::vector<double> m_boresight;
     double m_majorAxis;
     double m_minorAxis;
     double m_focalLength;
-    double m_spacecraftVelocity[3];
-    double m_sunPosition[3];
-    double m_ccdCenter[2];
     double m_minElevation;
     double m_maxElevation;
-    double m_line_pp;
-    double m_sample_pp;
+    double m_linePp;
+    double m_samplePp;
     double m_startingDetectorSample;
     double m_startingDetectorLine;
     std::string m_targetName;
+    std::string m_modelName;
     double m_ifov;
     std::string m_instrumentID;
     double m_focalLengthEpsilon;
     double m_originalHalfLines;
     std::string m_spacecraftName;
     double m_pixelPitch;
-    double m_iTransS[3];
-    double m_iTransL[3];
+
     double m_ephemerisTime;
     double m_originalHalfSamples;
-    double m_boresight[3];
     int m_nLines;
     int m_nSamples;
     int m_nParameters;
 
+    json _state;
+    static const int         _NUM_STATE_KEYWORDS;
+    static const int         NUM_PARAMETERS;
+    static const std::string _STATE_KEYWORD[];
+
     csm::NoCorrelationModel _no_corr_model;
 
     double getValue(int index,const std::vector<double> &adjustments) const;
@@ -371,6 +385,7 @@ protected:
                                 double xl, double yl,
                                 double zl,
                                 double& x,double& y, double&  z) const;
+
 };
 
 #endif
diff --git a/include/usgscsm/UsgsAstroLsISD.h b/include/usgscsm/UsgsAstroLsISD.h
deleted file mode 100644
index 2b0d683..0000000
--- a/include/usgscsm/UsgsAstroLsISD.h
+++ /dev/null
@@ -1,154 +0,0 @@
-//----------------------------------------------------------------------------
-//
-//                                UNCLASSIFIED
-//
-// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc.
-//                            ALL RIGHTS RESERVED
-// Use of this software product is governed by the terms of a license
-// agreement. The license agreement is found in the installation directory.
-//
-//             For support, please visit http://www.baesystems.com/gxp
-//
-//    FILENAME:          UsgsAstroLsISD.h
-//
-//    DESCRIPTION:
-//
-//     Image Support Data (ISD) to build the Astro Line Scanner sensor model.
-//     The ISD format is defined by the imagery provider. A few common formats
-//     include name/value pairs, XML, NITF TREs, and GeoTiff tags.
-//
-//     This ISD is formatted as a list of name/value pairs. The order of the
-//     list generally does not matter, except that the length of a vector needs
-//     to be read in before the vector itself. Extra data in the support data
-//     file will be ignored.
-//
-//     There is data describing the ellipsoid that can optionally be in a
-//     seperate file.  This is to support legacy data, but is not encouraged.
-//
-//     For the Astro LS sensor model there is a close relationship between the
-//     ISD and the State data. This is not always the case. So, it is best to
-//     seperate the ISD parsing (done here), the translation of ISD to state
-//     data (done in the plugin), and the instantiation of the sensor model
-//     from state data (done in the sensor model).
-//
-//    SOFTWARE HISTORY:
-//
-//    Date          Author       Comment
-//    -----------   ----------   -------
-//    16-Oct-2017   BAE Systems  Initial Release
-//
-//#############################################################################
-#ifndef __USGS_ASTRO_LINE_SCANNER_ISD_H
-#define __USGS_ASTRO_LINE_SCANNER_ISD_H
-
-#include <vector>
-#include <string>
-
-#include <csm.h>
-#include <Isd.h>
-#include <SettableEllipsoid.h>
-
-class UsgsAstroLsISD
-{
-   public:
-
-
-   UsgsAstroLsISD()
-   {
-      reset();
-   }
-
-   UsgsAstroLsISD(
-      const std::string&   lis_file_name,
-      const std::string&   ell_file_name)
-   {
-      reset();
-      setISD(lis_file_name, ell_file_name);
-   }
-
-   virtual ~UsgsAstroLsISD() {}
-
-   // Formats the support data as a string
-   // This is mainly used to check that the
-   // support data is read in correctly.
-   std::string toString() const;
-
-   // Initializes the class from ISD as formatted by the image provider.
-   //
-   // Note that if the ellipsoid data is found in the main ISD file,
-   // the ellipsoid data file is not needed.
-   void setISD(
-      const std::string&   lis_file_name,
-      const std::string&   ell_file_name);
-
-
-   //--------------------------------------------------------------------------
-   // Helper Routines
-   //--------------------------------------------------------------------------
-   // Initial check that support data file exists and looks like Astro LS ISD.
-   static bool checkFileValidity(
-      const csm::Isd&     image_support_data,
-      std::string&        lis_file_name,
-      std::string&        ell_file_name,
-      std::string&        img_rel_name);
-
-
-   // ISD elements;
-   // The support data is defined by USGS. See the documentation at
-   // http://htmlpreview.github.io/?https://github.com/USGS-Astrogeology/socet_set/blob/master/SS4HiRISE/Tutorials/ISD_keyword_examples/AstroLineScanner_ISD_Keywords.ls.htm
-   // Even for fields that do not change, it is best to include them in
-   // the support data rather than hard code values in the sensor model.
-   // Since this is not always done, some fields are optional.
-   std::string         m_sensor_type;
-   int                 m_total_lines;
-   int                 m_total_samples;
-   int                 m_platform;
-   int                 m_aberr;
-   int                 m_atmref;
-   double              m_int_time;
-   double              m_starting_ephemeris_time;
-   double              m_center_ephemeris_time;
-   double              m_detector_sample_summing;
-   double              m_starting_sample;
-   int                 m_ikcode;
-   double              m_focal;
-   double              m_isis_z_direction;
-   double              m_optical_dist_coef[3];
-   double              m_itranss[3];
-   double              m_itransl[3];
-   double              m_detector_sample_origin;
-   double              m_detector_line_origin;
-   double              m_detector_line_offset;
-   double              m_mounting_angles[3];
-   double              m_dt_ephem;
-   double              m_t0_ephem;
-   double              m_dt_quat;
-   double              m_t0_quat;
-   int                 m_number_of_ephem;
-   int                 m_number_of_quaternions;
-   std::vector<double> m_ephem_pts;
-   std::vector<double> m_ephem_rates;
-   std::vector<double> m_quaternions;
-   std::vector<double> m_tri_parameters;
-   double              m_semi_major_axis;
-   double              m_eccentricity;
-
-   // Optional fields
-   double              m_ref_height;
-   double              m_min_valid_ht;
-   double              m_max_valid_ht;
-   std::string         m_image_id;
-   std::string         m_sensor_id;
-   std::string         m_platform_id;
-   std::string         m_traj_id;
-   std::string         m_coll_id;
-   std::string         m_ref_date_time;
-
-   static const std::string mISD_KEYWORDS[];
-
-   protected:
-   // Set to default values
-   void reset();
-};
-
-#endif
diff --git a/include/usgscsm/UsgsAstroLsPlugin.h b/include/usgscsm/UsgsAstroLsPlugin.h
deleted file mode 100644
index fd41ce4..0000000
--- a/include/usgscsm/UsgsAstroLsPlugin.h
+++ /dev/null
@@ -1,219 +0,0 @@
-//----------------------------------------------------------------------------
-//
-//                                UNCLASSIFIED
-//
-// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc.
-//                            ALL RIGHTS RESERVED
-// Use of this software product is governed by the terms of a license
-// agreement. The license agreement is found in the installation directory.
-//
-//             For support, please visit http://www.baesystems.com/gxp
-//
-// Description:
-//  This class creates instances of the Astro Line Scanner sensor model.  The
-//  sensor model can be created from either image support data or sensor model
-//  state data. This plugin is an implementation of the CSM 3.0.3 CSM plugin
-//  class. It supports ISD specified by image file name.  It is expected that
-//  a support data file exist in the same directory with the images file name
-//  with "_keywords.lis" appended instead of the original extension. An optional
-//  file containing ellipsoid data (ellipsoid.ell) can also be placed in this
-//  directory. Otherwise, the ellipsoid data is found in the .lis file.
-//
-//  Revision History:
-//  Date        Name        Description
-//  ----------- ---------   -----------------------------------------------
-//  30-APR-2017 BAE Systems Initial Implementation based on CSM 2.0 code
-//  16-OCT-2017 BAE Systems Update for CSM 3.0.3
-//-----------------------------------------------------------------------------
-
-#ifndef __USGS_ASTRO_LINE_SCANNER_PLUGIN_H
-#define __USGS_ASTRO_LINE_SCANNER_PLUGIN_H
-
-#include <string>
-#include <Plugin.h>
-
-
-class UsgsAstroLsPlugin : public csm::Plugin
-{
-public:
-
-   //---
-   // The public interface is inherited from the csm::Plugin class.
-   //---
-
-   //--------------------------------------------------------------------------
-   // Plugin Interface
-   //--------------------------------------------------------------------------
-   virtual std::string getPluginName() const;
-   //> This method returns the character std::string that identifies the
-   //  plugin.
-   //<
-
-   //---
-   // CSM Plugin Descriptors
-   //---
-   virtual std::string getManufacturer() const;
-   //> This method returns name of the organization that created the plugin.
-   //<
-
-   virtual std::string getReleaseDate() const;
-   //> This method returns release date of the plugin.
-   //  The returned string follows the ISO 8601 standard.
-   //
-   //-    Precision   Format           Example
-   //-    year        yyyy             "1961"
-   //-    month       yyyymm           "196104"
-   //-    day         yyyymmdd         "19610420"
-   //<
-
-   virtual csm::Version getCsmVersion() const;
-   //> This method returns the CSM API version that the plugin conforms to.
-   //<
-
-   //---
-   // Model Availability
-   //---
-   virtual size_t getNumModels() const;
-   //> This method returns the number of types of models that this plugin
-   //  can create.
-   //<
-
-   virtual std::string getModelName(size_t modelIndex) const;
-   //> This method returns the name of the model for the given modelIndex.
-   //  The order does not matter - the index is only used to cycle through
-   //  all of the model names.
-   //
-   //  The model index must be less than getNumModels(), or an exception
-   //  will be thrown.
-   //<
-
-   virtual std::string getModelFamily(size_t modelIndex) const;
-   //> This method returns the model "family" for the model for the given
-   //  modelIndex.  This should be the same as what is returned from
-   //  csm::Model::getFamily() for the model.
-   //
-   //  SETs can use this information to exclude models when searching for a
-   //  model to create.
-   //
-   //  The model index must be less than getNumModels(), or an exception
-   //  will be thrown.
-   //<
-
-   //---
-   // Model Descriptors
-   //---
-   virtual csm::Version getModelVersion(const std::string& modelName) const;
-   //> This method returns the version of the code for the model given
-   //  by modelIndex.  The Version object can be compared to other Version
-   //  objects with its comparison operators.  Not to be confused with the
-   //  CSM API version.
-   //<
-
-   //---
-   // Model Construction
-   //---
-   virtual bool canModelBeConstructedFromState(
-      const std::string& modelName,
-      const std::string& modelState,
-      csm::WarningList* warnings = NULL) const;
-   //> This method returns a boolean indicating whether or not a model of the
-   //  given modelName can be constructed from the given modelState.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   virtual bool canModelBeConstructedFromISD(
-      const csm::Isd& imageSupportData,
-      const std::string& modelName,
-      csm::WarningList* warnings = NULL) const;
-   //> This method returns a boolean indicating whether or not a model of the
-   //  given modelName can be constructed from the given imageSupportData.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   virtual csm::Model* constructModelFromState(
-      const std::string& modelState,
-      csm::WarningList* warnings = NULL) const;
-   //> This method allocates and initializes an object of the appropriate
-   //  derived Model class with the given modelState and returns a pointer to
-   //  the Model base class.  The object is allocated by this method using
-   //  new; it is the responsibility of the calling application to delete it.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   virtual csm::Model* constructModelFromISD(
-      const csm::Isd& imageSupportData,
-      const std::string& modelName,
-      csm::WarningList* warnings = NULL) const;
-   //> This method allocates and initializes an object of the appropriate
-   //  derived Model class with the given imageSupportData and returns a
-   //  pointer to the Model base class.  The object is allocated by this
-   //  method using new; it is the responsibility of the calling
-   //  application to delete it.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   virtual std::string getModelNameFromModelState(
-      const std::string& modelState,
-      csm::WarningList* warnings = NULL) const;
-   // This method returns the model name for which the given modelState
-   // is applicable.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   //---
-   // Image Support Data Conversions
-   //---
-   virtual bool canISDBeConvertedToModelState(
-      const csm::Isd& imageSupportData,
-      const std::string& modelName,
-      csm::WarningList* warnings = NULL) const;
-   //> This method returns a boolean indicating whether or not a model state
-   //  of the given modelName can be constructed from the given
-   //  imageSupportData.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-   virtual std::string convertISDToModelState(
-      const csm::Isd&    imageSupportData,
-      const std::string& modelName,
-      csm::WarningList*  warnings = NULL) const;
-   //> This method returns a model state string for the given modelName,
-   //  constructed from the given imageSupportData.
-   //
-   //  If a non-NULL warnings argument is received, it will be populated
-   //  as applicable.
-   //<
-
-//private:
-
-   //--------------------------------------------------------------------------
-   // Constructors/Destructor
-   //--------------------------------------------------------------------------
-
-   UsgsAstroLsPlugin();
-   ~UsgsAstroLsPlugin();
-
-private:
-   //--------------------------------------------------------------------------
-   // Data Members
-   //--------------------------------------------------------------------------
-
-   // This is needed to allow the plugin to be registered.
-   static const UsgsAstroLsPlugin  _theRegisteringObject;
-   static const std::string mISD_KEYWORDS[];
-   static const std::string mSTATE_KEYWORDS[];
-}; // UsgsAstroLsPlugin
-
-#endif // __USGS_ASTRO_LINE_SCANNER_PLUGIN_H
diff --git a/include/usgscsm/UsgsAstroLsSensorModel.h b/include/usgscsm/UsgsAstroLsSensorModel.h
index 5306a0b..2fc6d7e 100644
--- a/include/usgscsm/UsgsAstroLsSensorModel.h
+++ b/include/usgscsm/UsgsAstroLsSensorModel.h
@@ -27,7 +27,6 @@
 #ifndef __USGS_ASTRO_LINE_SCANNER_SENSORMODEL_H
 #define __USGS_ASTRO_LINE_SCANNER_SENSORMODEL_H
 
-#include "UsgsAstroLsStateData.h"
 #include <RasterGM.h>
 #include <SettableEllipsoid.h>
 #include <CorrelationModel.h>
@@ -37,6 +36,102 @@ class UsgsAstroLsSensorModel : public csm::RasterGM, virtual public csm::Settabl
 {
 public:
 
+   // Initializes the class from state data as formatted
+   // in a string by the toString() method
+   void setState(const std::string &state);
+
+
+    virtual void replaceModelState(const std::string& argState);
+    //> This method attempts to initialize the current model with the state
+    //  given by argState.  The argState argument can be a string previously
+    //  retrieved from the getModelState method.
+    //
+    //  If argState contains a valid state for the current model,
+    //  the internal state of the model is updated.
+    //
+    //  If the model cannot be updated to the given state, a csm::Error is
+    //  thrown and the internal state of the model is undefined.
+    //
+    //  If the argument state string is empty, the model remains unchanged.
+    //<
+
+
+   // This method checks to see if the model name is recognized
+   // in the input state string.
+   static std::string getModelNameFromModelState(
+      const std::string& model_state);
+
+  std::string constructStateFromIsd(const std::string imageSupportData, csm::WarningList *list) const;
+
+   // State data elements;
+   std::string  m_imageIdentifier;                // 1
+   std::string  m_sensorType;                     // 2
+   int          m_totalLines;                     // 3
+   int          m_totalSamples;                   // 4
+   double       m_offsetLines;                    // 5
+   double       m_offsetSamples;                  // 6
+   int          m_platformFlag;                   // 7
+   int          m_aberrFlag;                      // 8
+   int          m_atmRefFlag;                     // 9
+   std::vector<double> m_intTimeLines;
+   std::vector<double> m_intTimeStartTimes;
+   std::vector<double> m_intTimes;
+   double       m_startingEphemerisTime;          // 11
+   double       m_centerEphemerisTime;            // 12
+   double       m_detectorSampleSumming;          // 13
+   double       m_startingSample;                 // 14
+   int          m_ikCode;                         // 15
+   double       m_focal;                          // 16
+   double       m_isisZDirection;                 // 17
+   double       m_opticalDistCoef[3];             // 18
+   double       m_iTransS[3];                     // 19
+   double       m_iTransL[3];                     // 20
+   double       m_detectorSampleOrigin;           // 21
+   double       m_detectorLineOrigin;             // 22
+   double       m_detectorLineOffset;             // 23
+   double       m_mountingMatrix[9];              // 24
+   double       m_semiMajorAxis;                  // 25
+   double       m_semiMinorAxis;                  // 26
+   std::string  m_referenceDateAndTime;           // 27
+   std::string  m_platformIdentifier;             // 28
+   std::string  m_sensorIdentifier;               // 29
+   std::string  m_trajectoryIdentifier;           // 30
+   std::string  m_collectionIdentifier;           // 31
+   double       m_refElevation;                   // 32
+   double       m_minElevation;                   // 33
+   double       m_maxElevation;                   // 34
+   double       m_dtEphem;                        // 35
+   double       m_t0Ephem;                        // 36
+   double       m_dtQuat;                         // 37
+   double       m_t0Quat;                         // 38
+   int          m_numEphem;                       // 39
+   int          m_numQuaternions;                 // 40
+   std::vector<double> m_ephemPts;                // 41
+   std::vector<double> m_ephemRates;              // 42
+   std::vector<double> m_quaternions;             // 43
+   std::vector<double> m_parameterVals;           // 44
+   std::vector<csm::param::Type> m_parameterType; // 45
+   csm::EcefCoord m_referencePointXyz;            // 46
+   double       m_gsd;                            // 47
+   double       m_flyingHeight;                   // 48
+   double       m_halfSwath;                      // 49
+   double       m_halfTime;                       // 50
+   std::vector<double> m_covariance;              // 51
+   int          m_imageFlipFlag;                  // 52
+
+   // Hardcoded
+   static const std::string      _SENSOR_MODEL_NAME; // state date element 0
+
+   static const std::string      _STATE_KEYWORD[];
+   static const int              NUM_PARAM_TYPES;
+   static const std::string      PARAM_STRING_ALL[];
+   static const csm::param::Type PARAM_CHAR_ALL[];
+   static const int              NUM_PARAMETERS;
+   static const std::string      PARAMETER_NAME[];
+
+   // Set to default values
+   void reset();
+
    //--------------------------------------------------------------
    // Constructors/Destructor
    //--------------------------------------------------------------
@@ -44,8 +139,11 @@ public:
    UsgsAstroLsSensorModel();
    ~UsgsAstroLsSensorModel();
 
+   virtual std::string getModelState() const;
+
+
    // Set the sensor model based on the input state data
-   void set( const UsgsAstroLsStateData &state_data );
+   void set( const std::string &state_data );
 
 
    //----------------------------------------------------------------
@@ -775,7 +873,7 @@ public:
    //---
    // Sensor Model State
    //---
-   virtual std::string getModelState() const;
+   // virtual std::string setModelState(std::string stateString) const;
    //> This method returns a string containing the data to exactly recreate
    //  the current model.  It can be used to restore this model to a
    //  previous state with the replaceModelState method or create a new
@@ -785,20 +883,6 @@ public:
    //  current state.
    //<
 
-   virtual void replaceModelState(const std::string& argState);
-   //> This method attempts to initialize the current model with the state
-   //  given by argState.  The argState argument can be a string previously
-   //  retrieved from the getModelState method.
-   //
-   //  If argState contains a valid state for the current model,
-   //  the internal state of the model is updated.
-   //
-   //  If the model cannot be updated to the given state, a csm::Error is
-   //  thrown and the internal state of the model is undefined.
-   //
-   //  If the argument state string is empty, the model remains unchanged.
-   //<
-
    virtual csm::Ellipsoid getEllipsoid() const;
    //> This method returns the planetary ellipsoid.
    //<
@@ -951,7 +1035,6 @@ private:
    double determinant3x3(double mat[9]) const;
 
 
-   UsgsAstroLsStateData _data;  // Holds the state data
 
    csm::NoCorrelationModel     _no_corr_model; // A way to report no correlation between images is supported
    std::vector<double>         _no_adjustment; // A vector of zeros indicating no internal adjustment
diff --git a/include/usgscsm/UsgsAstroLsStateData.h b/include/usgscsm/UsgsAstroLsStateData.h
deleted file mode 100644
index 1527194..0000000
--- a/include/usgscsm/UsgsAstroLsStateData.h
+++ /dev/null
@@ -1,208 +0,0 @@
-//----------------------------------------------------------------------------
-//
-//                                UNCLASSIFIED
-//
-// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc.
-//                            ALL RIGHTS RESERVED
-// Use of this software product is governed by the terms of a license
-// agreement. The license agreement is found in the installation directory.
-//
-//             For support, please visit http://www.baesystems.com/gxp
-//
-//  DESCRIPTION:
-//
-//    Holds State data that runs the Astro Line Scanner Sensor Model.
-//    The format of the state data is determined by the sensor model
-//    developer. The CSM plugin converts ISD to state data and the
-//    CSM sensor model is instantiated based on the state data.
-//
-//    By CSM convention, the sensor model name is the first element in
-//    the state data. The rest of the state data is order independent
-//    with the exception that the length of vectors must come before
-//    the vector data.
-//
-//    For the Astro Line Scanner sensor model, the state data closely
-//    follows the support data. This is not always the case. For this
-//    model, the state data is a list name/value pairs.
-//
-//
-//    SOFTWARE HISTORY:
-//
-//    Date          Author       Comment
-//    -----------   ----------   -------
-//    13-OCT-2017   BAE Systems  Initial Release
-//
-//#############################################################################
-#ifndef __USGS_ASTRO_LINE_SCANNER_STATE_DATA_H
-#define __USGS_ASTRO_LINE_SCANNER_STATE_DATA_H
-
-#include <vector>
-#include <string>
-
-#include <csm.h>
-#include <SettableEllipsoid.h>
-
-class UsgsAstroLsStateData
-{
-   public:
-
-   UsgsAstroLsStateData()
-   {
-      reset();
-   }
-
-   UsgsAstroLsStateData(const std::string &state)
-   {
-      reset();
-      setState(state);
-   }
-
-   ~UsgsAstroLsStateData() {}
-
-   // Formats the state data as a string.
-   // This is the format that is used to instantiate a sensor model.
-   std::string toString() const;
-
-   // Formats the sate data as a JSON string.
-   std::string toJson() const;
-
-   // Initializes the class from state data as formatted
-   // in a string by the toString() method
-   void setState(const std::string &state);
-
-   // This method checks to see if the model name is recognized
-   // in the input state string.
-   static std::string getModelNameFromModelState(
-      const std::string& model_state);
-
-   // State data elements;
-   std::string  m_ImageIdentifier;                // 1
-   std::string  m_SensorType;                     // 2
-   int          m_TotalLines;                     // 3
-   int          m_TotalSamples;                   // 4
-   double       m_OffsetLines;                    // 5
-   double       m_OffsetSamples;                  // 6
-   int          m_PlatformFlag;                   // 7
-   int          m_AberrFlag;                      // 8
-   int          m_AtmRefFlag;                     // 9
-   std::vector<double> m_IntTimeLines;
-   std::vector<double> m_IntTimeStartTimes;
-   std::vector<double> m_IntTimes;
-   double       m_StartingEphemerisTime;          // 11
-   double       m_CenterEphemerisTime;            // 12
-   double       m_DetectorSampleSumming;          // 13
-   double       m_StartingSample;                 // 14
-   int          m_IkCode;                         // 15
-   double       m_Focal;                          // 16
-   double       m_IsisZDirection;                 // 17
-   double       m_OpticalDistCoef[3];             // 18
-   double       m_ITransS[3];                     // 19
-   double       m_ITransL[3];                     // 20
-   double       m_DetectorSampleOrigin;           // 21
-   double       m_DetectorLineOrigin;             // 22
-   double       m_DetectorLineOffset;             // 23
-   double       m_MountingMatrix[9];              // 24
-   double       m_SemiMajorAxis;                  // 25
-   double       m_SemiMinorAxis;                  // 26
-   std::string  m_ReferenceDateAndTime;           // 27
-   std::string  m_PlatformIdentifier;             // 28
-   std::string  m_SensorIdentifier;               // 29
-   std::string  m_TrajectoryIdentifier;           // 30
-   std::string  m_CollectionIdentifier;           // 31
-   double       m_RefElevation;                   // 32
-   double       m_MinElevation;                   // 33
-   double       m_MaxElevation;                   // 34
-   double       m_DtEphem;                        // 35
-   double       m_T0Ephem;                        // 36
-   double       m_DtQuat;                         // 37
-   double       m_T0Quat;                         // 38
-   int          m_NumEphem;                       // 39
-   int          m_NumQuaternions;                 // 40
-   std::vector<double> m_EphemPts;                // 41
-   std::vector<double> m_EphemRates;              // 42
-   std::vector<double> m_Quaternions;             // 43
-   std::vector<double> m_ParameterVals;           // 44
-   std::vector<csm::param::Type> m_ParameterType; // 45
-   csm::EcefCoord m_ReferencePointXyz;            // 46
-   double       m_Gsd;                            // 47
-   double       m_FlyingHeight;                   // 48
-   double       m_HalfSwath;                      // 49
-   double       m_HalfTime;                       // 50
-   std::vector<double> m_Covariance;              // 51
-   int          m_ImageFlipFlag;                  // 52
-
-   // Hardcoded
-   static const std::string      SENSOR_MODEL_NAME; // state date element 0
-
-   static const std::string      STATE_KEYWORD[];
-   static const int              NUM_PARAM_TYPES;
-   static const std::string      PARAM_STRING_ALL[];
-   static const csm::param::Type PARAM_CHAR_ALL[];
-   static const int              NUM_PARAMETERS;
-   static const std::string      PARAMETER_NAME[];
-
-   enum
-   {
-       STA_SENSOR_MODEL_NAME,
-       STA_IMAGE_IDENTIFIER,
-       STA_SENSOR_TYPE,
-       STA_TOTAL_LINES,
-       STA_TOTAL_SAMPLES,
-       STA_OFFSET_LINES,
-       STA_OFFSET_SAMPLES,
-       STA_PLATFORM_FLAG,
-       STA_ABERR_FLAG,
-       STA_ATMREF_FLAG,
-       STA_INT_TIME_LINES,
-       STA_INT_TIME_START_TIMES,
-       STA_INT_TIMES,
-       STA_STARTING_EPHEMERIS_TIME,
-       STA_CENTER_EPHEMERIS_TIME,
-       STA_DETECTOR_SAMPLE_SUMMING,
-       STA_STARTING_SAMPLE,
-       STA_IK_CODE,
-       STA_FOCAL,
-       STA_ISIS_Z_DIRECTION,
-       STA_OPTICAL_DIST_COEF,
-       STA_I_TRANS_S,
-       STA_I_TRANS_L,
-       STA_DETECTOR_SAMPLE_ORIGIN,
-       STA_DETECTOR_LINE_ORIGIN,
-       STA_DETECTOR_LINE_OFFSET,
-       STA_MOUNTING_MATRIX,
-       STA_SEMI_MAJOR_AXIS,
-       STA_SEMI_MINOR_AXIS,
-       STA_REFERENCE_DATE_AND_TIME,
-       STA_PLATFORM_IDENTIFIER,
-       STA_SENSOR_IDENTIFIER,
-       STA_TRAJECTORY_IDENTIFIER,
-       STA_COLLECTION_IDENTIFIER,
-       STA_REF_ELEVATION,
-       STA_MIN_ELEVATION,
-       STA_MAX_ELEVATION,
-       STA_DT_EPHEM,
-       STA_T0_EPHEM,
-       STA_DT_QUAT,
-       STA_T0_QUAT,
-       STA_NUM_EPHEM,
-       STA_NUM_QUATERNIONS,
-       STA_EPHEM_PTS,
-       STA_EPHEM_RATES,
-       STA_QUATERNIONS,
-       STA_PARAMETER_VALS,
-       STA_PARAMETER_TYPE,
-       STA_REFERENCE_POINT_XYZ,
-       STA_GSD,
-       STA_FLYING_HEIGHT,
-       STA_HALF_SWATH,
-       STA_HALF_TIME,
-       STA_COVARIANCE,
-       STA_IMAGE_FLIP_FLAG,
-       _NUM_STATE_KEYWORDS
-   };
-
-   // Set to default values
-   void reset();
-};
-
-#endif
diff --git a/include/usgscsm/UsgsAstroFramePlugin.h b/include/usgscsm/UsgsAstroPlugin.h
similarity index 82%
rename from include/usgscsm/UsgsAstroFramePlugin.h
rename to include/usgscsm/UsgsAstroPlugin.h
index 8b6f57e..a3a3c76 100644
--- a/include/usgscsm/UsgsAstroFramePlugin.h
+++ b/include/usgscsm/UsgsAstroPlugin.h
@@ -1,5 +1,5 @@
-#ifndef UsgsAstroFramePlugin_h
-#define UsgsAstroFramePlugin_h
+#ifndef UsgsAstroPlugin_h
+#define UsgsAstroPlugin_h
 
 
 #include <string>
@@ -7,13 +7,16 @@
 #include <Plugin.h>
 #include <Version.h>
 
+#include <json.hpp>
+using json = nlohmann::json;
 
-class UsgsAstroFramePlugin : public csm::Plugin {
+class UsgsAstroPlugin : public csm::Plugin {
 
   public:
-    UsgsAstroFramePlugin();
-    ~UsgsAstroFramePlugin();
+    UsgsAstroPlugin();
+    ~UsgsAstroPlugin();
 
+    virtual std::string getStateFromISD(csm::Isd imageSupportData) const;
     virtual std::string getPluginName() const;
     virtual std::string getManufacturer() const;
     virtual std::string getReleaseDate() const;
@@ -42,12 +45,12 @@ class UsgsAstroFramePlugin : public csm::Plugin {
                                                const std::string &modelName,
                                                csm::WarningList *warnings = NULL) const;
 
+    std::string loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const;
+
     // TODO when implementing, add any other necessary members.
 
 private:
-    csm::Isd loadImageSupportData(const csm::Isd &imageSupportData) const; 
-
-    static const UsgsAstroFramePlugin m_registeredPlugin;
+    static const UsgsAstroPlugin m_registeredPlugin;
     static const std::string _PLUGIN_NAME;
     static const std::string _MANUFACTURER_NAME;
     static const std::string _RELEASE_DATE;
@@ -56,6 +59,10 @@ private:
     static const std::string _ISD_KEYWORD[];
     static const int         _NUM_STATE_KEYWORDS;
     static const std::string _STATE_KEYWORD[];
+    static const json MODEL_KEYWORDS;
+
+    typedef csm::Model* (*sensorConstructor)(void);
+    static std::map<std::string, sensorConstructor> MODELS;
 };
 
 #endif
diff --git a/recipe/bld.bat b/recipe/bld.bat
new file mode 100644
index 0000000..04c8729
--- /dev/null
+++ b/recipe/bld.bat
@@ -0,0 +1,7 @@
+mkdir build
+cd build
+cmake -G "Visual Studio 15 2017 Win64" -DBUILD_TESTS=OFF ..
+cmake --build . --target ALL_BUILD --config Release
+copy Release\usgscsm.dll %LIBRARY_BIN%
+
+if errorlevel 1 exit 1 
diff --git a/recipe/meta.yaml b/recipe/meta.yaml
index f9eee4d..fc8a832 100644
--- a/recipe/meta.yaml
+++ b/recipe/meta.yaml
@@ -1,22 +1,30 @@
+
 package:
-  name: usgscam
+  name: usgscsm
   version: "0.1.0"
 
 source:
   git_url: https://github.com/USGS-Astrogeology/CSM-CameraModel.git
+build:
+  string: dev
 
 requirements:
   build:
     - {{ compiler('cxx') }}  # [linux]
+    - vc 14  # [win]
     - cmake >=3.10
     - libcsm
+    - vc 14  # [win]
+  run:
+    - vc  # [win]
 
 test:
   commands:
     - test -e $PREFIX/lib/libusgscsm.so  # [linux]
     - test -e $PREFIX/lib/libusgscsm.dylib  # [osx]
+    - if not exist %LIBRARY_BIN%\usgscsm.dll exit 1  # [win]
 
 about:
   home: https://github.com/USGS-Astrogeology/CSM-CameraModels
   license: None
-  summary: "USGS Astrogeology Community Sensor Model compliant sensor models."
+summary: "USGS Astrogeology Community Sensor Model compliant sensor models."
diff --git a/src/UsgsAstroFramePlugin.cpp b/src/UsgsAstroFramePlugin.cpp
deleted file mode 100644
index 74cf266..0000000
--- a/src/UsgsAstroFramePlugin.cpp
+++ /dev/null
@@ -1,620 +0,0 @@
-#include "UsgsAstroFramePlugin.h"
-#include "UsgsAstroFrameSensorModel.h"
-
-#include <cstdlib>
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <fstream>
-#include <map> 
-
-#include <csm.h>
-#include <Error.h>
-#include <Plugin.h>
-#include <Warning.h>
-#include <Version.h>
-
-#include <json.hpp>
-
-
-using json = nlohmann::json;
-
-#ifdef _WIN32
-# define DIR_DELIMITER_STR "\\"
-#else
-# define DIR_DELIMITER_STR  "/"
-#endif
-
-
-// Declaration of static variables
-const std::string UsgsAstroFramePlugin::_PLUGIN_NAME = "UsgsAstroFramePluginCSM";
-const std::string UsgsAstroFramePlugin::_MANUFACTURER_NAME = "UsgsAstrogeology";
-const std::string UsgsAstroFramePlugin::_RELEASE_DATE = "20170425";
-const int         UsgsAstroFramePlugin::_N_SENSOR_MODELS = 1;
-
-const int         UsgsAstroFramePlugin::_NUM_ISD_KEYWORDS = 36;
-const std::string UsgsAstroFramePlugin::_ISD_KEYWORD[] =
-{
-    "boresight",
-    "ccd_center",
-    "ephemeris_time",
-    "focal_length",
-    "focal_length_epsilon",
-    "ifov",
-    "instrument_id",
-    "itrans_line",
-    "itrans_sample",
-    "kappa",
-    "min_elevation",
-    "max_elevation",
-    "model_name",
-    "nlines",
-    "nsamples",
-    "odt_x",
-    "odt_y",
-    "omega",
-    "original_half_lines",
-    "original_half_samples",
-    "phi",
-    "pixel_pitch",
-    "semi_major_axis",
-    "semi_minor_axis",
-    "spacecraft_name",
-    "starting_detector_line",
-    "starting_detector_sample",
-    "target_name",
-    "transx",
-    "transy",
-    "x_sensor_origin",
-    "y_sensor_origin",
-    "z_sensor_origin",
-    "x_sensor_velocity",
-    "y_sensor_velocity",
-    "z_sensor_velocity",
-    "x_sun_position",
-    "y_sun_position",
-    "z_sun_position"
-};
-
-const int         UsgsAstroFramePlugin::_NUM_STATE_KEYWORDS = 32;
-const std::string UsgsAstroFramePlugin::_STATE_KEYWORD[] =
-{
-    "m_focalLength",
-    "m_iTransS",
-    "m_iTransL",
-    "m_boresight",
-    "m_transX",
-    "m_transY",
-    "m_majorAxis",
-    "m_minorAxis",
-    "m_spacecraftVelocity",
-    "m_sunPosition",
-    "m_startingDetectorSample",
-    "m_startingDetectorLine",
-    "m_targetName",
-    "m_ifov",
-    "m_instrumentID",
-    "m_focalLengthEpsilon",
-    "m_ccdCenter",
-    "m_line_pp",
-    "m_sample_pp",
-    "m_minElevation",
-    "m_maxElevation",
-    "m_odtX",
-    "m_odtY",
-    "m_originalHalfLines",
-    "m_originalHalfSamples",
-    "m_spacecraftName",
-    "m_pixelPitch",
-    "m_ephemerisTime",
-    "m_nLines",
-    "m_nSamples",
-    "m_currentParameterValue",
-    "m_currentParameterCovariance"
-};
-
-
-// Static Instance of itself
-const UsgsAstroFramePlugin UsgsAstroFramePlugin::m_registeredPlugin;
-
-UsgsAstroFramePlugin::UsgsAstroFramePlugin() {
-}
-
-
-UsgsAstroFramePlugin::~UsgsAstroFramePlugin() {
-}
-
-
-std::string UsgsAstroFramePlugin::getPluginName() const {
-  return _PLUGIN_NAME;
-}
-
-
-std::string UsgsAstroFramePlugin::getManufacturer() const {
-  return _MANUFACTURER_NAME;
-}
-
-
-std::string UsgsAstroFramePlugin::getReleaseDate() const {
-  return _RELEASE_DATE;
-}
-
-
-csm::Version UsgsAstroFramePlugin::getCsmVersion() const {
-  return CURRENT_CSM_VERSION;
-}
-
-
-size_t UsgsAstroFramePlugin::getNumModels() const {
-  return _N_SENSOR_MODELS;
-}
-
-
-std::string UsgsAstroFramePlugin::getModelName(size_t modelIndex) const {
-
-  return UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME;
-}
-
-
-std::string UsgsAstroFramePlugin::getModelFamily(size_t modelIndex) const {
-  return CSM_RASTER_FAMILY;
-}
-
-
-csm::Version UsgsAstroFramePlugin::getModelVersion(const std::string &modelName) const {
-  return csm::Version(1, 0, 0);
-}
-
-
-bool UsgsAstroFramePlugin::canModelBeConstructedFromState(const std::string &modelName,
-                                                const std::string &modelState,
-                                                csm::WarningList *warnings) const {
-  bool constructible = true;
-
-  // Get the model name from the model state
-  std::string model_name_from_state;
-  try {
-    model_name_from_state = getModelNameFromModelState(modelState, warnings);
-  }
-  catch(...) {
-    return false;
-  }
-
-  // Check that the plugin supports the model
-  if (modelName != model_name_from_state ||
-      modelName != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){
-          constructible = false;
-      }
-
-  // Check that the necessary keys are there (this does not check values at all.)
-  auto state = json::parse(modelState);
-  for(auto &key : _STATE_KEYWORD){
-      if (state.find(key) == state.end()){
-          constructible = false;
-          break;
-      }
-  }
-  return constructible;
-}
-
-
-bool UsgsAstroFramePlugin::canModelBeConstructedFromISD(const csm::Isd &imageSupportData,
-                                              const std::string &modelName,
-                                              csm::WarningList *warnings) const {
-  return canISDBeConvertedToModelState(imageSupportData, modelName, warnings);
-}
-
-
-csm::Model *UsgsAstroFramePlugin::constructModelFromState(const std::string& modelState,
-                                                csm::WarningList *warnings) const {
-    csm::Model *sensor_model = 0;
-
-    // Get the sensor model name from the sensor model state
-    std::string model_name_from_state = getModelNameFromModelState(modelState);
-
-    if (model_name_from_state != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){
-        csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-        std::string aMessage = "Model name from state is not recognized.";
-        std::string aFunction = "UsgsAstroFramePlugin::constructModelFromState()";
-        throw csm::Error(aErrorType, aMessage, aFunction);
-    }
-
-    if (!canModelBeConstructedFromState(model_name_from_state, modelState)){
-        csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-        std::string aMessage = "Model state is not valid.";
-        std::string aFunction = "UsgsAstroFramePlugin::constructModelFromState()";
-        throw csm::Error(aErrorType, aMessage, aFunction);
-    }
-
-    // Create the model from the state
-    UsgsAstroFrameSensorModel* mdsensor_model = new UsgsAstroFrameSensorModel();
-
-    auto state = json::parse(modelState);
-
-    mdsensor_model->m_ccdCenter[0] = state["m_ccdCenter"][0];
-    mdsensor_model->m_ccdCenter[1] = state["m_ccdCenter"][1];
-    mdsensor_model->m_ephemerisTime = state["m_ephemerisTime"];
-    mdsensor_model->m_focalLength = state["m_focalLength"];
-    mdsensor_model->m_focalLengthEpsilon = state["m_focalLengthEpsilon"];
-    mdsensor_model->m_ifov = state["m_ifov"];
-    mdsensor_model->m_instrumentID = state["m_instrumentID"];
-
-    mdsensor_model->m_majorAxis = state["m_majorAxis"];
-    mdsensor_model->m_minorAxis = state["m_minorAxis"];
-    mdsensor_model->m_startingDetectorLine = state["m_startingDetectorLine"];
-    mdsensor_model->m_startingDetectorSample = state["m_startingDetectorSample"];
-    mdsensor_model->m_line_pp = state["m_line_pp"];
-    mdsensor_model->m_sample_pp = state["m_sample_pp"];
-    mdsensor_model->m_originalHalfLines = state["m_originalHalfLines"];
-    mdsensor_model->m_originalHalfSamples = state["m_originalHalfSamples"];
-    mdsensor_model->m_spacecraftName = state["m_spacecraftName"];
-    mdsensor_model->m_pixelPitch = state["m_pixelPitch"];
-    mdsensor_model->m_nLines = state["m_nLines"];
-    mdsensor_model->m_nSamples = state["m_nSamples"];
-    mdsensor_model->m_minElevation = state["m_minElevation"];
-    mdsensor_model->m_maxElevation = state["m_maxElevation"];
-
-    for (int i=0;i<3;i++){
-        mdsensor_model->m_boresight[i] = state["m_boresight"][i];
-        mdsensor_model->m_iTransL[i] = state["m_iTransL"][i];
-        mdsensor_model->m_iTransS[i] = state["m_iTransS"][i];
-
-        mdsensor_model->m_transX[i] = state["m_transX"][i];
-        mdsensor_model->m_transY[i] = state["m_transY"][i];
-        mdsensor_model->m_spacecraftVelocity[i] = state["m_spacecraftVelocity"][i];
-        mdsensor_model->m_sunPosition[i] = state["m_sunPosition"][i];
-    }
-
-    // Having types as vectors, instead of arrays makes interoperability with
-    // the JSON library very easy.
-    mdsensor_model->m_currentParameterValue = state["m_currentParameterValue"].get<std::vector<double>>();
-    mdsensor_model->m_odtX = state["m_odtX"].get<std::vector<double>>();
-    mdsensor_model->m_odtY = state["m_odtY"].get<std::vector<double>>();
-
-    mdsensor_model->m_currentParameterCovariance = state["m_currentParameterCovariance"].get<std::vector<double>>();
-
-sensor_model = mdsensor_model;
-return sensor_model;
-}
-
-
-// This function takes a csm::Isd which only has the image filename set. It uses this filename to
-// find a metadata json file loacated alongside the image file. It creates and returns new csm::Isd
-// with its parameters populated by the metadata file. 
-csm::Isd UsgsAstroFramePlugin::loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const{
-  // Get image location from the input csm::Isd: 
-  std::string imageFilename = imageSupportDataOriginal.filename(); 
-  
-  // Load 'sidecar' ISD file
-  size_t lastIndex = imageFilename.find_last_of("."); 
-  std::string baseName = imageFilename.substr(0, lastIndex); 
-  std::string isdFilename = baseName.append(".json");
-
-  csm::Isd imageSupportData(isdFilename);
-  imageSupportData.clearAllParams();
-
-  try {
-    std::ifstream isdFile(isdFilename); 
-    json jsonIsd = json::parse(isdFile);
-     for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) {
-      if (it.value().size() >1 ) {
-        std::vector<double> v = it.value();
-        for (int j=0;j < v.size(); j++) {
-          std::ostringstream val;
-          val << std::setprecision(15) << v[j];
-          imageSupportData.addParam(it.key(),val.str());
-        }
-      }
-      else {
-        imageSupportData.addParam(it.key(), it.value().dump());
-      }
-    }
-    isdFile.close(); 
-  } catch (...) {
-    std::string errorMessage = "Could not read metadata file associated with image: ";
-    errorMessage.append(isdFilename);
-    throw csm::Error(csm::Error::FILE_READ, errorMessage, 
-                     "UsgsAstroFramePlugin::loadImageSupportData"); 
-  }
-
-  return imageSupportData; 
-}
-
-csm::Model *UsgsAstroFramePlugin::constructModelFromISD(const csm::Isd &imageSupportDataOriginal,
-                                              const std::string &modelName,
-                                              csm::WarningList *warnings) const {
-
-  csm::Isd imageSupportData = loadImageSupportData(imageSupportDataOriginal); 
-
-  // FIXME: Check needs to be updated to use new JSON isd spec
-  // Check if the sensor model can be constructed from ISD given the model name
-  if (!canModelBeConstructedFromISD(imageSupportData, modelName)) {
-      throw csm::Error(csm::Error::ISD_NOT_SUPPORTED,
-                     "Sensor model support data provided is not supported by this plugin",
-                       "UsgsAstroFramePlugin::constructModelFromISD");
-  }
-
-  // Create the empty sensorModel
-  UsgsAstroFrameSensorModel *sensorModel = new UsgsAstroFrameSensorModel();
-  
-  // Keep track of necessary keywords that are missing from the ISD.
-  std::vector<std::string> missingKeywords;
-
-  sensorModel->m_startingDetectorSample =
-      atof(imageSupportData.param("starting_detector_sample").c_str());
-  sensorModel->m_startingDetectorLine =
-      atof(imageSupportData.param("starting_detector_line").c_str());
-
-  sensorModel->m_targetName = imageSupportData.param("target_name");
-
-  sensorModel->m_ifov = atof(imageSupportData.param("ifov").c_str());
-
-  sensorModel->m_instrumentID = imageSupportData.param("instrument_id");
-  if (imageSupportData.param("instrument_id") == "") {
-    missingKeywords.push_back("instrument_id");
-  }
-  sensorModel->m_focalLength = atof(imageSupportData.param("focal_length").c_str());
-  if (imageSupportData.param("focal_length") == "") {
-    missingKeywords.push_back("focal_length");
-  }
-  sensorModel->m_focalLengthEpsilon =
-      atof(imageSupportData.param("focal_length_epsilon").c_str());
-
-  sensorModel->m_currentParameterValue[0] =
-      atof(imageSupportData.param("x_sensor_origin").c_str());
-  sensorModel->m_currentParameterValue[1] =
-      atof(imageSupportData.param("y_sensor_origin").c_str());
-  sensorModel->m_currentParameterValue[2] =
-      atof(imageSupportData.param("z_sensor_origin").c_str());
-  if (imageSupportData.param("x_sensor_origin") == "") {
-    missingKeywords.push_back("x_sensor_origin");
-  }
-  if (imageSupportData.param("y_sensor_origin") == "") {
-    missingKeywords.push_back("y_sensor_origin");
-  }
-  if (imageSupportData.param("z_sensor_origin") == "") {
-    missingKeywords.push_back("z_sensor_origin");
-  }
-
-  sensorModel->m_spacecraftVelocity[0] =
-      atof(imageSupportData.param("x_sensor_velocity").c_str());
-  sensorModel->m_spacecraftVelocity[1] =
-      atof(imageSupportData.param("y_sensor_velocity").c_str());
-  sensorModel->m_spacecraftVelocity[2] =
-      atof(imageSupportData.param("z_sensor_velocity").c_str());
-  // sensor velocity not strictly necessary?
-
-  sensorModel->m_sunPosition[0] =
-      atof(imageSupportData.param("x_sun_position").c_str());
-  sensorModel->m_sunPosition[1] =
-      atof(imageSupportData.param("y_sun_position").c_str());
-  sensorModel->m_sunPosition[2] =
-      atof(imageSupportData.param("z_sun_position").c_str());
-  // sun position is not strictly necessary, but is required for getIlluminationDirection.
-
-  sensorModel->m_currentParameterValue[3] = atof(imageSupportData.param("omega").c_str());
-  sensorModel->m_currentParameterValue[4] = atof(imageSupportData.param("phi").c_str());
-  sensorModel->m_currentParameterValue[5] = atof(imageSupportData.param("kappa").c_str());
-  if (imageSupportData.param("omega") == "") {
-    missingKeywords.push_back("omega");
-  }
-  if (imageSupportData.param("phi") == "") {
-    missingKeywords.push_back("phi");
-  }
-  if (imageSupportData.param("kappa") == "") {
-    missingKeywords.push_back("kappa");
-  }
-
-  sensorModel->m_odtX[0] = atof(imageSupportData.param("odt_x", 0).c_str());
-  sensorModel->m_odtX[1] = atof(imageSupportData.param("odt_x", 1).c_str());
-  sensorModel->m_odtX[2] = atof(imageSupportData.param("odt_x", 2).c_str());
-  sensorModel->m_odtX[3] = atof(imageSupportData.param("odt_x", 3).c_str());
-  sensorModel->m_odtX[4] = atof(imageSupportData.param("odt_x", 4).c_str());
-  sensorModel->m_odtX[5] = atof(imageSupportData.param("odt_x", 5).c_str());
-  sensorModel->m_odtX[6] = atof(imageSupportData.param("odt_x", 6).c_str());
-  sensorModel->m_odtX[7] = atof(imageSupportData.param("odt_x", 7).c_str());
-  sensorModel->m_odtX[8] = atof(imageSupportData.param("odt_x", 8).c_str());
-  sensorModel->m_odtX[9] = atof(imageSupportData.param("odt_x", 9).c_str());
-
-  sensorModel->m_odtY[0] = atof(imageSupportData.param("odt_y", 0).c_str());
-  sensorModel->m_odtY[1] = atof(imageSupportData.param("odt_y", 1).c_str());
-  sensorModel->m_odtY[2] = atof(imageSupportData.param("odt_y", 2).c_str());
-  sensorModel->m_odtY[3] = atof(imageSupportData.param("odt_y", 3).c_str());
-  sensorModel->m_odtY[4] = atof(imageSupportData.param("odt_y", 4).c_str());
-  sensorModel->m_odtY[5] = atof(imageSupportData.param("odt_y", 5).c_str());
-  sensorModel->m_odtY[6] = atof(imageSupportData.param("odt_y", 6).c_str());
-  sensorModel->m_odtY[7] = atof(imageSupportData.param("odt_y", 7).c_str());
-  sensorModel->m_odtY[8] = atof(imageSupportData.param("odt_y", 8).c_str());
-  sensorModel->m_odtY[9] = atof(imageSupportData.param("odt_y", 9).c_str());
-
-  sensorModel->m_ccdCenter[0] = atof(imageSupportData.param("ccd_center", 0).c_str());
-  sensorModel->m_ccdCenter[1] = atof(imageSupportData.param("ccd_center", 1).c_str());
-
-  sensorModel->m_originalHalfLines = atof(imageSupportData.param("original_half_lines").c_str());
-  sensorModel->m_spacecraftName = imageSupportData.param("spacecraft_name");
-
-  sensorModel->m_pixelPitch = atof(imageSupportData.param("pixel_pitch").c_str());
-
-  sensorModel->m_iTransS[0] = atof(imageSupportData.param("itrans_sample", 0).c_str());
-  sensorModel->m_iTransS[1] = atof(imageSupportData.param("itrans_sample", 1).c_str());
-  sensorModel->m_iTransS[2] = atof(imageSupportData.param("itrans_sample", 2).c_str());
-
-  if (imageSupportData.param("itrans_sample", 0) == "") {
-    missingKeywords.push_back("itrans_sample missing first element");
-  }
-  else if (imageSupportData.param("itrans_sample", 1) == "") {
-    missingKeywords.push_back("itrans_sample missing second element");
-  }
-  else if (imageSupportData.param("itrans_sample", 2) == "") {
-    missingKeywords.push_back("itrans_sample missing third element");
-  }
-
-  sensorModel->m_ephemerisTime = atof(imageSupportData.param("ephemeris_time").c_str());
-  if (imageSupportData.param("ephemeris_time") == "") {
-    missingKeywords.push_back("ephemeris_time");
-  }
-
-  sensorModel->m_originalHalfSamples =
-      atof(imageSupportData.param("original_half_samples").c_str());
-
-  sensorModel->m_boresight[0] = atof(imageSupportData.param("boresight", 0).c_str());
-  sensorModel->m_boresight[1] = atof(imageSupportData.param("boresight", 1).c_str());
-  sensorModel->m_boresight[2] = atof(imageSupportData.param("boresight", 2).c_str());
-
-  sensorModel->m_iTransL[0] = atof(imageSupportData.param("itrans_line", 0).c_str());
-  sensorModel->m_iTransL[1] = atof(imageSupportData.param("itrans_line", 1).c_str());
-  sensorModel->m_iTransL[2] = atof(imageSupportData.param("itrans_line", 2).c_str());
-  if (imageSupportData.param("itrans_line", 0) == "") {
-    missingKeywords.push_back("itrans_line needs 3 elements");
-  }
-  else if (imageSupportData.param("itrans_line", 1) == "") {
-    missingKeywords.push_back("itrans_line needs 3 elements");
-  }
-  else if (imageSupportData.param("itrans_line", 2) == "") {
-    missingKeywords.push_back("itrans_line needs 3 elements");
-  }
-
-  sensorModel->m_nLines = atoi(imageSupportData.param("nlines").c_str());
-  sensorModel->m_nSamples = atoi(imageSupportData.param("nsamples").c_str());
-  if (imageSupportData.param("nlines") == "") {
-    missingKeywords.push_back("nlines");
-  }
-  if (imageSupportData.param("nsamples") == "") {
-    missingKeywords.push_back("nsamples");
-  }
-
-  sensorModel->m_transY[0] = atof(imageSupportData.param("transy", 0).c_str());
-  sensorModel->m_transY[1] = atof(imageSupportData.param("transy", 1).c_str());
-  sensorModel->m_transY[2] = atof(imageSupportData.param("transy", 2).c_str());
-  if (imageSupportData.param("transy", 0) == "") {
-    missingKeywords.push_back("transy 0");
-  }
-  else if (imageSupportData.param("transy", 1) == "") {
-    missingKeywords.push_back("transy 1");
-  }
-  else if (imageSupportData.param("transy", 2) == "") {
-    missingKeywords.push_back("transy 2");
-  }
-
-  sensorModel->m_transX[0] = atof(imageSupportData.param("transx", 0).c_str());
-  sensorModel->m_transX[1] = atof(imageSupportData.param("transx", 1).c_str());
-  sensorModel->m_transX[2] = atof(imageSupportData.param("transx", 2).c_str());
-  if (imageSupportData.param("transx", 0) == "") {
-    missingKeywords.push_back("transx 0");
-  }
-  else if (imageSupportData.param("transx", 1) == "") {
-    missingKeywords.push_back("transx 1");
-  }
-  else if (imageSupportData.param("transx", 2) == "") {
-    missingKeywords.push_back("transx");
-  }
-
-  sensorModel->m_majorAxis = 1000 * atof(imageSupportData.param("semi_major_axis").c_str());
-  if (imageSupportData.param("semi_major_axis") == "") {
-    missingKeywords.push_back("semi_major_axis");
-  }
-  // Do we assume that if we do not have a semi-minor axis, then the body is a sphere?
-  if (imageSupportData.param("semi_minor_axis") == "") {
-    sensorModel->m_minorAxis = sensorModel->m_majorAxis;
-  }
-  else {
-    sensorModel->m_minorAxis = 1000 * atof(imageSupportData.param("semi_minor_axis").c_str());
-  }
-
-  sensorModel->m_minElevation = atof(imageSupportData.param("min_elevation").c_str());
-  sensorModel->m_maxElevation = atof(imageSupportData.param("max_elevation").c_str());
-  if (imageSupportData.param("min_elevation") == ""){
-      missingKeywords.push_back("min_elevation");
-  }
-  if (imageSupportData.param("max_elevation") == ""){
-      missingKeywords.push_back("max_elevation");
-  }
-  // If we are missing necessary keywords from ISD, we cannot create a valid sensor model.
-  if (missingKeywords.size() != 0) {
-
-    std::string errorMessage = "ISD is missing the necessary keywords: [";
-
-    for (int i = 0; i < (int)missingKeywords.size(); i++) {
-      if (i == (int)missingKeywords.size() - 1) {
-        errorMessage += missingKeywords[i] + "]";
-      }
-      else {
-        errorMessage += missingKeywords[i] + ", ";
-      }
-    }
-
-    throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE,
-                     errorMessage,
-                     "UsgsAstroFramePlugin::constructModelFromISD");
-  }
-
-  return sensorModel;
-}
-
-
-std::string UsgsAstroFramePlugin::getModelNameFromModelState(const std::string &modelState,
-                                                   csm::WarningList *warnings) const {
-  std::string name;
-  auto state = json::parse(modelState);
-  if(state.find("model_name") != state.end()){
-      name = state["model_name"];
-  }
-  else{
-      csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-      std::string aMessage = "No 'model_name' key in the model state object.";
-      std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState";
-      csm::Error csmErr(aErrorType, aMessage, aFunction);
-      throw(csmErr);
-  }
-
-  if (name != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){
-      csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
-      std::string aMessage = "Sensor model not supported.";
-      std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState()";
-      csm::Error csmErr(aErrorType, aMessage, aFunction);
-      throw(csmErr);
-  }
-
-
-  return UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME;
-}
-
-
-bool UsgsAstroFramePlugin::canISDBeConvertedToModelState(const csm::Isd &imageSupportData,
-                                               const std::string &modelName,
-                                               csm::WarningList *warnings) const {
-  bool convertible = true;
-  if (modelName !=UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){
-      convertible = false;
-  }
-
-  csm::Isd localImageSupportData = imageSupportData; 
-  if (imageSupportData.parameters().empty()) {
-    localImageSupportData = loadImageSupportData(imageSupportData); 
-  }
-
-  std::string value;
-  for(auto &key : _ISD_KEYWORD){
-      value = localImageSupportData.param(key);
-      if (value.empty()){
-          convertible = false;
-      }
-  }
-  return convertible;
-}
-
-
-std::string UsgsAstroFramePlugin::convertISDToModelState(const csm::Isd &imageSupportData,
-                                               const std::string &modelName,
-                                               csm::WarningList *warnings) const {
-  csm::Model* sensor_model = constructModelFromISD(
-                             imageSupportData, modelName);
-
-  if (sensor_model == 0){
-      csm::Error::ErrorType aErrorType = csm::Error::ISD_NOT_SUPPORTED;
-      std::string aMessage = "ISD not supported: ";
-      std::string aFunction = "UsgsAstroFramePlugin::convertISDToModelState()";
-      throw csm::Error(aErrorType, aMessage, aFunction);
-  }
-  return sensor_model->getModelState();
-}
diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp
index f3050b4..2ef4aea 100644
--- a/src/UsgsAstroFrameSensorModel.cpp
+++ b/src/UsgsAstroFrameSensorModel.cpp
@@ -15,134 +15,63 @@ using namespace std;
 // Declaration of static variables
 const std::string UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME
                                       = "USGS_ASTRO_FRAME_SENSOR_MODEL";
-const int UsgsAstroFrameSensorModel::m_numParameters = 6;
+const int UsgsAstroFrameSensorModel::NUM_PARAMETERS = 7;
 const std::string UsgsAstroFrameSensorModel::m_parameterName[] = {
   "X Sensor Position (m)",  // 0
   "Y Sensor Position (m)",  // 1
   "Z Sensor Position (m)",  // 2
-  "Omega (radians)",        // 3
-  "Phi (radians)",          // 4
-  "Kappa (radians)"         // 5
+  "w",                      // 3
+  "v1",                     // 4
+  "v2",                     // 5
+  "v3"                      // 6
 };
 
 const int         UsgsAstroFrameSensorModel::_NUM_STATE_KEYWORDS = 32;
-const std::string UsgsAstroFrameSensorModel::_STATE_KEYWORD[] =
-{
-    "m_focalLength",
-    "m_iTransS",
-    "m_iTransL",
-    "m_boresight",
-    "m_transX",
-    "m_transY",
-    "m_majorAxis",
-    "m_minorAxis",
-    "m_spacecraftVelocity",
-    "m_sunPosition",
-    "m_startingDetectorSample",
-    "m_startingDetectorLine",
-    "m_targetName",
-    "m_ifov",
-    "m_instrumentID",
-    "m_focalLengthEpsilon",
-    "m_ccdCenter",
-    "m_line_pp",
-    "m_sample_pp",
-    "m_minElevation",
-    "m_maxElevation",
-    "m_odtX",
-    "m_odtY",
-    "m_originalHalfLines",
-    "m_originalHalfSamples",
-    "m_spacecraftName",
-    "m_pixelPitch",
-    "m_ephemerisTime",
-    "m_nLines",
-    "m_nSamples",
-    "m_minElevation",
-    "m_maxElevation",
-    "m_currentParameterValue",
-    "m_currentParameterCovariance"
-};
 
 UsgsAstroFrameSensorModel::UsgsAstroFrameSensorModel() {
+    reset();
+}
 
-  m_transX[0] = 0.0;
-  m_transX[1] = 0.0;
-  m_transX[2] = 0.0;
-
-  m_transY[0] = 0.0;
-  m_transY[1] = 0.0;
-  m_transY[2] = 0.0;
-
-  m_iTransS[0] = 0.0;
-  m_iTransS[1] = 0.0;
-  m_iTransS[2] = 0.0;
-
-  m_iTransL[0] = 0.0;
-  m_iTransL[0] = 0.0;
-  m_iTransL[0] = 0.0;
-
-  m_majorAxis = 0.0;
-  m_minorAxis = 0.0;
-  m_focalLength = 0.0;
-
-  m_spacecraftVelocity[0] = 0.0;
-  m_spacecraftVelocity[1] = 0.0;
-  m_spacecraftVelocity[2] = 0.0;
-
-  m_sunPosition[0] = 0.0;
-  m_sunPosition[1] = 0.0;
-  m_sunPosition[2] = 0.0;
-
-  m_startingDetectorSample = 0.0;
-  m_startingDetectorLine = 0.0;
-  m_targetName = "";
-  m_ifov = 0.0;
-  m_instrumentID = "";
-  m_focalLengthEpsilon = 0.0;
-
-  m_ccdCenter[0] = 0.0;
-  m_ccdCenter[1] = 0.0;
-
-  m_line_pp = 0.0;
-  m_sample_pp = 0.0;
-
-  m_odtX.assign(10, 0.0);
-  m_odtY.assign(10, 0.0);
-
-  m_originalHalfLines = 0.0;
-  m_spacecraftName = "";
-  m_pixelPitch = 0.0;
-
-  m_iTransS[0] = 0.0;
-  m_iTransS[1] = 0.0;
-  m_iTransS[2] = 0.0;
-
-  m_iTransL[0] = 0.0;
-  m_iTransL[1] = 0.0;
-  m_iTransL[2] = 0.0;
-
-  m_ephemerisTime = 0.0;
-  m_originalHalfSamples = 0.0;
-  m_boresight[0] = 0.0;
-  m_boresight[1] = 0.0;
-  m_boresight[2] = 0.0;
-
-  m_nLines = 0;
-  m_nSamples = 0;
-
-  m_currentParameterValue.assign(m_numParameters, 0.0);
-  m_currentParameterCovariance.assign(m_numParameters*m_numParameters,0.0);
-  m_noAdjustments.assign(m_numParameters,0.0);
-
-  m_parameterType.assign(m_numParameters, csm::param::REAL);
-
+void UsgsAstroFrameSensorModel::reset() {
+    m_modelName = _SENSOR_MODEL_NAME;
+    m_majorAxis = 0.0;
+    m_minorAxis = 0.0;
+    m_focalLength = 0.0;
+    m_startingDetectorSample = 0.0;
+    m_startingDetectorLine = 0.0;
+    m_targetName = "";
+    m_ifov = 0;
+    m_instrumentID = "";
+    m_focalLengthEpsilon = 0.0;
+    m_linePp = 0.0;
+    m_samplePp = 0.0;
+    m_originalHalfLines = 0.0;
+    m_spacecraftName = "";
+    m_pixelPitch = 0.0;
+    m_ephemerisTime = 0.0;
+    m_originalHalfSamples = 0.0;
+    m_nLines = 0;
+    m_nSamples = 0;
+
+    m_currentParameterValue = std::vector<double>(NUM_PARAMETERS, 0.0);
+    m_currentParameterCovariance = std::vector<double>(NUM_PARAMETERS*NUM_PARAMETERS,0.0);
+    m_noAdjustments = std::vector<double>(NUM_PARAMETERS,0.0);
+    m_ccdCenter = std::vector<double>(2, 0.0);
+    m_spacecraftVelocity = std::vector<double>(3, 0.0);
+    m_sunPosition = std::vector<double>(3, 0.0);
+    m_odtX = std::vector<double>(10, 0.0);
+    m_odtY = std::vector<double>(10, 0.0);
+    m_transX = std::vector<double>(3, 0.0);
+    m_transY = std::vector<double>(3, 0.0);
+    m_iTransS = std::vector<double>(3, 0.0);
+    m_iTransL = std::vector<double>(3, 0.0);
+    m_boresight = std::vector<double>(3, 0.0);
+    m_parameterType = std::vector<csm::param::Type>(NUM_PARAMETERS, csm::param::REAL);
 }
 
 
 UsgsAstroFrameSensorModel::~UsgsAstroFrameSensorModel() {}
 
-
 /**
  * @brief UsgsAstroFrameSensorModel::groundToImage
  * @param groundPt
@@ -157,7 +86,7 @@ csm::ImageCoord UsgsAstroFrameSensorModel::groundToImage(const csm::EcefCoord &g
                               double *achievedPrecision,
                               csm::WarningList *warnings) const {
 
-  return groundToImage(groundPt,m_noAdjustments,desiredPrecision,achievedPrecision,warnings);
+  return groundToImage(groundPt, m_noAdjustments, desiredPrecision, achievedPrecision, warnings);
 }
 
 
@@ -196,18 +125,18 @@ csm::ImageCoord UsgsAstroFrameSensorModel::groundToImage(
   // Sensor position
   double undistortedx, undistortedy, denom;
   denom = m[0][2] * xo + m[1][2] * yo + m[2][2] * zo;
-  undistortedx = (f * (m[0][0] * xo + m[1][0] * yo + m[2][0] * zo)/denom) + m_sample_pp;  //m_sample_pp like this assumes mm
-  undistortedy = (f * (m[0][1] * xo + m[1][1] * yo + m[2][1] * zo)/denom) + m_line_pp;
+  undistortedx = (f * (m[0][0] * xo + m[1][0] * yo + m[2][0] * zo)/denom) + m_samplePp;  //m_samplePp like this assumes mm
+  undistortedy = (f * (m[0][1] * xo + m[1][1] * yo + m[2][1] * zo)/denom) + m_linePp;
 
   // Apply the distortion to the line/sample location and then convert back to line/sample
   double distortedx, distortedy;
   distortionFunction(undistortedx, undistortedy, distortedx, distortedy);
 
 
-  //Convert distorted mm into line/sample
+  // Convert distorted mm into line/sample
   double sample, line;
-  sample = m_iTransS[0] + m_iTransS[1] * distortedx + m_iTransS[2] * distortedx + m_ccdCenter[0];
-  line =   m_iTransL[0] + m_iTransL[1] * distortedy + m_iTransL[2] * distortedy + m_ccdCenter[0];
+  sample = m_iTransS[0] + m_iTransS[1] * distortedx + m_iTransS[2] * distortedy + m_ccdCenter[1];
+  line =   m_iTransL[0] + m_iTransL[1] * distortedx + m_iTransL[2] * distortedy + m_ccdCenter[0];
 
   return csm::ImageCoord(line, sample);
 }
@@ -233,27 +162,28 @@ csm::EcefCoord UsgsAstroFrameSensorModel::imageToGround(const csm::ImageCoord &i
   double sample = imagePt.samp;
   double line = imagePt.line;
 
-  //Here is where we should be able to apply an adjustment to opk
+  // Here is where we should be able to apply an adjustment to opk
   double m[3][3];
   calcRotationMatrix(m);
 
-  //Apply the principal point offset, assuming the pp is given in pixels
+  // Apply the principal point offset, assuming the pp is given in pixels
   double xl, yl, zl, lo, so;
-  lo = line - m_line_pp;
-  so = sample - m_sample_pp;
+  lo = line - m_linePp;
+  so = sample - m_samplePp;
 
-  //Convert from the pixel space into the metric space
-  double optical_center_x, optical_center_y, x_camera, y_camera;
-  optical_center_x = m_ccdCenter[0];
-  optical_center_y = m_ccdCenter[1];
-  y_camera = m_transY[0] + m_transY[1] * (lo - optical_center_y) + m_transY[2] * (lo - optical_center_y);
-  x_camera = m_transX[0] + m_transX[1] * (so - optical_center_x) + m_transX[2] * (so - optical_center_x);
+  // Convert from the pixel space into the metric space
+  double line_center, sample_center, x_camera, y_camera;
+  line_center = m_ccdCenter[0];
+  sample_center = m_ccdCenter[1];
+  y_camera = m_transY[0] + m_transY[1] * (lo - line_center) + m_transY[2] * (so - sample_center);
+  x_camera = m_transX[0] + m_transX[1] * (lo - line_center) + m_transX[2] * (so - sample_center);
 
   // Apply the distortion model (remove distortion)
   double undistorted_cameraX, undistorted_cameraY = 0.0;
+
   setFocalPlane(x_camera, y_camera, undistorted_cameraX, undistorted_cameraY);
 
-  //Now back from distorted mm to pixels
+  // Now back from distorted mm to pixels
   double udx, udy; //distorted line and sample
   udx = undistorted_cameraX;
   udy = undistorted_cameraY;
@@ -269,6 +199,7 @@ csm::EcefCoord UsgsAstroFrameSensorModel::imageToGround(const csm::ImageCoord &i
   zc = m_currentParameterValue[2];
 
   // Intersect with some height about the ellipsoid.
+
   losEllipsoidIntersect(height, xc, yc, zc, xl, yl, zl, x, y, z);
 
   return csm::EcefCoord(x, y, z);
@@ -301,10 +232,10 @@ csm::EcefLocus UsgsAstroFrameSensorModel::imageToRemoteImagingLocus(const csm::I
                                                              csm::WarningList *warnings) const {
   // Find the line,sample on the focal plane (mm)
   // CSM center = 0.5, MDIS IK center = 1.0
-  double col = imagePt.samp - (m_ccdCenter[0]);
-  double row = imagePt.line - (m_ccdCenter[1]);
-  double focalPlaneX = m_transX[0] + m_transX[1] * col + m_transX[2] * col;
-  double focalPlaneY = m_transY[0] + m_transY[1] * row + m_transY[2] * row;
+  double row = imagePt.line - m_ccdCenter[0];
+  double col = imagePt.samp - m_ccdCenter[1];
+  double focalPlaneX = m_transX[0] + m_transX[1] * row + m_transX[2] * col;
+  double focalPlaneY = m_transY[0] + m_transY[1] * row + m_transY[2] * col;
 
   // Distort
   double undistortedFocalPlaneX = focalPlaneX;
@@ -500,7 +431,7 @@ csm::RasterGM::SensorPartials UsgsAstroFrameSensorModel::computeSensorPartials(i
 
   const double delta = 1.0;
   // Update the parameter
-  std::vector<double>adj(m_numParameters, 0.0);
+  std::vector<double>adj(NUM_PARAMETERS, 0.0);
   adj[index] = delta;
 
   csm::ImageCoord imagePt1 = groundToImage(groundPt,adj,desiredPrecision,achievedPrecision);
@@ -520,103 +451,101 @@ std::vector<csm::RasterGM::SensorPartials> UsgsAstroFrameSensorModel::computeAll
     csm::param::Set pset,
     double desiredPrecision,
     double *achievedPrecision,
-    csm::WarningList *warnings) const
-    {
-        std::vector<int> indices = getParameterSetIndices(pset);
-        size_t num = indices.size();
-        std::vector<csm::RasterGM::SensorPartials> partials;
-        for (int index = 0;index < num;index++){
-            partials.push_back(computeSensorPartials(
-                                indices[index],
-                                imagePt, groundPt,
-                                desiredPrecision, achievedPrecision, warnings));
-        }
-        return partials;
-    }
+    csm::WarningList *warnings) const {
+  std::vector<int> indices = getParameterSetIndices(pset);
+  size_t num = indices.size();
+  std::vector<csm::RasterGM::SensorPartials> partials;
+  for (int index = 0;index < num;index++){
+    partials.push_back(computeSensorPartials(
+        indices[index],
+        imagePt, groundPt,
+        desiredPrecision, achievedPrecision, warnings));
+  }
+  return partials;
+}
 
 std::vector<csm::RasterGM::SensorPartials> UsgsAstroFrameSensorModel::computeAllSensorPartials(
     const csm::EcefCoord& groundPt,
     csm::param::Set pset,
     double desiredPrecision,
     double *achievedPrecision,
-    csm::WarningList *warnings) const
-    {
-        csm::ImageCoord imagePt = groundToImage(groundPt,
-                                    desiredPrecision, achievedPrecision, warnings);
-        return computeAllSensorPartials(imagePt, groundPt,
-                                    pset, desiredPrecision, achievedPrecision, warnings);
+    csm::WarningList *warnings) const {
+  csm::ImageCoord imagePt = groundToImage(groundPt,
+                                          desiredPrecision, achievedPrecision, warnings);
+  return computeAllSensorPartials(imagePt, groundPt,
+                                  pset, desiredPrecision, achievedPrecision, warnings);
     }
 
-std::vector<double> UsgsAstroFrameSensorModel::computeGroundPartials(const csm::EcefCoord &groundPt) const {
-
-    // Partials of line, sample wrt X, Y, Z
-    // Uses collinearity equations
-    std::vector<double> partials(6, 0.0);
-
-    double m[3][3];
-    calcRotationMatrix(m, m_noAdjustments);
-
-    double xo, yo, zo;
-    xo = groundPt.x - m_currentParameterValue[0];
-    yo = groundPt.y - m_currentParameterValue[1];
-    zo = groundPt.z - m_currentParameterValue[2];
-
-    double u, v, w;
-    u = m[0][0] * xo + m[0][1] * yo + m[0][2] * zo;
-    v = m[1][0] * xo + m[1][1] * yo + m[1][2] * zo;
-    w = m[2][0] * xo + m[2][1] * yo + m[2][2] * zo;
+std::vector<double> UsgsAstroFrameSensorModel::computeGroundPartials(const csm::EcefCoord
+                                                                     &groundPt) const {
+  // Partials of line, sample wrt X, Y, Z
+  // Uses collinearity equations
+  std::vector<double> partials(6, 0.0);
 
-    double fdw, udw, vdw;
-    fdw = m_focalLength / w;
-    udw = u / w;
-    vdw = v / w;
-
-    double upx, vpx, wpx;
-    upx = m[0][0];
-    vpx = m[1][0];
-    wpx = m[2][0];
-    partials[0] = -fdw * ( upx - udw * wpx );
-    partials[3] = -fdw * ( vpx - vdw * wpx );
-
-    double upy, vpy, wpy;
-    upy = m[0][1];
-    vpy = m[1][1];
-    wpy = m[2][1];
-    partials[1] = -fdw * ( upy - udw * wpy );
-    partials[4] = -fdw * ( vpy - vdw * wpy );
-
-    double upz, vpz, wpz;
-    upz = m[0][2];
-    vpz = m[1][2];
-    wpz = m[2][2];
-    partials[2] = -fdw * ( upz - udw * wpz );
-    partials[5] = -fdw * ( vpz - vdw * wpz );
+  double m[3][3];
+  calcRotationMatrix(m, m_noAdjustments);
+
+  double xo, yo, zo;
+  xo = groundPt.x - m_currentParameterValue[0];
+  yo = groundPt.y - m_currentParameterValue[1];
+  zo = groundPt.z - m_currentParameterValue[2];
+
+  double u, v, w;
+  u = m[0][0] * xo + m[0][1] * yo + m[0][2] * zo;
+  v = m[1][0] * xo + m[1][1] * yo + m[1][2] * zo;
+  w = m[2][0] * xo + m[2][1] * yo + m[2][2] * zo;
+
+  double fdw, udw, vdw;
+  fdw = m_focalLength / w;
+  udw = u / w;
+  vdw = v / w;
+
+  double upx, vpx, wpx;
+  upx = m[0][0];
+  vpx = m[1][0];
+  wpx = m[2][0];
+  partials[0] = -fdw * ( upx - udw * wpx );
+  partials[3] = -fdw * ( vpx - vdw * wpx );
+
+  double upy, vpy, wpy;
+  upy = m[0][1];
+  vpy = m[1][1];
+  wpy = m[2][1];
+  partials[1] = -fdw * ( upy - udw * wpy );
+  partials[4] = -fdw * ( vpy - vdw * wpy );
+
+  double upz, vpz, wpz;
+  upz = m[0][2];
+  vpz = m[1][2];
+  wpz = m[2][2];
+  partials[2] = -fdw * ( upz - udw * wpz );
+  partials[5] = -fdw * ( vpz - vdw * wpz );
 
-    return partials;
+  return partials;
 }
 
 
 const csm::CorrelationModel& UsgsAstroFrameSensorModel::getCorrelationModel() const {
-    return _no_corr_model;
+  return _no_corr_model;
 }
 
 
 std::vector<double> UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance(const csm::ImageCoord &pt1,
                                                 const csm::ImageCoord &pt2) const {
 
-    throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION,
-      "Unsupported function",
-      "UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance");
+  throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION,
+                   "Unsupported function",
+                   "UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance");
 }
 
 
 csm::Version UsgsAstroFrameSensorModel::getVersion() const {
-    return csm::Version(0,1,0);
+  return csm::Version(0,1,0);
 }
 
 
 std::string UsgsAstroFrameSensorModel::getModelName() const {
-    return _SENSOR_MODEL_NAME;
+  return _SENSOR_MODEL_NAME;
 }
 
 
@@ -689,7 +618,7 @@ std::string UsgsAstroFrameSensorModel::getReferenceDateAndTime() const {
 
 std::string UsgsAstroFrameSensorModel::getModelState() const {
     json state = {
-      {"model_name", _SENSOR_MODEL_NAME},
+      {"m_modelName", _SENSOR_MODEL_NAME},
       {"m_focalLength" , m_focalLength},
       {"m_iTransS", {m_iTransS[0], m_iTransS[1], m_iTransS[2]}},
       {"m_iTransL", {m_iTransL[0], m_iTransL[1], m_iTransL[2]}},
@@ -709,8 +638,8 @@ std::string UsgsAstroFrameSensorModel::getModelState() const {
       {"m_instrumentID", m_instrumentID},
       {"m_focalLengthEpsilon", m_focalLengthEpsilon},
       {"m_ccdCenter", {m_ccdCenter[0], m_ccdCenter[1]}},
-      {"m_line_pp", m_line_pp},
-      {"m_sample_pp", m_sample_pp},
+      {"m_linePp", m_linePp},
+      {"m_samplePp", m_samplePp},
       {"m_minElevation", m_minElevation},
       {"m_maxElevation", m_maxElevation},
       {"m_odtX", {m_odtX[0], m_odtX[1], m_odtX[2], m_odtX[3], m_odtX[4],
@@ -726,69 +655,321 @@ std::string UsgsAstroFrameSensorModel::getModelState() const {
       {"m_nSamples", m_nSamples},
       {"m_currentParameterValue", {m_currentParameterValue[0], m_currentParameterValue[1],
                                    m_currentParameterValue[2], m_currentParameterValue[3],
-                                   m_currentParameterValue[4], m_currentParameterValue[5]}},
+                                   m_currentParameterValue[4], m_currentParameterValue[5],
+                                   m_currentParameterValue[6]}},
       {"m_currentParameterCovariance", m_currentParameterCovariance}
     };
+
     return state.dump();
 }
 
+bool UsgsAstroFrameSensorModel::isValidModelState(const std::string& stringState, csm::WarningList *warnings) {
+  std::vector<std::string> requiredKeywords = {
+    "m_modelName",
+    "m_majorAxis",
+    "m_minorAxis",
+    "m_focalLength",
+    "m_startingDetectorSample",
+    "m_startingDetectorLine",
+    "m_focalLengthEpsilon",
+    "m_nLines",
+    "m_nSamples",
+    "m_currentParameterValue",
+    "m_ccdCenter",
+    "m_spacecraftVelocity",
+    "m_sunPosition",
+    "m_odtX",
+    "m_odtY",
+    "m_transX",
+    "m_transY",
+    "m_iTransS",
+    "m_iTransL"
+  };
+
+  json jsonState = json::parse(stringState);
+  std::vector<std::string> missingKeywords;
+
+  for (auto &key : requiredKeywords) {
+    if (jsonState.find(key) == jsonState.end()) {
+      missingKeywords.push_back(key);
+    }
+  }
+
+  if (!missingKeywords.empty()) {
+    std::ostringstream oss;
+    std::copy(missingKeywords.begin(), missingKeywords.end(), std::ostream_iterator<std::string>(oss, " "));
+    warnings->push_back(csm::Warning(
+      csm::Warning::DATA_NOT_AVAILABLE,
+      "State has missing keywrods: " + oss.str(),
+      "UsgsAstroFrameSensorModel::isValidModelState"
+    ));
+  }
+
+  std::string modelName = jsonState.value<std::string>("m_modelName", "");
+
+  if (modelName != _SENSOR_MODEL_NAME) {
+    warnings->push_back(csm::Warning(
+      csm::Warning::DATA_NOT_AVAILABLE,
+      "Incorrect model name in state, expected " + _SENSOR_MODEL_NAME + " but got " + modelName,
+      "UsgsAstroFrameSensorModel::isValidModelState"
+    ));
+  }
+
+  return modelName == _SENSOR_MODEL_NAME && missingKeywords.empty();
+}
+
+
+bool UsgsAstroFrameSensorModel::isValidIsd(const std::string& Isd, csm::WarningList *warnings) {
+  // no obvious clean way to truely validate ISD with it's nested structure,
+  // or rather, it would be a pain to maintain, so just check if
+  // we can get a valid state from ISD. Once ISD schema is 100% clear
+  // we can change this.
+   try {
+     std::string state = constructStateFromIsd(Isd, warnings);
+     return isValidModelState(state, warnings);
+   }
+   catch(...) {
+     return false;
+   }
+}
+
 
-void UsgsAstroFrameSensorModel::replaceModelState(const std::string& modelState) {
-    auto state = json::parse(modelState);
-    for(auto &key : _STATE_KEYWORD){
-        if (state.find(key) == state.end()){
-            csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-            std::string aMessage = "State key %s mission", key;
-            std::string aFunction = "UsgsAstroFramePlugin::replaceModelState()";
-            throw csm::Error(aErrorType, aMessage, aFunction);
-        }
-        // TODO: This is pulled right out of the plugin - good reason to have the state be a
-        // distinct class a la the generic line scan model.
-        m_ccdCenter[0] = state["m_ccdCenter"][0];
-        m_ccdCenter[1] = state["m_ccdCenter"][1];
-        m_ephemerisTime = state["m_ephemerisTime"];
-        m_focalLength = state["m_focalLength"];
-        m_focalLengthEpsilon = state["m_focalLengthEpsilon"];
-        m_ifov = state["m_ifov"];
-        m_instrumentID = state["m_instrumentID"];
-
-        m_majorAxis = state["m_majorAxis"];
-        m_minorAxis = state["m_minorAxis"];
-        m_startingDetectorLine = state["m_startingDetectorLine"];
-        m_startingDetectorSample = state["m_startingDetectorSample"];
-        m_line_pp = state["m_line_pp"];
-        m_sample_pp = state["m_sample_pp"];
-        m_originalHalfLines = state["m_originalHalfLines"];
-        m_originalHalfSamples = state["m_originalHalfSamples"];
-        m_spacecraftName = state["m_spacecraftName"];
-        m_pixelPitch = state["m_pixelPitch"];
-        m_nLines = state["m_nLines"];
-        m_nSamples = state["m_nSamples"];
-        m_minElevation = state["m_minElevation"];
-        m_maxElevation = state["m_maxElevation"];
-
-        for (int i=0;i<3;i++){
-            m_boresight[i] = state["m_boresight"][i];
-            m_iTransL[i] = state["m_iTransL"][i];
-            m_iTransS[i] = state["m_iTransS"][i];
-
-            m_transX[i] = state["m_transX"][i];
-            m_transY[i] = state["m_transY"][i];
-            m_spacecraftVelocity[i] = state["m_spacecraftVelocity"][i];
-            m_sunPosition[i] = state["m_sunPosition"][i];
-        }
-
-        // Having types as vectors, instead of arrays makes interoperability with
-        // the JSON library very easy.
-        m_currentParameterValue = state["m_currentParameterValue"].get<std::vector<double>>();
-        m_odtX = state["m_odtX"].get<std::vector<double>>();
-        m_odtY = state["m_odtY"].get<std::vector<double>>();
-
-        m_currentParameterCovariance = state["m_currentParameterCovariance"].get<std::vector<double>>();
+void UsgsAstroFrameSensorModel::replaceModelState(const std::string& stringState) {
+
+    json state = json::parse(stringState);
+
+    // The json library's .at() will except if key is missing
+    try {
+        m_modelName = state.at("m_modelName").get<std::string>();
+        m_majorAxis = state.at("m_majorAxis").get<double>();
+        m_minorAxis = state.at("m_minorAxis").get<double>();
+        m_focalLength = state.at("m_focalLength").get<double>();
+        m_startingDetectorSample = state.at("m_startingDetectorSample").get<double>();
+        m_startingDetectorLine = state.at("m_startingDetectorLine").get<double>();
+        m_focalLengthEpsilon = state.at("m_focalLengthEpsilon").get<double>();
+        m_nLines = state.at("m_nLines").get<int>();
+        m_nSamples = state.at("m_nSamples").get<int>();
+        m_currentParameterValue = state.at("m_currentParameterValue").get<std::vector<double>>();
+        m_ccdCenter = state.at("m_ccdCenter").get<std::vector<double>>();
+        m_spacecraftVelocity = state.at("m_spacecraftVelocity").get<std::vector<double>>();
+        m_sunPosition = state.at("m_sunPosition").get<std::vector<double>>();
+        m_odtX = state.at("m_odtX").get<std::vector<double>>();
+        m_odtY = state.at("m_odtY").get<std::vector<double>>();
+        m_transX = state.at("m_transX").get<std::vector<double>>();
+        m_transY = state.at("m_transY").get<std::vector<double>>();
+        m_iTransS = state.at("m_iTransS").get<std::vector<double>>();
+        m_iTransL = state.at("m_iTransL").get<std::vector<double>>();
+
+        // Leaving unused params commented out
+        // m_targetName = state.at("m_targetName").get<std::string>();
+        // m_ifov = state.at("m_ifov").get<double>();
+        // m_instrumentID = state.at("m_instrumentID").get<std::string>();
+        // m_currentParameterCovariance = state.at("m_currentParameterCovariance").get<std::vector<double>>();
+        // m_noAdjustments = state.at("m_noAdjustments").get<std::vector<double>>();
+        // m_linePp = state.at("m_linePp").get<double>();
+        // m_samplePp = state.at("m_samplePp").get<double>();
+        // m_originalHalfLines = state.at("m_originalHalfLines").get<double>();
+        // m_spacecraftName = state.at("m_spacecraftName").get<std::string>();
+        // m_pixelPitch = state.at("m_pixelPitch").get<double>();
+        // m_ephemerisTime = state.at("m_ephemerisTime").get<double>();
+        // m_originalHalfSamples = state.at("m_originalHalfSamples").get<double>();
+        // m_boresight = state.at("m_boresight").get<std::vector<double>>();
+
+        // Cast int vector to csm::param::Type vector by simply copying it
+        // std::vector<int> paramType = state.at("m_parameterType").get<std::vector<int>>();
+        // m_parameterType = std::vector<csm::param::Type>();
+        // for(auto &t : paramType){
+           // paramType.push_back(static_cast<csm::param::Type>(t));
+        // }
+    }
+    catch(std::out_of_range& e) {
+      throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE,
+                       "State keywords required to generate sensor model missing: " + std::string(e.what()) + "\nUsing model string: " + stringState,
+                       "UsgsAstroFrameSensorModel::replaceModelState");
     }
 }
 
 
+std::string UsgsAstroFrameSensorModel::constructStateFromIsd(const std::string& jsonIsd, csm::WarningList* warnings) {
+    auto metric_conversion = [](double val, std::string from, std::string to="m") {
+        json typemap = {
+          {"m", 0},
+          {"km", 3}
+        };
+
+        // everything to lowercase
+        std::transform(from.begin(), from.end(), from.begin(), ::tolower);
+        std::transform(to.begin(), to.end(), to.begin(), ::tolower);
+        return val*pow(10, typemap[from].get<int>() - typemap[to].get<int>());
+    };
+
+    json isd = json::parse(jsonIsd);
+    json state = {};
+
+
+    try {
+      state["m_modelName"] = isd.at("name_model");
+      std::cerr << "Model Name Parsed!" << std::endl;
+
+      state["m_startingDetectorSample"] = isd.at("starting_detector_sample");
+      state["m_startingDetectorLine"] = isd.at("starting_detector_line");
+
+      std::cerr << "Detector Starting Pixel Parsed!" << std::endl;
+
+      // get focal length
+      {
+        json jayson = isd.at("focal_length_model");
+        json focal_length = jayson.at("focal_length");
+        json epsilon = jayson.at("focal_epsilon");
+
+        state["m_focalLength"] = focal_length;
+        state["m_focalLengthEpsilon"] = epsilon;
+
+        std::cerr << "Focal Length Parsed!" << std::endl;
+      }
+
+      // get sensor_position
+      {
+        json jayson = isd.at("sensor_position");
+        json positions = jayson.at("positions")[0];
+        json velocities = jayson.at("velocities")[0];
+        json unit = jayson.at("unit");
+
+        unit = unit.get<std::string>();
+        state["m_currentParameterValue"] = json();
+        state["m_currentParameterValue"][0] = metric_conversion(positions[0].get<double>(), unit);
+        state["m_currentParameterValue"][1] = metric_conversion(positions[1].get<double>(), unit);
+        state["m_currentParameterValue"][2] = metric_conversion(positions[2].get<double>(), unit);
+        state["m_spacecraftVelocity"] = velocities;
+
+        std::cerr << "Sensor Location Parsed!" << std::endl;
+      }
+
+      // get sun_position
+      // sun position is not strictly necessary, but is required for getIlluminationDirection.
+      {
+        json jayson = isd.at("sun_position");
+        json positions = jayson.at("positions")[0];
+        json unit = jayson.at("unit");
+
+        unit = unit.get<std::string>();
+        state["m_sunPosition"] = json();
+        state["m_sunPosition"][0] = metric_conversion(positions[0].get<double>(), unit);
+        state["m_sunPosition"][1] = metric_conversion(positions[1].get<double>(), unit);
+        state["m_sunPosition"][2] = metric_conversion(positions[2].get<double>(), unit);
+
+        std::cerr << "Sun Position Parsed!" << std::endl;
+      }
+
+      // get sensor_orientation quaternion
+      {
+        json jayson = isd.at("sensor_orientation");
+        json quaternion = jayson.at("quaternions")[0];
+
+        state["m_currentParameterValue"][3] = quaternion[0];
+        state["m_currentParameterValue"][4] = quaternion[1];
+        state["m_currentParameterValue"][5] = quaternion[2];
+        state["m_currentParameterValue"][6] = quaternion[3];
+
+        std::cerr << "Sensor Orientation Parsed!" << std::endl;
+      }
+
+      // get optical_distortion
+      {
+        json jayson = isd.at("optical_distortion");
+        std::vector<double> xDistortion = jayson.at("transverse").at("x");
+        std::vector<double> yDistortion = jayson.at("transverse").at("y");
+        xDistortion.resize(10, 0.0);
+        yDistortion.resize(10, 0.0);
+
+        state["m_odtX"] = xDistortion;
+        state["m_odtY"] = yDistortion;
+
+        std::cerr << "Distortion Parsed!" << std::endl;
+      }
+
+      // get detector_center
+      {
+        json jayson = isd.at("detector_center");
+        json sample = jayson.at("sample");
+        json line = jayson.at("line");
+
+        state["m_ccdCenter"][0] = line;
+        state["m_ccdCenter"][1] = sample;
+
+        std::cerr << "Detector Center Parsed!" << std::endl;
+      }
+
+      // get radii
+      {
+        json jayson = isd.at("radii");
+        json semiminor = jayson.at("semiminor");
+        json semimajor = jayson.at("semimajor");
+        json unit = jayson.at("unit");
+
+        unit = unit.get<std::string>();
+        state["m_minorAxis"] = metric_conversion(semiminor.get<double>(), unit);
+        state["m_majorAxis"] = metric_conversion(semimajor.get<double>(), unit);
+
+        std::cerr << "Target Radii Parsed!" << std::endl;
+      }
+
+      // get reference_height
+      {
+        json reference_height = isd.at("reference_height");
+        json maxheight = reference_height.at("maxheight");
+        json minheight = reference_height.at("minheight");
+        json unit = reference_height.at("unit");
+
+        unit = unit.get<std::string>();
+        state["m_minElevation"] = metric_conversion(minheight.get<double>(), unit);
+        state["m_maxElevation"] = metric_conversion(maxheight.get<double>(), unit);
+
+        std::cerr << "Reference Height Parsed!" << std::endl;
+      }
+
+      state["m_ephemerisTime"] = isd.at("center_ephemeris_time");
+      state["m_nLines"] = isd.at("image_lines");
+      state["m_nSamples"] = isd.at("image_samples");
+
+      state["m_iTransL"] = isd.at("focal2pixel_lines");
+
+      state["m_iTransS"] = isd.at("focal2pixel_samples");
+
+      // We don't pass the pixel to focal plane transformation so invert the
+      // focal plane to pixel transformation
+      double determinant = state["m_iTransL"][1].get<double>() * state["m_iTransS"][2].get<double>() -
+                           state["m_iTransL"][2].get<double>() * state["m_iTransS"][1].get<double>();
+
+      state["m_transX"][1] =  state["m_iTransL"][1].get<double>() / determinant;
+      state["m_transX"][2] = -state["m_iTransS"][1].get<double>() / determinant;
+      state["m_transX"][0] = -(state["m_transX"][1].get<double>() * state["m_iTransL"][0].get<double>() +
+                              state["m_transX"][2].get<double>() * state["m_iTransS"][0].get<double>());
+
+      state["m_transY"][1] = -state["m_iTransL"][2].get<double>() / determinant;
+      state["m_transY"][2] =  state["m_iTransS"][2].get<double>() / determinant;
+      state["m_transY"][0] = -(state["m_transY"][1].get<double>() * state["m_iTransL"][0].get<double>() +
+                               state["m_transY"][2].get<double>() * state["m_iTransS"][0].get<double>());
+
+      std::cerr << "Focal To Pixel Transformation Parsed!" << std::endl;
+
+    }
+    catch(std::out_of_range& e) {
+      throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE,
+                       "ISD missing necessary keywords to create sensor model: " + std::string(e.what()),
+                       "UsgsAstroFrameSensorModel::constructStateFromIsd");
+    }
+    catch(...) {
+      throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE,
+                       "ISD is invalid for creating the sensor model.",
+                       "UsgsAstroFrameSensorModel::constructStateFromIsd");
+    }
+
+    return state.dump();
+
+}
+
+
 csm::EcefCoord UsgsAstroFrameSensorModel::getReferencePoint() const {
   throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION,
                    "Unsupported function",
@@ -804,13 +985,11 @@ void UsgsAstroFrameSensorModel::setReferencePoint(const csm::EcefCoord &groundPt
 
 
 int UsgsAstroFrameSensorModel::getNumParameters() const {
-
-  return m_numParameters;
+  return NUM_PARAMETERS;
 }
 
 
 std::string UsgsAstroFrameSensorModel::getParameterName(int index) const {
-
   return m_parameterName[index];
 }
 
@@ -925,49 +1104,41 @@ std::vector<double> UsgsAstroFrameSensorModel::getCrossCovarianceMatrix(
 
 void UsgsAstroFrameSensorModel::calcRotationMatrix(
     double m[3][3]) const {
-
   // Trigonometric functions for rotation matrix
-  double sinw = std::sin(m_currentParameterValue[3]);
-  double cosw = std::cos(m_currentParameterValue[3]);
-  double sinp = std::sin(m_currentParameterValue[4]);
-  double cosp = std::cos(m_currentParameterValue[4]);
-  double sink = std::sin(m_currentParameterValue[5]);
-  double cosk = std::cos(m_currentParameterValue[5]);
-
-  // Rotation matrix taken from Introduction to Mordern Photogrammetry by
-  // Edward M. Mikhail, et al., p. 373
-  m[0][0] = cosp * cosk;
-  m[0][1] = cosw * sink + sinw * sinp * cosk;
-  m[0][2] = sinw * sink - cosw * sinp * cosk;
-  m[1][0] = -1 * cosp * sink;
-  m[1][1] = cosw * cosk - sinw * sinp * sink;
-  m[1][2] = sinw * cosk + cosw * sinp * sink;
-  m[2][0] = sinp;
-  m[2][1] = -1 * sinw * cosp;
-  m[2][2] = cosw * cosp;
+  double w = m_currentParameterValue[3];
+  double x = m_currentParameterValue[4];
+  double y = m_currentParameterValue[5];
+  double z = m_currentParameterValue[6];
+
+  m[0][0] = w*w + x*x - y*y - z*z;
+  m[0][1] = 2 * (x*y - w*z);
+  m[0][2] = 2 * (w*y + x*z);
+  m[1][0] = 2 * (x*y + w*z);
+  m[1][1] = w*w - x*x + y*y - z*z;
+  m[1][2] = 2 * (y*z - w*x);
+  m[2][0] = 2 * (x*z - w*y);
+  m[2][1] = 2 * (w*x + y*z);
+  m[2][2] = w*w - x*x - y*y + z*z;
 }
 
 
 void UsgsAstroFrameSensorModel::calcRotationMatrix(
   double m[3][3], const std::vector<double> &adjustments) const {
-
   // Trigonometric functions for rotation matrix
-  double sinw = std::sin(getValue(3,adjustments));
-  double cosw = std::cos(getValue(3,adjustments));
-  double sinp = std::sin(getValue(4,adjustments));
-  double cosp = std::cos(getValue(4,adjustments));
-  double sink = std::sin(getValue(5,adjustments));
-  double cosk = std::cos(getValue(5,adjustments));
-
-  m[0][0] = cosp * cosk;
-  m[0][1] = cosw * sink + sinw * sinp * cosk;
-  m[0][2] = sinw * sink - cosw * sinp * cosk;
-  m[1][0] = -1 * cosp * sink;
-  m[1][1] = cosw * cosk - sinw * sinp * sink;
-  m[1][2] = sinw * cosk + cosw * sinp * sink;
-  m[2][0] = sinp;
-  m[2][1] = -1 * sinw * cosp;
-  m[2][2] = cosw * cosp;
+  double w = getValue(3, adjustments);
+  double x = getValue(4, adjustments);
+  double y = getValue(5, adjustments);
+  double z = getValue(6, adjustments);
+
+  m[0][0] = w*w + x*x - y*y - z*z;
+  m[0][1] = 2 * (x*y - w*z);
+  m[0][2] = 2 * (w*y + x*z);
+  m[1][0] = 2 * (x*y + w*z);
+  m[1][1] = w*w - x*x + y*y - z*z;
+  m[1][2] = 2 * (y*z - w*x);
+  m[2][0] = 2 * (x*z - w*y);
+  m[2][1] = 2 * (w*x + y*z);
+  m[2][2] = w*w - x*x - y*y + z*z;
 }
 
 
@@ -1045,7 +1216,7 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy,
 
   // Solve the distortion equation using the Newton-Raphson method.
   // Set the error tolerance to about one millionth of a NAC pixel.
-  const double tol = 1.4E-7;
+  const double tol = 1.4E-5;
 
   // The maximum number of iterations of the Newton-Raphson method.
   const int maxTries = 60;
@@ -1076,9 +1247,8 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy,
     distortionJacobian(x, y, Jxx, Jxy, Jyx, Jyy);
 
     double determinant = Jxx * Jyy - Jxy * Jyx;
-    if (fabs(determinant) < 1E-7) {
+    if (fabs(determinant) < 1E-6) {
 
-      cout << "Singular determinant." << endl;
       undistortedX = x;
       undistortedY = y;
       //
@@ -1106,9 +1276,7 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy,
     undistortedY = dy;
     return false;
   }
-
   return true;
-
 }
 
 
@@ -1161,8 +1329,6 @@ void UsgsAstroFrameSensorModel::distortionJacobian(double x, double y, double &J
     Jyx = Jyx + d_dx[i] * m_odtY[i];
     Jyy = Jyy + d_dy[i] * m_odtY[i];
   }
-
-
 }
 
 
diff --git a/src/UsgsAstroLsPlugin.cpp b/src/UsgsAstroLsPlugin.cpp
deleted file mode 100644
index f275a0c..0000000
--- a/src/UsgsAstroLsPlugin.cpp
+++ /dev/null
@@ -1,534 +0,0 @@
-//----------------------------------------------------------------------------
-//
-//                                UNCLASSIFIED
-//
-// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc.
-//                            ALL RIGHTS RESERVED
-// Use of this software product is governed by the terms of a license
-// agreement. The license agreement is found in the installation directory.
-//
-//             For support, please visit http://www.baesystems.com/gxp
-//
-//  Revision History:
-//  Date        Name        Description
-//  ----------- ---------   -----------------------------------------------
-//  30-APR-2017 BAE Systems Initial Implementation based on CSM 2.0 code
-//  16-OCT-2017 BAE Systems Update for CSM 3.0.3
-//
-//-----------------------------------------------------------------------------
-
-#define USGSASTROLINESCANNER_LIBRARY
-
-#include "UsgsAstroLsPlugin.h"
-#include "UsgsAstroLsISD.h"
-#include "UsgsAstroLsSensorModel.h"
-#include "UsgsAstroLsStateData.h"
-
-#ifdef _WIN32
-# define DIR_DELIMITER_STR "\\"
-#else
-# define DIR_DELIMITER_STR  "/"
-#endif
-
-//#ifdef WIN32
-//#pragma comment(linker, SENCSM_MANIFESTDEPENDENCY_GXP_CSMAPI)
-//#endif // WIN32
-
-#include <iostream>
-#include <sstream>
-#include <fstream>
-#include <stdlib.h>
-#include <math.h>
-#include <json.hpp>
-
-
-using json = nlohmann::json;
-
-// Declaration of static variables
-static const std::string  PLUGIN_NAME       = "USGS_ASTRO_LINE_SCANNER_PLUGIN";
-static const std::string  MANUFACTURER_NAME = "BAE_SYSTEMS_GXP";
-static const std::string  RELEASE_DATE      = "20171230";
-static const int          N_SENSOR_MODELS   = 1;
-const std::string  UsgsAstroLsPlugin::mISD_KEYWORDS[] =
-{
-   "SENSOR_TYPE",
-   "TOTAL_LINES",
-   "TOTAL_SAMPLES",
-   "PLATFORM",
-   "ABERR",
-   "ATMREF",
-   "INT_TIME",
-   "STARTING_EPHEMERIS_TIME",
-   "CENTER_EPHEMERIS_TIME",
-   "DETECTOR_SAMPLE_SUMMING",
-   "STARTING_SAMPLE",
-   "IKCODE",
-   "FOCAL",
-   "ISIS_Z_DIRECTION",
-   "OPTICAL_DIST_COEF",
-   "ITRANSS",
-   "ITRANSL",
-   "DETECTOR_SAMPLE_ORIGIN",
-   "DETECTOR_LINE_ORIGIN",
-   "DETECTOR_LINE_OFFSET",
-   "MOUNTING_ANGLES",
-   "DT_EPHEM",
-   "T0_EPHEM",
-   "DT_QUAT",
-   "T0_QUAT",
-   "NUMBER_OF_EPHEM",
-   "NUMBER_OF_QUATERNIONS",
-   "EPHEM_PTS",
-   "EPHEM_RATES",
-   "QUATERNIONS",
-   "TRI_PARAMETERS",
-   "SEMI_MAJOR_AXIS",
-   "ECCENTRICITY",
-   // Everything below here is optional
-   "REFERENCE_HEIGHT",
-   "MIN_VALID_HT",
-   "MAX_VALID_HT",
-   "IMAGE_ID",
-   "SENSOR_ID",
-   "PLATFORM_ID",
-   "TRAJ_ID",
-   "COLL_ID",
-   "REF_DATE_TIME"
-};
-
-const std::string  UsgsAstroLsPlugin::mSTATE_KEYWORDS[] =
-{
-   "STA_SENSOR_MODEL_NAME",
-   "STA_IMAGE_IDENTIFIER",
-   "STA_SENSOR_TYPE",
-   "STA_TOTAL_LINES",
-   "STA_TOTAL_SAMPLES",
-   "STA_OFFSET_LINES",
-   "STA_OFFSET_SAMPLES",
-   "STA_PLATFORM_FLAG",
-   "STA_ABERR_FLAG",
-   "STA_ATMREF_FLAG",
-   "STA_INT_TIME_LINES",
-   "STA_INT_TIME_START_TIMES",
-   "STA_INT_TIMES",
-   "STA_STARTING_EPHEMERIS_TIME",
-   "STA_CENTER_EPHEMERIS_TIME",
-   "STA_DETECTOR_SAMPLE_SUMMING",
-   "STA_STARTING_SAMPLE",
-   "STA_IK_CODE",
-   "STA_FOCAL",
-   "STA_ISIS_Z_DIRECTION",
-   "STA_OPTICAL_DIST_COEF",
-   "STA_I_TRANS_S",
-   "STA_I_TRANS_L",
-   "STA_DETECTOR_SAMPLE_ORIGIN",
-   "STA_DETECTOR_LINE_ORIGIN",
-   "STA_DETECTOR_LINE_OFFSET",
-   "STA_MOUNTING_MATRIX",
-   "STA_SEMI_MAJOR_AXIS",
-   "STA_SEMI_MINOR_AXIS",
-   "STA_REFERENCE_DATE_AND_TIME",
-   "STA_PLATFORM_IDENTIFIER",
-   "STA_SENSOR_IDENTIFIER",
-   "STA_TRAJECTORY_IDENTIFIER",
-   "STA_COLLECTION_IDENTIFIER",
-   "STA_REF_ELEVATION",
-   "STA_MIN_ELEVATION",
-   "STA_MAX_ELEVATION",
-   "STA_DT_EPHEM",
-   "STA_T0_EPHEM",
-   "STA_DT_QUAT",
-   "STA_T0_QUAT",
-   "STA_NUM_EPHEM",
-   "STA_NUM_QUATERNIONS",
-   "STA_EPHEM_PTS",
-   "STA_EPHEM_RATES",
-   "STA_QUATERNIONS",
-   "STA_PARAMETER_VALS",
-   "STA_PARAMETER_TYPE",
-   "STA_REFERENCE_POINT_XYZ",
-   "STA_GSD",
-   "STA_FLYING_HEIGHT",
-   "STA_HALF_SWATH",
-   "STA_HALF_TIME",
-   "STA_COVARIANCE",
-   "STA_IMAGE_FLIP_FLAG"
-};
-
-//***************************************************************************
-// Static instance of itself
-//***************************************************************************
-const UsgsAstroLsPlugin UsgsAstroLsPlugin::_theRegisteringObject;
-
-
-//***************************************************************************
-// UsgsAstroLsPlugin::UsgsAstroLsPlugin
-//***************************************************************************
-UsgsAstroLsPlugin::UsgsAstroLsPlugin()
-{
-}
-
-//*****************************************************************************
-// UsgsAstroLsPlugin::~UsgsAstroLsPlugin
-//*****************************************************************************
-UsgsAstroLsPlugin::~UsgsAstroLsPlugin()
-{
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getPluginName
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getPluginName() const
-{
-   return PLUGIN_NAME;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getManufacturer
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getManufacturer() const
-{
-   return MANUFACTURER_NAME;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getReleaseDate
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getReleaseDate() const
-{
-   return RELEASE_DATE;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getCSMVersion
-//***************************************************************************
-csm::Version UsgsAstroLsPlugin::getCsmVersion() const
-{
-   return CURRENT_CSM_VERSION;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getNSensorModels
-//***************************************************************************
-size_t UsgsAstroLsPlugin::getNumModels() const
-{
-   return N_SENSOR_MODELS;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getSensorModelName
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getModelName(size_t modelIndex) const
-{
-   // Always return the only sensor model name defined regardless of index
-   return UsgsAstroLsStateData::SENSOR_MODEL_NAME;
-}
-
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getModelFamily
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getModelFamily(size_t modelIndex) const
-{
-   return CSM_RASTER_FAMILY;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getSensorModelVersion
-//***************************************************************************
-csm::Version UsgsAstroLsPlugin::getModelVersion(
-   const std::string &model_name) const
-{
-   if (model_name != UsgsAstroLsStateData::SENSOR_MODEL_NAME)
-   {
-      csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
-      std::string aMessage = " Sensor model not supported: ";
-      std::string aFunction = "UsgsAstroLsPlugin::getSensorModelVersion()";
-      csm::Error csmErr(aErrorType, aMessage, aFunction);
-      throw (csmErr);
-   }
-
-   return csm::Version(1, 0, 0);
-}
-
-
-//***************************************************************************
-// UsgsAstroLsPlugin::canSensorModelBeConstructedFromState
-//***************************************************************************
-bool UsgsAstroLsPlugin::canModelBeConstructedFromState(
-   const std::string& model_name,
-   const std::string& model_state,
-   csm::WarningList* warnings) const
-{
-   // Initialize constructible flag
-   bool constructible = true;
-
-   // Get sensor model from sensor model state
-   std::string name_from_state;
-
-   try
-   {
-      name_from_state = getModelNameFromModelState(model_state);
-   }
-   catch (...)
-   {
-   }
-
-   // Check if plugin supports sensor model name
-   if (model_name != name_from_state)
-   {
-      constructible = false;
-   }
-
-   // Check that all of the necessary state keys are in place
-   auto j = json::parse(model_state);
-   for (auto &key : mSTATE_KEYWORDS){
-       if (j.find(key) == j.end()){
-           constructible = false;
-       }
-   }
-
-   return constructible;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::canSensorModelBeConstructedFromISD
-//***************************************************************************
-bool UsgsAstroLsPlugin::canModelBeConstructedFromISD(
-   const csm::Isd &image_support_data,
-   const std::string& model_name,
-   csm::WarningList* warnings) const
-{
-   // Check file validity
-   bool constructible = true;
-
-   std::string value;
-   for(auto &key : mISD_KEYWORDS){
-       value = image_support_data.param(key);
-       if (value.empty()){
-           std::cout<<key<<"\n"<<std::endl;
-           constructible = false;
-       }
-   }
-
-   return constructible;
-}
-
-
-//***************************************************************************
-// UsgsAstroLsPlugin::constructSensorModelFromState
-//***************************************************************************
-csm::Model* UsgsAstroLsPlugin::constructModelFromState(
-   const std::string& model_state,
-   csm::WarningList* warnings ) const
-{
-
-    // Get the sensor model name from the sensor model state
-    std::string model_name_from_state = getModelNameFromModelState(model_state);
-
-    if (!canModelBeConstructedFromState(model_name_from_state, model_state)){
-        csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-        std::string aMessage = "Model state is not valid.";
-        std::string aFunction = "UsgsAstroLsPlugin::constructModelFromState()";
-        throw csm::Error(aErrorType, aMessage, aFunction);
-    }
-   UsgsAstroLsStateData data;
-   data.setState( model_state );
-
-   UsgsAstroLsSensorModel* sensor_model = new UsgsAstroLsSensorModel();
-   // I do not think that exposing a set method is necessarily CSM compliant?
-   sensor_model->set( data );
-
-   return sensor_model;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::constructSensorModelFromISD
-//***************************************************************************
-csm::Model* UsgsAstroLsPlugin::constructModelFromISD(
-   const csm::Isd&    image_support_data,
-   const std::string& model_name,
-   csm::WarningList*  warnings) const
-{
-   std::string stateStr = convertISDToModelState(image_support_data, model_name, warnings);
-   UsgsAstroLsStateData state(stateStr);
-
-   UsgsAstroLsSensorModel* sm = new UsgsAstroLsSensorModel();
-   // I do not see things like flying height getting set properly, are things overflowing?
-   sm->set(state);
-
-   csm::Model* sensor_model = sm;
-   return sensor_model;
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::getSensorModelNameFromSensorModelState
-//***************************************************************************
-std::string UsgsAstroLsPlugin::getModelNameFromModelState(
-   const std::string& model_state,
-   csm::WarningList* warnings) const
-{
-    return UsgsAstroLsStateData::getModelNameFromModelState( model_state );
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::canISDBeConvertedToSensorModelState
-//***************************************************************************
-bool UsgsAstroLsPlugin::canISDBeConvertedToModelState(
-   const csm::Isd&    image_support_data,
-   const std::string& model_name,
-   csm::WarningList*  warnings) const
-{
-   // Check if ISD is supported
-   return canModelBeConstructedFromISD(image_support_data, model_name);
-}
-
-//***************************************************************************
-// UsgsAstroLsPlugin::convertISDToSensorModelState
-//***************************************************************************
-std::string UsgsAstroLsPlugin::convertISDToModelState(
-   const csm::Isd&    image_support_data,
-   const std::string& model_name,
-   csm::WarningList*  warnings) const
-{
-
-   if (!canModelBeConstructedFromISD(image_support_data, model_name)){
-       throw csm::Error(csm::Error::ISD_NOT_SUPPORTED,
-                        "Sensor model support data provided is not supported by this plugin",
-                        "GenericLsPlugin::constructModelFromISD");
-   }
-
-   // Instantiate UsgsAstroLineScanner sensor model
-   UsgsAstroLsStateData state;
-   int num_params = state.NUM_PARAMETERS;
-   //int num_params_square = num_params * num_params;
-
-   // Translate the ISD to state data
-  // if( .m_image_id.size() > 1 && image_support_data.m_image_id != "UNKNOWN")
-   //{
-    //  state.m_ImageIdentifier = image_support_data.m_image_id;
-   //}
-
-   //else
-   //{
-    //  state.m_ImageIdentifier = img_rel_name;
-   //}
-
-   state.m_ImageIdentifier = image_support_data.param("IMAGE_ID");
-   state.m_SensorType = image_support_data.param("SENSOR_TYPE");
-   state.m_TotalLines = atoi(image_support_data.param("TOTAL_LINES").c_str());
-   state.m_TotalSamples = atoi(image_support_data.param("TOTAL_SAMPLES").c_str());
-   state.m_OffsetLines = 0.0;
-   state.m_OffsetSamples = 0.0;
-   state.m_PlatformFlag = atoi(image_support_data.param("PLATFORM").c_str());
-   state.m_AberrFlag = atoi(image_support_data.param("ABERR").c_str());
-   state.m_AtmRefFlag = atoi(image_support_data.param("ATMREF").c_str());
-   state.m_StartingEphemerisTime = atof(image_support_data.param("STARTING_EPHEMERIS_TIME").c_str());
-   state.m_CenterEphemerisTime = atof(image_support_data.param("CENTER_EPHEMERIS_TIME").c_str());
-   if (image_support_data.param("NUMBER_OF_INT_TIMES").empty()) {
-     state.m_IntTimeLines = {0.5};
-     state.m_IntTimeStartTimes = {state.m_StartingEphemerisTime - state.m_CenterEphemerisTime};
-     state.m_IntTimes = {atof(image_support_data.param("INT_TIME").c_str())};
-   }
-   else {
-     int numIntTimes = atoi(image_support_data.param("NUMBER_OF_INT_TIMES").c_str());
-     for (int i = 0; i < numIntTimes; i++) {
-       state.m_IntTimeLines.push_back(atof(image_support_data.param("INT_TIME", i*3).c_str()));
-       state.m_IntTimeStartTimes.push_back(atof(image_support_data.param("INT_TIME", i*3 + 1).c_str()));
-       state.m_IntTimes.push_back(atof(image_support_data.param("INT_TIME", i*3 + 2).c_str()));
-     }
-   }
-   state.m_CenterEphemerisTime = atof(image_support_data.param("CENTER_EPHEMERIS_TIME").c_str());
-   state.m_DetectorSampleSumming = atoi(image_support_data.param("DETECTOR_SAMPLE_SUMMING").c_str());
-   state.m_StartingSample = atoi(image_support_data.param("STARTING_SAMPLE").c_str());
-   state.m_IkCode = atoi(image_support_data.param("IKCODE").c_str());
-   state.m_Focal = atof(image_support_data.param("FOCAL").c_str());
-   state.m_IsisZDirection = atof(image_support_data.param("ISIS_Z_DIRECTION").c_str());
-
-   for (int i = 0; i < 3; i++)
-   {
-      state.m_OpticalDistCoef[i] = atof(image_support_data.param("OPTICAL_DIST_COEF", i).c_str());
-      state.m_ITransS[i] = atof(image_support_data.param("ITRANSS", i).c_str());
-      state.m_ITransL[i] = atof(image_support_data.param("ITRANSL", i).c_str());
-   }
-
-   state.m_DetectorSampleOrigin = atof(image_support_data.param("DETECTOR_SAMPLE_ORIGIN").c_str());
-   state.m_DetectorLineOrigin = atof(image_support_data.param("DETECTOR_LINE_ORIGIN").c_str());
-   state.m_DetectorLineOffset = atof(image_support_data.param("DETECTOR_LINE_OFFSET").c_str());
-
-   double cos_a = cos(atof(image_support_data.param("MOUNTING_ANGLES", 0).c_str()));
-   double sin_a = sin(atof(image_support_data.param("MOUNTING_ANGLES", 0).c_str()));
-   double cos_b = cos(atof(image_support_data.param("MOUNTING_ANGLES", 1).c_str()));
-   double sin_b = sin(atof(image_support_data.param("MOUNTING_ANGLES", 1).c_str()));
-   double cos_c = cos(atof(image_support_data.param("MOUNTING_ANGLES", 2).c_str()));
-   double sin_c = sin(atof(image_support_data.param("MOUNTING_ANGLES", 2).c_str()));
-   state.m_MountingMatrix[0] = cos_b * cos_c;
-   state.m_MountingMatrix[1] = -cos_a * sin_c + sin_a * sin_b * cos_c;
-   state.m_MountingMatrix[2] = sin_a * sin_c + cos_a * sin_b * cos_c;
-   state.m_MountingMatrix[3] = cos_b * sin_c;
-   state.m_MountingMatrix[4] = cos_a * cos_c + sin_a * sin_b * sin_c;
-   state.m_MountingMatrix[5] = -sin_a * cos_c + cos_a * sin_b * sin_c;
-   state.m_MountingMatrix[6] = -sin_b;
-   state.m_MountingMatrix[7] = sin_a * cos_b;
-   state.m_MountingMatrix[8] = cos_a * cos_b;
-
-   state.m_DtEphem = atof(image_support_data.param("DT_EPHEM").c_str());
-   state.m_T0Ephem = atof(image_support_data.param("T0_EPHEM").c_str());
-   state.m_DtQuat = atof(image_support_data.param("DT_QUAT").c_str());
-   state.m_T0Quat = atof(image_support_data.param("T0_QUAT").c_str());
-   state.m_NumEphem = atoi(image_support_data.param("NUMBER_OF_EPHEM").c_str());
-   state.m_NumQuaternions = atoi(image_support_data.param("NUMBER_OF_QUATERNIONS").c_str());
-
-   int numEphem = atoi(image_support_data.param("NUMBER_OF_EPHEM").c_str());
-   for (int i=0;i < numEphem * 3; i++){
-       state.m_EphemPts.push_back(atof(image_support_data.param("EPHEM_PTS", i).c_str()));
-       state.m_EphemRates.push_back(atof(image_support_data.param("EPHEM_RATES", i).c_str()));
-   }
-
-   int numQuat = atoi(image_support_data.param("NUMBER_OF_QUATERNIONS").c_str());
-   for (int i=0; i < numQuat * 4; i++){
-       state.m_Quaternions.push_back(atof(image_support_data.param("QUATERNIONS", i).c_str()));
-   }
-
-   //state.m_EphemPts = image_support_data.m_ephem_pts;
-   //state.m_EphemRates = image_support_data.m_ephem_rates;
-   //state.m_Quaternions = image_support_data.m_quaternions;
-
-   for (int i=0; i < 18;i++){
-       state.m_ParameterVals.push_back(atof(image_support_data.param("TRI_PARAMETERS", i).c_str()));
-   }
-   //state.m_ParameterVals = image_support_data.m_tri_parameters;
-   double deltaF = state.m_ParameterVals[num_params - 1] - state.m_Focal;
-   if (fabs(deltaF) < 0.4 * state.m_Focal)
-      state.m_ParameterVals[num_params - 1] = deltaF;
-
-   // Set the ellipsoid
-   state.m_SemiMajorAxis = atof(image_support_data.param("SEMI_MAJOR_AXIS").c_str());
-   state.m_SemiMinorAxis =
-      state.m_SemiMajorAxis * sqrt(1.0 - atof(image_support_data.param("ECCENTRICITY").c_str()) * atof(image_support_data.param("ECCENTRICITY").c_str()));
-
-   // Now finish setting the state data from the ISD read in
-
-   // set identifiers
-   state.m_ReferenceDateAndTime = image_support_data.param("REF_DATE_TIME");
-   state.m_PlatformIdentifier   = image_support_data.param("PLATFORM_ID");
-   state.m_SensorIdentifier     = image_support_data.param("SENSOR_ID");
-   state.m_TrajectoryIdentifier = image_support_data.param("TRAJ_ID");
-   state.m_CollectionIdentifier = image_support_data.param("COLL_ID");
-
-   // Ground elevations
-   state.m_RefElevation = atof(image_support_data.param("REFERNCE_HEIGHT").c_str());
-   state.m_MinElevation = atof(image_support_data.param("MIN_VALID_HT").c_str());
-   state.m_MaxElevation = atof(image_support_data.param("MAX_VALID_HT").c_str());
-
-   // Zero parameter values
-   for (int i = 0; i < num_params; i++)
-   {
-      state.m_ParameterVals[i] = 0.0;
-      state.m_ParameterType[i] = csm::param::REAL;
-   }
-
-   // The state data will still be updated when a sensor model is created since
-   // some state data is notin the ISD and requires a SM to compute them.
-   return state.toJson();
-}
diff --git a/src/UsgsAstroLsSensorModel.cpp b/src/UsgsAstroLsSensorModel.cpp
index de6ea12..c3b0be4 100644
--- a/src/UsgsAstroLsSensorModel.cpp
+++ b/src/UsgsAstroLsSensorModel.cpp
@@ -16,7 +16,7 @@
 //  24-Apr-2017 BAE Systems  Update for CSM 3.0.2
 //  24-OCT-2017 BAE Systems  Update for CSM 3.0.3
 //-----------------------------------------------------------------------------
-#define USGSASTROLINESCANNER_LIBRARY
+#define USGS_SENSOR_LIBRARY
 
 #include "UsgsAstroLsSensorModel.h"
 
@@ -25,14 +25,396 @@
 #include <sstream>
 #include <math.h>
 
+#define USGSASTROLINESCANNER_LIBRARY
+
+#include <sstream>
+#include <Error.h>
+#include <json.hpp>
+using json = nlohmann::json;
+
+const std::string UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME
+         = "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL";
+const int     UsgsAstroLsSensorModel::NUM_PARAMETERS = 16;
+const std::string  UsgsAstroLsSensorModel::PARAMETER_NAME[] =
+{
+   "IT Pos. Bias   ",   // 0
+   "CT Pos. Bias   ",   // 1
+   "Rad Pos. Bias  ",   // 2
+   "IT Vel. Bias   ",   // 3
+   "CT Vel. Bias   ",   // 4
+   "Rad Vel. Bias  ",   // 5
+   "Omega Bias     ",   // 6
+   "Phi Bias       ",   // 7
+   "Kappa Bias     ",   // 8
+   "Omega Rate     ",   // 9
+   "Phi Rate       ",   // 10
+   "Kappa Rate     ",   // 11
+   "Omega Accl     ",   // 12
+   "Phi Accl       ",   // 13
+   "Kappa Accl     ",   // 14
+   "Focal Bias     "    // 15
+};
+
+
+const std::string  UsgsAstroLsSensorModel::_STATE_KEYWORD[] =
+{
+   "m_sensorModelName",
+   "m_imageIdentifier",
+   "m_sensorType",
+   "m_totalLines",
+   "m_totalSamples",
+   "m_offsetLines",
+   "m_offsetSamples",
+   "m_platformFlag",
+   "m_aberrFlag",
+   "m_atmrefFlag",
+   "m_intTimeLines",
+   "m_intTimeStartTimes",
+   "m_intTimes",
+   "m_startingEphemerisTime",
+   "m_centerEphemerisTime",
+   "m_detectorSampleSumming",
+   "m_startingSample",
+   "m_ikCode",
+   "m_focal",
+   "m_isisZDirection",
+   "m_opticalDistCoef",
+   "m_iTransS",
+   "m_iTransL",
+   "m_detectorSampleOrigin",
+   "m_detectorLineOrigin",
+   "m_detectorLineOffset",
+   "m_mountingMatrix",
+   "m_semiMajorAxis",
+   "m_semiMinorAxis",
+   "m_referenceDateAndTime",
+   "m_platformIdentifier",
+   "m_sensorIdentifier",
+   "m_trajectoryIdentifier",
+   "m_collectionIdentifier",
+   "m_refElevation",
+   "m_minElevation",
+   "m_maxElevation",
+   "m_dtEphem",
+   "m_t0Ephem",
+   "m_dtQuat",
+   "m_t0Quat",
+   "m_numEphem",
+   "m_numQuaternions",
+   "m_ephemPts",
+   "m_ephemRates",
+   "m_quaternions",
+   "m_parameterVals",
+   "m_parameterType",
+   "m_referencePointXyz",
+   "m_gsd",
+   "m_flyingHeight",
+   "m_halfSwath",
+   "m_halfTime",
+   "m_covariance",
+   "m_imageFlipFlag"
+};
+
+const int UsgsAstroLsSensorModel::NUM_PARAM_TYPES = 4;
+const std::string UsgsAstroLsSensorModel::PARAM_STRING_ALL[] =
+{
+   "NONE",
+   "FICTITIOUS",
+   "REAL",
+   "FIXED"
+};
+const csm::param::Type
+      UsgsAstroLsSensorModel::PARAM_CHAR_ALL[] =
+{
+   csm::param::NONE,
+   csm::param::FICTITIOUS,
+   csm::param::REAL,
+   csm::param::FIXED
+};
+
+
+void UsgsAstroLsSensorModel::replaceModelState(const std::string &stateString )
+{
+   reset();
+   auto j = json::parse(stateString);
+   int num_params    = NUM_PARAMETERS;
+   int num_paramsSq = num_params * num_params;
+
+   m_imageIdentifier = j["m_imageIdentifier"].get<std::string>();
+   m_sensorType = j["m_sensorType"];
+   m_totalLines = j["m_totalLines"];
+   m_totalSamples = j["m_totalSamples"];
+   m_offsetLines = j["m_offsetLines"];
+   m_offsetSamples = j["m_offsetSamples"];
+   m_platformFlag = j["m_platformFlag"];
+   m_aberrFlag = j["m_aberrFlag"];
+   m_atmRefFlag = j["m_atmRefFlag"];
+   m_intTimeLines = j["m_intTimeLines"].get<std::vector<double>>();
+   m_intTimeStartTimes = j["m_intTimeStartTimes"].get<std::vector<double>>();
+   m_intTimes = j["m_intTimes"].get<std::vector<double>>();
+   m_startingEphemerisTime = j["m_startingEphemerisTime"];
+   m_centerEphemerisTime = j["m_centerEphemerisTime"];
+   m_detectorSampleSumming = j["m_detectorSampleSumming"];
+   m_startingSample = j["m_startingSample"];
+   m_ikCode = j["m_ikCode"];
+   m_focal = j["m_focal"];
+   m_isisZDirection = j["m_isisZDirection"];
+   for (int i = 0; i < 3; i++) {
+     m_opticalDistCoef[i] = j["m_opticalDistCoef"][i];
+     m_iTransS[i] = j["m_iTransS"][i];
+     m_iTransL[i] = j["m_iTransL"][i];
+   }
+   m_detectorSampleOrigin = j["m_detectorSampleOrigin"];
+   m_detectorLineOrigin = j["m_detectorLineOrigin"];
+   m_detectorLineOffset = j["m_detectorLineOffset"];
+   for (int i = 0; i < 9; i++) {
+       m_mountingMatrix[i] = j["m_mountingMatrix"][i];
+   }
+   m_semiMajorAxis = j["m_semiMajorAxis"];
+   m_semiMinorAxis = j["m_semiMinorAxis"];
+   m_referenceDateAndTime = j["m_referenceDateAndTime"];
+   m_platformIdentifier = j["m_platformIdentifier"];
+   m_sensorIdentifier = j["m_sensorIdentifier"];
+   m_trajectoryIdentifier = j["m_trajectoryIdentifier"];
+   m_collectionIdentifier = j["m_collectionIdentifier"];
+   m_refElevation = j["m_refElevation"];
+   m_minElevation = j["m_minElevation"];
+   m_maxElevation = j["m_maxElevation"];
+   m_dtEphem = j["m_dtEphem"];
+   m_t0Ephem = j["m_t0Ephem"];
+   m_dtQuat = j["m_dtQuat"];
+   m_t0Quat = j["m_t0Quat"];
+   m_numEphem = j["m_numEphem"];
+   m_numQuaternions = j["m_numQuaternions"];
+   m_referencePointXyz.x = j["m_referencePointXyz"][0];
+   m_referencePointXyz.y = j["m_referencePointXyz"][1];
+   m_referencePointXyz.z = j["m_referencePointXyz"][2];
+   m_gsd = j["m_gsd"];
+   m_flyingHeight = j["m_flyingHeight"];
+   m_halfSwath = j["m_halfSwath"];
+   m_halfTime = j["m_halfTime"];
+   m_imageFlipFlag = j["m_imageFlipFlag"];
+   // Vector = is overloaded so explicit get with type required.
+   m_ephemPts = j["m_ephemPts"].get<std::vector<double>>();
+   m_ephemRates = j["m_ephemRates"].get<std::vector<double>>();
+   m_quaternions = j["m_quaternions"].get<std::vector<double>>();
+   m_parameterVals = j["m_parameterVals"].get<std::vector<double>>();
+   m_covariance = j["m_covariance"].get<std::vector<double>>();
+   for (int i = 0; i < num_params; i++) {
+     for (int k = 0; k < NUM_PARAM_TYPES; k++) {
+       if (j["m_parameterType"][i] == PARAM_STRING_ALL[k]) {
+         m_parameterType[i] = PARAM_CHAR_ALL[k];
+         break;
+     }
+    }
+   }
+
+   // If computed state values are still default, then compute them
+   if (m_gsd == 1.0  && m_flyingHeight == 1000.0)
+   {
+     updateState();
+   }
+
+   try
+   {
+     setLinearApproximation();
+   }
+   catch (...)
+   {
+     _linear = false;
+   }
+}
+
+std::string UsgsAstroLsSensorModel::getModelNameFromModelState(
+   const std::string& model_state)
+{
+   // Parse the string to JSON
+   auto j = json::parse(model_state);
+   // If model name cannot be determined, return a blank string
+   std::string model_name;
+
+   if (j.find("m_sensorModelName") != j.end()) {
+       model_name = j["m_sensorModelName"];
+   } else {
+       csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
+       std::string aMessage = "No 'm_sensorModelName' key in the model state object.";
+       std::string aFunction = "UsgsAstroLsPlugin::getModelNameFromModelState";
+       csm::Error csmErr(aErrorType, aMessage, aFunction);
+       throw(csmErr);
+   }
+   if (model_name != _SENSOR_MODEL_NAME){
+       csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
+       std::string aMessage = "Sensor model not supported.";
+       std::string aFunction = "UsgsAstroLsPlugin::getModelNameFromModelState()";
+       csm::Error csmErr(aErrorType, aMessage, aFunction);
+       throw(csmErr);
+   }
+   return model_name;
+}
+
+std::string UsgsAstroLsSensorModel::getModelState() const {
+      json state;
+      state["m_imageIdentifier"] = m_imageIdentifier;
+      state["m_sensorType"] = m_sensorType;
+      state["m_totalLines"] = m_totalLines;
+      state["m_totalSamples"] = m_totalSamples;
+      state["m_offsetLines"] = m_offsetLines;
+      state["m_offsetSamples"] = m_offsetSamples;
+      state["m_platformFlag"] = m_platformFlag;
+      state["m_aberrFlag"] = m_aberrFlag;
+      state["m_atmRefFlag"] = m_atmRefFlag;
+      state["m_intTimeLines"] = m_intTimeLines;
+      state["m_intTimeStartTimes"] = m_intTimeStartTimes;
+      state["m_intTimes"] = m_intTimes;
+      state["m_startingEphemerisTime"] = m_startingEphemerisTime;
+      state["m_centerEphemerisTime"] = m_centerEphemerisTime;
+      state["m_detectorSampleSumming"] = m_detectorSampleSumming;
+      state["m_startingSample"] = m_startingSample;
+      state["m_ikCode"] = m_ikCode;
+      state["m_focal"] = m_focal;
+      state["m_isisZDirection"] = m_isisZDirection;
+      state["m_opticalDistCoef"] = std::vector<double>(m_opticalDistCoef, m_opticalDistCoef+3);
+      state["m_iTransS"] = std::vector<double>(m_iTransS, m_iTransS+3);
+      state["m_iTransL"] = std::vector<double>(m_iTransL, m_iTransL+3);
+      state["m_detectorSampleOrigin"] = m_detectorSampleOrigin;
+      state["m_detectorLineOrigin"] = m_detectorLineOrigin;
+      state["m_detectorLineOffset"] = m_detectorLineOffset;
+      state["m_mountingMatrix"] = std::vector<double>(m_mountingMatrix, m_mountingMatrix+9);
+      state["m_semiMajorAxis"] = m_semiMajorAxis;
+      state["m_semiMinorAxis"] = m_semiMinorAxis;
+      state["m_referenceDateAndTime"] = m_referenceDateAndTime;
+      state["m_platformIdentifier"] = m_platformIdentifier;
+      state["m_sensorIdentifier"] = m_sensorIdentifier;
+      state["m_trajectoryIdentifier"] = m_trajectoryIdentifier;
+      state["m_collectionIdentifier"] = m_collectionIdentifier;
+      state["m_refElevation"] = m_refElevation;
+      state["m_minElevation"] = m_minElevation;
+      state["m_maxElevation"] = m_maxElevation;
+      state["m_dtEphem"] = m_dtEphem;
+      state["m_t0Ephem"] = m_t0Ephem;
+      state["m_dtQuat"] = m_dtQuat;
+      state["m_t0Quat"] = m_t0Quat;
+      state["m_numEphem"] = m_numEphem;
+      state["m_numQuaternions"] = m_numQuaternions;
+      state["m_ephemPts"] = m_ephemPts;
+      state["m_ephemRates"] = m_ephemRates;
+      state["m_quaternions"] = m_quaternions;
+      state["m_parameterVals"] = m_parameterVals;
+      state["m_parameterType"] = m_parameterType;
+      state["m_gsd"] = m_gsd;
+      state["m_flyingHeight"] = m_flyingHeight;
+      state["m_halfSwath"] = m_halfSwath;
+      state["m_halfTime"] = m_halfTime;
+      state["m_covariance"] = m_covariance;
+      state["m_imageFlipFlag"] = m_imageFlipFlag;
+
+      state["m_referencePointXyz"] = json();
+      state["m_referencePointXyz"]["x"] = m_referencePointXyz.x;
+      state["m_referencePointXyz"]["y"] = m_referencePointXyz.y;
+      state["m_referencePointXyz"]["z"] = m_referencePointXyz.z;
+
+      return state.dump();
+ }
+
+void UsgsAstroLsSensorModel::reset()
+{
+  _linear = false; // default until a linear model is made
+  _u0    = 0.0;
+  _du_dx = 0.0;
+  _du_dy = 0.0;
+  _du_dz = 0.0;
+  _v0    = 0.0;
+  _dv_dx = 0.0;
+  _dv_dy = 0.0;
+  _dv_dz = 0.0;
+
+  _no_adjustment.assign(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0);
+
+  m_imageIdentifier = "";                    // 1
+  m_sensorType    = "USGSAstroLineScanner";  // 2
+  m_totalLines    = 0;                       // 3
+  m_totalSamples  = 0;                       // 4
+  m_offsetLines   = 0.0;                     // 7
+  m_offsetSamples = 0.0;                     // 8
+  m_platformFlag  = 1;                       // 9
+  m_aberrFlag     = 0;                       // 10
+  m_atmRefFlag    = 0;                       // 11
+  m_intTimeLines.clear();
+  m_intTimeStartTimes.clear();
+  m_intTimes.clear();
+  m_startingEphemerisTime = 0.0;             // 13
+  m_centerEphemerisTime = 0.0;               // 14
+  m_detectorSampleSumming = 1.0;             // 15
+  m_startingSample = 1.0;                    // 16
+  m_ikCode = -85600;                         // 17
+  m_focal = 350.0;                           // 18
+  m_isisZDirection = 1.0;                    // 19
+  m_opticalDistCoef[0] = 0.0;                // 20
+  m_opticalDistCoef[1] = 0.0;                // 20
+  m_opticalDistCoef[2] = 0.0;                // 20
+  m_iTransS[0] = 0.0;                        // 21
+  m_iTransS[1] = 0.0;                        // 21
+  m_iTransS[2] = 150.0;                      // 21
+  m_iTransL[0] = 0.0;                        // 22
+  m_iTransL[1] = 150.0;                      // 22
+  m_iTransL[2] = 0.0;                        // 22
+  m_detectorSampleOrigin = 2500.0;           // 23
+  m_detectorLineOrigin = 0.0;                // 24
+  m_detectorLineOffset = 0.0;                // 25
+  m_mountingMatrix[0] = 1.0;                 // 26
+  m_mountingMatrix[1] = 0.0;                 // 26
+  m_mountingMatrix[2] = 0.0;                 // 26
+  m_mountingMatrix[3] = 0.0;                 // 26
+  m_mountingMatrix[4] = 1.0;                 // 26
+  m_mountingMatrix[5] = 0.0;                 // 26
+  m_mountingMatrix[6] = 0.0;                 // 26
+  m_mountingMatrix[7] = 0.0;                 // 26
+  m_mountingMatrix[8] = 1.0;                 // 26
+  m_semiMajorAxis = 3400000.0;               // 27
+  m_semiMinorAxis = 3350000.0;               // 28
+  m_referenceDateAndTime = "";               // 30
+  m_platformIdentifier = "";                 // 31
+  m_sensorIdentifier = "";                   // 32
+  m_trajectoryIdentifier = "";               // 33
+  m_collectionIdentifier = "";               // 33
+  m_refElevation = 30;                       // 34
+  m_minElevation = -8000.0;                  // 34
+  m_maxElevation =  8000.0;                  // 35
+  m_dtEphem = 2.0;                           // 36
+  m_t0Ephem = -70.0;                         // 37
+  m_dtQuat =  0.1;                           // 38
+  m_t0Quat = -40.0;                          // 39
+  m_numEphem = 0;                            // 40
+  m_numQuaternions = 0;                      // 41
+  m_ephemPts.clear();                        // 42
+  m_ephemRates.clear();                      // 43
+  m_quaternions.clear();                     // 44
+
+  m_parameterVals.assign(NUM_PARAMETERS,0.0);
+  m_parameterType.assign(NUM_PARAMETERS,csm::param::REAL);
+
+  m_referencePointXyz.x = 0.0;             // 47
+  m_referencePointXyz.y = 0.0;             // 47
+  m_referencePointXyz.z = 0.0;             // 47
+  m_gsd = 1.0;                             // 48
+  m_flyingHeight = 1000.0;                 // 49
+  m_halfSwath = 1000.0;                    // 50
+  m_halfTime = 10.0;                       // 51
+
+  m_covariance = std::vector<double>(NUM_PARAMETERS * NUM_PARAMETERS,0.0); // 52
+  m_imageFlipFlag = 0;                     // 53
+}
+
+
 //*****************************************************************************
 // UsgsAstroLsSensorModel Constructor
 //*****************************************************************************
 UsgsAstroLsSensorModel::UsgsAstroLsSensorModel()
 {
-   _no_adjustment.assign(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0);
+   _no_adjustment.assign(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0);
 }
 
+
 //*****************************************************************************
 // UsgsAstroLsSensorModel Destructor
 //*****************************************************************************
@@ -40,41 +422,6 @@ UsgsAstroLsSensorModel::~UsgsAstroLsSensorModel()
 {
 }
 
-//*****************************************************************************
-// UsgsAstroLsSensorModel set
-//*****************************************************************************
-void UsgsAstroLsSensorModel::set(const UsgsAstroLsStateData &state_data)
-{
-   _linear = false; // default until a linear model is made
-   _u0    = 0.0;
-   _du_dx = 0.0;
-   _du_dy = 0.0;
-   _du_dz = 0.0;
-   _v0    = 0.0;
-   _dv_dx = 0.0;
-   _dv_dy = 0.0;
-   _dv_dz = 0.0;
-
-   _no_adjustment.assign(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0);
-   _data = state_data;
-
-   // If needed set state data elements that need a sensor model to compute
-   // Update if still using default settings
-   if (_data.m_Gsd == 1.0  && _data.m_FlyingHeight == 1000.0)
-   {
-      updateState();
-   }
-
-   try
-   {
-      setLinearApproximation();
-   }
-   catch (...)
-   {
-      _linear = false;
-   }
-}
-
 //*****************************************************************************
 // UsgsAstroLsSensorModel updateState
 //*****************************************************************************
@@ -84,90 +431,47 @@ void UsgsAstroLsSensorModel::updateState()
    // This routine will set some parameters not found in the ISD.
 
    // Reference point (image center)
-   double lineCtr = _data.m_TotalLines / 2.0;
-   double sampCtr = _data.m_TotalSamples / 2.0;
+   double lineCtr = m_totalLines / 2.0;
+   double sampCtr = m_totalSamples / 2.0;
    csm::ImageCoord ip(lineCtr, sampCtr);
-   double refHeight = _data.m_RefElevation;
-   _data.m_ReferencePointXyz = imageToGround(ip, refHeight);
+   double refHeight = m_refElevation;
+   m_referencePointXyz = imageToGround(ip, refHeight);
    // Compute ground sample distance
    ip.line += 1;
    ip.samp += 1;
    csm::EcefCoord delta = imageToGround(ip, refHeight);
-   double dx = delta.x - _data.m_ReferencePointXyz.x;
-   double dy = delta.y - _data.m_ReferencePointXyz.y;
-   double dz = delta.z - _data.m_ReferencePointXyz.z;
-   _data.m_Gsd = sqrt((dx*dx + dy*dy + dz*dz) / 2.0);
+   double dx = delta.x - m_referencePointXyz.x;
+   double dy = delta.y - m_referencePointXyz.y;
+   double dz = delta.z - m_referencePointXyz.z;
+   m_gsd = sqrt((dx*dx + dy*dy + dz*dz) / 2.0);
 
    // Compute flying height
    csm::EcefCoord sensorPos = getSensorPosition(0.0);
-   dx = sensorPos.x - _data.m_ReferencePointXyz.x;
-   dy = sensorPos.y - _data.m_ReferencePointXyz.y;
-   dz = sensorPos.z - _data.m_ReferencePointXyz.z;
-   _data.m_FlyingHeight = sqrt(dx*dx + dy*dy + dz*dz);
+   dx = sensorPos.x - m_referencePointXyz.x;
+   dy = sensorPos.y - m_referencePointXyz.y;
+   dz = sensorPos.z - m_referencePointXyz.z;
+   m_flyingHeight = sqrt(dx*dx + dy*dy + dz*dz);
 
    // Compute half swath
-   _data.m_HalfSwath = _data.m_Gsd * _data.m_TotalSamples / 2.0;
+   m_halfSwath = m_gsd * m_totalSamples / 2.0;
 
    // Compute half time duration
-   double fullImageTime = _data.m_IntTimeStartTimes.back() - _data.m_IntTimeStartTimes.front()
-                          + _data.m_IntTimes.back() * (_data.m_TotalLines - _data.m_IntTimeLines.back());
-   _data.m_HalfTime = fullImageTime / 2.0;
+   double fullImageTime = m_intTimeStartTimes.back() - m_intTimeStartTimes.front()
+                          + m_intTimes.back() * (m_totalLines - m_intTimeLines.back());
+   m_halfTime = fullImageTime / 2.0;
 
    // Parameter covariance, hardcoded accuracy values
-   int num_params = _data.NUM_PARAMETERS;
-   int num_params_square = num_params * num_params;
-   double variance = _data.m_Gsd * _data.m_Gsd;
-   for (int i = 0; i < num_params_square; i++)
+   int num_params = NUM_PARAMETERS;
+   int num_paramsSquare = num_params * num_params;
+   double variance = m_gsd * m_gsd;
+   for (int i = 0; i < num_paramsSquare; i++)
    {
-      _data.m_Covariance[i] = 0.0;
+      m_covariance[i] = 0.0;
    }
    for (int i = 0; i < num_params; i++)
    {
-      _data.m_Covariance[i * num_params + i] = variance;
+      m_covariance[i * num_params + i] = variance;
    }
-
-   // Set flag for flipping image along horizontal axis
-   int index = int((_data.m_NumEphem - 1) / 2.0) * 3;
-   double xs, ys, zs;    // mid sensor position
-   xs = _data.m_EphemPts[index];
-   ys = _data.m_EphemPts[index + 1];
-   zs = _data.m_EphemPts[index + 2];
-   double xv, yv, zv;    // mid sensor velocity
-   xv = _data.m_EphemRates[index];
-   yv = _data.m_EphemRates[index + 1];
-   zv = _data.m_EphemRates[index + 2];
-   double xm, ym, zm;    // mid line position (mid sample)
-   xm = _data.m_ReferencePointXyz.x;
-   ym = _data.m_ReferencePointXyz.y;
-   zm = _data.m_ReferencePointXyz.z;
-   // mid line position (first sample)
-   csm::EcefCoord posf = imageToGround(csm::ImageCoord(lineCtr, 0.0), refHeight);
-   // mid line position (last sample)
-   csm::EcefCoord posl = imageToGround(csm::ImageCoord(lineCtr, _data.m_TotalSamples - 1), refHeight);
-   double xd, yd, zd;    // unit vector normal to image footprint
-   xd = posl.x - posf.x;
-   yd = posl.y - posf.y;
-   zd = posl.z - posf.z;
-   double xn, yn, zn;
-   xn = yv*zd - zv*yd;
-   yn = zv*xd - xv*zd;
-   zn = xv*yd - yv*xd;
-   double nmag = sqrt(xn*xn + yn*yn + zn*zn);
-   xn /= nmag;
-   yn /= nmag;
-   zn /= nmag;
-   double xo, yo, zo;   // unit vector ground-to_satellite
-   xo = xs - xm;
-   yo = ys - ym;
-   zo = zs - zm;
-   double omag = sqrt(xo*xo + yo*yo + zo*zo);
-   xo /= omag;
-   yo /= omag;
-   zo /= omag;
-   double triple_product = xn*xo + yn*yo + zn*zo;
-   _data.m_ImageFlipFlag = 0;
-   if (triple_product > 0.0)
-      _data.m_ImageFlipFlag = 1;
 }
 
 
@@ -222,9 +526,9 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage(
    // in some situations.
 
    // Start bisection search on the image lines
-   double sampCtr = _data.m_TotalSamples / 2.0;
+   double sampCtr = m_totalSamples / 2.0;
    double firstTime = getImageTime(csm::ImageCoord(0.0, sampCtr));
-   double lastTime = getImageTime(csm::ImageCoord(_data.m_TotalLines, sampCtr));
+   double lastTime = getImageTime(csm::ImageCoord(m_totalLines, sampCtr));
    double firstOffset = computeViewingPixel(firstTime, ground_pt, adj).line - 0.5;
    double lastOffset = computeViewingPixel(lastTime, ground_pt, adj).line - 0.5;
 
@@ -242,14 +546,14 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage(
    csm::ImageCoord approxPoint;
    computeLinearApproximation(ground_pt, approxPoint);
    csm::ImageCoord approxNextPoint = approxPoint;
-   if (approxNextPoint.line + 1 < _data.m_TotalLines) {
+   if (approxNextPoint.line + 1 < m_totalLines) {
       ++approxNextPoint.line;
    }
    else {
       --approxNextPoint.line;
    }
-   csm::EcefCoord approxIntersect = imageToGround(approxPoint, _data.m_RefElevation);
-   csm::EcefCoord approxNextIntersect = imageToGround(approxNextPoint, _data.m_RefElevation);
+   csm::EcefCoord approxIntersect = imageToGround(approxPoint, m_refElevation);
+   csm::EcefCoord approxNextIntersect = imageToGround(approxNextPoint, m_refElevation);
    double lineDX = approxNextIntersect.x - approxIntersect.x;
    double lineDY = approxNextIntersect.y - approxIntersect.y;
    double lineDZ = approxNextIntersect.z - approxIntersect.z;
@@ -283,17 +587,17 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage(
                        / (lastOffset - firstOffset);
    csm::ImageCoord calculatedPixel = computeViewingPixel(computedTime, ground_pt, adj);
    // The computed viewing line is the detector line, so we need to convert that to image lines
-   auto referenceTimeIt = std::upper_bound(_data.m_IntTimeStartTimes.begin(),
-                                           _data.m_IntTimeStartTimes.end(),
+   auto referenceTimeIt = std::upper_bound(m_intTimeStartTimes.begin(),
+                                           m_intTimeStartTimes.end(),
                                            computedTime);
-   if (referenceTimeIt != _data.m_IntTimeStartTimes.begin()) {
+   if (referenceTimeIt != m_intTimeStartTimes.begin()) {
       --referenceTimeIt;
    }
-   size_t referenceIndex = std::distance(_data.m_IntTimeStartTimes.begin(), referenceTimeIt);
-   calculatedPixel.line += _data.m_IntTimeLines[referenceIndex] - 1
-                         + (computedTime - _data.m_IntTimeStartTimes[referenceIndex])
-                         / _data.m_IntTimes[referenceIndex];
-   csm::EcefCoord calculatedPoint = imageToGround(calculatedPixel, _data.m_RefElevation);
+   size_t referenceIndex = std::distance(m_intTimeStartTimes.begin(), referenceTimeIt);
+   calculatedPixel.line += m_intTimeLines[referenceIndex] - 1
+                         + (computedTime - m_intTimeStartTimes[referenceIndex])
+                         / m_intTimes[referenceIndex];
+   csm::EcefCoord calculatedPoint = imageToGround(calculatedPixel, m_refElevation);
    double dx = ground_pt.x - calculatedPoint.x;
    double dy = ground_pt.y - calculatedPoint.y;
    double dz = ground_pt.z - calculatedPoint.z;
@@ -301,7 +605,7 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage(
 
    // Check that the pixel is actually in the image
    if ((calculatedPixel.samp < 0) ||
-       (calculatedPixel.samp > _data.m_TotalSamples)) {
+       (calculatedPixel.samp > m_totalSamples)) {
       throw csm::Warning(
          csm::Warning::IMAGE_COORD_OUT_OF_BOUNDS,
          "The image coordinate is out of bounds of the image size.",
@@ -422,7 +726,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::imageToGround(
    losToEcf(
       image_pt.line, image_pt.samp, _no_adjustment,
       xc, yc, zc, vx, vy, vz, xl, yl, zl);
-   if (_data.m_AberrFlag == 1)
+   if (m_aberrFlag == 1)
    {
       lightAberrationCorr(vx, vy, vz, xl, yl, zl, dxl, dyl, dzl);
       xl += dxl;
@@ -446,6 +750,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::imageToGround(
             "Desired precision not achieved.",
             "UsgsAstroLsSensorModel::imageToGround()"));
    }
+
    return csm::EcefCoord(x, y, z);
 }
 
@@ -492,7 +797,7 @@ csm::EcefCoordCovar UsgsAstroLsSensorModel::imageToGround(
    // Use numerical partials
 
    const double DELTA_IMAGE = 1.0;
-   const double DELTA_GROUND = _data.m_Gsd;
+   const double DELTA_GROUND = m_gsd;
    csm::ImageCoord ip(image_pt.line, image_pt.samp);
 
    csm::EcefCoord gp = imageToGround(
@@ -574,7 +879,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToProximateImagingLocus(
    csm::WarningList* warnings) const
 {
    // Object ray unit direction near given ground location
-   const double DELTA_GROUND = _data.m_Gsd;
+   const double DELTA_GROUND = m_gsd;
 
    double x = ground_pt.x;
    double y = ground_pt.y;
@@ -639,7 +944,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToRemoteImagingLocus(
 
    // Set esposure station elevation to zero
    double height = 0.0;
-   double GND_DELTA = _data.m_Gsd;
+   double GND_DELTA = m_gsd;
    // Point on object ray at zero elevation
    csm::EcefCoord gp1 = imageToGround(
       image_pt, height, desired_precision, achieved_precision, warnings);
@@ -677,7 +982,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToRemoteImagingLocus(
 std::vector<double> UsgsAstroLsSensorModel::computeGroundPartials(
    const csm::EcefCoord& ground_pt) const
 {
-   double GND_DELTA = _data.m_Gsd;
+   double GND_DELTA = m_gsd;
    // Partial of line, sample wrt X, Y, Z
    double x = ground_pt.x;
    double y = ground_pt.y;
@@ -732,8 +1037,8 @@ csm::RasterGM::SensorPartials UsgsAstroLsSensorModel::computeSensorPartials(
 {
    // Compute numerical partials ls wrt specific parameter
 
-   const double DELTA = _data.m_Gsd;
-   std::vector<double> adj(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0);
+   const double DELTA = m_gsd;
+   std::vector<double> adj(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0);
    adj[index] = DELTA;
 
    csm::ImageCoord img1 = groundToImage(
@@ -795,8 +1100,8 @@ double UsgsAstroLsSensorModel::getParameterCovariance(
    int index1,
    int index2) const
 {
-   int index = UsgsAstroLsStateData::NUM_PARAMETERS * index1 + index2;
-   return _data.m_Covariance[index];
+   int index = UsgsAstroLsSensorModel::NUM_PARAMETERS * index1 + index2;
+   return m_covariance[index];
 }
 
 //***************************************************************************
@@ -807,8 +1112,8 @@ void UsgsAstroLsSensorModel::setParameterCovariance(
    int index2,
    double covariance)
 {
-   int index = UsgsAstroLsStateData::NUM_PARAMETERS * index1 + index2;
-   _data.m_Covariance[index] = covariance;
+   int index = UsgsAstroLsSensorModel::NUM_PARAMETERS * index1 + index2;
+   m_covariance[index] = covariance;
 }
 
 //---------------------------------------------------------------------------
@@ -820,7 +1125,7 @@ void UsgsAstroLsSensorModel::setParameterCovariance(
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getTrajectoryIdentifier() const
 {
-   return _data.m_TrajectoryIdentifier;
+   return m_trajectoryIdentifier;
 }
 
 //***************************************************************************
@@ -828,14 +1133,14 @@ std::string UsgsAstroLsSensorModel::getTrajectoryIdentifier() const
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getReferenceDateAndTime() const
 {
-   if (_data.m_ReferenceDateAndTime == "UNKNOWN")
+   if (m_referenceDateAndTime == "UNKNOWN")
    {
       throw csm::Error(
          csm::Error::UNSUPPORTED_FUNCTION,
          "Unsupported function",
          "UsgsAstroLsSensorModel::getReferenceDateAndTime");
    }
-   return _data.m_ReferenceDateAndTime;
+   return m_referenceDateAndTime;
 }
 
 //***************************************************************************
@@ -850,21 +1155,21 @@ double UsgsAstroLsSensorModel::getImageTime(
    // CSM image convention: UL pixel center == (0.5, 0.5)
    // USGS image convention: UL pixel center == (1.0, 1.0)
 
-   double lineCSMFull = line1 + _data.m_OffsetLines;
+   double lineCSMFull = line1 + m_offsetLines;
    double lineUSGSFull = lineCSMFull + 0.5;
 
    // These calculation assumes that the values in the integration time
    // vectors are in terms of ISIS' pixels
-   auto referenceLineIt = std::upper_bound(_data.m_IntTimeLines.begin(),
-                                           _data.m_IntTimeLines.end(),
+   auto referenceLineIt = std::upper_bound(m_intTimeLines.begin(),
+                                           m_intTimeLines.end(),
                                            lineUSGSFull);
-   if (referenceLineIt != _data.m_IntTimeLines.begin()) {
+   if (referenceLineIt != m_intTimeLines.begin()) {
       --referenceLineIt;
    }
-   size_t referenceIndex = std::distance(_data.m_IntTimeLines.begin(), referenceLineIt);
+   size_t referenceIndex = std::distance(m_intTimeLines.begin(), referenceLineIt);
 
-   double time = _data.m_IntTimeStartTimes[referenceIndex]
-      + _data.m_IntTimes[referenceIndex] * (lineUSGSFull - _data.m_IntTimeLines[referenceIndex]);
+   double time = m_intTimeStartTimes[referenceIndex]
+      + m_intTimes[referenceIndex] * (lineUSGSFull - m_intTimeLines[referenceIndex]);
 
    return time;
 
@@ -920,7 +1225,7 @@ csm::EcefVector UsgsAstroLsSensorModel::getSensorVelocity(double time) const
 //***************************************************************************
 void UsgsAstroLsSensorModel::setParameterValue(int index, double value)
 {
-   _data.m_ParameterVals[index] = value;
+   m_parameterVals[index] = value;
 }
 
 //***************************************************************************
@@ -928,7 +1233,7 @@ void UsgsAstroLsSensorModel::setParameterValue(int index, double value)
 //***************************************************************************
 double UsgsAstroLsSensorModel::getParameterValue(int index) const
 {
-   return _data.m_ParameterVals[index];
+   return m_parameterVals[index];
 }
 
 //***************************************************************************
@@ -936,7 +1241,7 @@ double UsgsAstroLsSensorModel::getParameterValue(int index) const
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getParameterName(int index) const
 {
-   return _data.PARAMETER_NAME[index];
+   return PARAMETER_NAME[index];
 }
 
 std::string UsgsAstroLsSensorModel::getParameterUnits(int index) const
@@ -951,7 +1256,7 @@ std::string UsgsAstroLsSensorModel::getParameterUnits(int index) const
 //***************************************************************************
 int UsgsAstroLsSensorModel::getNumParameters() const
 {
-   return UsgsAstroLsStateData::NUM_PARAMETERS;
+   return UsgsAstroLsSensorModel::NUM_PARAMETERS;
 }
 
 
@@ -960,7 +1265,7 @@ int UsgsAstroLsSensorModel::getNumParameters() const
 //***************************************************************************
 csm::param::Type UsgsAstroLsSensorModel::getParameterType(int index) const
 {
-   return _data.m_ParameterType[index];
+   return m_parameterType[index];
 }
 
 
@@ -970,7 +1275,7 @@ csm::param::Type UsgsAstroLsSensorModel::getParameterType(int index) const
 void UsgsAstroLsSensorModel::setParameterType(
    int index, csm::param::Type pType)
 {
-   _data.m_ParameterType[index] = pType;
+   m_parameterType[index] = pType;
 }
 
 //---------------------------------------------------------------------------
@@ -990,7 +1295,7 @@ std::string UsgsAstroLsSensorModel::getPedigree() const
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getImageIdentifier() const
 {
-   return _data.m_ImageIdentifier;
+   return m_imageIdentifier;
 }
 
 //***************************************************************************
@@ -1001,7 +1306,7 @@ void UsgsAstroLsSensorModel::setImageIdentifier(
    csm::WarningList* warnings)
 {
    // Image id should include the suffix without the path name
-   _data.m_ImageIdentifier = imageId;
+   m_imageIdentifier = imageId;
 }
 
 //***************************************************************************
@@ -1009,7 +1314,7 @@ void UsgsAstroLsSensorModel::setImageIdentifier(
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getSensorIdentifier() const
 {
-   return _data.m_SensorIdentifier;
+   return m_sensorIdentifier;
 }
 
 //***************************************************************************
@@ -1017,7 +1322,7 @@ std::string UsgsAstroLsSensorModel::getSensorIdentifier() const
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getPlatformIdentifier() const
 {
-   return _data.m_PlatformIdentifier;
+   return m_platformIdentifier;
 }
 
 //***************************************************************************
@@ -1025,7 +1330,7 @@ std::string UsgsAstroLsSensorModel::getPlatformIdentifier() const
 //***************************************************************************
 void UsgsAstroLsSensorModel::setReferencePoint(const csm::EcefCoord& ground_pt)
 {
-   _data.m_ReferencePointXyz = ground_pt;
+   m_referencePointXyz = ground_pt;
 }
 
 //***************************************************************************
@@ -1034,7 +1339,7 @@ void UsgsAstroLsSensorModel::setReferencePoint(const csm::EcefCoord& ground_pt)
 csm::EcefCoord UsgsAstroLsSensorModel::getReferencePoint() const
 {
    // Return ground point at image center
-   return _data.m_ReferencePointXyz;
+   return m_referencePointXyz;
 }
 
 //***************************************************************************
@@ -1042,7 +1347,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::getReferencePoint() const
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getModelName() const
 {
-   return UsgsAstroLsStateData::SENSOR_MODEL_NAME;
+   return UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME;
 }
 
 //***************************************************************************
@@ -1058,20 +1363,93 @@ csm::ImageCoord UsgsAstroLsSensorModel::getImageStart() const
 //***************************************************************************
 csm::ImageVector UsgsAstroLsSensorModel::getImageSize() const
 {
-   return csm::ImageVector(_data.m_TotalLines, _data.m_TotalSamples);
+   return csm::ImageVector(m_totalLines, m_totalSamples);
 }
 
 //---------------------------------------------------------------------------
 // Sensor Model State
 //---------------------------------------------------------------------------
-
-//***************************************************************************
-// UsgsAstroLsSensorModel::getSensorModelState
-//***************************************************************************
-std::string UsgsAstroLsSensorModel::getModelState() const
-{
-   return _data.toJson();
-}
+//
+// //***************************************************************************
+// // UsgsAstroLsSensorModel::getSensorModelState
+// //***************************************************************************
+// std::string UsgsAstroLsSensorModel::setModelState(std::string stateString) const
+// {
+//   auto j = json::parse(stateString);
+//   int num_params    = NUM_PARAMETERS;
+//   int num_paramsSq = num_params * num_params;
+//
+//   m_imageIdentifier = j["m_imageIdentifier"];
+//   m_sensorType = j["m_sensorType"];
+//   m_totalLines = j["m_totalLines"];
+//   m_totalSamples = j["m_totalSamples"];
+//   m_offsetLines = j["m_offsetLines"];
+//   m_offsetSamples = j["m_offsetSamples"];
+//   m_platformFlag = j["m_platformFlag"];
+//   m_aberrFlag = j["m_aberrFlag"];
+//   m_atmRefFlag = j["m_atmrefFlag"];
+//   m_intTimeLines = j["m_intTimeLines"].get<std::vector<double>>();
+//   m_intTimeStartTimes = j["m_intTimeStartTimes"].get<std::vector<double>>();
+//   m_intTimes = j["m_intTimes"].get<std::vector<double>>();
+//   m_startingEphemerisTime = j["m_startingEphemerisTime"];
+//   m_centerEphemerisTime = j["m_centerEphemerisTime"];
+//   m_detectorSampleSumming = j["m_detectorSampleSumming"];
+//   m_startingSample = j["m_startingSample"];
+//   m_ikCode = j["m_ikCode"];
+//   m_focal = j["m_focal"];
+//   m_isisZDirection = j["m_isisZDirection"];
+//   for (int i = 0; i < 3; i++) {
+//     m_opticalDistCoef[i] = j["m_opticalDistCoef"][i];
+//     m_iTransS[i] = j["m_iTransS"][i];
+//     m_iTransL[i] = j["m_iTransL"][i];
+//   }
+//   m_detectorSampleOrigin = j["m_detectorSampleOrigin"];
+//   m_detectorLineOrigin = j["m_detectorLineOrigin"];
+//   m_detectorLineOffset = j["m_detectorLineOffset"];
+//   for (int i = 0; i < 9; i++) {
+//       m_mountingMatrix[i] = j["m_mountingMatrix"][i];
+//   }
+//   m_semiMajorAxis = j["m_semiMajorAxis"];
+//   m_semiMinorAxis = j["m_semiMinorAxis"];
+//   m_referenceDateAndTime = j["m_referenceDateAndTime"];
+//   m_platformIdentifier = j["m_platformIdentifier"];
+//   m_sensorIdentifier = j["m_sensorIdentifier"];
+//   m_trajectoryIdentifier = j["m_trajectoryIdentifier"];
+//   m_collectionIdentifier = j["m_collectionIdentifier"];
+//   m_refElevation = j["m_refElevation"];
+//   m_minElevation = j["m_minElevation"];
+//   m_maxElevation = j["m_maxElevation"];
+//   m_dtEphem = j["m_dtEphem"];
+//   m_t0Ephem = j["m_t0Ephem"];
+//   m_dtQuat = j["m_dtQuat"];
+//   m_t0Quat = j["m_t0Quat"];
+//   m_numEphem = j["m_numEphem"];
+//   m_numQuaternions = j["m_numQuaternions"];
+//   m_referencePointXyz.x = j["m_referencePointXyz"][0];
+//   m_referencePointXyz.y = j["m_referencePointXyz"][1];
+//   m_referencePointXyz.z = j["m_referencePointXyz"][2];
+//   m_gsd = j["m_gsd"];
+//   m_flyingHeight = j["m_flyingHeight"];
+//   m_halfSwath = j["m_halfSwath"];
+//   m_halfTime = j["m_halfTime"];
+//   m_imageFlipFlag = j["m_imageFlipFlag"];
+//   // Vector = is overloaded so explicit get with type required.
+//   m_ephemPts = j["m_ephemPts"].get<std::vector<double>>();
+//   m_ephemRates = j["m_ephemRates"].get<std::vector<double>>();
+//   m_quaternions = j["m_quaternions"].get<std::vector<double>>();
+//   m_parameterVals = j["m_parameterVals"].get<std::vector<double>>();
+//   m_covariance = j["m_covariance"].get<std::vector<double>>();
+//
+//   for (int i = 0; i < num_params; i++) {
+//     for (int k = 0; k < NUM_PARAM_TYPES; k++) {
+//       if (j["m_parameterType"][i] == PARAM_STRING_ALL[k]) {
+//         m_parameterType[i] = PARAM_CHAR_ALL[k];
+//         break;
+//     }
+//    }
+//   }
+//
+// }
 
 //---------------------------------------------------------------------------
 //  Monoscopic Mensuration
@@ -1082,7 +1460,7 @@ std::string UsgsAstroLsSensorModel::getModelState() const
 //***************************************************************************
 std::pair<double, double> UsgsAstroLsSensorModel::getValidHeightRange() const
 {
-   return std::pair<double, double>(_data.m_MinElevation, _data.m_MaxElevation);
+   return std::pair<double, double>(m_minElevation, m_maxElevation);
 }
 
 //***************************************************************************
@@ -1093,7 +1471,7 @@ UsgsAstroLsSensorModel::getValidImageRange() const
 {
    return std::pair<csm::ImageCoord, csm::ImageCoord>(
       csm::ImageCoord(0.0, 0.0),
-      csm::ImageCoord(_data.m_TotalLines, _data.m_TotalSamples));
+      csm::ImageCoord(m_totalLines, m_totalSamples));
 }
 
 //***************************************************************************
@@ -1202,7 +1580,7 @@ std::vector<double> UsgsAstroLsSensorModel::getUnmodeledCrossCovariance(
 //***************************************************************************
 std::string UsgsAstroLsSensorModel::getCollectionIdentifier() const
 {
-   return _data.m_CollectionIdentifier;
+   return m_collectionIdentifier;
 }
 
 //***************************************************************************
@@ -1261,25 +1639,17 @@ csm::Version UsgsAstroLsSensorModel::getVersion() const
    return csm::Version(1, 0, 0);
 }
 
-//***************************************************************************
-// UsgsAstroLsSensorModel::replaceModelState
-//***************************************************************************
-void UsgsAstroLsSensorModel::replaceModelState(const std::string& argState)
-{
-   set(argState);
-}
-
 
 csm::Ellipsoid UsgsAstroLsSensorModel::getEllipsoid() const
 {
-   return csm::Ellipsoid(_data.m_SemiMajorAxis, _data.m_SemiMinorAxis);
+   return csm::Ellipsoid(m_semiMajorAxis, m_semiMinorAxis);
 }
 
 void UsgsAstroLsSensorModel::setEllipsoid(
    const csm::Ellipsoid &ellipsoid)
 {
-   _data.m_SemiMajorAxis = ellipsoid.getSemiMajorRadius();
-   _data.m_SemiMinorAxis = ellipsoid.getSemiMinorRadius();
+   m_semiMajorAxis = ellipsoid.getSemiMajorRadius();
+   m_semiMinorAxis = ellipsoid.getSemiMinorRadius();
 }
 
 
@@ -1288,7 +1658,7 @@ double UsgsAstroLsSensorModel::getValue(
    int   index,
    const std::vector<double> &adjustments) const
 {
-   return _data.m_ParameterVals[index] + adjustments[index];
+   return m_parameterVals[index] + adjustments[index];
 }
 
 //***************************************************************************
@@ -1317,22 +1687,21 @@ void UsgsAstroLsSensorModel::losToEcf(
    getAdjSensorPosVel(time, adj, xc, yc, zc, vx, vy, vz);
    // CSM image image convention: UL pixel center == (0.5, 0.5)
    // USGS image convention: UL pixel center == (1.0, 1.0)
-
-   double sampleCSMFull = sample + _data.m_OffsetSamples;
+   double sampleCSMFull = sample + m_offsetSamples;
    double sampleUSGSFull = sampleCSMFull + 0.5;
    double fractionalLine = line - floor(line) - 0.5;
 
    // Compute distorted image coordinates in mm
 
    double isisDetSample = (sampleUSGSFull - 1.0)
-      * _data.m_DetectorSampleSumming + _data.m_StartingSample;
-   double m11 = _data.m_ITransL[1];
-   double m12 = _data.m_ITransL[2];
-   double m21 = _data.m_ITransS[1];
-   double m22 = _data.m_ITransS[2];
-   double t1 = fractionalLine + _data.m_DetectorLineOffset
-               - _data.m_DetectorLineOrigin - _data.m_ITransL[0];
-   double t2 = isisDetSample - _data.m_DetectorSampleOrigin - _data.m_ITransS[0];
+      * m_detectorSampleSumming + m_startingSample;
+   double m11 = m_iTransL[1];
+   double m12 = m_iTransL[2];
+   double m21 = m_iTransS[1];
+   double m22 = m_iTransS[2];
+   double t1 = fractionalLine + m_detectorLineOffset
+               - m_detectorLineOrigin - m_iTransL[0];
+   double t2 = isisDetSample - m_detectorSampleOrigin - m_iTransS[0];
    double determinant = m11 * m22 - m12 * m21;
    double p11 = m11 / determinant;
    double p12 = -m12 / determinant;
@@ -1344,38 +1713,27 @@ void UsgsAstroLsSensorModel::losToEcf(
    // Remove lens distortion
    double isisFocalPlaneX = isisNatFocalPlaneX;
    double isisFocalPlaneY = isisNatFocalPlaneY;
-   switch (_data.m_IkCode)
+  if (m_opticalDistCoef[0] != 0.0 ||
+     m_opticalDistCoef[1] != 0.0 ||
+     m_opticalDistCoef[2] != 0.0)
    {
-   case -85610:
-   case -85600:
-      isisFocalPlaneY = isisNatFocalPlaneY / (1.0 + _data.m_OpticalDistCoef[0]
-         * isisNatFocalPlaneY * isisNatFocalPlaneY);
-      break;
-
-   default:
-      if (_data.m_OpticalDistCoef[0] != 0.0 ||
-         _data.m_OpticalDistCoef[1] != 0.0 ||
-         _data.m_OpticalDistCoef[2] != 0.0)
+      double rr = isisNatFocalPlaneX * isisNatFocalPlaneX
+         + isisNatFocalPlaneY * isisNatFocalPlaneY;
+      if (rr > 1.0E-6)
       {
-         double rr = isisNatFocalPlaneX * isisNatFocalPlaneX
-            + isisNatFocalPlaneY * isisNatFocalPlaneY;
-         if (rr > 1.0E-6)
-         {
-            double dr = _data.m_OpticalDistCoef[0] + (rr * (_data.m_OpticalDistCoef[1]
-               + rr * _data.m_OpticalDistCoef[2]));
-            isisFocalPlaneX = isisNatFocalPlaneX * (1.0 - dr);
-            isisFocalPlaneY = isisNatFocalPlaneY * (1.0 - dr);
-         }
+         double dr = m_opticalDistCoef[0] + (rr * (m_opticalDistCoef[1]
+            + rr * m_opticalDistCoef[2]));
+         isisFocalPlaneX = isisNatFocalPlaneX * (1.0 - dr);
+         isisFocalPlaneY = isisNatFocalPlaneY * (1.0 - dr);
       }
-      break;
    }
 
    // Define imaging ray in image space
 
    double losIsis[3];
-   losIsis[0] = -isisFocalPlaneX * _data.m_IsisZDirection;
-   losIsis[1] = -isisFocalPlaneY * _data.m_IsisZDirection;
-   losIsis[2] = -_data.m_Focal * (1.0 - getValue(15, adj) / _data.m_HalfSwath);
+   losIsis[0] = -isisFocalPlaneX * m_isisZDirection;
+   losIsis[1] = -isisFocalPlaneY * m_isisZDirection;
+   losIsis[2] = -m_focal * (1.0 - getValue(15, adj) / m_halfSwath);
    double isisMag = sqrt(losIsis[0] * losIsis[0]
       + losIsis[1] * losIsis[1]
       + losIsis[2] * losIsis[2]);
@@ -1387,30 +1745,30 @@ void UsgsAstroLsSensorModel::losToEcf(
 
    double losApl[3];
    losApl[0] =
-      _data.m_MountingMatrix[0] * losIsis[0]
-      + _data.m_MountingMatrix[1] * losIsis[1]
-      + _data.m_MountingMatrix[2] * losIsis[2];
+      m_mountingMatrix[0] * losIsis[0]
+      + m_mountingMatrix[1] * losIsis[1]
+      + m_mountingMatrix[2] * losIsis[2];
    losApl[1] =
-      _data.m_MountingMatrix[3] * losIsis[0]
-      + _data.m_MountingMatrix[4] * losIsis[1]
-      + _data.m_MountingMatrix[5] * losIsis[2];
+      m_mountingMatrix[3] * losIsis[0]
+      + m_mountingMatrix[4] * losIsis[1]
+      + m_mountingMatrix[5] * losIsis[2];
    losApl[2] =
-      _data.m_MountingMatrix[6] * losIsis[0]
-      + _data.m_MountingMatrix[7] * losIsis[1]
-      + _data.m_MountingMatrix[8] * losIsis[2];
+      m_mountingMatrix[6] * losIsis[0]
+      + m_mountingMatrix[7] * losIsis[1]
+      + m_mountingMatrix[8] * losIsis[2];
 
    // Apply attitude correction
 
-   double aTime = time - _data.m_T0Quat;
+   double aTime = time - m_t0Quat;
    double euler[3];
-   double nTime = aTime / _data.m_HalfTime;
+   double nTime = aTime / m_halfTime;
    double nTime2 = nTime * nTime;
    euler[0] =
-      (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / _data.m_FlyingHeight;
+      (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / m_flyingHeight;
    euler[1] =
-      (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / _data.m_FlyingHeight;
+      (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / m_flyingHeight;
    euler[2] =
-      (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / _data.m_HalfSwath;
+      (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / m_halfSwath;
    double cos_a = cos(euler[0]);
    double sin_a = sin(euler[0]);
    double cos_b = cos(euler[1]);
@@ -1427,6 +1785,7 @@ void UsgsAstroLsSensorModel::losToEcf(
    plFromApl[6] = -sin_b;
    plFromApl[7] = sin_a * cos_b;
    plFromApl[8] = cos_a * cos_b;
+
    double losPl[3];
    losPl[0] = plFromApl[0] * losApl[0] + plFromApl[1] * losApl[1]
       + plFromApl[2] * losApl[2];
@@ -1438,14 +1797,14 @@ void UsgsAstroLsSensorModel::losToEcf(
    // Apply rotation matrix from sensor quaternions
 
    int nOrder = 8;
-   if (_data.m_PlatformFlag == 0)
+   if (m_platformFlag == 0)
       nOrder = 4;
    int nOrderQuat = nOrder;
-   if (_data.m_NumQuaternions < 6 && nOrder == 8)
+   if (m_numQuaternions < 6 && nOrder == 8)
       nOrderQuat = 4;
    double q[4];
    lagrangeInterp(
-      _data.m_NumQuaternions, &_data.m_Quaternions[0], _data.m_T0Quat, _data.m_DtQuat,
+      m_numQuaternions, &m_quaternions[0], m_t0Quat, m_dtQuat,
       time, 4, nOrderQuat, q);
    double norm = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
    q[0] /= norm;
@@ -1462,6 +1821,8 @@ void UsgsAstroLsSensorModel::losToEcf(
    ecfFromPl[6] = 2 * (q[0] * q[2] - q[1] * q[3]);
    ecfFromPl[7] = 2 * (q[1] * q[2] + q[0] * q[3]);
    ecfFromPl[8] = -q[0] * q[0] - q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
+
+
    xl = ecfFromPl[0] * losPl[0] + ecfFromPl[1] * losPl[1]
       + ecfFromPl[2] * losPl[2];
    yl = ecfFromPl[3] * losPl[0] + ecfFromPl[4] * losPl[1]
@@ -1667,7 +2028,7 @@ void UsgsAstroLsSensorModel::computeElevation(
    // Compute elevation given xyz
    // Requires semi-major-axis and eccentricity-square
    const int MKTR = 10;
-   double ecc_sqr = 1.0 - _data.m_SemiMinorAxis * _data.m_SemiMinorAxis / _data.m_SemiMajorAxis / _data.m_SemiMajorAxis;
+   double ecc_sqr = 1.0 - m_semiMinorAxis * m_semiMinorAxis / m_semiMajorAxis / m_semiMajorAxis;
    double ep2 = 1.0 - ecc_sqr;
    double d2 = x * x + y * y;
    double d = sqrt(d2);
@@ -1684,7 +2045,7 @@ void UsgsAstroLsSensorModel::computeElevation(
       {
          hPrev = h;
          tt = tanPhi * tanPhi;
-         r = _data.m_SemiMajorAxis / sqrt(1.0 + ep2 * tt);
+         r = m_semiMajorAxis / sqrt(1.0 + ep2 * tt);
          zz = z + r * ecc_sqr * tanPhi;
          n = r * sqrt(1.0 + tt);
          h = sqrt(d2 + zz * zz) - n;
@@ -1702,7 +2063,7 @@ void UsgsAstroLsSensorModel::computeElevation(
       {
          hPrev = h;
          cc = cotPhi * cotPhi;
-         r = _data.m_SemiMajorAxis / sqrt(ep2 + cc);
+         r = m_semiMajorAxis / sqrt(ep2 + cc);
          dd = d - r * ecc_sqr * cotPhi;
          nn = r * sqrt(1.0 + cc) * ep2;
          h = sqrt(dd * dd + z * z) - nn;
@@ -1739,8 +2100,8 @@ void UsgsAstroLsSensorModel::losEllipsoidIntersect(
    const int MKTR = 10;
 
    double ap, bp, k;
-   ap = _data.m_SemiMajorAxis + height;
-   bp = _data.m_SemiMinorAxis + height;
+   ap = m_semiMajorAxis + height;
+   bp = m_semiMinorAxis + height;
    k = ap * ap / (bp * bp);
 
    // Solve quadratic equation for scale factor
@@ -1889,7 +2250,7 @@ void UsgsAstroLsSensorModel::imageToPlane(
 
    losToEcf(line, sample, adj, xc, yc, zc, vx, vy, vz, xl, yl, zl);
 
-   if (_data.m_AberrFlag == 1)
+   if (m_aberrFlag == 1)
    {
       lightAberrationCorr(vx, vy, vz, xl, yl, zl, dxl, dyl, dzl);
       xl += dxl;
@@ -1915,13 +2276,13 @@ void UsgsAstroLsSensorModel::getAdjSensorPosVel(
 {
    // Sensor position and velocity (4th or 8th order Lagrange).
    int nOrder = 8;
-   if (_data.m_PlatformFlag == 0)
+   if (m_platformFlag == 0)
       nOrder = 4;
    double sensPosNom[3];
-   lagrangeInterp(_data.m_NumEphem, &_data.m_EphemPts[0], _data.m_T0Ephem, _data.m_DtEphem,
+   lagrangeInterp(m_numEphem, &m_ephemPts[0], m_t0Ephem, m_dtEphem,
       time, 3, nOrder, sensPosNom);
    double sensVelNom[3];
-   lagrangeInterp(_data.m_NumEphem, &_data.m_EphemRates[0], _data.m_T0Ephem, _data.m_DtEphem,
+   lagrangeInterp(m_numEphem, &m_ephemRates[0], m_t0Ephem, m_dtEphem,
       time, 3, nOrder, sensVelNom);
    // Compute rotation matrix from ICR to ECF
 
@@ -1960,13 +2321,12 @@ void UsgsAstroLsSensorModel::getAdjSensorPosVel(
    ecfFromIcr[6] = inTrackUnitVec[2];
    ecfFromIcr[7] = crossTrackUnitVec[2];
    ecfFromIcr[8] = radialUnitVec[2];
-
    // Apply position and velocity corrections
 
-   double aTime = time - _data.m_T0Ephem;
-   double dvi = getValue(3, adj) / _data.m_HalfTime;
-   double dvc = getValue(4, adj) / _data.m_HalfTime;
-   double dvr = getValue(5, adj) / _data.m_HalfTime;
+   double aTime = time - m_t0Ephem;
+   double dvi = getValue(3, adj) / m_halfTime;
+   double dvc = getValue(4, adj) / m_halfTime;
+   double dvr = getValue(5, adj) / m_halfTime;
    vx = sensVelNom[0]
       + ecfFromIcr[0] * dvi + ecfFromIcr[1] * dvc + ecfFromIcr[2] * dvr;
    vy = sensVelNom[1]
@@ -2004,14 +2364,14 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel(
 
    // Rotate the look vector into the camera reference frame
    int nOrder = 8;
-   if (_data.m_PlatformFlag == 0)
+   if (m_platformFlag == 0)
       nOrder = 4;
    int nOrderQuat = nOrder;
-   if (_data.m_NumQuaternions < 6 && nOrder == 8)
+   if (m_numQuaternions < 6 && nOrder == 8)
       nOrderQuat = 4;
    double q[4];
    lagrangeInterp(
-      _data.m_NumQuaternions, &_data.m_Quaternions[0], _data.m_T0Quat, _data.m_DtQuat,
+      m_numQuaternions, &m_quaternions[0], m_t0Quat, m_dtQuat,
       time, 4, nOrderQuat, q);
    double norm = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
    // Divide by the negative norm for 0 through 2 to invert the quaternion
@@ -2040,16 +2400,16 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel(
                       + bodyToCamera[8] * bodyLookZ;
 
    // Invert the attitude correction
-   double aTime = time - _data.m_T0Quat;
+   double aTime = time - m_t0Quat;
    double euler[3];
-   double nTime = aTime / _data.m_HalfTime;
+   double nTime = aTime / m_halfTime;
    double nTime2 = nTime * nTime;
    euler[0] =
-      (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / _data.m_FlyingHeight;
+      (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / m_flyingHeight;
    euler[1] =
-      (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / _data.m_FlyingHeight;
+      (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / m_flyingHeight;
    euler[2] =
-      (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / _data.m_HalfSwath;
+      (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / m_halfSwath;
    double cos_a = cos(euler[0]);
    double sin_a = sin(euler[0]);
    double cos_b = cos(euler[1]);
@@ -2077,18 +2437,18 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel(
                         + attCorr[8] * cameraLookZ;
 
    // Invert the boresight correction
-   double correctedLookX = _data.m_MountingMatrix[0] * adjustedLookX
-                         + _data.m_MountingMatrix[3] * adjustedLookY
-                         + _data.m_MountingMatrix[6] * adjustedLookZ;
-   double correctedLookY = _data.m_MountingMatrix[1] * adjustedLookX
-                         + _data.m_MountingMatrix[4] * adjustedLookY
-                         + _data.m_MountingMatrix[7] * adjustedLookZ;
-   double correctedLookZ = _data.m_MountingMatrix[2] * adjustedLookX
-                         + _data.m_MountingMatrix[5] * adjustedLookY
-                         + _data.m_MountingMatrix[8] * adjustedLookZ;
+   double correctedLookX = m_mountingMatrix[0] * adjustedLookX
+                         + m_mountingMatrix[3] * adjustedLookY
+                         + m_mountingMatrix[6] * adjustedLookZ;
+   double correctedLookY = m_mountingMatrix[1] * adjustedLookX
+                         + m_mountingMatrix[4] * adjustedLookY
+                         + m_mountingMatrix[7] * adjustedLookZ;
+   double correctedLookZ = m_mountingMatrix[2] * adjustedLookX
+                         + m_mountingMatrix[5] * adjustedLookY
+                         + m_mountingMatrix[8] * adjustedLookZ;
 
    // Convert to focal plane coordinate
-   double lookScale = _data.m_Focal / correctedLookZ;
+   double lookScale = m_focal / correctedLookZ;
    double focalX = correctedLookX * lookScale;
    double focalY = correctedLookY * lookScale;
 
@@ -2098,18 +2458,18 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel(
    // sometimes only well behaved close to the CCD.
 
    // Convert to detector line and sample
-   double detectorLine = _data.m_ITransL[0]
-                       + _data.m_ITransL[1] * focalX
-                       + _data.m_ITransL[2] * focalY;
-   double detectorSample = _data.m_ITransS[0]
-                         + _data.m_ITransS[1] * focalX
-                         + _data.m_ITransS[2] * focalY;
+   double detectorLine = m_iTransL[0]
+                       + m_iTransL[1] * focalX
+                       + m_iTransL[2] * focalY;
+   double detectorSample = m_iTransS[0]
+                         + m_iTransS[1] * focalX
+                         + m_iTransS[2] * focalY;
 
    // Convert to image sample line
-   double line = detectorLine + _data.m_DetectorLineOrigin - _data.m_DetectorLineOffset
-               - _data.m_OffsetLines + 0.5;
-   double sample = (detectorSample + _data.m_DetectorSampleOrigin - _data.m_StartingSample)
-                 / _data.m_DetectorSampleSumming - _data.m_OffsetSamples + 0.5;
+   double line = detectorLine + m_detectorLineOrigin - m_detectorLineOffset
+               - m_offsetLines + 0.5;
+   double sample = (detectorSample + m_detectorSampleOrigin - m_startingSample)
+                 / m_detectorSampleSumming - m_offsetSamples + 0.5;
    return csm::ImageCoord(line, sample);
 }
 
@@ -2128,8 +2488,8 @@ void UsgsAstroLsSensorModel::computeLinearApproximation(
 
       // Since this is valid only over image,
       // don't let result go beyond the image border.
-      double numRows = _data.m_TotalLines;
-      double numCols = _data.m_TotalSamples;
+      double numRows = m_totalLines;
+      double numCols = m_totalSamples;
       if (ip.line < 0.0)     ip.line = 0.0;
       if (ip.line > numRows) ip.line = numRows;
 
@@ -2138,8 +2498,8 @@ void UsgsAstroLsSensorModel::computeLinearApproximation(
    }
    else
    {
-      ip.line = _data.m_TotalLines / 2.0;
-      ip.samp = _data.m_TotalSamples / 2.0;
+      ip.line = m_totalLines / 2.0;
+      ip.samp = m_totalSamples / 2.0;
    }
 }
 
@@ -2164,8 +2524,8 @@ void UsgsAstroLsSensorModel::setLinearApproximation()
    }
 
 
-   double numRows = _data.m_TotalLines;
-   double numCols = _data.m_TotalSamples;
+   double numRows = m_totalLines;
+   double numCols = m_totalSamples;
 
    csm::ImageCoord imagePt;
    csm::EcefCoord  gp[8];
@@ -2279,3 +2639,136 @@ double UsgsAstroLsSensorModel::determinant3x3(double mat[9]) const
       mat[1] * (mat[3] * mat[8] - mat[6] * mat[5]) +
       mat[2] * (mat[3] * mat[7] - mat[6] * mat[4]);
 }
+
+
+
+
+std::string UsgsAstroLsSensorModel::constructStateFromIsd(const std::string imageSupportData, csm::WarningList *warnings) const
+{
+   // Instantiate UsgsAstroLineScanner sensor model
+   json isd = json::parse(imageSupportData);
+   json state;
+
+   int num_params = NUM_PARAMETERS;
+
+   state["m_imageIdentifier"] = "UNKNOWN";
+   state["m_sensorType"] = "LINE_SCAN";
+   state["m_totalLines"] = isd.at("image_lines");
+   state["m_totalSamples"] = isd.at("image_samples");
+   state["m_offsetLines"] = 0.0;
+   state["m_offsetSamples"] = 0.0;
+   state["m_platformFlag"] = 1;
+   state["m_aberrFlag"] = 0;
+   state["m_atmRefFlag"] = 0;
+   state["m_centerEphemerisTime"] = isd.at("center_ephemeris_time");
+   state["m_startingEphemerisTime"] = isd.at("starting_ephemeris_time");
+
+   for (auto& scanRate : isd.at("line_scan_rate")) {
+     state["m_intTimeLines"].push_back(scanRate[0]);
+     state["m_intTimeStartTimes"].push_back(scanRate[1]);
+     state["m_intTimes"].push_back(scanRate[2]);
+   }
+
+   state["m_detectorSampleSumming"] = isd.at("detector_sample_summing");
+   state["m_startingSample"] = isd.at("detector_line_summing");
+   state["m_ikCode"] = 0;
+   state["m_focal"] = isd.at("focal_length_model").at("focal_length");
+   state["m_isisZDirection"] = 1;
+   state["m_opticalDistCoef"] = isd.at("optical_distortion").at("radial").at("coefficients");
+   state["m_iTransS"] = isd.at("focal2pixel_samples");
+   state["m_iTransL"] = isd.at("focal2pixel_lines");
+
+   state["m_detectorSampleOrigin"] = isd.at("detector_center").at("sample");
+   state["m_detectorLineOrigin"] = isd.at("detector_center").at("line");
+   state["m_detectorLineOffset"] = 0;
+
+   double cos_a = cos(0);
+   double sin_a = sin(0);
+   double cos_b = cos(0);
+   double sin_b = sin(0);
+   double cos_c = cos(0);
+   double sin_c = sin(0);
+
+   state["m_mountingMatrix"] = json::array();
+   state["m_mountingMatrix"][0] = cos_b * cos_c;
+   state["m_mountingMatrix"][1] = -cos_a * sin_c + sin_a * sin_b * cos_c;
+   state["m_mountingMatrix"][2] = sin_a * sin_c + cos_a * sin_b * cos_c;
+   state["m_mountingMatrix"][3] = cos_b * sin_c;
+   state["m_mountingMatrix"][4] = cos_a * cos_c + sin_a * sin_b * sin_c;
+   state["m_mountingMatrix"][5] = -sin_a * cos_c + cos_a * sin_b * sin_c;
+   state["m_mountingMatrix"][6] = -sin_b;
+   state["m_mountingMatrix"][7] = sin_a * cos_b;
+   state["m_mountingMatrix"][8] = cos_a * cos_b;
+
+   state["m_dtEphem"] = isd.at("dt_ephemeris");
+   state["m_t0Ephem"] = isd.at("t0_ephemeris");
+   state["m_dtQuat"] =  isd.at("dt_quaternion");
+   state["m_t0Quat"] =  isd.at("t0_quaternion");
+
+   state["m_numEphem"] = isd.at("sensor_position").at("positions").size();
+   state["m_numQuaternions"] = isd.at("sensor_orientation").at("quaternions").size();
+
+   for (auto& location : isd.at("sensor_position").at("positions")) {
+     state["m_ephemPts"].push_back(location[0]);
+     state["m_ephemPts"].push_back(location[1]);
+     state["m_ephemPts"].push_back(location[2]);
+   }
+
+   for (auto& velocity : isd.at("sensor_position").at("velocities")) {
+     state["m_ephemRates"].push_back(velocity[0]);
+     state["m_ephemRates"].push_back(velocity[1]);
+     state["m_ephemRates"].push_back(velocity[2]);
+   }
+
+   for (auto& quaternion : isd.at("sensor_orientation").at("quaternions")) {
+     state["m_quaternions"].push_back(quaternion[0]);
+     state["m_quaternions"].push_back(quaternion[1]);
+     state["m_quaternions"].push_back(quaternion[2]);
+     state["m_quaternions"].push_back(quaternion[3]);
+    }
+
+
+   state["m_parameterVals"] = std::vector<double>(NUM_PARAMETERS, 0.0);
+   state["m_parameterVals"][15] = state["m_focal"].get<double>();
+
+   // Set the ellipsoid
+   state["m_semiMajorAxis"] = isd.at("radii").at("semimajor");
+   state["m_semiMinorAxis"] = isd.at("radii").at("semiminor");
+
+   // Now finish setting the state data from the ISD read in
+
+   // set identifiers
+   state["m_referenceDateAndTime"] = "UNKNOWN";
+   state["m_platformIdentifier"]   = isd.at("name_platform");
+   state["m_sensorIdentifier"]     = isd.at("name_sensor");
+   state["m_trajectoryIdentifier"] = "UNKNOWN";
+   state["m_collectionIdentifier"] = "UNKNOWN";
+
+   // Ground elevations
+   state["m_refElevation"] = 0.0;
+   state["m_minElevation"] = isd.at("reference_height").at("minheight");
+   state["m_maxElevation"] = isd.at("reference_height").at("maxheight");
+
+   // Zero ateter values
+   for (int i = 0; i < NUM_PARAMETERS; i++) {
+      state["m_ateterType"][i] = csm::param::REAL;
+   }
+
+   // Default to identity covariance
+   state["m_covariance"] =
+         std::vector<double>(NUM_PARAMETERS * NUM_PARAMETERS, 0.0);
+   for (int i = 0; i < NUM_PARAMETERS; i++) {
+     state["m_covariance"][i * NUM_PARAMETERS + i] = 1.0;
+   }
+
+   // Zero computed state values
+   state["m_referencePointXyz"] = std::vector<double>(3, 0.0);
+   state["m_gsd"] = 1.0;
+   state["m_flyingHeight"] = 1000.0;
+   state["m_halfSwath"] = 1000.0;
+   state["m_halfTime"] = 10.0;
+   state["m_imageFlipFlag"] = 0;
+   // The state data will still be updated when a sensor model is created since
+   // some state data is notin the ISD and requires a SM to compute them.
+   return state.dump();
+}
diff --git a/src/UsgsAstroLsStateData.cpp b/src/UsgsAstroLsStateData.cpp
deleted file mode 100644
index 9b1fba8..0000000
--- a/src/UsgsAstroLsStateData.cpp
+++ /dev/null
@@ -1,538 +0,0 @@
-//----------------------------------------------------------------------------
-//
-//                                UNCLASSIFIED
-//
-// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc.
-//                            ALL RIGHTS RESERVED
-// Use of this software product is governed by the terms of a license
-// agreement. The license agreement is found in the installation directory.
-//
-//             For support, please visit http://www.baesystems.com/gxp
-//
-//    FILENAME:          UsgsAstroLsStateData.h
-//
-//    DESCRIPTION:
-//
-//    Holds state data used to build the Astro Line Scanner sensor model.
-//
-//    LIMITATIONS:       None
-//
-//    SOFTWARE HISTORY:
-//
-//    Date          Author       Comment
-//    -----------   ----------   -------
-//    13-OCT-2017   BAE Systems  Initial Release
-//
-//
-//#############################################################################
-
-#define USGSASTROLINESCANNER_LIBRARY
-
-
-#include <UsgsAstroLsStateData.h>
-#include <UsgsAstroLsPlugin.h>
-#include <sstream>
-#include <Error.h>
-#include <json.hpp>
-using json = nlohmann::json;
-
-const std::string  UsgsAstroLsStateData::SENSOR_MODEL_NAME
-         = "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL";
-const int     UsgsAstroLsStateData::NUM_PARAMETERS = 16;
-const std::string  UsgsAstroLsStateData::PARAMETER_NAME[] =
-{
-   "IT Pos. Bias   ",   // 0
-   "CT Pos. Bias   ",   // 1
-   "Rad Pos. Bias  ",   // 2
-   "IT Vel. Bias   ",   // 3
-   "CT Vel. Bias   ",   // 4
-   "Rad Vel. Bias  ",   // 5
-   "Omega Bias     ",   // 6
-   "Phi Bias       ",   // 7
-   "Kappa Bias     ",   // 8
-   "Omega Rate     ",   // 9
-   "Phi Rate       ",   // 10
-   "Kappa Rate     ",   // 11
-   "Omega Accl     ",   // 12
-   "Phi Accl       ",   // 13
-   "Kappa Accl     ",   // 14
-   "Focal Bias     "    // 15
-};
-
-
-const std::string  UsgsAstroLsStateData::STATE_KEYWORD[] =
-{
-   "STA_SENSOR_MODEL_NAME",
-   "STA_IMAGE_IDENTIFIER",
-   "STA_SENSOR_TYPE",
-   "STA_TOTAL_LINES",
-   "STA_TOTAL_SAMPLES",
-   "STA_OFFSET_LINES",
-   "STA_OFFSET_SAMPLES",
-   "STA_PLATFORM_FLAG",
-   "STA_ABERR_FLAG",
-   "STA_ATMREF_FLAG",
-   "STA_INT_TIME_LINES",
-   "STA_INT_TIME_START_TIMES",
-   "STA_INT_TIMES",
-   "STA_STARTING_EPHEMERIS_TIME",
-   "STA_CENTER_EPHEMERIS_TIME",
-   "STA_DETECTOR_SAMPLE_SUMMING",
-   "STA_STARTING_SAMPLE",
-   "STA_IK_CODE",
-   "STA_FOCAL",
-   "STA_ISIS_Z_DIRECTION",
-   "STA_OPTICAL_DIST_COEF",
-   "STA_I_TRANS_S",
-   "STA_I_TRANS_L",
-   "STA_DETECTOR_SAMPLE_ORIGIN",
-   "STA_DETECTOR_LINE_ORIGIN",
-   "STA_DETECTOR_LINE_OFFSET",
-   "STA_MOUNTING_MATRIX",
-   "STA_SEMI_MAJOR_AXIS",
-   "STA_SEMI_MINOR_AXIS",
-   "STA_REFERENCE_DATE_AND_TIME",
-   "STA_PLATFORM_IDENTIFIER",
-   "STA_SENSOR_IDENTIFIER",
-   "STA_TRAJECTORY_IDENTIFIER",
-   "STA_COLLECTION_IDENTIFIER",
-   "STA_REF_ELEVATION",
-   "STA_MIN_ELEVATION",
-   "STA_MAX_ELEVATION",
-   "STA_DT_EPHEM",
-   "STA_T0_EPHEM",
-   "STA_DT_QUAT",
-   "STA_T0_QUAT",
-   "STA_NUM_EPHEM",
-   "STA_NUM_QUATERNIONS",
-   "STA_EPHEM_PTS",
-   "STA_EPHEM_RATES",
-   "STA_QUATERNIONS",
-   "STA_PARAMETER_VALS",
-   "STA_PARAMETER_TYPE",
-   "STA_REFERENCE_POINT_XYZ",
-   "STA_GSD",
-   "STA_FLYING_HEIGHT",
-   "STA_HALF_SWATH",
-   "STA_HALF_TIME",
-   "STA_COVARIANCE",
-   "STA_IMAGE_FLIP_FLAG"
-};
-
-const int UsgsAstroLsStateData::NUM_PARAM_TYPES = 4;
-const std::string UsgsAstroLsStateData::PARAM_STRING_ALL[] =
-{
-   "NONE",
-   "FICTITIOUS",
-   "REAL",
-   "FIXED"
-};
-const csm::param::Type
-      UsgsAstroLsStateData::PARAM_CHAR_ALL[] =
-{
-   csm::param::NONE,
-   csm::param::FICTITIOUS,
-   csm::param::REAL,
-   csm::param::FIXED
-};
-
-
-std::string UsgsAstroLsStateData::toJson() const {
-    json state = {
-        {STATE_KEYWORD[STA_SENSOR_MODEL_NAME], SENSOR_MODEL_NAME},
-        {STATE_KEYWORD[STA_IMAGE_IDENTIFIER], m_ImageIdentifier},
-        {STATE_KEYWORD[STA_SENSOR_TYPE], m_SensorType},
-        {STATE_KEYWORD[STA_TOTAL_LINES], m_TotalLines},
-        {STATE_KEYWORD[STA_TOTAL_SAMPLES], m_TotalSamples},
-        {STATE_KEYWORD[STA_OFFSET_LINES], m_OffsetLines},
-        {STATE_KEYWORD[STA_OFFSET_SAMPLES], m_OffsetSamples},
-        {STATE_KEYWORD[STA_PLATFORM_FLAG], m_PlatformFlag},
-        {STATE_KEYWORD[STA_ABERR_FLAG], m_AberrFlag},
-        {STATE_KEYWORD[STA_ATMREF_FLAG], m_AtmRefFlag},
-        {STATE_KEYWORD[STA_INT_TIME_LINES], m_IntTimeLines},
-        {STATE_KEYWORD[STA_INT_TIME_START_TIMES], m_IntTimeStartTimes},
-        {STATE_KEYWORD[STA_INT_TIMES], m_IntTimes},
-        {STATE_KEYWORD[STA_STARTING_EPHEMERIS_TIME], m_StartingEphemerisTime},
-        {STATE_KEYWORD[STA_CENTER_EPHEMERIS_TIME], m_CenterEphemerisTime},
-        {STATE_KEYWORD[STA_DETECTOR_SAMPLE_SUMMING], m_DetectorSampleSumming},
-        {STATE_KEYWORD[STA_STARTING_SAMPLE], m_StartingSample},
-        {STATE_KEYWORD[STA_IK_CODE], m_IkCode},
-        {STATE_KEYWORD[STA_FOCAL], m_Focal},
-        {STATE_KEYWORD[STA_ISIS_Z_DIRECTION], m_IsisZDirection},
-        {STATE_KEYWORD[STA_IMAGE_FLIP_FLAG] , m_ImageFlipFlag},
-        {STATE_KEYWORD[STA_REFERENCE_POINT_XYZ],
-          {m_ReferencePointXyz.x,m_ReferencePointXyz.y, m_ReferencePointXyz.z}},
-        {STATE_KEYWORD[STA_GSD], m_Gsd},
-        {STATE_KEYWORD[STA_FLYING_HEIGHT], m_FlyingHeight},
-        {STATE_KEYWORD[STA_HALF_SWATH], m_HalfSwath},
-        {STATE_KEYWORD[STA_HALF_TIME], m_HalfTime},
-        {STATE_KEYWORD[STA_SEMI_MAJOR_AXIS], m_SemiMajorAxis},
-        {STATE_KEYWORD[STA_SEMI_MINOR_AXIS], m_SemiMinorAxis},
-        {STATE_KEYWORD[STA_REFERENCE_DATE_AND_TIME], m_ReferenceDateAndTime},
-        {STATE_KEYWORD[STA_PLATFORM_IDENTIFIER], m_PlatformIdentifier},
-        {STATE_KEYWORD[STA_SENSOR_IDENTIFIER], m_SensorIdentifier},
-        {STATE_KEYWORD[STA_TRAJECTORY_IDENTIFIER], m_TrajectoryIdentifier},
-        {STATE_KEYWORD[STA_COLLECTION_IDENTIFIER], m_CollectionIdentifier},
-        {STATE_KEYWORD[STA_REF_ELEVATION], m_RefElevation},
-        {STATE_KEYWORD[STA_MIN_ELEVATION], m_MinElevation},
-        {STATE_KEYWORD[STA_MAX_ELEVATION], m_MaxElevation},
-        {STATE_KEYWORD[STA_DT_EPHEM], m_DtEphem},
-        {STATE_KEYWORD[STA_T0_EPHEM], m_T0Ephem},
-        {STATE_KEYWORD[STA_DT_QUAT], m_DtQuat},
-        {STATE_KEYWORD[STA_T0_QUAT], m_T0Quat},
-        {STATE_KEYWORD[STA_NUM_EPHEM], m_NumEphem},
-        {STATE_KEYWORD[STA_NUM_QUATERNIONS], m_NumQuaternions},
-        {STATE_KEYWORD[STA_DETECTOR_SAMPLE_ORIGIN], m_DetectorSampleOrigin},
-        {STATE_KEYWORD[STA_DETECTOR_LINE_ORIGIN], m_DetectorLineOrigin},
-        {STATE_KEYWORD[STA_DETECTOR_LINE_OFFSET], m_DetectorLineOffset},
-        {STATE_KEYWORD[STA_OPTICAL_DIST_COEF],
-                {m_OpticalDistCoef[0], m_OpticalDistCoef[1], m_OpticalDistCoef[2]}},
-        {STATE_KEYWORD[STA_COVARIANCE], m_Covariance},
-        {STATE_KEYWORD[STA_I_TRANS_S], {m_ITransS[0], m_ITransS[1], m_ITransS[2]}},
-        {STATE_KEYWORD[STA_I_TRANS_L],{m_ITransL[0], m_ITransL[1], m_ITransL[2]}},
-        {STATE_KEYWORD[STA_MOUNTING_MATRIX],
-             {m_MountingMatrix[0], m_MountingMatrix[1], m_MountingMatrix[2],
-              m_MountingMatrix[3], m_MountingMatrix[4], m_MountingMatrix[5],
-              m_MountingMatrix[6], m_MountingMatrix[7], m_MountingMatrix[8]}},
-        {STATE_KEYWORD[STA_EPHEM_PTS], m_EphemPts},
-        {STATE_KEYWORD[STA_EPHEM_RATES], m_EphemRates},
-        {STATE_KEYWORD[STA_QUATERNIONS], m_Quaternions},
-        {STATE_KEYWORD[STA_PARAMETER_VALS], m_ParameterVals},
-        {STATE_KEYWORD[STA_PARAMETER_TYPE], m_ParameterType}
-    };
-    return state.dump();
-}
-
-std::string UsgsAstroLsStateData::toString() const
-{
-   std::stringstream state_stream(std::ios_base::out);
-   state_stream.unsetf (std::ios::floatfield);
-   state_stream.precision(14);
-   state_stream << STATE_KEYWORD[STA_SENSOR_MODEL_NAME] << " " << SENSOR_MODEL_NAME << "\n";  // 0
-   state_stream << STATE_KEYWORD[STA_IMAGE_IDENTIFIER]  << " " << m_ImageIdentifier   << "\n";  // 1
-   state_stream << STATE_KEYWORD[STA_SENSOR_TYPE]       << " " << m_SensorType        << "\n";  // 2
-   state_stream << STATE_KEYWORD[STA_TOTAL_LINES]       << " " << m_TotalLines        << "\n";  // 3
-   state_stream << STATE_KEYWORD[STA_TOTAL_SAMPLES]     << " " << m_TotalSamples      << "\n";  // 4
-   state_stream << STATE_KEYWORD[STA_OFFSET_LINES]      << " " << m_OffsetLines       << "\n";  // 7
-   state_stream << STATE_KEYWORD[STA_OFFSET_SAMPLES]    << " " << m_OffsetSamples     << "\n";  // 8
-   state_stream << STATE_KEYWORD[STA_PLATFORM_FLAG]     << " " << m_PlatformFlag      << "\n";  // 9
-   state_stream << STATE_KEYWORD[STA_ABERR_FLAG] << " " << m_AberrFlag         << "\n";  // 10
-   state_stream << STATE_KEYWORD[STA_ATMREF_FLAG]<< " " << m_AtmRefFlag        << "\n";  // 11
-   state_stream << STATE_KEYWORD[STA_INT_TIME_LINES]    << " " ;
-   for (size_t i = 0; i < m_IntTimeLines.size(); i++)
-   {
-      state_stream << m_IntTimeLines[i] << " ";
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_INT_TIME_START_TIMES] << " " ;
-   for (size_t i = 0; i < m_IntTimeStartTimes.size(); i++)
-   {
-      state_stream << m_IntTimeStartTimes[i] << " ";
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_INT_TIMES]         << " " ;
-   for (size_t i = 0; i < m_IntTimes.size(); i++)
-   {
-      state_stream << m_IntTimes[i] << " ";
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_STARTING_EPHEMERIS_TIME]  << " "
-                                           << m_StartingEphemerisTime << "\n";  // 13
-   state_stream << STATE_KEYWORD[STA_CENTER_EPHEMERIS_TIME]    << " "
-                                           << m_CenterEphemerisTime   << "\n";  // 14
-   state_stream << STATE_KEYWORD[STA_DETECTOR_SAMPLE_SUMMING]  << " "
-                                           << m_DetectorSampleSumming << "\n";  // 15
-   state_stream << STATE_KEYWORD[STA_STARTING_SAMPLE]   << " " << m_StartingSample     << "\n";  // 16
-   state_stream << STATE_KEYWORD[STA_IK_CODE]    << " " << m_IkCode             << "\n";  // 17
-   state_stream << STATE_KEYWORD[STA_FOCAL]      << " " << m_Focal              << "\n";  // 18
-   state_stream << STATE_KEYWORD[STA_ISIS_Z_DIRECTION]  << " " << m_IsisZDirection     << "\n";  // 19
-   state_stream << STATE_KEYWORD[STA_OPTICAL_DIST_COEF] << " ";
-   for (int i = 0; i < 3; i++) {
-      state_stream << m_OpticalDistCoef[i] << " " ;                      // 20
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_I_TRANS_S] << " ";
-   for (int i = 0; i < 3; i++) {
-      state_stream << m_ITransS[i] << " " ;                              // 21
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_I_TRANS_L]<< " ";
-   for (int i = 0; i < 3; i++) {
-      state_stream << m_ITransL[i] << " ";                              // 22
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_DETECTOR_SAMPLE_ORIGIN] << " "
-                                          << m_DetectorSampleOrigin << "\n";    // 23
-   state_stream << STATE_KEYWORD[STA_DETECTOR_LINE_ORIGIN] << " "
-                                          << m_DetectorLineOrigin << "\n";      // 24
-   state_stream << STATE_KEYWORD[STA_DETECTOR_LINE_OFFSET] << " "
-                                          << m_DetectorLineOffset << "\n";      // 25
-   state_stream << STATE_KEYWORD[STA_MOUNTING_MATRIX] << " ";
-   for (int i =0; i < 9; i++) {
-      state_stream << m_MountingMatrix[i] << " ";                       // 26
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_SEMI_MAJOR_AXIS] << " " << m_SemiMajorAxis  << "\n";          // 27
-   state_stream << STATE_KEYWORD[STA_SEMI_MINOR_AXIS] << " " << m_SemiMinorAxis << "\n";          // 28
-   state_stream << STATE_KEYWORD[STA_REFERENCE_DATE_AND_TIME] << " "
-                                           << m_ReferenceDateAndTime << "\n";   // 30
-   state_stream << STATE_KEYWORD[STA_PLATFORM_IDENTIFIER] << " "
-                                       << m_PlatformIdentifier << "\n";         // 31
-   state_stream << STATE_KEYWORD[STA_SENSOR_IDENTIFIER]   << " "
-                                       << m_SensorIdentifier << "\n";           // 32
-   state_stream << STATE_KEYWORD[STA_TRAJECTORY_IDENTIFIER] << " "
-                                       << m_TrajectoryIdentifier << "\n";       // 33
-   state_stream << STATE_KEYWORD[STA_COLLECTION_IDENTIFIER] << " "
-                                       << m_CollectionIdentifier << "\n";       // 33
-   state_stream << STATE_KEYWORD[STA_REF_ELEVATION]   << " " << m_RefElevation   << "\n";  // 34
-   state_stream << STATE_KEYWORD[STA_MIN_ELEVATION]   << " " << m_MinElevation   << "\n";  // 34
-   state_stream << STATE_KEYWORD[STA_MAX_ELEVATION]   << " " << m_MaxElevation   << "\n";  // 35
-   state_stream << STATE_KEYWORD[STA_DT_EPHEM] << " " <<m_DtEphem        << "\n";  // 36
-   state_stream << STATE_KEYWORD[STA_T0_EPHEM] << " " <<m_T0Ephem        << "\n";  // 37
-   state_stream << STATE_KEYWORD[STA_DT_QUAT]  << " " << m_DtQuat         << "\n";  // 38
-   state_stream << STATE_KEYWORD[STA_T0_QUAT]  << " " <<m_T0Quat         << "\n";  // 39
-   state_stream << STATE_KEYWORD[STA_NUM_EPHEM]<< " " <<m_NumEphem       << "\n";  // 40
-   state_stream << STATE_KEYWORD[STA_NUM_QUATERNIONS] << " " << m_NumQuaternions << "\n";  // 41
-   state_stream << STATE_KEYWORD[STA_EPHEM_PTS]       << " " ;
-   for (int i = 0; i < 3*m_NumEphem; i++)
-   {
-      state_stream << m_EphemPts[i] << " ";                             // 42
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_EPHEM_RATES] << " ";
-   for (int i = 0; i < 3*m_NumEphem; i++)
-   {
-      state_stream << m_EphemRates[i] << " ";                           // 43
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_QUATERNIONS] << " ";
-   for (int i = 0; i < 4*m_NumQuaternions; i++)
-   {
-      state_stream << m_Quaternions[i] << " ";                          // 44
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_PARAMETER_VALS]  << " ";
-   for (int i = 0; i < NUM_PARAMETERS; i++)
-   {
-      state_stream << m_ParameterVals[i] << " ";                     // 45
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_PARAMETER_TYPE]  << " ";
-   for (int i = 0; i < NUM_PARAMETERS; i++)
-   {
-      for (int j = 0; j < NUM_PARAM_TYPES; j++)
-      {
-         if (m_ParameterType[i] == PARAM_CHAR_ALL[j])
-         {
-            state_stream << PARAM_STRING_ALL[j] << " ";               // 46
-            break;
-         }
-      }
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_REFERENCE_POINT_XYZ]  << " ";
-   state_stream << m_ReferencePointXyz.x << " " ;                    // 47
-   state_stream << m_ReferencePointXyz.y << " " ;                    // 47
-   state_stream << m_ReferencePointXyz.z << "\n" ;                   // 47
-   state_stream << STATE_KEYWORD[STA_GSD]    << " " <<m_Gsd           << "\n";  // 48
-   state_stream << STATE_KEYWORD[STA_FLYING_HEIGHT] << " " << m_FlyingHeight  << "\n";  // 49
-   state_stream << STATE_KEYWORD[STA_HALF_SWATH]    << " " << m_HalfSwath     << "\n";  // 50
-   state_stream << STATE_KEYWORD[STA_HALF_TIME]     << " " << m_HalfTime      << "\n";  // 51
-   state_stream << STATE_KEYWORD[STA_COVARIANCE] << " ";
-   for (int i = 0; i < NUM_PARAMETERS*NUM_PARAMETERS; i++)
-   {
-      state_stream << m_Covariance[i] << " ";                    // 52
-   }
-   state_stream << "\n";
-   state_stream << STATE_KEYWORD[STA_IMAGE_FLIP_FLAG] << " " << m_ImageFlipFlag << "\n";  // 53
-//   state_stream << std::ends;
-   return state_stream.str();
-}
-
-
-void UsgsAstroLsStateData::setState(const std::string &stateString )
-{
-   reset();
-   auto j = json::parse(stateString);
-   int num_params    = NUM_PARAMETERS;
-   int num_params_sq = num_params * num_params;
-
-   m_ImageIdentifier = j["STA_IMAGE_IDENTIFIER"];
-   m_SensorType = j["STA_SENSOR_TYPE"];
-   m_TotalLines = j["STA_TOTAL_LINES"];
-   m_TotalSamples = j["STA_TOTAL_SAMPLES"];
-   m_OffsetLines = j["STA_OFFSET_LINES"];
-   m_OffsetSamples = j["STA_OFFSET_SAMPLES"];
-   m_PlatformFlag = j["STA_PLATFORM_FLAG"];
-   m_AberrFlag = j["STA_ABERR_FLAG"];
-   m_AtmRefFlag = j["STA_ATMREF_FLAG"];
-   m_IntTimeLines = j["STA_INT_TIME_LINES"].get<std::vector<double>>();
-   m_IntTimeStartTimes = j["STA_INT_TIME_START_TIMES"].get<std::vector<double>>();
-   m_IntTimes = j["STA_INT_TIMES"].get<std::vector<double>>();
-   m_StartingEphemerisTime = j["STA_STARTING_EPHEMERIS_TIME"];
-   m_CenterEphemerisTime = j["STA_CENTER_EPHEMERIS_TIME"];
-   m_DetectorSampleSumming = j["STA_DETECTOR_SAMPLE_SUMMING"];
-   m_StartingSample = j["STA_STARTING_SAMPLE"];
-   m_IkCode = j["STA_IK_CODE"];
-   m_Focal = j["STA_FOCAL"];
-   m_IsisZDirection = j["STA_ISIS_Z_DIRECTION"];
-   for (int i = 0; i < 3; i++) {
-     m_OpticalDistCoef[i] = j["STA_OPTICAL_DIST_COEF"][i];
-     m_ITransS[i] = j["STA_I_TRANS_S"][i];
-     m_ITransL[i] = j["STA_I_TRANS_L"][i];
-   }
-   m_DetectorSampleOrigin = j["STA_DETECTOR_SAMPLE_ORIGIN"];
-   m_DetectorLineOrigin = j["STA_DETECTOR_LINE_ORIGIN"];
-   m_DetectorLineOffset = j["STA_DETECTOR_LINE_OFFSET"];
-   for (int i = 0; i < 9; i++) {
-       m_MountingMatrix[i] = j["STA_MOUNTING_MATRIX"][i];
-   }
-   m_SemiMajorAxis = j["STA_SEMI_MAJOR_AXIS"];
-   m_SemiMinorAxis = j["STA_SEMI_MINOR_AXIS"];
-   m_ReferenceDateAndTime = j["STA_REFERENCE_DATE_AND_TIME"];
-   m_PlatformIdentifier = j["STA_PLATFORM_IDENTIFIER"];
-   m_SensorIdentifier = j["STA_SENSOR_IDENTIFIER"];
-   m_TrajectoryIdentifier = j["STA_TRAJECTORY_IDENTIFIER"];
-   m_CollectionIdentifier = j["STA_COLLECTION_IDENTIFIER"];
-   m_RefElevation = j["STA_REF_ELEVATION"];
-   m_MinElevation = j["STA_MIN_ELEVATION"];
-   m_MaxElevation = j["STA_MAX_ELEVATION"];
-   m_DtEphem = j["STA_DT_EPHEM"];
-   m_T0Ephem = j["STA_T0_EPHEM"];
-   m_DtQuat = j["STA_DT_QUAT"];
-   m_T0Quat = j["STA_T0_QUAT"];
-   m_NumEphem = j["STA_NUM_EPHEM"];
-   m_NumQuaternions = j["STA_NUM_QUATERNIONS"];
-   m_ReferencePointXyz.x = j["STA_REFERENCE_POINT_XYZ"][0];
-   m_ReferencePointXyz.y = j["STA_REFERENCE_POINT_XYZ"][1];
-   m_ReferencePointXyz.z = j["STA_REFERENCE_POINT_XYZ"][2];
-   m_Gsd = j["STA_GSD"];
-   m_FlyingHeight = j["STA_FLYING_HEIGHT"];
-   m_HalfSwath = j["STA_HALF_SWATH"];
-   m_HalfTime = j["STA_HALF_TIME"];
-   m_ImageFlipFlag = j["STA_IMAGE_FLIP_FLAG"];
-   // Vector = is overloaded so explicit get with type required.
-   m_EphemPts = j["STA_EPHEM_PTS"].get<std::vector<double>>();
-   m_EphemRates = j["STA_EPHEM_RATES"].get<std::vector<double>>();
-   m_Quaternions = j["STA_QUATERNIONS"].get<std::vector<double>>();
-   m_ParameterVals = j["STA_PARAMETER_VALS"].get<std::vector<double>>();
-   m_Covariance = j["STA_COVARIANCE"].get<std::vector<double>>();
-   for (int i = 0; i < num_params; i++) {
-     for (int k = 0; k < NUM_PARAM_TYPES; k++) {
-       if (j["STA_PARAMETER_TYPE"][i] == PARAM_STRING_ALL[k]) {
-         m_ParameterType[i] = PARAM_CHAR_ALL[k];
-         break;
-     }
-    }
-   }
-}
-
-std::string UsgsAstroLsStateData::getModelNameFromModelState(
-   const std::string& model_state)
-{
-   // Parse the string to JSON
-   auto j = json::parse(model_state);
-   // If model name cannot be determined, return a blank string
-   std::string model_name;
-
-   if (j.find("STA_SENSOR_MODEL_NAME") != j.end()) {
-       model_name = j["STA_SENSOR_MODEL_NAME"];
-   } else {
-       csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
-       std::string aMessage = "No 'STA_SENSOR_MODEL_NAME' key in the model state object.";
-       std::string aFunction = "UsgsAstroLsPlugin::getModelNameFromModelState";
-       csm::Error csmErr(aErrorType, aMessage, aFunction);
-       throw(csmErr);
-   }
-   if (model_name != SENSOR_MODEL_NAME){
-       csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
-       std::string aMessage = "Sensor model not supported.";
-       std::string aFunction = "UsgsAstroLsPlugin::getModelNameFromModelState()";
-       csm::Error csmErr(aErrorType, aMessage, aFunction);
-       throw(csmErr);
-   }
-   return model_name;
-}
-
-
-void UsgsAstroLsStateData::reset()
-{
-   m_ImageIdentifier = "";                    // 1
-   m_SensorType    = "USGSAstroLineScanner";  // 2
-   m_TotalLines    = 0;                       // 3
-   m_TotalSamples  = 0;                       // 4
-   m_OffsetLines   = 0.0;                     // 7
-   m_OffsetSamples = 0.0;                     // 8
-   m_PlatformFlag  = 1;                       // 9
-   m_AberrFlag     = 0;                       // 10
-   m_AtmRefFlag    = 0;                       // 11
-   m_IntTimeLines.clear();
-   m_IntTimeStartTimes.clear();
-   m_IntTimes.clear();
-   m_StartingEphemerisTime = 0.0;             // 13
-   m_CenterEphemerisTime = 0.0;               // 14
-   m_DetectorSampleSumming = 1.0;             // 15
-   m_StartingSample = 1.0;                    // 16
-   m_IkCode = -85600;                         // 17
-   m_Focal = 350.0;                           // 18
-   m_IsisZDirection = 1.0;                    // 19
-   m_OpticalDistCoef[0] = 0.0;                // 20
-   m_OpticalDistCoef[1] = 0.0;                // 20
-   m_OpticalDistCoef[2] = 0.0;                // 20
-   m_ITransS[0] = 0.0;                        // 21
-   m_ITransS[1] = 0.0;                        // 21
-   m_ITransS[2] = 150.0;                      // 21
-   m_ITransL[0] = 0.0;                        // 22
-   m_ITransL[1] = 150.0;                      // 22
-   m_ITransL[2] = 0.0;                        // 22
-   m_DetectorSampleOrigin = 2500.0;           // 23
-   m_DetectorLineOrigin = 0.0;                // 24
-   m_DetectorLineOffset = 0.0;                // 25
-   m_MountingMatrix[0] = 1.0;                 // 26
-   m_MountingMatrix[1] = 0.0;                 // 26
-   m_MountingMatrix[2] = 0.0;                 // 26
-   m_MountingMatrix[3] = 0.0;                 // 26
-   m_MountingMatrix[4] = 1.0;                 // 26
-   m_MountingMatrix[5] = 0.0;                 // 26
-   m_MountingMatrix[6] = 0.0;                 // 26
-   m_MountingMatrix[7] = 0.0;                 // 26
-   m_MountingMatrix[8] = 1.0;                 // 26
-   m_SemiMajorAxis = 3400000.0;               // 27
-   m_SemiMinorAxis = 3350000.0;               // 28
-   m_ReferenceDateAndTime = "";               // 30
-   m_PlatformIdentifier = "";                 // 31
-   m_SensorIdentifier = "";                   // 32
-   m_TrajectoryIdentifier = "";               // 33
-   m_CollectionIdentifier = "";               // 33
-   m_RefElevation = 30;                       // 34
-   m_MinElevation = -8000.0;                  // 34
-   m_MaxElevation =  8000.0;                  // 35
-   m_DtEphem = 2.0;                           // 36
-   m_T0Ephem = -70.0;                         // 37
-   m_DtQuat =  0.1;                           // 38
-   m_T0Quat = -40.0;                          // 39
-   m_NumEphem = 0;                            // 40
-   m_NumQuaternions = 0;                      // 41
-   m_EphemPts.clear();                        // 42
-   m_EphemRates.clear();                      // 43
-   m_Quaternions.clear();                     // 44
-
-   m_ParameterVals.assign(NUM_PARAMETERS,0.0);
-   m_ParameterType.assign(NUM_PARAMETERS,csm::param::REAL);
-
-   m_ReferencePointXyz.x = 0.0;             // 47
-   m_ReferencePointXyz.y = 0.0;             // 47
-   m_ReferencePointXyz.z = 0.0;             // 47
-   m_Gsd = 1.0;                             // 48
-   m_FlyingHeight = 1000.0;                 // 49
-   m_HalfSwath = 1000.0;                    // 50
-   m_HalfTime = 10.0;                       // 51
-
-   m_Covariance.assign(NUM_PARAMETERS * NUM_PARAMETERS,0.0); // 52
-   for (int i = 0; i < NUM_PARAMETERS; i++)
-   {
-      m_Covariance[i * NUM_PARAMETERS + i] = 1.0;
-   }
-   m_ImageFlipFlag = 0;                     // 53
-
-}
diff --git a/src/UsgsAstroPlugin.cpp b/src/UsgsAstroPlugin.cpp
new file mode 100644
index 0000000..fc67553
--- /dev/null
+++ b/src/UsgsAstroPlugin.cpp
@@ -0,0 +1,284 @@
+#include "UsgsAstroPlugin.h"
+
+#include "UsgsAstroFrameSensorModel.h"
+#include "UsgsAstroLsSensorModel.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <string>
+#include <fstream>
+
+#include <math.h>
+#include <csm.h>
+#include <Error.h>
+#include <Plugin.h>
+#include <Warning.h>
+#include <Version.h>
+
+#include <json.hpp>
+using json = nlohmann::json;
+
+#ifdef _WIN32
+# define DIR_DELIMITER_STR "\\"
+#else
+# define DIR_DELIMITER_STR  "/"
+#endif
+
+
+// Declaration of static variables
+const std::string UsgsAstroPlugin::_PLUGIN_NAME = "UsgsAstroPluginCSM";
+const std::string UsgsAstroPlugin::_MANUFACTURER_NAME = "UsgsAstrogeology";
+const std::string UsgsAstroPlugin::_RELEASE_DATE = "20170425";
+const int         UsgsAstroPlugin::_N_SENSOR_MODELS = 2;
+const int         UsgsAstroPlugin::_NUM_ISD_KEYWORDS = 21;
+
+const std::string UsgsAstroPlugin::_ISD_KEYWORD[] =
+{
+   "name_model",
+   "center_ephemeris_time",
+   "dt_ephemeris",
+   "focal2pixel_lines",
+   "focal2pixel_samples",
+   "focal_length_model",
+   "image_lines",
+   "image_samples",
+   "interpolation_method",
+   "number_of_ephemerides",
+   "optical_distortion",
+   "radii",
+   "reference_height",
+   "sensor_location_unit",
+   "sensor_location",
+   "sensor_orientation",
+   "sensor_velocity",
+   "detector_center",
+   "starting_detector_line",
+   "starting_detector_sample",
+   "starting_ephemeris_time",
+   "sun_position"
+};
+
+// const json UsgsAstroPlugin::MODEL_KEYWORDS = {
+//   {UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME, UsgsAstroFrameSensorModel::_STATE_KEYWORD},
+//   {UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME, UsgsAstroLsSensorModel::_STATE_KEYWORD}
+// };
+
+
+// Static Instance of itself
+const UsgsAstroPlugin UsgsAstroPlugin::m_registeredPlugin;
+
+UsgsAstroPlugin::UsgsAstroPlugin() {
+}
+
+
+UsgsAstroPlugin::~UsgsAstroPlugin() {
+}
+
+
+std::string UsgsAstroPlugin::getPluginName() const {
+  return _PLUGIN_NAME;
+}
+
+
+std::string UsgsAstroPlugin::getManufacturer() const {
+  return _MANUFACTURER_NAME;
+}
+
+
+std::string UsgsAstroPlugin::getReleaseDate() const {
+  return _RELEASE_DATE;
+}
+
+
+csm::Version UsgsAstroPlugin::getCsmVersion() const {
+  return CURRENT_CSM_VERSION;
+}
+
+
+size_t UsgsAstroPlugin::getNumModels() const {
+  return _N_SENSOR_MODELS;
+}
+
+
+std::string UsgsAstroPlugin::getModelName(size_t modelIndex) const {
+  std::vector<std::string> supportedModelNames = {
+    UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME,
+    UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME
+  };
+  return supportedModelNames[modelIndex];
+}
+
+
+std::string UsgsAstroPlugin::getModelFamily(size_t modelIndex) const {
+  return CSM_RASTER_FAMILY;
+}
+
+
+csm::Version UsgsAstroPlugin::getModelVersion(const std::string &modelName) const {
+  return csm::Version(1, 0, 0);
+}
+
+
+bool UsgsAstroPlugin::canModelBeConstructedFromState(const std::string &modelName,
+                                                const std::string &modelState,
+                                                csm::WarningList *warnings) const {
+    try {
+      csm::Model* model = constructModelFromState(modelState, warnings);
+      return (bool)model;
+    }
+    catch(...) {
+      return false;
+    }
+}
+
+
+bool UsgsAstroPlugin::canModelBeConstructedFromISD(const csm::Isd &imageSupportData,
+                                              const std::string &modelName,
+                                              csm::WarningList *warnings) const {
+  try {
+    csm::Model* model = constructModelFromISD(imageSupportData, modelName, warnings);
+    return (bool)model;
+  }
+  catch(...) {
+    return false;
+  }
+}
+
+
+// This function takes a csm::Isd which only has the image filename set. It uses this filename to
+// find a metadata json file located alongside the image file and returns a json
+// encoded string.
+std::string UsgsAstroPlugin::loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const {
+
+  // Get image location from the input csm::Isd:
+  std::string imageFilename = imageSupportDataOriginal.filename();
+  size_t lastIndex = imageFilename.find_last_of(".");
+  std::string baseName = imageFilename.substr(0, lastIndex);
+  std::string isdFilename = baseName.append(".json");
+
+  try {
+    std::ifstream isd_sidecar(isdFilename);
+    json jsonisd;
+    isd_sidecar >> jsonisd;
+    return jsonisd.dump();
+
+  } catch (...) {
+    std::string errorMessage = "Could not read metadata file associated with image: ";
+    errorMessage.append(isdFilename);
+    throw csm::Error(csm::Error::FILE_READ, errorMessage,
+                     "UsgsAstroPlugin::loadImageSupportData");
+  }
+}
+
+
+std::string UsgsAstroPlugin::getModelNameFromModelState(const std::string &modelState,
+                                                   csm::WarningList *warnings) const {
+  auto state = json::parse(modelState);
+
+  std::string name = state.value<std::string>("name_model", "");
+
+  if (name == "") {
+      csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
+      std::string aMessage = "No 'name_model' key in the model state object.";
+      std::string aFunction = "UsgsAstroPlugin::getModelNameFromModelState";
+      csm::Error csmErr(aErrorType, aMessage, aFunction);
+      throw(csmErr);
+  }
+
+  return name;
+}
+
+
+bool UsgsAstroPlugin::canISDBeConvertedToModelState(const csm::Isd &imageSupportData,
+                                               const std::string &modelName,
+                                               csm::WarningList *warnings) const {
+  try {
+       convertISDToModelState(imageSupportData, modelName, warnings);
+  }
+  catch(...) {
+      return false;
+  }
+  return true;
+}
+
+
+std::string UsgsAstroPlugin::getStateFromISD(csm::Isd imageSupportData) const {
+    std::string stringIsd = loadImageSupportData(imageSupportData);
+    json jsonIsd = json::parse(stringIsd);
+    return convertISDToModelState(imageSupportData, jsonIsd.at("modelName"));
+}
+
+
+std::string UsgsAstroPlugin::convertISDToModelState(const csm::Isd &imageSupportData,
+                                               const std::string &modelName,
+                                               csm::WarningList *warnings) const {
+
+  csm::Model* sensor_model = constructModelFromISD(imageSupportData, modelName, warnings);
+  return sensor_model->getModelState();
+}
+
+
+csm::Model *UsgsAstroPlugin::constructModelFromISD(const csm::Isd &imageSupportDataOriginal,
+                                              const std::string &modelName,
+                                              csm::WarningList *warnings) const {
+
+    std::string stringIsd = loadImageSupportData(imageSupportDataOriginal);
+
+    if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) {
+      UsgsAstroFrameSensorModel *model =  new UsgsAstroFrameSensorModel();
+      try {
+        model->replaceModelState(model->constructStateFromIsd(stringIsd, warnings));
+      }
+      catch (...) {
+        csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE;
+        std::string aMessage = "Invalid ISD for Model " + modelName + ": ";
+        std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()";
+        throw csm::Error(aErrorType, aMessage, aFunction);
+      }
+      return model;
+    }
+    else if (modelName == UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME) {
+      UsgsAstroLsSensorModel *model =  new UsgsAstroLsSensorModel();
+      try {
+        model->replaceModelState(model->constructStateFromIsd(stringIsd, warnings));
+      }
+      catch (...) {
+        csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE;
+        std::string aMessage = "Invalid ISD for Model " + modelName + ": ";
+        std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()";
+        throw csm::Error(aErrorType, aMessage, aFunction);
+      }
+      return model;
+    }
+    else {
+      csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
+      std::string aMessage = "Model" + modelName + " not supported: ";
+      std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()";
+      throw csm::Error(aErrorType, aMessage, aFunction);
+    }
+}
+
+
+csm::Model *UsgsAstroPlugin::constructModelFromState(const std::string& modelState,
+                                                csm::WarningList *warnings) const {
+
+    json state = json::parse(modelState);
+    std::string modelName = state["modelName"];
+
+    if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) {
+         UsgsAstroFrameSensorModel* model = new UsgsAstroFrameSensorModel();
+         model->replaceModelState(modelState);
+         return model;
+    }
+    else if (modelName == UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME) {
+        UsgsAstroLsSensorModel* model = new UsgsAstroLsSensorModel();
+        model->replaceModelState(modelState);
+        return model;
+    }
+    else {
+      csm::Error::ErrorType aErrorType = csm::Error::ISD_NOT_SUPPORTED;
+      std::string aMessage = "Model" + modelName + " not supported: ";
+      std::string aFunction = "UsgsAstroPlugin::constructModelFromState()";
+      throw csm::Error(aErrorType, aMessage, aFunction);
+    }
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 749de24..3388d81 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,7 +1,15 @@
 cmake_minimum_required(VERSION 3.10)
 
 # Link runCSMCameraModelTests with what we want to test and the GTest and pthread library
-add_executable(runCSMCameraModelTests TestyMcTestFace.cpp FrameCameraTests.cpp)
-target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
+add_executable(runCSMCameraModelTests
+               PluginTests.cpp
+               FrameCameraTests.cpp)
+if(WIN32)
+  option(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON)
+  option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
+  target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
+else()
+    target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
+endif()
 
 gtest_discover_tests(runCSMCameraModelTests WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
diff --git a/tests/Fixtures.h b/tests/Fixtures.h
new file mode 100644
index 0000000..be28df3
--- /dev/null
+++ b/tests/Fixtures.h
@@ -0,0 +1,144 @@
+#ifndef Fixtures_h
+#define Fixtures_h
+
+#include "UsgsAstroPlugin.h"
+#include "UsgsAstroFrameSensorModel.h"
+
+#include <json.hpp>
+
+#include <map>
+#include <sstream>
+#include <fstream>
+
+#include <gtest/gtest.h>
+
+using json = nlohmann::json;
+
+// Should this be positioned somewhere in the public API?
+inline void jsonToIsd(json &object, csm::Isd &isd, std::string prefix="") {
+  for (json::iterator it = object.begin(); it != object.end(); ++it) {
+     json jsonValue = it.value();
+     if (jsonValue.is_array()) {
+        for (int i = 0; i < jsonValue.size(); i++) {
+           isd.addParam(prefix+it.key(), jsonValue[i].dump());
+        }
+     }
+     else if (jsonValue.is_string()) {
+        isd.addParam(prefix+it.key(), jsonValue.get<std::string>());
+     }
+     else {
+        isd.addParam(prefix+it.key(), jsonValue.dump());
+     }
+  }
+}
+
+class FrameSensorModel : public ::testing::Test {
+   protected:
+      csm::Isd isd;
+      UsgsAstroFrameSensorModel *sensorModel;
+
+      void SetUp() override {
+         sensorModel = NULL;
+
+         isd.setFilename("data/simpleFramerISD.img");
+         UsgsAstroPlugin frameCameraPlugin;
+
+         csm::Model *model = frameCameraPlugin.constructModelFromISD(
+               isd,
+               "USGS_ASTRO_FRAME_SENSOR_MODEL");
+         sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+         ASSERT_NE(sensorModel, nullptr);
+      }
+
+      void TearDown() override {
+         if (sensorModel) {
+            delete sensorModel;
+            sensorModel = NULL;
+         }
+      }
+};
+
+class FrameIsdTest : public ::testing::Test {
+   protected:
+      csm::Isd isd;
+
+   virtual void SetUp() {
+      isd.setFilename("data/simpleFramerISD.img");
+   }
+};
+
+class ConstVelLineScanIsdTest : public ::testing::Test {
+   protected:
+      csm::Isd isd;
+
+   virtual void SetUp() {
+      isd.setFilename("data/constVelocityLineScan.img");
+   }
+};
+
+class FramerParameterizedTest : public ::testing::TestWithParam<csm::ImageCoord> {
+
+protected:
+  csm::Isd isd;
+
+  std::string printIsd(csm::Isd &localIsd) {
+    std::string str;
+    std::multimap<std::string,std::string> isdmap= localIsd.parameters();
+    for (auto it = isdmap.begin(); it != isdmap.end();++it){
+      str.append(it->first);
+      str.append(":");
+      str.append(it->second);
+    }
+    return str;
+  }
+  UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) {
+
+    UsgsAstroPlugin frameCameraPlugin;
+    csm::Model *model = frameCameraPlugin.constructModelFromISD(
+        modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+    if (sensorModel)
+      return sensorModel;
+    else
+      return nullptr;
+  }
+
+
+  virtual void SetUp() {
+    isd.setFilename("data/simpleFramerISD.img");
+  };
+};
+
+class FrameStateTest : public ::testing::Test {
+  protected:
+    csm::Isd isd;
+    UsgsAstroFrameSensorModel* createModifiedStateSensorModel(std::string key, double newValue) {
+      UsgsAstroPlugin cameraPlugin;
+      csm::Model *model = cameraPlugin.constructModelFromISD(isd,"USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+      UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+      if (sensorModel) {
+        sensorModel->getModelState();
+        std::string modelState = sensorModel->getModelState();
+        auto state = json::parse(modelState);
+        state[key] = newValue;
+        sensorModel->replaceModelState(state.dump());
+
+        return sensorModel;
+      }
+      else {
+        return nullptr;
+      }
+    }
+
+    void SetUp() override {
+      isd.setFilename("data/simpleFramerISD.img");
+    }
+};
+
+
+
+#endif
diff --git a/tests/FrameCameraTests.cpp b/tests/FrameCameraTests.cpp
index 27bdb6e..cab179e 100644
--- a/tests/FrameCameraTests.cpp
+++ b/tests/FrameCameraTests.cpp
@@ -1,122 +1,31 @@
-#include "UsgsAstroFramePlugin.h"
+#include "UsgsAstroPlugin.h"
 #include "UsgsAstroFrameSensorModel.h"
 
 #include <json.hpp>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#include <fstream>
-#include <map>
-#include <vector>
 #include <gtest/gtest.h>
 
-using namespace std;
-using json = nlohmann::json;
-
+#include "Fixtures.h"
 
-class FramerParameterizedTest : public ::testing::TestWithParam<csm::ImageCoord> {
-
-protected:
-  csm::Isd isd;
-
-      void printIsd(csm::Isd &localIsd) {
-           multimap<string,string> isdmap= localIsd.parameters();
-           for (auto it = isdmap.begin(); it != isdmap.end();++it){
-
-                      cout << it->first << " : " << it->second << endl;
-           }
-      }
-      UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) {
-
-        UsgsAstroFramePlugin frameCameraPlugin;
-        csm::Model *model = frameCameraPlugin.constructModelFromISD(
-              modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL");
-
-        UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-
-        if (sensorModel)
-          return sensorModel;
-        else
-          return nullptr;
-      }
-
-
-   virtual void SetUp() {
-     isd.setFilename("data/simpleFramerISD.img");
-   };
-};
-
-
-class FrameIsdTest : public ::testing::Test {
-  protected:
-    csm::Isd isd;
-    void printIsd(csm::Isd &localIsd) {
-      multimap<string,string> isdmap= localIsd.parameters();
-      for (auto it = isdmap.begin(); it != isdmap.end();++it){
-        cout << it->first << " : " << it->second << endl;
-      }
-    }
-    UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) {
-      UsgsAstroFramePlugin frameCameraPlugin;
-      csm::Model *model = frameCameraPlugin.constructModelFromISD(
-              modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL");
-      UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-      if (sensorModel)
-        return sensorModel;
-      else
-        return nullptr;
-      }
-
-
-    virtual void SetUp() {
-      isd.setFilename("data/simpleFramerISD.img");
-   }
-};
-
-class FrameSensorModel : public ::testing::Test {
-   protected:
-      protected :
-      csm::Isd isd;
-      UsgsAstroFrameSensorModel *sensorModel;
-
-      void SetUp() override {
-         sensorModel = NULL;
-
-         isd.setFilename("data/simpleFramerISD.img");
-         UsgsAstroFramePlugin frameCameraPlugin;
-         csm::Model *model = frameCameraPlugin.constructModelFromISD(
-               isd,
-               "USGS_ASTRO_FRAME_SENSOR_MODEL");
-         sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-         ASSERT_NE(sensorModel, nullptr);
-      }
-
-      void TearDown() override {
-         if (sensorModel) {
-            delete sensorModel;
-            sensorModel = NULL;
-         }
-      }
-};
+using json = nlohmann::json;
 
 INSTANTIATE_TEST_CASE_P(JacobianTest,FramerParameterizedTest,
                         ::testing::Values(csm::ImageCoord(2.5,2.5),csm::ImageCoord(7.5,7.5)));
 
-TEST_P(FramerParameterizedTest,JacobianTest) {
+TEST_P(FramerParameterizedTest, JacobianTest) {
 
    UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-   std::string modelState = sensorModel->getModelState(); 
+   std::string modelState = sensorModel->getModelState();
    auto state = json::parse(modelState);
 
    state["m_odtX"] = {1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0};
    state["m_odtY"] = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0};
-   sensorModel->replaceModelState(state.dump()); 
-   
+   sensorModel->replaceModelState(state.dump());
+
    double Jxx,Jxy,Jyx,Jyy;
    ASSERT_NE(sensorModel, nullptr);
 
    csm::ImageCoord imagePt1 = GetParam();
-   cout << "[" << imagePt1.samp << "," << imagePt1.line << "]"<< endl;
+//   cout << "[" << imagePt1.samp << "," << imagePt1.line << "]"<< endl;
    sensorModel->distortionJacobian(imagePt1.samp, imagePt1.line, Jxx, Jxy,Jyx,Jyy);
 
    double determinant = fabs(Jxx*Jyy - Jxy*Jyx);
@@ -128,6 +37,14 @@ TEST_P(FramerParameterizedTest,JacobianTest) {
 
 // NOTE: The imagePt format is (Lines,Samples)
 
+TEST_F(FrameSensorModel, State) {
+   std::string modelState = sensorModel->getModelState();
+   EXPECT_NO_THROW(
+         sensorModel->replaceModelState(modelState)
+   );
+   EXPECT_EQ(sensorModel->getModelState(), modelState);
+}
+
 // centered and slightly off-center:
 TEST_F(FrameSensorModel, Center) {
    csm::ImageCoord imagePt(7.5, 7.5);
@@ -136,6 +53,7 @@ TEST_F(FrameSensorModel, Center) {
    EXPECT_NEAR(groundPt.y, 0, 1e-8);
    EXPECT_NEAR(groundPt.z, 0, 1e-8);
 }
+
 TEST_F(FrameSensorModel, SlightlyOffCenter) {
    csm::ImageCoord imagePt(7.5, 6.5);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -159,6 +77,7 @@ TEST_F(FrameSensorModel, OffBody2) {
    EXPECT_NEAR(groundPt.y, 14.99325304, 1e-8);
    EXPECT_NEAR(groundPt.z, -14.99325304, 1e-8);
 }
+
 TEST_F(FrameSensorModel, OffBody3) {
    csm::ImageCoord imagePt(0.0, 0.0);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -166,6 +85,7 @@ TEST_F(FrameSensorModel, OffBody3) {
    EXPECT_NEAR(groundPt.y, 14.99325304, 1e-8);
    EXPECT_NEAR(groundPt.z, 14.99325304, 1e-8);
 }
+
 TEST_F(FrameSensorModel, OffBody4) {
    csm::ImageCoord imagePt(15.0, 15.0);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -174,39 +94,34 @@ TEST_F(FrameSensorModel, OffBody4) {
    EXPECT_NEAR(groundPt.z, -14.99325304, 1e-8);
 }
 
-
-
-TEST_F(FrameIsdTest, setFocalPlane1) {
+TEST_F(FrameSensorModel, setFocalPlane1) {
   csm::ImageCoord imagePt(7.5, 7.5);
   double ux,uy;
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
 
   state["m_odtX"] = {0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
   state["m_odtY"] = {0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   ASSERT_NE(sensorModel, nullptr);
   sensorModel->setFocalPlane(imagePt.samp, imagePt.line, ux, uy);
   EXPECT_NEAR(imagePt.samp,7.5,1e-8 );
-  EXPECT_NEAR(imagePt.line,7.5,1e-8);   
+  EXPECT_NEAR(imagePt.line,7.5,1e-8);
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, Jacobian1) {
+TEST_F(FrameSensorModel, Jacobian1) {
   csm::ImageCoord imagePt(7.5, 7.5);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
   state["m_odtX"] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0};
   state["m_odtY"] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   double Jxx,Jxy,Jyx,Jyy;
 
@@ -217,42 +132,40 @@ TEST_F(FrameIsdTest, Jacobian1) {
   EXPECT_NEAR(Jxy,112.5,1e-8);
   EXPECT_NEAR(Jyx,56.25,1e-8);
   EXPECT_NEAR(Jyy,281.25,1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, distortMe_AllCoefficientsOne) {
+TEST_F(FrameSensorModel, distortMe_AllCoefficientsOne) {
   csm::ImageCoord imagePt(7.5, 7.5);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
   state["m_odtX"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
   state["m_odtY"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   double dx,dy;
   ASSERT_NE(sensorModel, nullptr);
   sensorModel->distortionFunction(imagePt.samp, imagePt.line,dx,dy );
-  
+
   EXPECT_NEAR(dx,1872.25,1e-8 );
   EXPECT_NEAR(dy,1872.25,1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
-TEST_F(FrameIsdTest, setFocalPlane_AllCoefficientsOne) {
+TEST_F(FrameSensorModel, setFocalPlane_AllCoefficientsOne) {
   csm::ImageCoord imagePt(1872.25, 1872.25);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
   state["m_odtX"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
   state["m_odtY"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   double ux,uy;
   ASSERT_NE(sensorModel, nullptr);
@@ -268,37 +181,35 @@ TEST_F(FrameIsdTest, setFocalPlane_AllCoefficientsOne) {
 }
 
 
-TEST_F(FrameIsdTest, distortMe_AlternatingOnes) {
+TEST_F(FrameSensorModel, distortMe_AlternatingOnes) {
   csm::ImageCoord imagePt(7.5, 7.5);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
   state["m_odtX"] = {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0};
   state["m_odtY"] = {0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   double dx,dy;
   ASSERT_NE(sensorModel, nullptr);
   sensorModel->distortionFunction(imagePt.samp, imagePt.line,dx,dy );
-  
+
   EXPECT_NEAR(dx,908.5,1e-8 );
   EXPECT_NEAR(dy,963.75,1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, setFocalPlane_AlternatingOnes) {
+TEST_F(FrameSensorModel, setFocalPlane_AlternatingOnes) {
   csm::ImageCoord imagePt(963.75, 908.5);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
+  std::string modelState = sensorModel->getModelState();
   auto state = json::parse(modelState);
   state["m_odtX"] = {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0};
   state["m_odtY"] = {0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0};
-  sensorModel->replaceModelState(state.dump()); 
+  sensorModel->replaceModelState(state.dump());
 
   double ux,uy;
   ASSERT_NE(sensorModel, nullptr);
@@ -313,61 +224,45 @@ TEST_F(FrameIsdTest, setFocalPlane_AlternatingOnes) {
 }
 
 
-
 // Focal Length Tests:
-TEST_F(FrameIsdTest, FL500_OffBody4) {
+TEST_F(FrameStateTest, FL500_OffBody4) {
   std::string key = "m_focalLength";
   double newValue = 500.0;
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
-  
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(15.0, 15.0);
   csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
   EXPECT_NEAR(groundPt.x, 9.77688917, 1e-8);
   EXPECT_NEAR(groundPt.y, -1.48533467, 1e-8);
   EXPECT_NEAR(groundPt.z, -1.48533467, 1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, FL500_OffBody3) {
+TEST_F(FrameStateTest, FL500_OffBody3) {
   std::string key = "m_focalLength";
   double newValue = 500.0;
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
-  
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(0.0, 0.0);
   csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
   EXPECT_NEAR(groundPt.x, 9.77688917, 1e-8);
   EXPECT_NEAR(groundPt.y, 1.48533467, 1e-8);
   EXPECT_NEAR(groundPt.z, 1.48533467, 1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, FL500_Center) {
+TEST_F(FrameStateTest, FL500_Center) {
   std::string key = "m_focalLength";
   double newValue = 500.0;
-
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(7.5, 7.5);
@@ -375,21 +270,16 @@ TEST_F(FrameIsdTest, FL500_Center) {
   EXPECT_NEAR(groundPt.x, 10.0, 1e-8);
   EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
   EXPECT_NEAR(groundPt.z, 0.0, 1e-8);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, FL500_SlightlyOffCenter) {
+TEST_F(FrameStateTest, FL500_SlightlyOffCenter) {
   std::string key = "m_focalLength";
   double newValue = 500.0;
-
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(7.5, 6.5);
@@ -403,9 +293,8 @@ TEST_F(FrameIsdTest, FL500_SlightlyOffCenter) {
 }
 
 // Observer x position:
-TEST_F(FrameIsdTest, X10_SlightlyOffCenter) {
+TEST_F(FrameSensorModel, X10_SlightlyOffCenter) {
    double newValue = 10.0;
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
    sensorModel->setParameterValue(0, newValue); // X
 
    ASSERT_NE(sensorModel, nullptr);
@@ -419,11 +308,8 @@ TEST_F(FrameIsdTest, X10_SlightlyOffCenter) {
    sensorModel = NULL;
 }
 
-
-TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) {
+TEST_F(FrameSensorModel, X1e9_SlightlyOffCenter) {
    double newValue = 1000000000.0;
-
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
    sensorModel->setParameterValue(0, newValue); // X
 
    ASSERT_NE(sensorModel, nullptr);
@@ -440,9 +326,16 @@ TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) {
 
 
 // Angle rotations:
-TEST_F(FrameIsdTest, Rotation_omegaPi_Center) {
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-   sensorModel->setParameterValue(3, M_PI); // omega
+TEST_F(FrameSensorModel, Rotation_omegaPi_Center) {
+   sensorModel->setParameterValue(3, 1.0);
+   sensorModel->setParameterValue(4, 1.0);
+   sensorModel->setParameterValue(5, 1.0);
+
+   sensorModel->setParameterValue(6, 1.0);
+
+   sensorModel->setParameterValue(0, 1000.0); // X
+   sensorModel->setParameterValue(1, 0.0); // Y
+   sensorModel->setParameterValue(2, 0.0); // Z
 
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(7.5, 7.5);
@@ -456,30 +349,33 @@ TEST_F(FrameIsdTest, Rotation_omegaPi_Center) {
 }
 
 
-TEST_F(FrameIsdTest, Rotation_NPole_Center) {
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-   sensorModel->setParameterValue(4, -M_PI); // phi
-   sensorModel->setParameterValue(0, 0.0); // X
-   sensorModel->setParameterValue(1, 0.0); // Y 
-   sensorModel->setParameterValue(2, 1000.0); // Z
+TEST_F(FrameSensorModel, Rotation_NPole_Center) {
+  sensorModel->setParameterValue(3, 0.0);
+  sensorModel->setParameterValue(4, -1.0);
+  sensorModel->setParameterValue(5, 0.0);
 
-   ASSERT_NE(sensorModel, nullptr);
-   csm::ImageCoord imagePt(7.5, 7.5);
-   csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
-   EXPECT_NEAR(groundPt.x, 0.0, 1e-8);
-   EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
-   EXPECT_NEAR(groundPt.z, 10.0, 1e-8);
+  sensorModel->setParameterValue(6, 0.0);
 
-   delete sensorModel;
-   sensorModel = NULL;
+  sensorModel->setParameterValue(0, 0.0); // X
+  sensorModel->setParameterValue(1, 0.0); // Y
+  sensorModel->setParameterValue(2, 1000.0); // Z
+
+  ASSERT_NE(sensorModel, nullptr);
+  csm::ImageCoord imagePt(7.5, 7.5);
+  csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
+  EXPECT_NEAR(groundPt.x, 0.0, 1e-8);
+  EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
+  EXPECT_NEAR(groundPt.z, 10.0, 1e-8);
+
+  delete sensorModel;
+  sensorModel = NULL;
 }
 
 
-TEST_F(FrameIsdTest, Rotation_SPole_Center) {
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
+TEST_F(FrameSensorModel, Rotation_SPole_Center) {
    sensorModel->setParameterValue(4, 0.0); // phi
    sensorModel->setParameterValue(0, 0.0); // X
-   sensorModel->setParameterValue(1, 0.0); // Y 
+   sensorModel->setParameterValue(1, 0.0); // Y
    sensorModel->setParameterValue(2, -1000.0); // Z
 
    ASSERT_NE(sensorModel, nullptr);
@@ -495,15 +391,11 @@ TEST_F(FrameIsdTest, Rotation_SPole_Center) {
 
 
 // Ellipsoid axis tests:
-TEST_F(FrameIsdTest, SemiMajorAxis100x_Center) {
+TEST_F(FrameStateTest, SemiMajorAxis100x_Center) {
   std::string key = "m_majorAxis";
   double newValue = 1000.0;
 
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(7.5, 7.5);
@@ -517,15 +409,10 @@ TEST_F(FrameIsdTest, SemiMajorAxis100x_Center) {
 }
 
 
-TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) {
+TEST_F(FrameStateTest, SemiMajorAxis10x_SlightlyOffCenter) {
   std::string key = "m_majorAxis";
   double newValue = 100.0;
-
-  UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-  std::string modelState = sensorModel->getModelState(); 
-  auto state = json::parse(modelState);
-  state[key] = newValue; 
-  sensorModel->replaceModelState(state.dump()); 
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
   ASSERT_NE(sensorModel, nullptr);
   csm::ImageCoord imagePt(7.5, 6.5);
@@ -535,7 +422,7 @@ TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) {
   EXPECT_NEAR(groundPt.x, 9.83606557e+01, 1e-7);
   EXPECT_NEAR(groundPt.y, 0.0, 1e-7);
   EXPECT_NEAR(groundPt.z, 1.80327869, 1e-7);
-  
+
   delete sensorModel;
   sensorModel = NULL;
 }
@@ -543,23 +430,18 @@ TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) {
 
 // The following test is for the scenario where the semi_minor_axis is actually larger
 // than the semi_major_axis:
-TEST_F(FrameIsdTest, SemiMinorAxis10x_SlightlyOffCenter) {
-   std::string key = "m_minorAxis";
-   double newValue = 100.0;
-
-   UsgsAstroFrameSensorModel* sensorModel = createModel(isd);
-   std::string modelState = sensorModel->getModelState(); 
-   auto state = json::parse(modelState);
-   state[key] = newValue;
-   sensorModel->replaceModelState(state.dump()); 
+TEST_F(FrameStateTest, SemiMinorAxis10x_SlightlyOffCenter) {
+  std::string key = "m_minorAxis";
+  double newValue = 100.0;
+  UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue);
 
-   ASSERT_NE(sensorModel, nullptr);
-   csm::ImageCoord imagePt(7.5, 6.5);
-   csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
-   EXPECT_NEAR(groundPt.x, 9.99803960, 1e-8);
-   EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
-   EXPECT_NEAR(groundPt.z, 1.98000392, 1e-8);
+  ASSERT_NE(sensorModel, nullptr);
+  csm::ImageCoord imagePt(7.5, 6.5);
+  csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
+  EXPECT_NEAR(groundPt.x, 9.99803960, 1e-8);
+  EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
+  EXPECT_NEAR(groundPt.z, 1.98000392, 1e-8);
 
-   delete sensorModel;
-   sensorModel = NULL;
+  delete sensorModel;
+  sensorModel = NULL;
 }
diff --git a/tests/PluginTests.cpp b/tests/PluginTests.cpp
new file mode 100644
index 0000000..2252e88
--- /dev/null
+++ b/tests/PluginTests.cpp
@@ -0,0 +1,190 @@
+#include "UsgsAstroPlugin.h"
+#include "UsgsAstroFrameSensorModel.h"
+#include "UsgsAstroLsSensorModel.h"
+
+#include <sstream>
+#include <fstream>
+
+#include <gtest/gtest.h>
+
+#include "Fixtures.h"
+
+TEST(PluginTests, PluginName) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_EQ("UsgsAstroPluginCSM", testPlugin.getPluginName());
+}
+
+TEST(PluginTests, ManufacturerName) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_EQ("UsgsAstrogeology", testPlugin.getManufacturer());
+}
+
+TEST(PluginTests, ReleaseDate) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_EQ("20170425", testPlugin.getReleaseDate());
+}
+
+TEST(PluginTests, NumModels) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_EQ(2, testPlugin.getNumModels());
+}
+
+TEST(PluginTests, BadISDFile) {
+   UsgsAstroPlugin testPlugin;
+   csm::Isd badIsd("Not a file");
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD(
+                badIsd,
+                "USGS_ASTRO_FRAME_SENSOR_MODEL"));
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD(
+                badIsd,
+                "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL"));
+}
+
+TEST(FrameStateTests, NoStateName) {
+   UsgsAstroPlugin testPlugin;
+   std::string badState = "{\"not_a_name\":\"bad_name\"}";
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
+         "USGS_ASTRO_FRAME_SENSOR_MODEL",
+         badState));
+}
+
+TEST(FrameStateTests, BadStateName) {
+   UsgsAstroPlugin testPlugin;
+   std::string badState = "{\"m_model_name\":\"bad_name\"}";
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
+         "USGS_ASTRO_FRAME_SENSOR_MODEL",
+         badState));
+}
+
+TEST(FrameStateTests, BadStateValue) {
+   UsgsAstroPlugin testPlugin;
+   std::string badState = "{"
+         "\"m_model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\","
+         "\"bad_param\":\"bad_value\"}";
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
+         "USGS_ASTRO_FRAME_SENSOR_MODEL",
+         badState));
+}
+
+TEST(FrameStateTests, MissingStateValue) {
+   UsgsAstroPlugin testPlugin;
+   std::string badState = "{"
+         "\"m_model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"}";
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
+         "USGS_ASTRO_FRAME_SENSOR_MODEL",
+         badState));
+}
+
+TEST_F(FrameIsdTest, Constructible) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD(
+               isd,
+               "USGS_ASTRO_FRAME_SENSOR_MODEL"));
+}
+
+TEST_F(FrameIsdTest, NotConstructible) {
+   UsgsAstroPlugin testPlugin;
+   isd.setFilename("data/constVelocityLineScan.img");
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD(
+                isd,
+                "USGS_ASTRO_FRAME_SENSOR_MODEL"));
+}
+
+
+TEST_F(FrameIsdTest, ConstructValidCamera) {
+   UsgsAstroPlugin testPlugin;
+   csm::Model *cameraModel = NULL;
+   EXPECT_NO_THROW(
+         cameraModel = testPlugin.constructModelFromISD(
+               isd,
+               "USGS_ASTRO_FRAME_SENSOR_MODEL",
+               NULL)
+   );
+   UsgsAstroFrameSensorModel *frameModel = dynamic_cast<UsgsAstroFrameSensorModel *>(cameraModel);
+   EXPECT_NE(frameModel, nullptr);
+   if (cameraModel) {
+      delete cameraModel;
+   }
+}
+
+
+TEST_F(FrameIsdTest, ConstructInValidCamera) {
+   UsgsAstroPlugin testPlugin;
+   isd.setFilename("data/constVelocityLineScan.img");
+   csm::Model *cameraModel = NULL;
+   try {
+      testPlugin.constructModelFromISD(
+            isd,
+            "USGS_ASTRO_FRAME_SENSOR_MODEL",
+            NULL);
+      FAIL() << "Expected an error";
+   }
+   catch(csm::Error &e) {
+      EXPECT_EQ(e.getError(), csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE);
+   }
+   catch(...) {
+      FAIL() << "Expected csm SENSOR_MODEL_NOT_CONSTRUCTIBLE error";
+   }
+   if (cameraModel) {
+      delete cameraModel;
+   }
+}
+
+TEST_F(ConstVelLineScanIsdTest, Constructible) {
+   UsgsAstroPlugin testPlugin;
+   EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD(
+               isd,
+               "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL"));
+}
+
+TEST_F(ConstVelLineScanIsdTest, NotConstructible) {
+   UsgsAstroPlugin testPlugin;
+   isd.setFilename("data/simpleFramerISD.img");
+   EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD(
+               isd,
+               "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL"));
+}
+
+TEST_F(ConstVelLineScanIsdTest, ConstructValidCamera) {
+   UsgsAstroPlugin testPlugin;
+   csm::Model *cameraModel = NULL;
+   EXPECT_NO_THROW(
+         cameraModel = testPlugin.constructModelFromISD(
+               isd,
+               "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL",
+               NULL)
+   );
+   UsgsAstroLsSensorModel *frameModel = dynamic_cast<UsgsAstroLsSensorModel *>(cameraModel);
+   EXPECT_NE(frameModel, nullptr);
+   if (cameraModel) {
+      delete cameraModel;
+   }
+}
+
+TEST_F(ConstVelLineScanIsdTest, ConstructInValidCamera) {
+   UsgsAstroPlugin testPlugin;
+   isd.setFilename("data/simpleFramerISD.img");
+   csm::Model *cameraModel = NULL;
+   try {
+      testPlugin.constructModelFromISD(
+            isd,
+            "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL",
+            NULL);
+      FAIL() << "Expected an error";
+
+   }
+   catch(csm::Error &e) {
+      EXPECT_EQ(e.getError(), csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE);
+   }
+   catch(...) {
+      FAIL() << "Expected csm SENSOR_MODEL_NOT_CONSTRUCTIBLE error";
+   }
+   if (cameraModel) {
+      delete cameraModel;
+   }
+}
+
+int main(int argc, char **argv) {
+   ::testing::InitGoogleTest(&argc, argv);
+   return RUN_ALL_TESTS();
+}
diff --git a/tests/TestyMcTestFace.cpp b/tests/TestyMcTestFace.cpp
deleted file mode 100644
index 7b0696c..0000000
--- a/tests/TestyMcTestFace.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#include "UsgsAstroFramePlugin.h"
-#include "UsgsAstroFrameSensorModel.h"
-
-#include <json.hpp>
-
-#include <sstream>
-#include <fstream>
-
-#include <gtest/gtest.h>
-
-using json = nlohmann::json;
-
-class FrameIsdTest : public ::testing::Test {
-   protected:
-     csm::Isd isd;
-     virtual void SetUp() {
-       isd.setFilename("data/simpleFramerISD.img");
-     };
-};
-
-TEST(FramePluginTests, PluginName) {
-   UsgsAstroFramePlugin testPlugin;
-   EXPECT_EQ("UsgsAstroFramePluginCSM", testPlugin.getPluginName());;
-}
-
-TEST(FramePluginTests, ManufacturerName) {
-   UsgsAstroFramePlugin testPlugin;
-   EXPECT_EQ("UsgsAstrogeology", testPlugin.getManufacturer());;
-}
-
-TEST(FramePluginTests, ReleaseDate) {
-   UsgsAstroFramePlugin testPlugin;
-   EXPECT_EQ("20170425", testPlugin.getReleaseDate());;
-}
-
-TEST(FramePluginTests, NumModels) {
-   UsgsAstroFramePlugin testPlugin;
-   EXPECT_EQ(1, testPlugin.getNumModels());;
-}
-
-TEST(FramePluginTests, NoStateName) {
-   UsgsAstroFramePlugin testPlugin;
-   std::string badState = "{\"not_a_name\":\"bad_name\"}";
-   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
-         "USGS_ASTRO_FRAME_SENSOR_MODEL",
-         badState));;
-}
-
-TEST(FramePluginTests, BadStateName) {
-   UsgsAstroFramePlugin testPlugin;
-   std::string badState = "{\"model_name\":\"bad_name\"}";
-   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
-         "USGS_ASTRO_FRAME_SENSOR_MODEL",
-         badState));;
-}
-
-TEST(FramePluginTests, BadStateValue) {
-   UsgsAstroFramePlugin testPlugin;
-   std::string badState = "{"
-         "\"model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\","
-         "\"bad_param\":\"bad_value\"}";
-   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
-         "USGS_ASTRO_FRAME_SENSOR_MODEL",
-         badState));;
-}
-
-TEST(FramePluginTests, MissingStateValue) {
-   UsgsAstroFramePlugin testPlugin;
-   std::string badState = "{"
-         "\"model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"}";
-   EXPECT_FALSE(testPlugin.canModelBeConstructedFromState(
-         "USGS_ASTRO_FRAME_SENSOR_MODEL",
-         badState));;
-}
-
-TEST_F(FrameIsdTest, Constructible) {
-   UsgsAstroFramePlugin testPlugin;
-   EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD(
-               isd,
-               "USGS_ASTRO_FRAME_SENSOR_MODEL"));
-}
-
-TEST_F(FrameIsdTest, ConstructValidCamera) {
-   UsgsAstroFramePlugin testPlugin;
-   csm::Model *cameraModel = NULL;
-   EXPECT_NO_THROW(
-         cameraModel = testPlugin.constructModelFromISD(
-               isd,
-               "USGS_ASTRO_FRAME_SENSOR_MODEL",
-               NULL)
-   );
-   UsgsAstroFrameSensorModel *frameModel = dynamic_cast<UsgsAstroFrameSensorModel *>(cameraModel);
-   EXPECT_NE(frameModel, nullptr);
-   if (cameraModel) {
-      delete cameraModel;
-   }
-}
-
-TEST_F(FrameIsdTest, ConstructInValidCamera) {
-   UsgsAstroFramePlugin testPlugin;
-   // Remove the model_name keyword from the ISD to make it invalid
-   isd.clearParams("model_name");
-   csm::Model *cameraModel = NULL;
-   try {
-      testPlugin.constructModelFromISD(
-            isd,
-            "USGS_ASTRO_FRAME_SENSOR_MODEL",
-            NULL);
-   }
-   catch(csm::Error &e) {
-      EXPECT_EQ(e.getError(), csm::Error::ISD_NOT_SUPPORTED);
-   }
-   catch(...) {
-      FAIL() << "Expected csm ISD_NOT_SUPPORTED error";
-   }
-   if (cameraModel) {
-      delete cameraModel;
-   }
-}
-
-int main(int argc, char **argv) {
-   ::testing::InitGoogleTest(&argc, argv);
-   return RUN_ALL_TESTS();
-}
diff --git a/tests/data/constVelocityLineScan.json b/tests/data/constVelocityLineScan.json
new file mode 100644
index 0000000..7f910ef
--- /dev/null
+++ b/tests/data/constVelocityLineScan.json
@@ -0,0 +1,93 @@
+{
+  "name_model" : "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL",
+  "name_platform" : "TEST_PLATFORM",
+  "name_sensor" : "TEST_SENSOR",
+  "center_ephemeris_time": 1000.0,
+  "starting_ephemeris_time": 992.0,
+  "line_scan_rate": [
+    [0.5, 992.0, 0.1]
+  ],
+  "detector_sample_summing": 1,
+  "detector_line_summing": 1,
+  "t0_ephemeris": -8.0,
+  "dt_ephemeris": 0.2,
+  "t0_quaternion": -8.0,
+  "dt_quaternion": 0.2,
+  "focal2pixel_lines": [0.0, 10.0, 0.0],
+  "focal2pixel_samples": [0.0, 0.0, 10.0],
+  "focal_length_model": {
+    "focal_length": 50,
+    "focal_epsilon": 1.0
+  },
+  "image_lines": 16,
+  "image_samples": 16,
+  "detector_center" : {
+    "line" : 0.5,
+    "sample" : 7.5
+  },
+  "interpolation_method": "lagrange",
+  "optical_distortion": {
+    "radial": {
+      "coefficients": [0.0, 0.0, 0.0]
+    }
+  },
+  "radii": {
+    "semimajor": 10,
+    "semiminor": 10,
+    "unit":"m"
+  },
+  "reference_height": {
+    "maxheight": 1,
+    "minheight": -1,
+    "unit": "m"
+  },
+  "sensor_position": {
+    "unit": "m",
+    "positions": [
+      [1000.0, 0.0, 16.0],
+      [1000.0, 0.0, 12.0],
+      [1000.0, 0.0, 8.0],
+      [1000.0, 0.0, 4.0],
+      [1000.0, 0.0, 0.0],
+      [1000.0, 0.0, -4.0],
+      [1000.0, 0.0, -8.0],
+      [1000.0, 0.0, -12.0],
+      [1000.0, 0.0, -16.0]
+    ],
+    "velocities": [
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0],
+      [0.0, 0.0, -20.0]
+    ]
+  },
+  "sensor_orientation": {
+    "quaternions": [
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547],
+      [0.0, -0.707106781186547, 0.0, 0.707106781186547]
+    ]
+  },
+  "starting_detector_line": 0,
+  "starting_detector_sample": 0,
+  "sun_position": {
+    "positions": [
+      [100.0, 100.0, 0.0]
+    ],
+    "velocities": [
+      [0.0, 0.0, 0.0]
+    ],
+    "unit": "m"
+  }
+}
diff --git a/tests/data/simpleFramerISD.json b/tests/data/simpleFramerISD.json
index f1c3733..63fb799 100644
--- a/tests/data/simpleFramerISD.json
+++ b/tests/data/simpleFramerISD.json
@@ -1,86 +1,61 @@
 {
-    "boresight": [
-        0.0,
-        0.0,
-        1.0
-    ],
-    "ccd_center": [
-        7.5,
-        7.5
-    ],
-    "ephemeris_time": 100.0,
-    "focal_length": 50,
-    "focal_length_epsilon": 1.0,
-    "ifov": 6.0,
-    "model_name": "USGS_ASTRO_FRAME_SENSOR_MODEL",
-    "spacecraft_name": "TEST_CRAFT",
-    "instrument_id": "TEST_SENSOR",
-    "target_name": "TEST_BALL",
-    "pixel_pitch": 0.1,
-    "itrans_line": [
-        0.0,
-        0.0,
-        10
-    ],
-    "itrans_sample": [
-        0.0,
-        10,
-        0.0
-    ],
-    "transx": [
-        0.0,
-        0.1,
-        0.0
-    ],
-    "transy": [
-        0.0,
-        0.0,
-        0.1
-    ],
-    "min_elevation": -1,
-    "max_elevation": 1,
-    "nlines": 16,
-    "nsamples": 16,
-    "original_half_lines": 8.0,
-    "original_half_samples": 8.0,
-    "omega": 0,
-    "phi": -1.5707963267948966,
-    "kappa": 3.141592653589793,
-    "semi_major_axis":0.01,
-    "semi_minor_axis":0.01, 
-    "x_sensor_origin": 1000,
-    "y_sensor_origin": 0,
-    "z_sensor_origin": 0,
-    "x_sensor_velocity": 1,
-    "y_sensor_velocity": 0,
-    "z_sensor_velocity": 0,
-    "x_sun_position": 100,
-    "y_sun_position": 100,
-    "z_sun_position": 0,
-    "odt_x": [
-        0.0,
-        1.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0
-    ],
-    "odt_y": [
-        0.0,
-        1.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0,
-        0.0
-    ],
-    "starting_detector_line": 0.0,
-    "starting_detector_sample": 0.0
+	"name_model" : "USGS_ASTRO_FRAME_SENSOR_MODEL",
+	"center_ephemeris_time": 50,
+	"dt_ephemeris": 100,
+  "focal2pixel_lines": [0.0, 0.0, 10.0],
+  "focal2pixel_samples": [0.0, 10.0, 0.0],
+	"focal_length_model": {
+		"focal_length": 50,
+		"focal_epsilon": 1.0
+	},
+	"image_lines": 15,
+	"image_samples": 15,
+  "detector_center" : {
+    "line" : 7.5,
+    "sample" : 7.5
+  },
+	"interpolation_method": "lagrange",
+	"number_of_ephemerides": 1,
+	"optical_distortion": {
+		"transverse": {
+			"x": [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+			"y": [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+		}
+	},
+	"radii": {
+		"semimajor": 0.01,
+    "semiminor": 0.01,
+    "unit":"km"
+	},
+	"reference_height": {
+		"maxheight": 1,
+		"minheight": -1,
+		"unit": "m"
+	},
+	"sensor_position": {
+		"unit": "m",
+		"positions": [
+			[1000.0, 0.0, 0.0]
+		],
+		"velocities": [
+			[0.0, 0.0, 0.0]
+		]
+	},
+	"sensor_orientation": {
+		"quaternions": [
+			[0.0, -0.707106781186547, 0.0, 0.707106781186547]
+		]
+	},
+	"starting_detector_line": 0,
+	"starting_detector_sample": 0,
+	"starting_ephemeris_time": 0,
+	"sun_position": {
+		"unit": "m",
+		"positions": [
+			[100.0, 100.0, 0.0]
+		],
+		"velocities": [
+			[0.0, 0.0, 0.0]
+		]
+	}
 }
-- 
GitLab