Skip to content
Snippets Groups Projects
Select Git revision
  • 2b492b9217710813fe90fa25733f9aa549f6e8be
  • master default protected
  • feature/kasm_0.9.2
3 results

build.sh

Blame
  • UsgsAstroFramePlugin.cpp 22.68 KiB
    #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();
    }