Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ release.
### Added

- Added getTargetStatesRanged so a request can be made with start, end, and range of ETs instead of a list [#115](https://github.com/DOI-USGS/SpiceQL/pull/115)
- Added additional support for ISD to kernel generation [#116](https://github.com/DOI-USGS/SpiceQL/pull/116)

### 1.2.7

Expand Down
1 change: 1 addition & 0 deletions SpiceQL/include/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
**/

#include <cstddef>
#include <optional>
#include <string>
#include <vector>
Expand Down
39 changes: 39 additions & 0 deletions SpiceQL/include/spice_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,45 @@ namespace SpiceQL {
**/
static Type translateType(std::string type);

/**
* @brief Get Kernel extension
*
* @param type Kernel type string
* @return Kernel extension as string
*/
static std::string getExt(std::string type);

/**
* @brief Check if kernel type is binary
*
* @param type Kernel type string
* @return Whether kernel type is binary
*/
static bool isBinary(std::string type);

/**
* @brief Check if kernel type is text-based
*
* @param type Kernel type string
* @return Whether kernel type is text-based
*/
static bool isText(std::string type);

/**
* @brief Check if kernel type is CK
*
* @param type Kernel type string
* @return Whether kernel type is CK
*/
static bool isCk(std::string type);

/**
* @brief Check if kernel type is SPK
*
* @param type Kernel type string
* @return Whether kernel type is SPK
*/
static bool isSpk(std::string type);

/**
* @brief Switch between Quality enum to string
Expand Down
10 changes: 10 additions & 0 deletions SpiceQL/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ namespace SpiceQL {
std::string replaceAll(std::string str, const std::string &from, const std::string &to);


/**
* @brief turn a string into a vector with a deliminator
*
* @param s input string
* @param delim char deliminator
* @return std::vector<std::string>
*/
std::vector<std::string> split(const std::string& s, char delim);


/**
* @brief glob, but with json
*
Expand Down
36 changes: 34 additions & 2 deletions SpiceQL/src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@ namespace SpiceQL {
vector<string> default_KernelQualities = {"smithed", "reconstructed"};

json aliasMap = {
{"A15_METRIC", "apollo"},
{"AMICA", "amica"},
{"CHANDRAYAAN-1_M3", "m3"},
{"CHANDRAYAAN-1_MRFFR", "mrffr"},
{"CASSINI_ISS_NAC", "cassini"},
{"CASSINI_ISS_WAC", "cassini"},
{"CASSINI_VIMS_V", "cassini"},
{"Cassini-Huygens", "cassini"},
{"DAWN_FC2_FILTER_1", "fc2"},
{"DAWN_FC2_FILTER_2", "fc2"},
{"DAWN_FC2_FILTER_3", "fc2"},
Expand All @@ -46,6 +49,7 @@ namespace SpiceQL {
{"DAWN_FC2_FILTER_6", "fc2"},
{"DAWN_FC2_FILTER_7", "fc2"},
{"DAWN_FC2_FILTER_8", "fc2"},
{"DAWN_VIR_IR", "vir"},
{"GLL_SSI_PLATFORM", "galileo"},
{"HAYABUSA_AMICA", "amica"},
{"HAYABUSA_NIRS", "nirs"},
Expand All @@ -59,24 +63,35 @@ namespace SpiceQL {
{"LRO_MINIRF", "minirf"},
{"M10_VIDICON_A", "m10_vidicon_a"},
{"M10_VIDICON_B", "m10_vidicon_b"},
{"VIDICON_A", "m10_vidicon_a"},
{"MARS", "mro"},
{"MSGR_MDIS_WAC", "mdis"},
{"MSGR_MDIS_NAC", "mdis"},
{"MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA", "mdis"},
{"MEX_HRSC_HEAD", "hrsc"},
{"MEX_HRSC_SRC", "src"},
{"MEX_HRSC_IR", "hrsc"},
{"MGS_MOC_NA", "mgs"},
{"MGS_MOC_WA_RED", "mgs"},
{"MGS_MOC_WA_BLUE", "mgs"},
{"MRO_MARCI_VIS", "marci"},
{"MRO_MARCI_UV", "marci"},
{"MRO_MARCI_BASE", "marci"},
{"MRO_CTX", "ctx"},
{"MRO_HIRISE", "hirise"},
{"MRO_HIRISE_LOOK_DIRECTION", "hirise"},
{"MRO_CRISM_VNIR", "crism"},
{"NEAR EARTH ASTEROID RENDEZVOUS", ""},
{"NEAR EARTH ASTEROID RENDEZVOUS", "near"},
{"NEAR_MSI", "msi"},
{"NH_LORRI", "lorri"},
{"NH_LORRI_1X1", "lorri"},
{"NH_RALPH_LEISA", "leisa"},
{"NH_MVIC", "mvic_tdi"},
{"ISIS_NH_RALPH_LEISA", "leisa"},
{"ISIS_NH_RALPH_MVIC_METHANE", "mvic_framing"},
{"ISIS_NH_RALPH_MVIC_FT", "mvic_framing"},
{"M01_THEMIS_IR", "odyssey"},
{"M01_THEMIS_VIS", "odyssey"},
{"THEMIS_IR", "odyssey"},
{"THEMIS_VIS", "odyssey"},
{"LISM_MI-VIS1", "kaguya"},
Expand All @@ -101,16 +116,27 @@ namespace SpiceQL {
{"LISM_TC1_SDH", "kaguya"},
{"LISM_TC1_STH", "kaguya"},
{"LISM_TC1_SSH", "kaguya"},
{"SELENE", "kaguya"},
{"KAGUYA", "kaguya"},
{"SELENE MAIN ORBITER", "kaguya"},
{"LO1_HIGH_RESOLUTION_CAMERA", "lo"},
{"LO2_HIGH_RESOLUTION_CAMERA", "lo"},
{"LO3_HIGH_RESOLUTION_CAMERA", "lo"},
{"LO4_HIGH_RESOLUTION_CAMERA", "lo"},
{"LO5_HIGH_RESOLUTION_CAMERA", "lo"},
{"LO3_MED_RESOLUTION_CAMERA", "lo"},
{"NEPTUNE", "voyager1"},
{"SATURN", "voyager1"},
{"TGO_CASSIS", "cassis"},
{"TGO_CASSIS_CRU", "cassis"},
{"VIKING ORBITER 1", "viking1"},
{"VIKING_ORBITER_1", "viking1"},
{"VIKING ORBITER 2", "viking2"},
{"VIKING_ORBITER_2", "viking2"},
{"VO2_VISB", "viking2"},
{"VO2_VISA", "viking2"},
{"VO1_VISA", "viking1"},
{"VO1_VISB", "viking1"},
{"VG1_ISSNA", "voyager1"},
{"VG1_ISSWA", "voyager1"},
{"VG2_ISSNA", "voyager2"},
Expand All @@ -120,8 +146,14 @@ namespace SpiceQL {
{"High Resolution Camera", "clementine1"},
{"Long Wave Infrared Camera", "clementine1"},
{"Visual and Infrared Spectrometer", "vir"},
{"CLEM_HIRES", "clementine1"},
{"CLEM_UVVIS_A", "uvvis"},
{"CLEM_LWIR", "clementine1"},
{"CLEM_NIR", "nir"},
{"CH2", "chandrayaan2"},
{"CH-2", "chandrayaan2"}
{"CH-2", "chandrayaan2"},
{"ROS_VIRTIS-M_IR", "virtis"},
{"MSL_MASTCAM_LEFT", "msl"}
};

/**
Expand Down
63 changes: 58 additions & 5 deletions SpiceQL/src/io.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <sstream>

#include <fmt/format.h>
#include <ghc/fs_std.hpp>
Expand All @@ -10,6 +12,8 @@
#include "io.h"
#include "utils.h"

#include <spdlog/spdlog.h>


using namespace std;

Expand Down Expand Up @@ -74,7 +78,7 @@ namespace SpiceQL {
this->angularVelocities = angularVelocities;
this->comment = comment;
}


void writeCk(string path,
vector<vector<double>> quats,
Expand All @@ -90,9 +94,15 @@ namespace SpiceQL {
SpiceInt handle;

// convert times, but first, we need SCLK+LSK kernels
Kernel sclkKernel(sclk);
Kernel lskKernel(lsk);

// allow and furnish multiple sclks
std::vector<std::unique_ptr<Kernel>> sclkKernels;
if (!sclk.empty()) {
for (const std::string& sclkPath : split(sclk, ','))
sclkKernels.push_back(std::make_unique<Kernel>(sclkPath));
}
Kernel lskKernel(lsk);

for(auto &et : times) {
double sclkdp;
checkNaifErrors();
Expand All @@ -109,6 +119,33 @@ namespace SpiceQL {
ckopn_c(path.c_str(), "CK", comment.size(), &handle);
checkNaifErrors();

// Flatten the nested quaternions into a single contiguous array.
// CSPICE functions (like ckw03_c) are C-based and expect a pointer to a
// contiguous block of memory (SpiceDouble quats[][4]).
// A std::vector<std::vector<double>> stores inner vectors in fragmented
// locations on the heap; we must "flatten" them into a single ribbon
// of doubles so that pointer arithmetic works correctly inside SPICE.
vector<double> flatQuats;
flatQuats.reserve(quats.size() * 4);
for (const auto& q : quats) {
for (double d : q) {
flatQuats.push_back(d);
}
}

// Flatten angular velocities if they exist.
// Similar to quaternions, AV data must be contiguous (SpiceDouble av[][3]).
// We check if the input nested vector is non-empty before proceeding.
vector<double> flatAv;
if (!angularVelocities.empty()) {
flatAv.reserve(angularVelocities.size() * 3);
for (const auto& a : angularVelocities) {
for (double d : a) {
flatAv.push_back(d);
}
}
}

ckw03_c (handle,
times.at(0),
times.at(times.size()-1),
Expand All @@ -118,8 +155,8 @@ namespace SpiceQL {
segmentId.c_str(),
times.size(),
times.data(),
quats.data(),
(!angularVelocities.empty()) ? angularVelocities.data() : nullptr,
flatQuats.data(),
(!angularVelocities.empty()) ? flatAv.data() : nullptr,
times.size(),
times.data());
checkNaifErrors();
Expand All @@ -141,6 +178,22 @@ namespace SpiceQL {
vector<vector<double>> stateVelocities,
string segmentComment) {

if (stateTimes.empty() || statePositions.empty()) {
throw runtime_error("writeSpk: stateTimes and statePositions must be non-empty.");
}

// NAIF spkw13_c requires segment start time < end time. Single-epoch (e.g. from ISD) has start == end.
if (stateTimes.size() == 1) {
stateTimes.push_back(stateTimes.front() + 1E-6);
statePositions.push_back(statePositions.front());
if (!stateVelocities.empty()) {
stateVelocities.push_back(stateVelocities.front());
}
} else if (stateTimes.front() >= stateTimes.back()) {
throw runtime_error(
"writeSpk: segment start time must be less than end time (got start == end or reversed order).");
}

vector<vector<double>> states;

if (stateVelocities.empty()) {
Expand Down
36 changes: 34 additions & 2 deletions SpiceQL/src/spice_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,53 @@ namespace SpiceQL {
"reconstructed",
"smithed"};

const std::unordered_map<Kernel::Type, std::string> KERNEL_EXTS = { {Kernel::Type::CK, ".bc"},
{Kernel::Type::SPK, ".bsp"},
{Kernel::Type::FK, ".tf"},
{Kernel::Type::IK, ".ti"},
{Kernel::Type::LSK, ".tls"},
{Kernel::Type::MK, ".tm"},
{Kernel::Type::PCK, ".tpc"},
{Kernel::Type::SCLK, ".tsc"}};

string Kernel::translateType(Kernel::Type type) {
return KERNEL_TYPES[static_cast<int>(type)];
}


Kernel::Type Kernel::translateType(string type) {
auto res = findInVector<string>(KERNEL_TYPES, type);
auto res = findInVector<string>(KERNEL_TYPES, toLower(type));
if (res.first) {
return static_cast<Kernel::Type>(res.second);
}

throw invalid_argument(fmt::format("{} is not a valid kernel type", type));
};
}

std::string Kernel::getExt(std::string type) {
Kernel::Type ktype = translateType(type);
auto it = KERNEL_EXTS.find(ktype);
if (it != KERNEL_EXTS.end()) {
return it->second;
}
throw invalid_argument(fmt::format("{} is not a valid kernel type", type));
}

bool Kernel::isBinary(std::string type) {
return (isCk(type) || isSpk(type));
}

bool Kernel::isText(std::string type) {
return !isBinary(type);
}

bool Kernel::isCk(std::string type) {
return translateType(type) == Kernel::Type::CK;
}

bool Kernel::isSpk(std::string type) {
return translateType(type) == Kernel::Type::SPK;
}

string Kernel::translateQuality(Kernel::Quality qa) {
return KERNEL_QUALITIES[static_cast<int>(qa)];
Expand Down
14 changes: 14 additions & 0 deletions SpiceQL/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ namespace SpiceQL {
}


vector<string> split(const string& s, char delim) {
vector<string> out;
istringstream ss(s);
string part;
while (std::getline(ss, part, delim)) {
auto start = part.find_first_not_of(" \t");
if (start == string::npos) continue;
auto end = part.find_last_not_of(" \t");
out.push_back(part.substr(start, end == string::npos ? part.size() : end - start + 1));
}
return out;
}


vector<vector<string>> getPathsFromRegex(string root, vector<string> regexes) {
vector<string> files_to_search = Memo::ls(root, true);

Expand Down
Loading