diff --git a/CMakeLists.txt b/CMakeLists.txt index b2124098d26eaa850e5bd3f2fd42994fd7485a35..91467c370e07dce674c0f921273116e488aa9d3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(CMAKE_CXX_STANDARD 11) # Third Party Dependencies find_package(GSL REQUIRED) find_package(Eigen3 3.3 REQUIRED NO_MODULE) +find_package(PythonLibs REQUIRED COMPONENTS Development Interpreter Compiler) # Library setup add_library(ale SHARED @@ -34,14 +35,16 @@ target_include_directories(ale PRIVATE ${GSL_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIR} PUBLIC ${ALE_INCLUDE_DIRS}) # Setup for GoogleTest -find_package (Threads) +find_package(Threads) target_link_libraries(ale PRIVATE ${GSL_LIBRARIES} + ${PYTHON_LIBRARY} PUBLIC gtest ${CMAKE_THREAD_LIBS_INIT}) diff --git a/ale/__init__.py b/ale/__init__.py index 7fdacb91804e55d9f53cf08f3c87f3c38973b819..f2d46ca2575f049a9d174327036200f3c0d83b73 100644 --- a/ale/__init__.py +++ b/ale/__init__.py @@ -1 +1,2 @@ from . import drivers +from .drivers import load diff --git a/include/ale.h b/include/ale.h index 83e5ccea72fdeacc6eb3fc2865c2b98b4786f0a1..ff1810f5697d0b15b25c5a2c38cd95bd2dd6e80a 100644 --- a/include/ale.h +++ b/include/ale.h @@ -40,6 +40,7 @@ namespace ale { std::vector<double> coefficients, double time); double evaluatePolynomial(std::vector<double> coeffs, double time, int d); double interpolate(std::vector<double> points, std::vector<double> times, double time, interpolation interp, int d); + std::string load(std::string filename); } #endif // ALE_H diff --git a/notebooks/cpp_load.ipynb b/notebooks/cpp_load.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..40c8874edd2f819c95727b6c1591288e1eb4eb19 --- /dev/null +++ b/notebooks/cpp_load.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#pragma cling add_include_path(\"/Users/krodriguez-pr/repos/ale/include/\")\n", + "#pragma cling add_include_path(\"/Users/krodriguez-pr/repos/ale/include/json\")\n", + "#pragma cling add_include_path(\"/Users/krodriguez-pr/anaconda3/envs/ale/include/python3.7m\")\n", + "\n", + "#pragma cling load(\"/Users/krodriguez-pr/repos/ale/build/libale.dylib\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "#include \"Python.h\"\n", + "#include \"ale.h\"\n", + "\n", + "std::string test_lro_label =\n", + " \"PDS_VERSION_ID = PDS3\"\n", + " \"\"\n", + " \"/*FILE CHARACTERISTICS*/\"\n", + " \"RECORD_TYPE = FIXED_LENGTH\"\n", + " \"RECORD_BYTES = 5064\"\n", + " \"FILE_RECORDS = 13313\"\n", + " \"LABEL_RECORDS = 1\"\n", + " \"^IMAGE = 2\"\n", + " \"\"\n", + " \"/*DATA IDENTIFICATION*/\"\n", + " \"DATA_SET_ID = \\\"LRO-L-LROC-2-EDR-V1.0\\\"\"\n", + " \"ORIGINAL_PRODUCT_ID = nacl0002fc60\"\n", + " \"PRODUCT_ID = M128963531LE\"\n", + " \"MISSION_NAME = \\\"LUNAR RECONNAISSANCE ORBITER\\\"\"\n", + " \"MISSION_PHASE_NAME = \\\"NOMINAL MISSION\\\"\"\n", + " \"INSTRUMENT_HOST_NAME = \\\"LUNAR RECONNAISSANCE ORBITER\\\"\"\n", + " \"INSTRUMENT_HOST_ID = LRO\"\n", + " \"INSTRUMENT_NAME = \\\"LUNAR RECONNAISSANCE ORBITER CAMERA\\\"\"\n", + " \"INSTRUMENT_ID = LROC\"\n", + " \"LRO:PREROLL_TIME = 2010-05-20T02:57:44.373\"\n", + " \"START_TIME = 2010-05-20T02:57:44.720\"\n", + " \"STOP_TIME = 2010-05-20T02:57:49.235\"\n", + " \"LRO:SPACECRAFT_CLOCK_PREROLL_COUNT = \\\"1/296017064:22937\\\"\"\n", + " \"SPACECRAFT_CLOCK_START_COUNT = \\\"1/296017064:45694\\\"\"\n", + " \"SPACECRAFT_CLOCK_STOP_COUNT = \\\"1/296017069:13866\\\"\"\n", + " \"ORBIT_NUMBER = 4138\"\n", + " \"PRODUCER_ID = LRO_LROC_TEAM\"\n", + " \"PRODUCT_CREATION_TIME = 2013-09-16T19:57:12\"\n", + " \"PRODUCER_INSTITUTION_NAME = \\\"ARIZONA STATE UNIVERSITY\\\"\"\n", + " \"PRODUCT_TYPE = EDR\"\n", + " \"PRODUCT_VERSION_ID = \\\"v1.8\\\"\"\n", + " \"UPLOAD_ID = \\\"SC_2010140_0000_A_V01.txt\\\"\"\n", + " \"\"\n", + " \"/*DATA DESCRIPTION*/\"\n", + " \"TARGET_NAME = \\\"MOON\\\"\"\n", + " \"RATIONALE_DESC = \\\"TARGET OF OPPORTUNITY\\\"\"\n", + " \"FRAME_ID = LEFT\"\n", + " \"DATA_QUALITY_ID = \\\"0\\\"\"\n", + " \"DATA_QUALITY_DESC = \\\"The DATA_QUALITY_ID is set to an 8-bit\"\n", + " \" value that encodes the following data quality information for the\"\n", + " \" observation. For each bit a value of 0 means FALSE and a value of 1 means\"\n", + " \" TRUE. More information about the data quality ID can be found in the LROC\"\n", + " \" EDR/CDR SIS, section 3.3 'Label and Header Descriptions'.\"\n", + " \" Bit 1: Temperature of focal plane array is out of bounds.\"\n", + " \" Bit 2: Threshold for saturated pixels is reached.\"\n", + " \" Bit 3: Threshold for under-saturated pixels is reached.\"\n", + " \" Bit 4: Observation is missing telemetry packets.\"\n", + " \" Bit 5: SPICE information is bad or missing.\"\n", + " \" Bit 6: Observation or housekeeping information is bad or missing.\"\n", + " \" Bit 7: Spare.\"\n", + " \" Bit 8: Spare.\\\"\"\n", + " \"\"\n", + " \"/*ENVIRONMENT*/\"\n", + " \"LRO:TEMPERATURE_SCS = 4.51 <degC>\"\n", + " \"LRO:TEMPERATURE_FPA = 17.88 <degC>\"\n", + " \"LRO:TEMPERATURE_FPGA = -12.33 <degC>\"\n", + " \"LRO:TEMPERATURE_TELESCOPE = 5.91 <degC>\"\n", + " \"LRO:TEMPERATURE_SCS_RAW = 2740\"\n", + " \"LRO:TEMPERATURE_FPA_RAW = 2107\"\n", + " \"LRO:TEMPERATURE_FPGA_RAW = 3418\"\n", + " \"LRO:TEMPERATURE_TELESCOPE_RAW = 2675\"\n", + " \"\"\n", + " \"/*IMAGING PARAMETERS*/\"\n", + " \"CROSSTRACK_SUMMING = 1\"\n", + " \"BANDWIDTH = 300 <nm>\"\n", + " \"CENTER_FILTER_WAVELENGTH = 600 <nm>\"\n", + " \"LINE_EXPOSURE_DURATION = 0.337600 <ms>\"\n", + " \"LRO:LINE_EXPOSURE_CODE = 0\"\n", + " \"LRO:DAC_RESET_LEVEL = 198\"\n", + " \"LRO:CHANNEL_A_OFFSET = 60\"\n", + " \"LRO:CHANNEL_B_OFFSET = 123\"\n", + " \"LRO:COMPAND_CODE = 3\"\n", + " \"LRO:LINE_CODE = 13\"\n", + " \"LRO:BTERM = (0,16,69,103,128)\"\n", + " \"LRO:MTERM = (0.5,0.25,0.125,0.0625,0.03125)\"\n", + " \"LRO:XTERM = (0,64,424,536,800)\"\n", + " \"LRO:COMPRESSION_FLAG = 1\"\n", + " \"LRO:MODE = 7\"\n", + " \"\"\n", + " \"/*DATA OBJECT*/\"\n", + " \"OBJECT = IMAGE\"\n", + " \" LINES = 13312\"\n", + " \" LINE_SAMPLES = 5064\"\n", + " \" SAMPLE_BITS = 8\"\n", + " \" SAMPLE_TYPE = LSB_INTEGER\"\n", + " \" UNIT = \\\"RAW_INSTRUMENT_COUNT\\\"\"\n", + " \" MD5_CHECKSUM = \\\"0fe91f4b2e93083ee0093e7c8d05f3bc\\\"\"\n", + " \"END_OBJECT = IMAGE\"\n", + " \"END\";" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "Standard Exception", + "evalue": "Calling the load method failed.", + "output_type": "error", + "traceback": [ + "Standard Exception: Calling the load method failed." + ] + } + ], + "source": [ + "ale::load(test_lro_label);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++11", + "language": "C++11", + "name": "xeus-cling-cpp11" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "c++", + "version": "-std=c++11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/ale.cpp b/src/ale.cpp index d522513200c413725556088559453f9ac590ecc0..27e4e4127a507da2bf5988c622ffa9f722651cc3 100644 --- a/src/ale.cpp +++ b/src/ale.cpp @@ -9,6 +9,9 @@ #include <Eigen/Core> #include <Eigen/Geometry> +#include <iostream> +#include <Python.h> + #include <string> #include <iostream> #include <stdexcept> @@ -260,4 +263,50 @@ namespace ale { return result; } + + +std::string load(std::string filename) { + + // Initialize the Python interpreter. + Py_Initialize(); + + // Import the file as a Python module. + PyObject *pModule = PyImport_Import(PyUnicode_FromString("ale")); + + // Create a dictionary for the contents of the module. + PyObject *pDict = PyModule_GetDict(pModule); + + // Get the add method from the dictionary. + PyObject *pFunc = PyDict_GetItemString(pDict, "load"); + + // Create a Python tuple to hold the arguments to the method. + PyObject *pArgs = PyTuple_New(1); + + // Set the Python int as the first and second arguments to the method. + PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(filename.c_str())); + + // Call the function with the arguments. + PyObject* pResult = PyObject_CallObject(pFunc, pArgs); + + // Print a message if calling the method failed. + if(pResult == NULL) { + throw invalid_argument("Calling the load method failed."); + } + + char *cResult = 0; + if (PyUnicode_Check(pResult)) { + PyObject * temp_bytes = PyUnicode_AsEncodedString(pResult, "UTF-8", "strict"); // Owned reference + if (temp_bytes != NULL) { + cResult = PyBytes_AS_STRING(temp_bytes); // Borrowed pointer + cResult = strdup(cResult); + Py_DECREF(temp_bytes); + } else { + // some error handling + } + } + + Py_Finalize(); + + return std::string(cResult); +} } diff --git a/tests/pytests/test_lro_drivers.py b/tests/pytests/test_lro_drivers.py index 2e0bd6dae3c09d148edc39a96b93679406378825..51a32eac6d3e3e5f2e0328011d15f180e5516a25 100644 --- a/tests/pytests/test_lro_drivers.py +++ b/tests/pytests/test_lro_drivers.py @@ -116,3 +116,5 @@ def test_lro_creation(lro_lroclabel): with LRO_LROC(lro_lroclabel) as m: d = m.to_dict() assert isinstance(d, dict) + from ale import load + print(load(lro_lroclabel))