Isis 3 Programmer Reference
Kernels.cpp
Go to the documentation of this file.
1 
24 #include "Kernels.h"
25 
26 #include <string>
27 #include <vector>
28 #include <numeric>
29 #include <iostream>
30 #include <fstream>
31 #include <iomanip>
32 #include <sstream>
33 
34 #include <QVector>
35 
36 #include <SpiceUsr.h>
37 
38 #include "FileName.h"
39 #include "IException.h"
40 #include "NaifStatus.h"
41 #include "PvlKeyword.h"
42 #include "Pvl.h"
43 
44 using namespace std;
45 
46 namespace Isis {
47 
49  Kernels::Kernels() {
50  _kernels.clear();
51  _camVersion = -1;
52  }
53 
54 
69  Kernels::Kernels(const Kernels &kernels) {
70  _kernels = kernels._kernels;
71  _camVersion = kernels._camVersion;
72  UpdateLoadStatus();
73  UpdateManagedStatus();
74  }
75 
93  Kernels &Kernels::operator=(const Kernels &kernels) {
94  if (this != &kernels) {
95  Clear();
96  _kernels = kernels._kernels;
97  _camVersion = kernels._camVersion;
98  UpdateLoadStatus();
99  UpdateManagedStatus();
100  }
101  return (*this);
102  }
103 
109  Kernels::Kernels(const QString &filename) {
110  Pvl pvl(filename);
111  Init(pvl);
112  }
113 
119  Kernels::Kernels(Cube &cube) {
120  Init(*cube.label());
121  }
122 
128  Kernels::Kernels(Pvl &pvl) {
129  Init(pvl);
130  }
131 
137  int Kernels::Missing() const {
138  int nMissing(0);
139  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
140  if (!_kernels[i].exists) nMissing++;
141  }
142  return (nMissing);
143  }
144 
159  void Kernels::Init(Pvl &pvl) {
160  UnLoad();
161  _kernels.clear();
162  addKernels(findKernels(pvl, "TargetPosition"));
163  addKernels(findKernels(pvl, "InstrumentPosition"));
164  addKernels(findKernels(pvl, "InstrumentPointing"));
165  addKernels(findKernels(pvl, "Frame"));
166  addKernels(findKernels(pvl, "TargetAttitudeShape"));
167  addKernels(findKernels(pvl, "Instrument"));
168  addKernels(findKernels(pvl, "InstrumentAddendum"));
169  addKernels(findKernels(pvl, "LeapSecond"));
170  addKernels(findKernels(pvl, "SpacecraftClock"));
171  addKernels(findKernels(pvl, "ShapeModel"));
172  addKernels(findKernels(pvl, "Extra"));
173  _camVersion = getCameraVersion(pvl);
174  return;
175  }
176 
195  bool Kernels::Add(const QString &kfile) {
196  if (!findByName(kfile)) {
197  _kernels.push_back(examine(kfile, true));
198  return (true);
199  }
200  return (false);
201  }
202 
212  void Kernels::Clear() {
213  _kernels.clear();
214  }
215 
252  int Kernels::Discover() {
253  _kernels.clear();
254  SpiceInt count;
255  NaifStatus::CheckErrors();
256  ktotal_c("ALL", &count);
257  int nfound(0);
258  for (int i = 0 ; i < count ; i++) {
259  SpiceChar file[128];
260  SpiceChar ktype[32];
261  SpiceChar source[128];
262  SpiceInt handle;
263  SpiceBoolean found;
264  kdata_c(i, "ALL", sizeof(file), sizeof(ktype), sizeof(source),
265  file, ktype,source, &handle, &found);
266  if (found == SPICETRUE) {
267  _kernels.push_back(examine(file, false));
268  nfound++;
269  }
270  }
271  NaifStatus::CheckErrors();
272  return (nfound);
273  }
274 
275 
286  void Kernels::Manage() {
287  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
288  _kernels[i].managed = true;
289  }
290  return;
291  }
292 
293 
305  void Kernels::UnManage() {
306  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
307  _kernels[i].managed = false;
308  }
309  return;
310  }
311 
325  bool Kernels::IsManaged() const {
326  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
327  if (!_kernels[i].managed) return (false);;
328  }
329  return (true);
330  }
331 
332 
350  void Kernels::InitializeNaifKernelPool() {
351  NaifStatus::CheckErrors();
352  kclear_c();
353  NaifStatus::CheckErrors();
354  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
355  _kernels[i].loaded = false;
356  }
357  return;
358  }
359 
360 
381  int Kernels::Load(const QString &ktypes) {
382  // If no types specified, return them all
383  int nLoaded(0);
384  if (ktypes.isEmpty()) {
385  for (unsigned int k = 0 ; k < _kernels.size() ; k++) {
386  if (Load(_kernels[k])) { nLoaded++; }
387  }
388  }
389  else {
390  // Find types and return requested types
391  QStringList tlist = getTypes(ktypes);
392  for (int t = 0 ; t < tlist.size() ; t++) {
393  for (unsigned int k = 0; k < _kernels.size() ; k++) {
394  if (_kernels[k].ktype == tlist[t]) {
395  if (Load(_kernels[k])) { nLoaded++; }
396  }
397  }
398  }
399  }
400  return (nLoaded);
401  }
402 
403 
422  int Kernels::Load() {
423  // If not types specified, return them all
424  int nLoaded(0);
425  for (unsigned int k = 0 ; k < _kernels.size() ; k++) {
426  if (Load(_kernels[k])) { nLoaded++; }
427  }
428  return (nLoaded);
429  }
430 
431 
442  int Kernels::UnLoad() {
443  int nUnloaded(0);
444  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
445  if (UnLoad(_kernels[i])) nUnloaded++;
446  }
447  return (nUnloaded);
448  }
449 
470  int Kernels::UnLoad(const QString &ktypes) {
471  // If not types specified, return them all
472  int nUnloaded(0);
473  if (ktypes.isEmpty()) {
474  nUnloaded = UnLoad();
475  }
476  else {
477  // Find types and return requested types
478  QStringList tlist = getTypes(ktypes);
479  for (int t = 0 ; t < tlist.size() ; t++) {
480  for (unsigned int k = 0; k < _kernels.size() ; k++) {
481  if (_kernels[k].ktype == tlist[t]) {
482  if (UnLoad(_kernels[k])) nUnloaded++;
483  }
484  }
485  }
486  }
487  return (nUnloaded);
488  }
489 
508  int Kernels::UpdateLoadStatus() {
509  int nchanged(0);
510  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
511  // Use NAIF to determine if it is loaded
512  if (IsNaifType(_kernels[i].ktype)) {
513  SpiceChar ktype[32];
514  SpiceChar source[128];
515  SpiceInt handle;
516  SpiceBoolean found;
517 
518  NaifStatus::CheckErrors();
519  kinfo_c(_kernels[i].fullpath.toLatin1().data(), sizeof(ktype), sizeof(source),
520  ktype,source, &handle, &found);
521  NaifStatus::CheckErrors();
522 
523  if (found == SPICETRUE) {
524  if (!_kernels[i].loaded) nchanged++;
525  _kernels[i].loaded = true;
526  }
527  else {
528  if (_kernels[i].loaded) nchanged++;
529  _kernels[i].loaded = false;
530  }
531  }
532  }
533 
534  return (nchanged);
535  }
536 
556  int Kernels::UpdateManagedStatus() {
557  int nchanged(0);
558  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
559  if (_kernels[i].loaded) {
560  _kernels[i].managed = false;
561  nchanged++;
562  }
563  else {
564  _kernels[i].managed = true;
565  }
566  }
567  return (nchanged);
568  }
569 
616  int Kernels::Merge(const Kernels &other) {
617  int nAdded(0);
618  for (unsigned int i = 0 ; i < other._kernels.size() ; i++) {
619  KernelFile *kernel = findByName(other._kernels[i].fullpath);
620  if (kernel == 0) {
621  KernelFile kfile = other._kernels[i];
622  kfile.managed = false;
623  _kernels.push_back(kfile);
624  nAdded++;
625  }
626  else {
627  if (other._kernels[i].loaded) {
628  kernel->loaded = true;
629  kernel->managed = false;
630  }
631  }
632  }
633  return (nAdded);
634  }
635 
636 
667  QStringList Kernels::getKernelTypes() const {
668  TypeList kmap = categorizeByType();
669  QStringList types;
670  for (int i = 0 ; i < kmap.size() ; i++) {
671  types.append(kmap.key(i));
672  }
673  return (types);
674  }
675 
676 
689  QStringList Kernels::getKernelList(const QString &ktypes) const {
690 
691  // If not types specified, return them all
692  QStringList flist;
693  if (ktypes.isEmpty()) {
694  for (unsigned int k = 0; k < _kernels.size() ; k++) {
695  flist.push_back(_kernels[k].pathname);
696  }
697  }
698  else {
699  // Find types and return requested types
700  QStringList tlist = getTypes(ktypes);
701  for (int t = 0 ; t < tlist.size() ; t++) {
702  for (unsigned int k = 0; k < _kernels.size() ; k++) {
703  if (_kernels[k].ktype == tlist[t]) {
704  flist.push_back(_kernels[k].pathname);
705  }
706  }
707  }
708  }
709  return (flist);
710  }
711 
712 
737  QStringList Kernels::getLoadedList(const QString &ktypes)
738  const {
739  QStringList flist;
740  if (ktypes.isEmpty()) {
741  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
742  if (_kernels[i].loaded) flist.push_back(_kernels[i].pathname);
743  }
744  }
745  else {
746  QStringList tlist = getTypes(ktypes);
747  for (int t = 0 ; t < tlist.size() ; t++ ) {
748  for (unsigned int k = 0; k < _kernels.size() ; k++) {
749  if (_kernels[k].ktype == tlist[t]) {
750  flist.push_back(_kernels[k].pathname);
751  }
752  }
753  }
754  }
755  return (flist);
756  }
757 
758 
769  QStringList Kernels::getMissingList() const {
770  QStringList flist;
771  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
772  if (!_kernels[i].exists) flist.push_back(_kernels[i].pathname);
773  }
774  return (flist);
775  }
776 
791  bool Kernels::Load(Kernels::KernelFile &kfile) {
792  if (IsNaifType(kfile.ktype)) {
793  if (!kfile.loaded) {
794  NaifStatus::CheckErrors();
795  try {
796  furnsh_c(kfile.fullpath.toLatin1().data());
797  NaifStatus::CheckErrors();
798  kfile.loaded = true;
799  kfile.managed = true;
800  }
801  catch (IException &ie) {
802  return (false);
803  }
804  }
805  }
806  return (kfile.loaded);
807  }
808 
831  bool Kernels::UnLoad(KernelFile &kfile) {
832  // If its loaded assume its a loaded NAIF kernel and unload it
833  bool wasLoaded(false);
834  if (kfile.loaded) {
835  if (kfile.managed) {
836  NaifStatus::CheckErrors();
837  try {
838  unload_c(kfile.fullpath.toLatin1().data());
839  NaifStatus::CheckErrors();
840  }
841  catch (IException &) {
842  // Errors are trapped and ignored. It may be unloaded by other source
843  }
844  kfile.loaded = false;
845  wasLoaded = true;
846  }
847  }
848  return (wasLoaded);
849  }
850 
882  QStringList Kernels::getTypes(const QString &ktypes) const {
883  // Find types and return requested types
884  QStringList tlist = ktypes.split(",");
885  for (int k = 0 ; k < tlist.size() ; k++) {
886  tlist[k] = IString(tlist[k]).Trim(" \r\n\t\v\b\f").UpCase().ToQt();
887  }
888  return (tlist);
889  }
890 
898  void Kernels::addKernels(const KernelList &klist) {
899  copy(klist.begin(), klist.end(), back_inserter(_kernels));
900  return;
901  }
902 
903 
920  Kernels::KernelList Kernels::findKernels(Pvl &pvl,
921  const QString &kname,
922  const bool &manage) {
923  KernelList klist;
924  // Get the kernel group and load main kernels
925  PvlGroup &kernels = pvl.findGroup("Kernels",Pvl::Traverse);
926  // Check for the keyword
927  if (kernels.hasKeyword(kname)) {
928  PvlKeyword &kkey = kernels[kname];
929  for (int i = 0 ; i < kkey.size() ; i++) {
930  if (!kkey.isNull(i)) {
931  if (kkey[i].toLower() != "table") {
932  klist.push_back(examine(kkey[i], manage));
933  }
934  }
935  }
936  }
937 
938  return (klist);
939  }
940 
941 
966  Kernels::KernelFile *Kernels::findByName(const QString &kfile) {
967  KernelList::iterator klist;
968  for (klist = _kernels.begin() ; klist != _kernels.end() ; ++klist) {
969  if (klist->pathname == kfile) { return (&(*klist)); }
970  if (klist->name == kfile) { return (&(*klist)); }
971  if (klist->fullpath == kfile) { return (&(*klist)); }
972  }
973  return (0);
974  }
975 
976 
985  Kernels::TypeList Kernels::categorizeByType() const {
986  TypeList ktypes;
987  for (unsigned int i = 0 ; i < _kernels.size() ; i++) {
988  KernelFile *kfile = const_cast<KernelFile *> (&_kernels[i]);
989  if (ktypes.exists(_kernels[i].ktype)) {
990  ktypes.get(_kernels[i].ktype).push_back(kfile);
991  }
992  else {
993  ktypes.add(_kernels[i].ktype, KernelFileList(1, kfile));
994  }
995  }
996  return (ktypes);
997  }
998 
999 
1008  bool Kernels::IsNaifType(const QString &ktype) const {
1009  if (ktype.toUpper() == "UNKNOWN") return (false);
1010  if (ktype.toUpper() == "DEM") return (false);
1011  return (true);
1012  }
1061  Kernels::KernelFile Kernels::examine(const QString &kfile,
1062  const bool &manage) const {
1063 
1064  FileName kernfile(kfile);
1065  KernelFile kf;
1066  kf.pathname = kfile;
1067  kf.name = kernfile.name();
1068  kf.fullpath = kernfile.expanded();
1069  kf.exists = kernfile.fileExists();
1070  kf.ktype = "UNKNOWN";
1071  kf.loaded = false; // Assumes its not loaded
1072  kf.managed = manage;
1073 
1074  // Determine type and load info
1075  if (kf.exists) {
1076  kf.ktype = resolveType(kf.fullpath);
1077 
1078  // Use NAIF to determine if it is loaded
1079  if (IsNaifType(kf.ktype)) {
1080  SpiceChar ktype[32];
1081  SpiceChar source[128];
1082  SpiceInt handle;
1083  SpiceBoolean found;
1084 
1085  NaifStatus::CheckErrors();
1086  kinfo_c(kf.fullpath.toLatin1().data(), sizeof(ktype), sizeof(source), ktype,
1087  source, &handle, &found);
1088  NaifStatus::CheckErrors();
1089 
1090  if (found == SPICETRUE) {
1091  kf.loaded = true;
1092  kf.managed = false;
1093  kf.ktype = IString(ktype).UpCase().ToQt();
1094  }
1095  }
1096  }
1097 
1098  return (kf);
1099  }
1100 
1125  QString Kernels::resolveType(const QString &kfile) const {
1126  FileName kernFile(kfile);
1127  QString kpath = kernFile.expanded();
1128  ifstream ifile(kpath.toLatin1().data(), ios::in | ios::binary);
1129  QString ktype("UNKNOWN");
1130  if (ifile) {
1131  char ibuf[10];
1132  ifile.read(ibuf, 8);
1133  ibuf[8] = '\0';
1134  for (int i = 0 ; i < 8 ; i++)
1135  if (ibuf[i] == '\n') ibuf[i] = '\0';
1136 
1137  // See if the file is a known NAIF type. Assume it has been
1138  // extracted from a NAIF compliant kernel
1139  QString istr = IString(ibuf).Trim(" \n\r\f\t\v\b").ToQt();
1140  if (istr.contains("/")) {
1141  ktype = istr.split("/").last();
1142  }
1143 
1144  // If type is not resolved, check file extensions and special ISIS types
1145  if ((ktype == "UNKNOWN") || (ktype == "DAF")) {
1146  ktype = resolveTypeByExt(kfile, ktype);
1147  }
1148 
1149  }
1150  return (ktype);
1151  }
1152 
1198  QString Kernels::resolveTypeByExt(const QString &kfile,
1199  const QString &iktype) const {
1200 
1201  QString ktype(iktype); // Set default condition
1202 
1203  // Deciminate file parts
1204  FileName kf(kfile);
1205  string ext = IString(kf.extension()).DownCase();
1206 
1207  // Check extensions for types
1208  if (ext == "cub") {
1209  ktype = "DEM";
1210  }
1211  else if (ext == "ti") {
1212  // Assume its an instrument kernel but check for ISIS IAK file
1213  ktype = "IK";
1214  string base = IString(kf.baseName()).DownCase();
1215  string::size_type idx = base.find("addendum");
1216  if (idx != string::npos) { // This is an ISIS IK addendum (IAK)
1217  ktype = "IAK";
1218  }
1219  }
1220  else if (ext == "tsc") {
1221  ktype = "SCLK";
1222  }
1223  else if (ext == "tf") {
1224  ktype = "FK";
1225  }
1226  else if (ext == "tls") {
1227  ktype = "LSK";
1228  }
1229  else if (ext == "tpc") {
1230  ktype = "PCK";
1231  }
1232  else if (ext == "bc") {
1233  ktype = "CK";
1234  }
1235  else if (ext == "bsp") {
1236  ktype = "SPK";
1237  }
1238  else if (ext == "bes") {
1239  ktype = "EK";
1240  }
1241  else if (ext == "bds") {
1242  ktype = "DSK";
1243  }
1244  else if (ext == "meta") {
1245  ktype = "META";
1246  }
1247  return (ktype);
1248  }
1249 
1250 
1251 
1265  int Kernels::getCameraVersion(Pvl &pvl) const {
1266  PvlGroup &kernels = pvl.findGroup("Kernels",Pvl::Traverse);
1267  int cv(0);
1268  // Check for the keyword
1269  if (kernels.hasKeyword("CameraVersion")) {
1270  PvlKeyword &kkey = kernels["CameraVersion"];
1271  cv = IString(kkey[0]).ToInteger();
1272  }
1273  return (cv);
1274  }
1275 
1276 } // namespace Isis
1277 
1278 
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
T & get(const K &key)
Returns the value associated with the name provided.
Definition: CollectorMap.h:583
File name manipulation and expansion.
Definition: FileName.h:116
Namespace for the standard library.
Determine SPICE kernels defined in an ISIS file.
Definition: Kernels.h:111
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
int ToInteger() const
Returns the object string as an integer.
Definition: IString.cpp:733
int size() const
Returns the size of the collection.
Definition: CollectorMap.h:528
const K & key(int nth) const
Returns the nth key in the collection.
Definition: CollectorMap.h:689
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:141
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
bool exists(const K &key) const
Checks the existance of a particular key in the list.
Definition: CollectorMap.h:567
void add(const K &key, const T &value)
Adds the element to the list.
Definition: CollectorMap.h:556
A single keyword-value pair.
Definition: PvlKeyword.h:98
QString ToQt() const
Retuns the object string as a QString.
Definition: IString.cpp:884
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
bool isNull(const int index=0) const
Decides whether a value is null or not at a given index.
Definition: PvlKeyword.cpp:118
Collector/container for arbitrary items.
Definition: CollectorMap.h:435
Container for cube-like labels.
Definition: Pvl.h:135
QString baseName() const
Returns the name of the file without the path and without extensions.
Definition: FileName.cpp:161
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
QString extension() const
Returns the last extension of the file name.
Definition: FileName.cpp:194
IString UpCase()
Converst any lower case characters in the object IString with uppercase characters.
Definition: IString.cpp:632
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
IString Trim(const std::string &chars)
Removes characters from the beginning and end of the IString.
Definition: IString.cpp:540
IO Handler for Isis Cubes.
Definition: Cube.h:170