Isis 3 Programmer Reference
Kernels.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Kernels.h"
8
9#include <string>
10#include <vector>
11#include <numeric>
12#include <iostream>
13#include <fstream>
14#include <iomanip>
15#include <sstream>
16
17#include <QVector>
18
19#include <SpiceUsr.h>
20
21#include "FileName.h"
22#include "IException.h"
23#include "NaifStatus.h"
24#include "PvlKeyword.h"
25#include "Pvl.h"
26
27using namespace std;
28
29namespace Isis {
30
33 _kernels.clear();
34 _camVersion = -1;
35 }
36
37
52 Kernels::Kernels(const Kernels &kernels) {
53 _kernels = kernels._kernels;
54 _camVersion = kernels._camVersion;
57 }
58
77 if (this != &kernels) {
78 Clear();
79 _kernels = kernels._kernels;
80 _camVersion = kernels._camVersion;
83 }
84 return (*this);
85 }
86
92 Kernels::Kernels(const QString &filename) {
93 Pvl pvl(filename);
94 Init(pvl);
95 }
96
103 Init(*cube.label());
104 }
105
112 Init(pvl);
113 }
114
120 int Kernels::Missing() const {
121 int nMissing(0);
122 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
123 if (!_kernels[i].exists) nMissing++;
124 }
125 return (nMissing);
126 }
127
142 void Kernels::Init(Pvl &pvl) {
143 UnLoad();
144 _kernels.clear();
145 addKernels(findKernels(pvl, "TargetPosition"));
146 addKernels(findKernels(pvl, "InstrumentPosition"));
147 addKernels(findKernels(pvl, "InstrumentPointing"));
148 addKernels(findKernels(pvl, "Frame"));
149 addKernels(findKernels(pvl, "TargetAttitudeShape"));
150 addKernels(findKernels(pvl, "Instrument"));
151 addKernels(findKernels(pvl, "InstrumentAddendum"));
152 addKernels(findKernels(pvl, "LeapSecond"));
153 addKernels(findKernels(pvl, "SpacecraftClock"));
154 addKernels(findKernels(pvl, "ShapeModel"));
155 addKernels(findKernels(pvl, "Extra"));
156 _camVersion = getCameraVersion(pvl);
157 return;
158 }
159
178 bool Kernels::Add(const QString &kfile) {
179 if (!findByName(kfile)) {
180 _kernels.push_back(examine(kfile, true));
181 return (true);
182 }
183 return (false);
184 }
185
196 _kernels.clear();
197 }
198
236 _kernels.clear();
237 SpiceInt count;
239 ktotal_c("ALL", &count);
240 int nfound(0);
241 for (int i = 0 ; i < count ; i++) {
242 SpiceChar file[128];
243 SpiceChar ktype[32];
244 SpiceChar source[128];
245 SpiceInt handle;
246 SpiceBoolean found;
247 kdata_c(i, "ALL", sizeof(file), sizeof(ktype), sizeof(source),
248 file, ktype,source, &handle, &found);
249 if (found == SPICETRUE) {
250 _kernels.push_back(examine(file, false));
251 nfound++;
252 }
253 }
255 return (nfound);
256 }
257
258
270 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
271 _kernels[i].managed = true;
272 }
273 return;
274 }
275
276
289 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
290 _kernels[i].managed = false;
291 }
292 return;
293 }
294
308 bool Kernels::IsManaged() const {
309 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
310 if (!_kernels[i].managed) return (false);;
311 }
312 return (true);
313 }
314
315
335 kclear_c();
337 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
338 _kernels[i].loaded = false;
339 }
340 return;
341 }
342
343
364 int Kernels::Load(const QString &ktypes) {
365 // If no types specified, return them all
366 int nLoaded(0);
367 if (ktypes.isEmpty()) {
368 for (unsigned int k = 0 ; k < _kernels.size() ; k++) {
369 if (Load(_kernels[k])) { nLoaded++; }
370 }
371 }
372 else {
373 // Find types and return requested types
374 QStringList tlist = getTypes(ktypes);
375 for (int t = 0 ; t < tlist.size() ; t++) {
376 for (unsigned int k = 0; k < _kernels.size() ; k++) {
377 if (_kernels[k].ktype == tlist[t]) {
378 if (Load(_kernels[k])) { nLoaded++; }
379 }
380 }
381 }
382 }
383 return (nLoaded);
384 }
385
386
406 // If not types specified, return them all
407 int nLoaded(0);
408 for (unsigned int k = 0 ; k < _kernels.size() ; k++) {
409 if (Load(_kernels[k])) { nLoaded++; }
410 }
411 return (nLoaded);
412 }
413
414
426 int nUnloaded(0);
427 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
428 if (UnLoad(_kernels[i])) nUnloaded++;
429 }
430 return (nUnloaded);
431 }
432
453 int Kernels::UnLoad(const QString &ktypes) {
454 // If not types specified, return them all
455 int nUnloaded(0);
456 if (ktypes.isEmpty()) {
457 nUnloaded = UnLoad();
458 }
459 else {
460 // Find types and return requested types
461 QStringList tlist = getTypes(ktypes);
462 for (int t = 0 ; t < tlist.size() ; t++) {
463 for (unsigned int k = 0; k < _kernels.size() ; k++) {
464 if (_kernels[k].ktype == tlist[t]) {
465 if (UnLoad(_kernels[k])) nUnloaded++;
466 }
467 }
468 }
469 }
470 return (nUnloaded);
471 }
472
492 int nchanged(0);
493 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
494 // Use NAIF to determine if it is loaded
495 if (IsNaifType(_kernels[i].ktype)) {
496 SpiceChar ktype[32];
497 SpiceChar source[128];
498 SpiceInt handle;
499 SpiceBoolean found;
500
502 kinfo_c(_kernels[i].fullpath.toLatin1().data(), sizeof(ktype), sizeof(source),
503 ktype,source, &handle, &found);
505
506 if (found == SPICETRUE) {
507 if (!_kernels[i].loaded) nchanged++;
508 _kernels[i].loaded = true;
509 }
510 else {
511 if (_kernels[i].loaded) nchanged++;
512 _kernels[i].loaded = false;
513 }
514 }
515 }
516
517 return (nchanged);
518 }
519
540 int nchanged(0);
541 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
542 if (_kernels[i].loaded) {
543 _kernels[i].managed = false;
544 nchanged++;
545 }
546 else {
547 _kernels[i].managed = true;
548 }
549 }
550 return (nchanged);
551 }
552
599 int Kernels::Merge(const Kernels &other) {
600 int nAdded(0);
601 for (unsigned int i = 0 ; i < other._kernels.size() ; i++) {
602 KernelFile *kernel = findByName(other._kernels[i].fullpath);
603 if (kernel == 0) {
604 KernelFile kfile = other._kernels[i];
605 kfile.managed = false;
606 _kernels.push_back(kfile);
607 nAdded++;
608 }
609 else {
610 if (other._kernels[i].loaded) {
611 kernel->loaded = true;
612 kernel->managed = false;
613 }
614 }
615 }
616 return (nAdded);
617 }
618
619
651 TypeList kmap = categorizeByType();
652 QStringList types;
653 for (int i = 0 ; i < kmap.size() ; i++) {
654 types.append(kmap.key(i));
655 }
656 return (types);
657 }
658
659
672 QStringList Kernels::getKernelList(const QString &ktypes) const {
673
674 // If not types specified, return them all
675 QStringList flist;
676 if (ktypes.isEmpty()) {
677 for (unsigned int k = 0; k < _kernels.size() ; k++) {
678 flist.push_back(_kernels[k].pathname);
679 }
680 }
681 else {
682 // Find types and return requested types
683 QStringList tlist = getTypes(ktypes);
684 for (int t = 0 ; t < tlist.size() ; t++) {
685 for (unsigned int k = 0; k < _kernels.size() ; k++) {
686 if (_kernels[k].ktype == tlist[t]) {
687 flist.push_back(_kernels[k].pathname);
688 }
689 }
690 }
691 }
692 return (flist);
693 }
694
695
720 QStringList Kernels::getLoadedList(const QString &ktypes)
721 const {
722 QStringList flist;
723 if (ktypes.isEmpty()) {
724 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
725 if (_kernels[i].loaded) flist.push_back(_kernels[i].pathname);
726 }
727 }
728 else {
729 QStringList tlist = getTypes(ktypes);
730 for (int t = 0 ; t < tlist.size() ; t++ ) {
731 for (unsigned int k = 0; k < _kernels.size() ; k++) {
732 if (_kernels[k].ktype == tlist[t]) {
733 flist.push_back(_kernels[k].pathname);
734 }
735 }
736 }
737 }
738 return (flist);
739 }
740
741
753 QStringList flist;
754 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
755 if (!_kernels[i].exists) flist.push_back(_kernels[i].pathname);
756 }
757 return (flist);
758 }
759
775 if (IsNaifType(kfile.ktype)) {
776 if (!kfile.loaded) {
778 try {
779 furnsh_c(kfile.fullpath.toLatin1().data());
781 kfile.loaded = true;
782 kfile.managed = true;
783 }
784 catch (IException &ie) {
785 return (false);
786 }
787 }
788 }
789 return (kfile.loaded);
790 }
791
815 // If its loaded assume its a loaded NAIF kernel and unload it
816 bool wasLoaded(false);
817 if (kfile.loaded) {
818 if (kfile.managed) {
820 try {
821 unload_c(kfile.fullpath.toLatin1().data());
823 }
824 catch (IException &) {
825 // Errors are trapped and ignored. It may be unloaded by other source
826 }
827 kfile.loaded = false;
828 wasLoaded = true;
829 }
830 }
831 return (wasLoaded);
832 }
833
865 QStringList Kernels::getTypes(const QString &ktypes) const {
866 // Find types and return requested types
867 QStringList tlist = ktypes.split(",");
868 for (int k = 0 ; k < tlist.size() ; k++) {
869 tlist[k] = IString(tlist[k]).Trim(" \r\n\t\v\b\f").UpCase().ToQt();
870 }
871 return (tlist);
872 }
873
881 void Kernels::addKernels(const KernelList &klist) {
882 copy(klist.begin(), klist.end(), back_inserter(_kernels));
883 return;
884 }
885
886
903 Kernels::KernelList Kernels::findKernels(Pvl &pvl,
904 const QString &kname,
905 const bool &manage) {
906 KernelList klist;
907 // Get the kernel group and load main kernels
908 PvlGroup &kernels = pvl.findGroup("Kernels",Pvl::Traverse);
909 // Check for the keyword
910 if (kernels.hasKeyword(kname)) {
911 PvlKeyword &kkey = kernels[kname];
912 for (int i = 0 ; i < kkey.size() ; i++) {
913 if (!kkey.isNull(i)) {
914 if (kkey[i].toLower() != "table") {
915 klist.push_back(examine(kkey[i], manage));
916 }
917 }
918 }
919 }
920
921 return (klist);
922 }
923
924
950 KernelList::iterator klist;
951 for (klist = _kernels.begin() ; klist != _kernels.end() ; ++klist) {
952 if (klist->pathname == kfile) { return (&(*klist)); }
953 if (klist->name == kfile) { return (&(*klist)); }
954 if (klist->fullpath == kfile) { return (&(*klist)); }
955 }
956 return (0);
957 }
958
959
968 Kernels::TypeList Kernels::categorizeByType() const {
969 TypeList ktypes;
970 for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
971 KernelFile *kfile = const_cast<KernelFile *> (&_kernels[i]);
972 if (ktypes.exists(_kernels[i].ktype)) {
973 ktypes.get(_kernels[i].ktype).push_back(kfile);
974 }
975 else {
976 ktypes.add(_kernels[i].ktype, KernelFileList(1, kfile));
977 }
978 }
979 return (ktypes);
980 }
981
982
991 bool Kernels::IsNaifType(const QString &ktype) const {
992 if (ktype.toUpper() == "UNKNOWN") return (false);
993 if (ktype.toUpper() == "DEM") return (false);
994 return (true);
995 }
1045 const bool &manage) const {
1046
1047 FileName kernfile(kfile);
1048 KernelFile kf;
1049 kf.pathname = kfile;
1050 kf.name = kernfile.name();
1051 kf.fullpath = kernfile.expanded();
1052 kf.exists = kernfile.fileExists();
1053 kf.ktype = "UNKNOWN";
1054 kf.loaded = false; // Assumes its not loaded
1055 kf.managed = manage;
1056
1057 // Determine type and load info
1058 if (kf.exists) {
1059 kf.ktype = resolveType(kf.fullpath);
1060
1061 // Use NAIF to determine if it is loaded
1062 if (IsNaifType(kf.ktype)) {
1063 SpiceChar ktype[32];
1064 SpiceChar source[128];
1065 SpiceInt handle;
1066 SpiceBoolean found;
1067
1069 kinfo_c(kf.fullpath.toLatin1().data(), sizeof(ktype), sizeof(source), ktype,
1070 source, &handle, &found);
1072
1073 if (found == SPICETRUE) {
1074 kf.loaded = true;
1075 kf.managed = false;
1076 kf.ktype = IString(ktype).UpCase().ToQt();
1077 }
1078 }
1079 }
1080
1081 return (kf);
1082 }
1083
1108 QString Kernels::resolveType(const QString &kfile) const {
1109 FileName kernFile(kfile);
1110 QString kpath = kernFile.expanded();
1111 ifstream ifile(kpath.toLatin1().data(), ios::in | ios::binary);
1112 QString ktype("UNKNOWN");
1113 if (ifile) {
1114 char ibuf[10];
1115 ifile.read(ibuf, 8);
1116 ibuf[8] = '\0';
1117 for (int i = 0 ; i < 8 ; i++)
1118 if (ibuf[i] == '\n') ibuf[i] = '\0';
1119
1120 // See if the file is a known NAIF type. Assume it has been
1121 // extracted from a NAIF compliant kernel
1122 QString istr = IString(ibuf).Trim(" \n\r\f\t\v\b").ToQt();
1123 if (istr.contains("/")) {
1124 ktype = istr.split("/").last();
1125 }
1126
1127 // If type is not resolved, check file extensions and special ISIS types
1128 if ((ktype == "UNKNOWN") || (ktype == "DAF")) {
1129 ktype = resolveTypeByExt(kfile, ktype);
1130 }
1131
1132 }
1133 return (ktype);
1134 }
1135
1181 QString Kernels::resolveTypeByExt(const QString &kfile,
1182 const QString &iktype) const {
1183
1184 QString ktype(iktype); // Set default condition
1185
1186 // Deciminate file parts
1187 FileName kf(kfile);
1188 string ext = IString(kf.extension()).DownCase();
1189
1190 // Check extensions for types
1191 if (ext == "cub") {
1192 ktype = "DEM";
1193 }
1194 else if (ext == "ti") {
1195 // Assume its an instrument kernel but check for ISIS IAK file
1196 ktype = "IK";
1197 string base = IString(kf.baseName()).DownCase();
1198 string::size_type idx = base.find("addendum");
1199 if (idx != string::npos) { // This is an ISIS IK addendum (IAK)
1200 ktype = "IAK";
1201 }
1202 }
1203 else if (ext == "tsc") {
1204 ktype = "SCLK";
1205 }
1206 else if (ext == "tf") {
1207 ktype = "FK";
1208 }
1209 else if (ext == "tls") {
1210 ktype = "LSK";
1211 }
1212 else if (ext == "tpc") {
1213 ktype = "PCK";
1214 }
1215 else if (ext == "bc") {
1216 ktype = "CK";
1217 }
1218 else if (ext == "bsp") {
1219 ktype = "SPK";
1220 }
1221 else if (ext == "bes") {
1222 ktype = "EK";
1223 }
1224 else if (ext == "bds") {
1225 ktype = "DSK";
1226 }
1227 else if (ext == "meta") {
1228 ktype = "META";
1229 }
1230 return (ktype);
1231 }
1232
1233
1234
1249 PvlGroup &kernels = pvl.findGroup("Kernels",Pvl::Traverse);
1250 int cv(0);
1251 // Check for the keyword
1252 if (kernels.hasKeyword("CameraVersion")) {
1253 PvlKeyword &kkey = kernels["CameraVersion"];
1254 cv = IString(kkey[0]).ToInteger();
1255 }
1256 return (cv);
1257 }
1258
1259} // namespace Isis
1260
1261
IO Handler for Isis Cubes.
Definition Cube.h:168
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
Adds specific functionality to C++ strings.
Definition IString.h:165
int ToInteger() const
Returns the object string as an integer.
Definition IString.cpp:718
IString Trim(const std::string &chars)
Removes characters from the beginning and end of the IString.
Definition IString.cpp:525
IString UpCase()
Converst any lower case characters in the object IString with uppercase characters.
Definition IString.cpp:617
IString DownCase()
Converts all upper case letters in the object IString into lower case characters.
Definition IString.cpp:644
QString ToQt() const
Retuns the object string as a QString.
Definition IString.cpp:869
Determine SPICE kernels defined in an ISIS file.
Definition Kernels.h:94
int UpdateManagedStatus()
Update the managed state of the kernel file list.
Definition Kernels.cpp:539
void InitializeNaifKernelPool()
Initialize the NAIF kernel keeper pool.
Definition Kernels.cpp:333
bool Add(const QString &kfile)
Add a new kernel to the list.
Definition Kernels.cpp:178
bool IsNaifType(const QString &ktype) const
Determine if the type is a NAIF supported kernel type.
Definition Kernels.cpp:991
void Manage()
Set each kernels management status to managed.
Definition Kernels.cpp:269
KernelFile examine(const QString &fname, const bool &manage=true) const
Determine type of NAIF kernel file.
Definition Kernels.cpp:1044
int Discover()
Determine which NAIF kernels are currently loaded in the pool.
Definition Kernels.cpp:235
int getCameraVersion(Pvl &pvl) const
Determine the ISIS camera model version number.
Definition Kernels.cpp:1248
int UpdateLoadStatus()
Determine the load status of all kernels known to this object.
Definition Kernels.cpp:491
QStringList getTypes(const QString &ktypes) const
Get a vector of comma separated types from a string.
Definition Kernels.cpp:865
KernelFile * findByName(const QString &kfile)
Search kernel file list of a particular pattern.
Definition Kernels.cpp:949
void Init(Pvl &pvl)
Determine Spice kernels in an ISIS label.
Definition Kernels.cpp:142
QString resolveType(const QString &kfile) const
Determines type of NAIF/ISIS kernel we're dealing with.
Definition Kernels.cpp:1108
Kernels()
Default Constructor.
Definition Kernels.cpp:32
QStringList getKernelList(const QString &ktype="") const
Provide a list of all the kernels found.
Definition Kernels.cpp:672
QString resolveTypeByExt(const QString &kfile, const QString &iktype="UNKNOWN") const
Check kernel type by file extension and special ISIS kernels.
Definition Kernels.cpp:1181
void Clear()
Remove all kernel files from internal list.
Definition Kernels.cpp:195
void addKernels(const KernelList &klist)
Add a list of kernel files to internal storage.
Definition Kernels.cpp:881
QStringList getLoadedList(const QString &ktypes="") const
Returns list of kernel currently loaded according to status.
Definition Kernels.cpp:720
int Missing() const
Return count of missing kernel files.
Definition Kernels.cpp:120
bool IsManaged() const
Determine if all kernels are managed by this object.
Definition Kernels.cpp:308
TypeList categorizeByType() const
Categorizes the kernel list by type.
Definition Kernels.cpp:968
std::vector< KernelFile > findKernels(Pvl &pvl, const QString &kname, const bool &manage=true)
Retrieve contents of keyword.
Definition Kernels.cpp:903
int UnLoad()
Unloads all kernels from the NAIF pool.
Definition Kernels.cpp:425
QStringList getMissingList() const
Returns list of kernels that were not found to exist.
Definition Kernels.cpp:752
int Merge(const Kernels &other)
Merge the contents of another Kernels object.
Definition Kernels.cpp:599
int Load()
Load all kernels in list.
Definition Kernels.cpp:405
QStringList getKernelTypes() const
Return list of types in kernel list.
Definition Kernels.cpp:650
Kernels & operator=(const Kernels &kernels)
Copy constructor for existing Kernels objecr.
Definition Kernels.cpp:76
void UnManage()
Set each kernels' management state to unmanaged.
Definition Kernels.cpp:288
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
@ Traverse
Search child objects.
Definition PvlObject.h:158
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.