diff --git a/.travis.yml b/.travis.yml index e444fc2362c6dfb4bbf3ee8642b6cf980eabce60..45beed915d37c5b4a0c55ebd6164a8c644e91dc7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,26 +4,57 @@ os: - linux - osx +env: + - PYTHON_VERSION=3.6 + - PYTHON_VERSION=3.7 + +before_install: + # Install a supported cmake version (>= 3.10) + - | + if [ "$TRAVIS_OS_NAME" == "linux" ]; then + wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; + else + curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh; + fi + - bash miniconda.sh -b -p $HOME/miniconda + - export PATH="$HOME/miniconda/bin:$PATH" + + # Set up the env + - conda create -q -n test -y python=$PYTHON_VERSION + - source activate test + + # Add the necessary channels + - conda config --add channels usgs-astrogeology + - conda config --add channels conda-forge + install: -# Install a supported cmake version (>= 3.10) -- | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - else - curl -o miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh; - fi -- bash miniconda.sh -b -p $HOME/miniconda -- export PATH="$HOME/miniconda/bin:$PATH" -# Add the channels that conda build is going to use -- conda config --add channels usgs-astrogeology -- conda config --add channels conda-forge # Setup to do the build -- conda install -y -q conda-build anaconda-client + - conda env update -n test -f environment.yml + - conda install -c conda-forge -y pytest + - | + if [ "$TRAVIS_OS_NAME" == "linux" ]; then + conda install -y -c conda-forge/label/gcc7 python=$PYTHON_VERSION + conda install -y gcc_linux-64 gxx_linux-64; + fi script: -# Build and upload on success -- if [ "${TRAVIS_PULL_REQUEST}" = "false" ] ;then - conda config --set anaconda_upload yes && conda build --token $CONDA_UPLOAD_TOKEN recipe -q; - else - conda build recipe -q; - fi + - mkdir build && cd build + - cmake .. && make + - cd python && python setup.py install && cd .. + - | + if [ "$TRAVIS_OS_NAME" == "linux" ]; then + pytest python/tests/ --lib fixture/libfixturecsm.so; + else + pytest python/tests/ --lib fixture/libfixturecsm.dylib; + fi + +after_success: + # - source deactivate + - conda install -y -q conda-build anaconda-client + - cd ../ # Step out of the python dir and out of the build dir + - pwd + - if [ "${TRAVIS_PULL_REQUEST}" = "false" ] ;then + conda build --token $CONDA_UPLOAD_TOKEN recipe -q; + else + conda build recipe -q; + fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 492658052283c6cb92c487c36eda253eedce3ebb..d81112e22a2db8b06ee3daf13ad3e387dcfd1c55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,5 @@ cmake_minimum_required(VERSION 3.10) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) -add_subdirectory(python) \ No newline at end of file +add_subdirectory(python) +add_subdirectory(fixture) \ No newline at end of file diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000000000000000000000000000000000000..c02ecc76b2d80e52fea3f1f53976e80e51fc09bb --- /dev/null +++ b/environment.yml @@ -0,0 +1,10 @@ +name: csmswig +channels: + - conda-forge + - usgs-astrogeology +dependencies: + - cmake >= 3.10 + - libcsm + - python + - swig + - numpy \ No newline at end of file diff --git a/fixture/CMakeLists.txt b/fixture/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6cbbf0d57a9e6a678bb359f93134598cfc2a448d --- /dev/null +++ b/fixture/CMakeLists.txt @@ -0,0 +1,16 @@ +find_path(CSM_INCLUDE_DIR NAMES "csm.h" + PATH_SUFFIXES "csm" + PATHS $ENV{CONDA_PREFIX}/include/) +find_library(CSM_LIBRARY csmapi PATHS $ENV{CONDA_PREFIX}/lib) + +add_library(fixturecsm SHARED + model.cpp + plugin.cpp) + +target_include_directories(fixturecsm + PRIVATE + ${CSM_INCLUDE_DIR} +) + +target_link_libraries(fixturecsm + ${CSM_LIBRARY}) \ No newline at end of file diff --git a/fixture/model.cpp b/fixture/model.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15bc633c6e77f29b3c866b3fb7cb2eb8cce0e005 --- /dev/null +++ b/fixture/model.cpp @@ -0,0 +1,485 @@ +#include "model.h" + +#include <iomanip> +#include <iostream> +#include <sstream> + +#include <Error.h> +#include <Version.h> + +using namespace std; + +FixtureSensorModel::FixtureSensorModel() { + +} + + +FixtureSensorModel::~FixtureSensorModel() {} + +csm::ImageCoord FixtureSensorModel::groundToImage(const csm::EcefCoord &groundPt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + csm::ImageCoord imagecoord = csm::ImageCoord(0,0); + + // Check that the pixel is actually in the image + if ((groundPt.x < 0) || (groundPt.y < 0)) { + csm::ImageCoord imagecoord = csm::ImageCoord(-1,-1); + throw csm::Warning( + csm::Warning::IMAGE_COORD_OUT_OF_BOUNDS, + "The image coordinate is out of bounds of the image size.", + "UsgsAstroLsSensorModel::groundToImage"); + }; + return imagecoord; +} + +csm::ImageCoord FixtureSensorModel::groundToImage( + const csm::EcefCoord& groundPt, + const std::vector<double>& adjustments, + double desired_precision, + double* achieved_precision, + csm::WarningList* warnings ) const { + + return csm::ImageCoord(0, 0); +} + + +csm::ImageCoordCovar FixtureSensorModel::groundToImage(const csm::EcefCoordCovar &groundPt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::groundToImage"); +} + + +csm::EcefCoord FixtureSensorModel::imageToGround(const csm::ImageCoord &imagePt, + double height, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + return csm::EcefCoord(0, 0, 0); +} + + +csm::EcefCoordCovar FixtureSensorModel::imageToGround(const csm::ImageCoordCovar &imagePt, double height, + double heightVariance, double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::imageToGround"); +} + + +csm::EcefLocus FixtureSensorModel::imageToProximateImagingLocus(const csm::ImageCoord &imagePt, + const csm::EcefCoord &groundPt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + // Ignore the ground point? + return imageToRemoteImagingLocus(imagePt); +} + + +csm::EcefLocus FixtureSensorModel::imageToRemoteImagingLocus(const csm::ImageCoord &imagePt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + return csm::EcefLocus(0,0,0,0,0,0); +} + + +csm::ImageCoord FixtureSensorModel::getImageStart() const { + return csm::ImageCoord(); +} + + +csm::ImageVector FixtureSensorModel::getImageSize() const { + return csm::ImageVector(); +} + + +std::pair<csm::ImageCoord, csm::ImageCoord> FixtureSensorModel::getValidImageRange() const { + csm::ImageCoord min_pt(0, 0); + csm::ImageCoord max_pt(1,1); + return std::pair<csm::ImageCoord, csm::ImageCoord>(min_pt, max_pt); +} + + +std::pair<double, double> FixtureSensorModel::getValidHeightRange() const { + return std::pair<double, double>(0, 1); +} + + +csm::EcefVector FixtureSensorModel::getIlluminationDirection(const csm::EcefCoord &groundPt) const { + // ground (body-fixed) - sun (body-fixed) gives us the illumination direction. + return csm::EcefVector(0,0,0); +} + + +double FixtureSensorModel::getImageTime(const csm::ImageCoord &imagePt) const { + + // check if the image point is in range + if (imagePt.samp >= 0 && + imagePt.samp <= 1 && + imagePt.line >= 0 && + imagePt.line <= 1) { + return 0; + } + else { + throw csm::Error(csm::Error::BOUNDS, + "Image Coordinate out of Bounds", + "FixtureSensorModel::getImageTime"); + } +} + + +csm::EcefCoord FixtureSensorModel::getSensorPosition(const csm::ImageCoord &imagePt) const { + + // check if the image point is in range + if (imagePt.samp >= 0 && + imagePt.samp <= 1 && + imagePt.line >= 0 && + imagePt.line <= 1) { + return csm::EcefCoord(); + } + else { + throw csm::Error(csm::Error::BOUNDS, + "Image Coordinate out of Bounds", + "FixtureSensorModel::getSensorPosition"); + } +} + +csm::EcefCoord FixtureSensorModel::getSensorPosition(double time) const { + if (time == 0){ + return csm::EcefCoord(); + } else { + std::string aMessage = "Valid image time is 0.0"; + throw csm::Error(csm::Error::BOUNDS, + aMessage, + "FixtureSensorModel::getSensorPosition"); + } +} + + +csm::EcefVector FixtureSensorModel::getSensorVelocity(const csm::ImageCoord &imagePt) const { + // Make sure the passed coordinate is with the image dimensions. + if (imagePt.samp < 0.0 || imagePt.samp > 1 || + imagePt.line < 0.0 || imagePt.line > 1) { + throw csm::Error(csm::Error::BOUNDS, "Image coordinate out of bounds.", + "FixtureSensorModel::getSensorVelocity"); + } + + // Since this is a frame, just return the sensor velocity the ISD gave us. + return csm::EcefVector(0,0,0); +} + + +csm::EcefVector FixtureSensorModel::getSensorVelocity(double time) const { + if (time == 0){ + return csm::EcefVector(0,0,0); + } else { + std::string aMessage = "Valid image time is 0.0"; + throw csm::Error(csm::Error::BOUNDS, + aMessage, + "FixtureSensorModel::getSensorVelocity"); + } +} + + +csm::RasterGM::SensorPartials FixtureSensorModel::computeSensorPartials(int index, + const csm::EcefCoord &groundPt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + csm::ImageCoord img_pt = groundToImage(groundPt, desiredPrecision, achievedPrecision); + + return computeSensorPartials(index, img_pt, groundPt, desiredPrecision, achievedPrecision); +} + +csm::RasterGM::SensorPartials FixtureSensorModel::computeSensorPartials(int index, + const csm::ImageCoord &imagePt, + const csm::EcefCoord &groundPt, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const { + + csm::RasterGM::SensorPartials partials; + partials.first = 0; + partials.second = 0; + + return partials; + +} + +std::vector<csm::RasterGM::SensorPartials> FixtureSensorModel::computeAllSensorPartials( + const csm::ImageCoord& imagePt, + const csm::EcefCoord& groundPt, + csm::param::Set pset, + double desiredPrecision, + double *achievedPrecision, + csm::WarningList *warnings) const + { + std::vector<csm::RasterGM::SensorPartials> partials; + for (int i=0;i<3;i++){ + csm::RasterGM::SensorPartials partial; + partial.first = 0; + partial.second = 0; + partials.push_back(partial); + } + return partials; + } + +std::vector<csm::RasterGM::SensorPartials> FixtureSensorModel::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); + } + +std::vector<double> FixtureSensorModel::computeGroundPartials(const csm::EcefCoord &groundPt) const { + std::vector<double> partials(6, 0.0); + return partials; +} + + +const csm::CorrelationModel& FixtureSensorModel::getCorrelationModel() const { + return csm::NoCorrelationModel(); +} + + +std::vector<double> FixtureSensorModel::getUnmodeledCrossCovariance(const csm::ImageCoord &pt1, + const csm::ImageCoord &pt2) const { + + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getUnmodeledCrossCovariance"); +} + + +csm::Version FixtureSensorModel::getVersion() const { + return csm::Version(0,1,0); +} + + +std::string FixtureSensorModel::getModelName() const { + return "FixtureSensorModel"; +} + + +std::string FixtureSensorModel::getPedigree() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getPedigree"); +} + + +std::string FixtureSensorModel::getImageIdentifier() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getImageIdentifier"); +} + + +void FixtureSensorModel::setImageIdentifier(const std::string& imageId, + csm::WarningList* warnings) { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::setImageIdentifier"); +} + + +std::string FixtureSensorModel::getSensorIdentifier() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getSensorIdentifier"); +} + + +std::string FixtureSensorModel::getPlatformIdentifier() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getPlatformIdentifier"); +} + + +std::string FixtureSensorModel::getCollectionIdentifier() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getCollectionIdentifier"); +} + + +std::string FixtureSensorModel::getTrajectoryIdentifier() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getTrajectoryIdentifier"); +} + + +std::string FixtureSensorModel::getSensorType() const { + return CSM_SENSOR_TYPE_EO; +} + + +std::string FixtureSensorModel::getSensorMode() const { + return CSM_SENSOR_MODE_FRAME; +} + + +std::string FixtureSensorModel::getReferenceDateAndTime() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getReferenceDateAndTime"); +} + + +std::string FixtureSensorModel::getModelState() const { + std::string state = "STATE"; + return state; +} + + +void FixtureSensorModel::replaceModelState(const std::string& modelState) { + +} + + +csm::EcefCoord FixtureSensorModel::getReferencePoint() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getReferencePoint"); +} + + +void FixtureSensorModel::setReferencePoint(const csm::EcefCoord &groundPt) { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::setReferencePoint"); +} + + +int FixtureSensorModel::getNumParameters() const { + return 6; +} + + +std::string FixtureSensorModel::getParameterName(int index) const { + return "Name"; +} + + +std::string FixtureSensorModel::getParameterUnits(int index) const { + if (index < 3) { + return "m"; + } + else { + return "radians"; + } +} + + +bool FixtureSensorModel::hasShareableParameters() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::hasShareableParameters"); +} + + +bool FixtureSensorModel::isParameterShareable(int index) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::isParameterShareable"); +} + + +csm::SharingCriteria FixtureSensorModel::getParameterSharingCriteria(int index) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getParameterSharingCriteria"); +} + + +double FixtureSensorModel::getParameterValue(int index) const { + return 0; +} + + +void FixtureSensorModel::setParameterValue(int index, double value) { +} + + +csm::param::Type FixtureSensorModel::getParameterType(int index) const { + return csm::param::REAL; +} + + +void FixtureSensorModel::setParameterType(int index, csm::param::Type pType) { +} + + +double FixtureSensorModel::getParameterCovariance(int index1, int index2) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getParameterCovariance"); +} + + +void FixtureSensorModel::setParameterCovariance(int index1, int index2, double covariance) { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::setParameterCovariance"); +} + + +int FixtureSensorModel::getNumGeometricCorrectionSwitches() const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getNumGeometricCorrectionSwitches"); +} + + +std::string FixtureSensorModel::getGeometricCorrectionName(int index) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getGeometricCorrectionName"); +} + + +void FixtureSensorModel::setGeometricCorrectionSwitch(int index, + bool value, + csm::param::Type pType) { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::setGeometricCorrectionSwitch"); +} + + +bool FixtureSensorModel::getGeometricCorrectionSwitch(int index) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getGeometricCorrectionSwitch"); +} + + +std::vector<double> FixtureSensorModel::getCrossCovarianceMatrix( + const GeometricModel &comparisonModel, + csm::param::Set pSet, + const GeometricModelList &otherModels) const { + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "FixtureSensorModel::getCrossCovarianceMatrix"); +} \ No newline at end of file diff --git a/fixture/model.h b/fixture/model.h new file mode 100644 index 0000000000000000000000000000000000000000..094fe73b9fda6c25e3a2acf23cfdae864db13ca6 --- /dev/null +++ b/fixture/model.h @@ -0,0 +1,203 @@ +#ifndef __SENSORMODEL_H +#define __SENSORMODEL_H + +#include <RasterGM.h> +#include <SettableEllipsoid.h> +#include <CorrelationModel.h> + + +class FixtureSensorModel : public csm::RasterGM, virtual public csm::SettableEllipsoid +{ +public: + FixtureSensorModel(); + ~FixtureSensorModel(); + + virtual csm::ImageCoord groundToImage( + const csm::EcefCoord& groundPt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::ImageCoordCovar groundToImage( + const csm::EcefCoordCovar& groundPt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::EcefCoord imageToGround( + const csm::ImageCoord& imagePt, + double height, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::EcefCoordCovar imageToGround( + const csm::ImageCoordCovar& imagePt, + double height, + double heightVariance, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::EcefLocus imageToProximateImagingLocus( + const csm::ImageCoord& imagePt, + const csm::EcefCoord& groundPt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::EcefLocus imageToRemoteImagingLocus( + const csm::ImageCoord& imagePt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::ImageCoord getImageStart() const; + + virtual csm::ImageVector getImageSize() const; + + virtual std::pair<csm::ImageCoord, csm::ImageCoord> getValidImageRange() const; + + virtual std::pair<double, double> getValidHeightRange() const; + + virtual csm::EcefVector getIlluminationDirection(const csm::EcefCoord& groundPt) const; + + virtual double getImageTime(const csm::ImageCoord& imagePt) const; + + virtual csm::EcefCoord getSensorPosition(const csm::ImageCoord& imagePt) const; + + virtual csm::EcefCoord getSensorPosition(double time) const; + + virtual csm::EcefVector getSensorVelocity(const csm::ImageCoord& imagePt) const; + + virtual csm::EcefVector getSensorVelocity(double time) const; + + + virtual csm::RasterGM::SensorPartials computeSensorPartials( + int index, + const csm::EcefCoord& groundPt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual csm::RasterGM::SensorPartials computeSensorPartials( + int index, + const csm::ImageCoord& imagePt, + const csm::EcefCoord& groundPt, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual std::vector<csm::RasterGM::SensorPartials> computeAllSensorPartials( + const csm::EcefCoord& groundPt, + csm::param::Set pSet = csm::param::VALID, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual std::vector<csm::RasterGM::SensorPartials> computeAllSensorPartials( + const csm::ImageCoord& imagePt, + const csm::EcefCoord& groundPt, + csm::param::Set pSet = csm::param::VALID, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; + + virtual std::vector<double> computeGroundPartials(const csm::EcefCoord& groundPt) const; + + virtual const csm::CorrelationModel& getCorrelationModel() const; + + virtual std::vector<double> getUnmodeledCrossCovariance( + const csm::ImageCoord& pt1, + const csm::ImageCoord& pt2) const; + + virtual csm::EcefCoord getReferencePoint() const; + + virtual void setReferencePoint(const csm::EcefCoord& groundPt); + + virtual int getNumParameters() const; + + virtual std::string getParameterName(int index) const; + + virtual std::string getParameterUnits(int index) const; + + virtual bool hasShareableParameters() const; + + virtual bool isParameterShareable(int index) const; + + virtual csm::SharingCriteria getParameterSharingCriteria(int index) const; + + virtual double getParameterValue(int index) const; + + virtual void setParameterValue(int index, double value); + + virtual csm::param::Type getParameterType(int index) const; + + virtual void setParameterType(int index, csm::param::Type pType); + + virtual double getParameterCovariance( + int index1, + int index2) const; + + virtual void setParameterCovariance( + int index1, + int index2, + double covariance); + + virtual int getNumGeometricCorrectionSwitches() const; + + virtual std::string getGeometricCorrectionName(int index) const; + + virtual void setGeometricCorrectionSwitch(int index, + bool value, + csm::param::Type pType); + + virtual bool getGeometricCorrectionSwitch(int index) const; + + virtual std::vector<double> getCrossCovarianceMatrix( + const csm::GeometricModel& comparisonModel, + csm::param::Set pSet = csm::param::VALID, + const csm::GeometricModel::GeometricModelList& otherModels = csm::GeometricModel::GeometricModelList()) const; + + virtual csm::Version getVersion() const; + + virtual std::string getModelName() const; + + virtual std::string getPedigree() const; + + virtual std::string getImageIdentifier() const; + + virtual void setImageIdentifier( + const std::string& imageId, + csm::WarningList* warnings = NULL); + + virtual std::string getSensorIdentifier() const; + + virtual std::string getPlatformIdentifier() const; + + virtual std::string getCollectionIdentifier() const; + + virtual std::string getTrajectoryIdentifier() const; + + virtual std::string getSensorType() const; + + virtual std::string getSensorMode() const; + + virtual std::string getReferenceDateAndTime() const; + + virtual std::string getModelState() const; + + virtual void replaceModelState(const std::string& argState); + + + +private: + // This private form of the g2i method is used to ensure thread safety. + virtual csm::ImageCoord groundToImage( + const csm::EcefCoord& groundPt, + const std::vector<double> &adjustments, + double desiredPrecision = 0.001, + double* achievedPrecision = NULL, + csm::WarningList* warnings = NULL) const; +}; +#endif diff --git a/fixture/plugin.cpp b/fixture/plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e98be4b70e0f2b0795e94c39a2d11bad4b23948 --- /dev/null +++ b/fixture/plugin.cpp @@ -0,0 +1,161 @@ +#include "plugin.h" + +#include "model.h" + +#include <cstdlib> +#include <string> + +#include <csm.h> +#include <Error.h> +#include <Plugin.h> +#include <Warning.h> +#include <Version.h> + +#ifdef _WIN32 +# define DIR_DELIMITER_STR "\\" +#else +# define DIR_DELIMITER_STR "/" +#endif + + +// Declaration of static variables +const std::string PluginFixture::_PLUGIN_NAME = "PluginFixture"; +const std::string PluginFixture::_MANUFACTURER_NAME = "Fakers"; +const std::string PluginFixture::_RELEASE_DATE = "20170425"; +const int PluginFixture::_N_SENSOR_MODELS = 1; +const int PluginFixture::_NUM_ISD_KEYWORDS = 0; +const std::string PluginFixture::_ISD_KEYWORD[] = {}; + +const int PluginFixture::_NUM_STATE_KEYWORDS = 0; +const std::string PluginFixture::_STATE_KEYWORD[] = {}; + + +// Static Instance of itself +const PluginFixture PluginFixture::m_registeredPlugin; + +PluginFixture::PluginFixture() { +} + + +PluginFixture::~PluginFixture() { +} + + +std::string PluginFixture::getPluginName() const { + return _PLUGIN_NAME; +} + + +std::string PluginFixture::getManufacturer() const { + return _MANUFACTURER_NAME; +} + + +std::string PluginFixture::getReleaseDate() const { + return _RELEASE_DATE; +} + + +csm::Version PluginFixture::getCsmVersion() const { + return CURRENT_CSM_VERSION; +} + + +size_t PluginFixture::getNumModels() const { + return _N_SENSOR_MODELS; +} + + +std::string PluginFixture::getModelName(size_t modelIndex) const { + return "FixtureSensorModel"; +} + + +std::string PluginFixture::getModelFamily(size_t modelIndex) const { + return CSM_RASTER_FAMILY; +} + + +csm::Version PluginFixture::getModelVersion(const std::string &modelName) const { + return csm::Version(1, 0, 0); +} + + +bool PluginFixture::canModelBeConstructedFromState(const std::string &modelName, + const std::string &modelState, + csm::WarningList *warnings) const { + bool constructible = true; + if (modelName == "False") { + constructible = false; + } + return constructible; +} + + +bool PluginFixture::canModelBeConstructedFromISD(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + return canISDBeConvertedToModelState(imageSupportData, modelName, warnings); +} + + +csm::Model *PluginFixture::constructModelFromState(const std::string& modelState, + csm::WarningList *warnings) const { + csm::Model *sensor_model = 0; + + // Instantiate the model + FixtureSensorModel* mdsensor_model = new FixtureSensorModel(); + +sensor_model = mdsensor_model; +return sensor_model; +} + + +csm::Model *PluginFixture::constructModelFromISD(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + + if (modelName == "False") { + std::string errorMessage; + throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, + "IntentionalError", + "PluginFixture::constructModelFromISD()"); + } + + FixtureSensorModel *sensorModel = new FixtureSensorModel(); + return sensorModel; +} + + +std::string PluginFixture::getModelNameFromModelState(const std::string &modelState, + csm::WarningList *warnings) const { + + if (modelState == "False"){ + throw csm::Error(csm::Error::INVALID_SENSOR_MODEL_STATE, + "IntentionalError", + "PluginFixture::constructModelFromISD()"); + } + return "FixtureSensorModel"; +} + + +bool PluginFixture::canISDBeConvertedToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + bool convertible = true; + if (modelName == "False"){ + convertible = false; + } + + return convertible; +} + + +std::string PluginFixture::convertISDToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + csm::Model* sensor_model = constructModelFromISD( + imageSupportData, modelName); + + return sensor_model->getModelState(); +} diff --git a/fixture/plugin.h b/fixture/plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..678ffa09fbf321dfd0491d98def763c4504b74a6 --- /dev/null +++ b/fixture/plugin.h @@ -0,0 +1,58 @@ +#ifndef PluginFixture_h +#define PluginFixture_h + +#include <string> + +#include <Plugin.h> +#include <Version.h> + + +class PluginFixture : public csm::Plugin { + + public: + PluginFixture(); + ~PluginFixture(); + + virtual std::string getPluginName() const; + virtual std::string getManufacturer() const; + virtual std::string getReleaseDate() const; + virtual csm::Version getCsmVersion() const; + virtual size_t getNumModels() const; + virtual std::string getModelName(size_t modelIndex) const; + virtual std::string getModelFamily(size_t modelIndex) const; + virtual csm::Version getModelVersion(const std::string &modelName) const; + virtual bool canModelBeConstructedFromState(const std::string &modelName, + const std::string &modelState, + csm::WarningList *warnings = NULL) const; + virtual bool canModelBeConstructedFromISD(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings = NULL) const; + virtual csm::Model *constructModelFromState(const std::string &modelState, + csm::WarningList *warnings = NULL) const; + virtual csm::Model *constructModelFromISD(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings = NULL) const; + virtual std::string getModelNameFromModelState(const std::string &modelState, + csm::WarningList *warnings = NULL) const; + virtual bool canISDBeConvertedToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings = NULL) const; + virtual std::string convertISDToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings = NULL) const; + + // TODO when implementing, add any other necessary members. + +private: + static const PluginFixture m_registeredPlugin; + static const std::string _PLUGIN_NAME; + static const std::string _MANUFACTURER_NAME; + static const std::string _RELEASE_DATE; + static const int _N_SENSOR_MODELS; + static const int _NUM_ISD_KEYWORDS; + static const std::string _ISD_KEYWORD[]; + static const int _NUM_STATE_KEYWORDS; + static const std::string _STATE_KEYWORD[]; +}; + +#endif diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 03f9cd64e0753ca581bf643d4fea5a1de44d9a2b..bd3edc7f7a66eff3d686b14f06d4a164f861bafd 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -11,7 +11,8 @@ set_source_files_properties(../csmapi.i find_path(CSM_INCLUDE_DIR NAMES csm.h PATH_SUFFIXES csm PATHS ${PYTHON_INCLUDE_DIR}/../) -find_library(CSM_LIBRARY NAMES csmapi) +find_library(CSM_LIBRARY NAMES csmapi + PATHS ${PYTHON_LIBRARY}/../) message("-- Found CSM Include: ${CSM_INCLUDE_DIR}") message("-- Found CSM Lib: ${CSM_LIBRARY}") @@ -25,10 +26,16 @@ set_target_properties(_csmapi PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SWIG_O swig_link_libraries(csmapi ${CSM_LIBRARY} ${PYTHON_LIBRARY}) # Build out a standard directory structure -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests) +# file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests) # Move the static files to move configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in - ${CMAKE_CURRENT_BINARY_DIR}/setup.py) + ${CMAKE_CURRENT_BINARY_DIR}/setup.py + COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py - ${CMAKE_CURRENT_BINARY_DIR}/csmapi/__init__.py) \ No newline at end of file + ${CMAKE_CURRENT_BINARY_DIR}/csmapi/__init__.py + COPYONLY) + +# Move the tests +file(COPY ${CMAKE_SOURCE_DIR}/python/tests + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/python/tests/conftest.py b/python/tests/conftest.py new file mode 100644 index 0000000000000000000000000000000000000000..f07a8049816877680b24d3deb626ca9590da17c3 --- /dev/null +++ b/python/tests/conftest.py @@ -0,0 +1,11 @@ +import ctypes + +import pytest + +def pytest_addoption(parser): + parser.addoption("--lib", action="store", default="libfixturecsm") + +@pytest.fixture(scope='module') +def loadlib(request): + libname = request.config.getoption("--lib") + return ctypes.CDLL(libname) \ No newline at end of file diff --git a/python/tests/test_functional.py b/python/tests/test_functional.py new file mode 100644 index 0000000000000000000000000000000000000000..cdbd15c6d9df57e6b58e8e75e27e6bdd4a8af9ec --- /dev/null +++ b/python/tests/test_functional.py @@ -0,0 +1,36 @@ +from distutils import dir_util +import json +import os + +import csmapi +import pytest + + +# Loads a CSM compliant lib defined by --lib= in the pytest invocation +def test_loadlib(loadlib): + assert loadlib is not None + +@pytest.fixture +def datadir(tmpdir, request): + ''' + Fixture responsible for searching a folder with the same name of test + module and, if available, moving all contents to a temporary directory so + tests can use them freely. + ''' + filename = request.module.__file__ + test_dir, _ = os.path.splitext(filename) + + if os.path.isdir(test_dir): + dir_util.copy_tree(test_dir, str(tmpdir)) + return tmpdir + +@pytest.fixture +def isd(datadir): + with open(datadir.join('simpleFramerISD.json')) as f: + i = csmapi.Isd.load(f) + return i + +@pytest.fixture +def plugin(): + plugin = csmapi.Plugin.findPlugin('PluginFixture') + return plugin diff --git a/tests/test_functional/isd.json b/python/tests/test_functional/isd.json similarity index 100% rename from tests/test_functional/isd.json rename to python/tests/test_functional/isd.json diff --git a/tests/test_functional/simpleFramerISD.json b/python/tests/test_functional/simpleFramerISD.json similarity index 100% rename from tests/test_functional/simpleFramerISD.json rename to python/tests/test_functional/simpleFramerISD.json diff --git a/python/tests/test_model.py b/python/tests/test_model.py new file mode 100644 index 0000000000000000000000000000000000000000..5999cceb8026f848825a5bdf5e42559b3aa409d6 --- /dev/null +++ b/python/tests/test_model.py @@ -0,0 +1,62 @@ +from distutils import dir_util +import json +import os + +import csmapi +import pytest + + +# Loads a CSM compliant lib defined by --lib= in the pytest invocation +def test_loadlib(loadlib): + assert loadlib is not None + + +@pytest.fixture +def isd(): + return csmapi.Isd() + +@pytest.fixture +def plugin(): + plugin = csmapi.Plugin.findPlugin('PluginFixture') + return plugin + +@pytest.fixture +def model(isd, plugin): + model_name = "FixtureSensorModel" + return plugin.constructModelFromISD(isd, model_name) + + +def test_instantiate_model(isd, plugin): + model_name = "FixtureSensorModel" + assert plugin.canModelBeConstructedFromISD(isd, model_name) + assert plugin.canISDBeConvertedToModelState(isd, model_name) + +def test_image_to_ground(model): + assert hasattr(model, 'imageToGround') + image_coord = csmapi.ImageCoord() + gnd = model.imageToGround(image_coord, 0) + assert gnd.x == 0 + assert gnd.y == 0 + assert gnd.z == 0 + +def test_model_version(model): + assert model.getVersion().version() == '0.1.0' + +def test_bad_get_image_time(model): + img_coord = csmapi.ImageCoord(-1,-1) + with pytest.raises(RuntimeError) as r: + model.getImageTime(img_coord) + +def test_ground_to_image(model): + assert hasattr(model, 'groundToImage') + gnd_coord = csmapi.EcefCoord(0,0,0) + img = model.groundToImage(gnd_coord, 0) + assert img.samp == 0 + assert img.line == 0 + +def test_bad_ground_to_image(model): + gnd_coord = csmapi.EcefCoord(-1, -1, 0) + with pytest.warns(Warning) as w: + img = model.groundToImage(gnd_coord, 0) + assert len(w) == 1 + \ No newline at end of file diff --git a/python/tests/test_plugin.py b/python/tests/test_plugin.py new file mode 100644 index 0000000000000000000000000000000000000000..2bd6d5d32b6e4a762dc28361aa58d311b97d3e1d --- /dev/null +++ b/python/tests/test_plugin.py @@ -0,0 +1,29 @@ +import csmapi +import pytest + +# Loads a CSM compliant lib defined by --lib= in the pytest invocation +def test_loadlib(loadlib): + assert loadlib is not None + +@pytest.fixture +def model(): + plugin = csmapi.Plugin + pl = plugin.findPlugin('PluginFixture') + return pl + +def test_plugin_size(): + + plugin_list = csmapi.Plugin.getList() + assert len(plugin_list) == 1 + +def test_plugin_name(): + plugin = csmapi.Plugin + pl = plugin.getList()[0] + plugin_name = pl.getPluginName() + assert plugin_name == "PluginFixture" + +def test_model_getNumModels(model): + assert model.getNumModels() == 1 + +def test_model_getModelName(model): + assert model.getModelName(0) == 'FixtureSensorModel' \ No newline at end of file diff --git a/rastergm.i b/rastergm.i index 60fc6c147401610f7af52fd9fa3803ed367a2d0f..ab8d93f014108e6e4e6d5f9fa69dab0cb856e724 100644 --- a/rastergm.i +++ b/rastergm.i @@ -10,12 +10,12 @@ $action } catch (const std::exception &e) { SWIG_exception(SWIG_RuntimeError, e.what()); + } catch (const csm::Warning &e) { + PyErr_WarnEx(PyExc_UserWarning, e.getMessage().c_str(), 1); } } - - %import model.i %import geometricmodel.i %import csm.i -%include RasterGM.h +%include RasterGM.h \ No newline at end of file diff --git a/recipe/build.sh b/recipe/build.sh index 2bcd1291a86cd7ab62792b4cd36dc2f8362a80e4..930bdd821875a6f11a9a120dca639a2371f1d95a 100644 --- a/recipe/build.sh +++ b/recipe/build.sh @@ -4,4 +4,5 @@ mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PREFIX -DANACONDA_PYTHON_VERBOSE=ON .. make cd python -$PYTHON setup.py install --single-version-externally-managed --record=/tmp/record.txt \ No newline at end of file +$PYTHON setup.py install --single-version-externally-managed --record=/tmp/record.txt +cd .. \ No newline at end of file diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 1c6f1ab520a18b4d470dd77940a7c28e2da06d9f..527e70d876086069b9bbe631f2daa06674639016 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -4,7 +4,7 @@ package: source: git_url: https://github.com/USGS-Astrogeology/CSM-Swig.git - + requirements: build: - {{ compiler('cxx') }} # [linux] diff --git a/tests/test_functional.py b/tests/test_functional.py deleted file mode 100644 index f7cf22d5a6e26c314454a018365266106d240ad0..0000000000000000000000000000000000000000 --- a/tests/test_functional.py +++ /dev/null @@ -1,51 +0,0 @@ -import ctypes -from distutils import dir_util -import json -import os - -import pytest - -import csmapi - -# Load a plugin with CSM compliant sensors -from ctypes.util import find_library - -lib = ctypes.CDLL(find_library('usgscsm.so')) - -@pytest.fixture -def datadir(tmpdir, request): - ''' - Fixture responsible for searching a folder with the same name of test - module and, if available, moving all contents to a temporary directory so - tests can use them freely. - ''' - filename = request.module.__file__ - test_dir, _ = os.path.splitext(filename) - - if os.path.isdir(test_dir): - dir_util.copy_tree(test_dir, str(tmpdir)) - return tmpdir - -@pytest.fixture -def isd(datadir): - with open(datadir.join('simpleFramerISD.json')) as f: - i = csmapi.Isd.load(f) - return i - - -@pytest.fixture -def plugin(): - plugin = csmapi.Plugin.findPlugin('UsgsAstroFramePluginCSM') - return plugin - -def test_isd_to_model_to_ground(isd, plugin): - model_name = "USGS_ASTRO_FRAME_SENSOR_MODEL" - assert plugin.canModelBeConstructedFromISD(isd, model_name) - assert plugin.canISDBeConvertedToModelState(isd, model_name) - - model = plugin.constructModelFromISD(isd, model_name) - assert model.getVersion().version() == '0.1.0' - image_coord = csmapi.ImageCoord(1,1) - assert hasattr(model, 'imageToGround') - gnd = model.imageToGround(image_coord, 0) - print(gnd.x, gnd.y, gnd.z) diff --git a/tests/test_plugin.py b/tests/test_plugin.py deleted file mode 100644 index 0fb697ade757e976bf71211bdd4e39773d0da795..0000000000000000000000000000000000000000 --- a/tests/test_plugin.py +++ /dev/null @@ -1,35 +0,0 @@ -import pytest - -import csmapi -import ctypes -from ctypes.util import find_library - -# Load a plugin with CSM compliant sensors -lib = ctypes.CDLL(find_library('usgscsm.so')) - -@pytest.fixture -def plugin(): - return csmapi.Plugin - -@pytest.fixture -def model(plugin): - pl = plugin.findPlugin('UsgsAstroFramePluginCSM') - return pl - -def test_plugin_size(plugin): - plugin_list = plugin.getList() - assert len(plugin_list) == 2 - -@pytest.mark.parametrize("plugin, index, expected_name", - [(plugin(), 0, 'UsgsAstroFramePluginCSM'), - (plugin(), 1, 'USGS_ASTRO_LINE_SCANNER_PLUGIN')]) -def test_plugin_name(plugin, index, expected_name): - pl = plugin.getList()[index] - plugin_name = pl.getPluginName() - assert plugin_name == expected_name - -def test_model_getNumModels(model): - assert model.getNumModels() == 1 - -def test_model_getModelName(model): - assert model.getModelName(0) == 'USGS_ASTRO_FRAME_SENSOR_MODEL' \ No newline at end of file diff --git a/warning.i b/warning.i index 04e85d4cc0b520b15ff4cf90fff77b58bccc6fd0..6656c55df7c1e7e5b8bf732c4845a3c6bd51aab7 100644 --- a/warning.i +++ b/warning.i @@ -3,4 +3,7 @@ #include "Warning.h" %} -%include Warning.h \ No newline at end of file +%include "std_list.i" +%include Warning.h + +%template(WarningList) std::list<csm::Warning>; \ No newline at end of file