Isis 3 Programmer Reference
KernelDb.cpp
Go to the documentation of this file.
1 
22 #include "KernelDb.h"
23 
24 #include <iomanip>
25 #include <queue>
26 
27 #include "CameraFactory.h"
28 #include "FileName.h"
29 #include "IException.h"
30 #include "IString.h"
31 #include "iTime.h"
32 #include "Kernel.h"
33 #include "Preference.h"
34 #include "Preference.h"
35 #include "PvlGroup.h"
36 #include "PvlKeyword.h"
37 #include "PvlObject.h"
38 
39 using namespace std;
40 namespace Isis {
61  KernelDb::KernelDb(const unsigned int allowedKernelTypes) {
62  m_filename = "None";
63  m_allowedKernelTypes = allowedKernelTypes;
64  m_kernelDbFiles.clear();
65  }
66 
67 
89  KernelDb::KernelDb(const QString &dbName, const unsigned int allowedKernelTypes) :
90  m_kernelData(dbName) {
91  m_filename = dbName;
92  m_allowedKernelTypes = allowedKernelTypes;
93  m_kernelDbFiles.clear();
94  }
95 
96 
118  KernelDb::KernelDb(std::istream &dbStream, const unsigned int allowedKernelTypes) {
119  dbStream >> m_kernelData;
120  m_filename = "internal stream";
121  m_allowedKernelTypes = allowedKernelTypes;
122  m_kernelDbFiles.clear();
123  }
124 
129  }
130 
148  return findLast("LeapSecond", lab);
149  }
150 
151 
169  return findLast("TargetAttitudeShape", lab);
170  }
171 
172 
190  return findLast("TargetPosition", lab);
191  }
192 
193 
211  return findAll("SpacecraftPointing", lab);
212  }
213 
214 
231  return findLast("SpacecraftClock", lab);
232  }
233 
234 
252  return findLast("SpacecraftPosition", lab);
253  }
254 
255 
273  return findLast("Instrument", lab);
274  }
275 
276 
294  return findLast("Frame", lab);
295  }
296 
314  return findLast("InstrumentAddendum", lab);
315  }
316 
317 
335  return findLast("Dem", lab);
336  }
337 
351  Kernel KernelDb::findLast(const QString &entry, Pvl &lab) {
352 
353  QList< priority_queue<Kernel> > queues = findAll(entry, lab);
354  Kernel lastKernel;
355 
356  if (queues.size() > 0 && queues.at(0).size() > 0) {
357  lastKernel = queues.at(0).top();
358  }
359 
360  return lastKernel;
361  }
362 
379  Pvl &lab) {
380 
382  PvlObject &cube = lab.findObject("IsisCube");
383  int cameraVersion = -1;
384 
385  try {
386  cameraVersion = CameraFactory::CameraVersion(lab);
387  }
388  catch (IException &) {
389  }
390 
391  // Make sure the entry has been loaded into memory
392  if (!m_kernelData.hasObject(entry)) {
393  priority_queue<Kernel> emptyKernelQueue;
394  emptyKernelQueue.push(Kernel());
395  queues.push_back(emptyKernelQueue);
396  return queues;
397  }
398 
399  // Get the start and end time for the cube
400  iTime start;
401  iTime end;
402 
403  if (cube.hasGroup("Instrument")) {
404  start = (QString) cube.findGroup("Instrument")["StartTime"];
405 
406  if (cube.findGroup("Instrument").hasKeyword("StopTime")) {
407  end = ((QString) cube.findGroup("Instrument")["StopTime"]);
408  }
409  else {
410  end = ((QString) cube.findGroup("Instrument")["StartTime"]);
411  }
412  }
413 
414  // Loop through the objects to look for all matches to the entry value
415  for (int i = 0; i < m_kernelData.objects(); i++) {
416  if (m_kernelData.object(i).isNamed(entry)) {
417  priority_queue<Kernel> filesFound;
418  PvlObject &obj = m_kernelData.object(i);
419 
420  for (int groupIndex = obj.groups() - 1; groupIndex >= 0; groupIndex--) {
421  // Get the group and start testing the cases in the keywords
422  // to see if they all match this cube
423  PvlGroup &grp = obj.group(groupIndex);
424 
425  // If the group name isn't selection, skip it.
426  if (!grp.isNamed("Selection")) continue;
427 
428  QString type = "";
429 
430  // Make sure the type is allowed
431  if (grp.hasKeyword("Type")) {
432  type = (QString) grp["Type"];
433  if (!(Kernel::typeEnum(type) & m_allowedKernelTypes)) {
434  // will return 1 for each bit that has 1 in both type and allowed and
435  // return 0 for all other bits
436  //
437  // so, if Type = 0010 and allowed = 1010, then this bitwise operator
438  // (type & allowed) returns 0010 and is true.
439  // That is, this type is allowed.
440  continue;
441  }
442  }
443 
444  bool startMatches = matches(lab, grp, start, cameraVersion);
445  bool endMatches = matches(lab, grp, end, cameraVersion);
446 
447  if (startMatches && endMatches) {
448  // Simple case - the selection simply matches
449  filesFound.push(Kernel(Kernel::typeEnum(type), files(grp)));
450  QStringList kernelfiles = files(grp);
451  }
452  else if (startMatches) {
453  // Well, the selection start matched but not the end.
454  // Let's look for a second selection to handle overlap areas.
455  for (int endTimeIndex = obj.groups() - 1;
456  endTimeIndex >= 0;
457  endTimeIndex--) {
458 
459  PvlGroup &endTimeGrp = obj.group(endTimeIndex);
460 
461  // The second selection must:
462  // Not be the current selection
463  // Be a selection
464  // Be of the same quality
465  // Match the end time
466  //
467  // *If start time is also matched, do not merge and simply take the
468  // secondary match
469  if (endTimeIndex == groupIndex) continue;
470  if (!endTimeGrp.isNamed("Selection")) continue;
471  if (grp.hasKeyword("Type") != endTimeGrp.hasKeyword("Type")) continue;
472  if (grp.hasKeyword("Type") &&
473  grp["Type"] != endTimeGrp["Type"]) continue;
474  if (!matches(lab, endTimeGrp, end, cameraVersion)) continue;
475 
476  // Better match is true if we find a full overlap
477  bool betterMatch = false;
478 
479  // True if we have matching time ranges = we want to merge
480  bool endTimesMatch = true;
481 
482  // Check for matching time ranges
483  for (int keyIndex = 0;
484  !betterMatch && keyIndex < grp.keywords();
485  keyIndex++) {
486  PvlKeyword &key = grp[keyIndex];
487 
488  if (!key.isNamed("Time")) continue;
489 
490  iTime timeRangeStart((QString)key[0]);
491  iTime timeRangeEnd((QString)key[1]);
492 
493  bool thisEndMatches = matches(lab, endTimeGrp,
494  timeRangeEnd, cameraVersion);
495  endTimesMatch = endTimesMatch && thisEndMatches;
496 
497  if (matches(lab, endTimeGrp, start, cameraVersion)
498  && matches(lab, endTimeGrp, end, cameraVersion)) {
499  // If we run into a continuous kernel, we want to take that in all
500  // cases.
501  betterMatch = true;
502  }
503  }
504 
505  // No exact match but time ranges overlap, merge the selections
506  if (!betterMatch && endTimesMatch) {
507  QStringList startMatchFiles = files(grp);
508  QStringList endMatchFiles = files(endTimeGrp);
509 
510  while (endMatchFiles.size()) {
511  startMatchFiles.push_back(endMatchFiles[endMatchFiles.size() - 1]);
512  endMatchFiles.pop_back();
513  }
514 
515  filesFound.push(
516  Kernel(Kernel::typeEnum(type), startMatchFiles));
517  }
518  // Found an exact match, use it
519  else if (betterMatch) {
520  filesFound.push(Kernel(Kernel::typeEnum(type), files(endTimeGrp)));
521  QStringList kernelfiles = files(endTimeGrp);
522  }
523  }
524  }
525  }
526 
527  queues.push_back(filesFound);
528  }
529  }
530 
531  if (queues.size() == 0) {
532  priority_queue<Kernel> emptyKernelQueue;
533  emptyKernelQueue.push(Kernel());
534  queues.push_back(emptyKernelQueue);
535  }
536 
537  return queues;
538  }
539 
583  bool KernelDb::matches(const Pvl &lab, PvlGroup &grp,
584  iTime timeToMatch, int cameraVersion) {
585  // These are the conditions that make this test pass:
586  // 1) No time OR At least one matching time
587  // 2) All keyword matches are true OR No keyword matches present
588  //
589  // In order to accomplish this, matchTime is initialized to true and remains
590  // as such if and only if there are no time conditionals. If Time keywords
591  // exist, one of them has to set matchTime to true. The matchKeywords is
592  // true until a mismatch is found.
593  const PvlObject &cube = lab.findObject("IsisCube");
594  bool matchTime = !grp.hasKeyword("Time");
595  bool matchKeywords = true;
596 
597  // First, the time search. Loop through the keywords, if the name isn't
598  // Time then skip it. If it is, then get the start/end times and keep
599  // looking until one is found.
600  for (int keyword = 0; keyword < grp.keywords(); keyword++) {
601  PvlKeyword key = grp[keyword];
602 
603  if (key.isNamed("Time")) {
604  // Pull the selections start and end time out
605  iTime kernelStart = (QString) key[0];
606  iTime kernelEnd = (QString) key[1];
607 
608  // If the kernel times inside of the requested times we
609  // set the matchTime to be true.
610  if ((kernelStart <= timeToMatch) && (kernelEnd >= timeToMatch)) {
611  matchTime = true;
612  }
613  }
614  else if (key.isNamed("Match")) {
615  try {
616  QString matchGroup = key[0];
617  QString matchKey = key[1];
618  QString matchValue = key[2];
619 
620  QString cubeValue = cube.findGroup(matchGroup)[matchKey];
621  cubeValue = cubeValue.simplified().trimmed().toUpper();
622  matchValue = matchValue.simplified().trimmed().toUpper();
623 
624  // If QStrings are not the same, match automatically fails
625  if (cubeValue.compare(matchValue) != 0) {
626  matchKeywords = false;
627  }
628  }
629  catch (IException &e) {
630  // This error is thrown if the group or keyword do not exist in 'lab'
631  matchKeywords = false;
632  }
633  }
634  else if (key.isNamed("CameraVersion")) {
635  try {
636  for (int camVersionKeyIndex = 0;
637  camVersionKeyIndex < key.size();
638  camVersionKeyIndex++) {
639 
640  bool versionMatch = false;
641  IString val = key[camVersionKeyIndex];
642  IString commaTok;
643 
644  while ((commaTok = val.Token(",")).ToQt().length() > 0) {
645  if (commaTok.find('-') != string::npos) {
646  QString dashTok;
647  int start = commaTok.Token("-").ToInteger();
648  int end = commaTok.Token("-").ToInteger();
649  int direction;
650  direction = (start <= end) ? 1 : -1;
651  // Save the entire range of bands
652  for (int version = start;
653  version != end + direction;
654  version += direction) {
655  if (version == cameraVersion) {
656  versionMatch = true;
657  }
658  }
659  }
660  // This token is a single band specification
661  else {
662  if (commaTok.ToInteger() == cameraVersion) {
663  versionMatch = true;
664  }
665  }
666  }
667 
668  if (!versionMatch) {
669  matchKeywords = false;
670  }
671  }
672  }
673  catch (IException &) {
674  matchKeywords = false;
675  }
676  }
677  }
678 
679  return matchKeywords && matchTime;
680  }
681 
719  void KernelDb::loadSystemDb(const QString &mission, const Pvl &lab) {
720 
721  // Get the base DataDirectory
722  PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory");
723  QString baseDir = dataDir["Base"];
724 
725  // Get the mission DataDirectory
726  QString missionDir = dataDir[mission];
727 
728  // Load the leapsecond DB
729  loadKernelDbFiles(dataDir, baseDir + "/kernels/lsk", lab);
730  // Load the target attitude shape DB
731  FileName tasDbPath(missionDir + "/kernels/pck");
732  if (tasDbPath.fileExists()) {
733  loadKernelDbFiles(dataDir, missionDir + "/kernels/pck", lab);
734  }
735  else {
736  loadKernelDbFiles(dataDir, baseDir + "/kernels/pck", lab);
737  }
738  // Load the target position DB
739  FileName tpDbPath(missionDir + "/kernels/tspk");
740  if (tpDbPath.fileExists()) {
741  loadKernelDbFiles(dataDir, missionDir + "/kernels/tspk", lab);
742  }
743  else {
744  loadKernelDbFiles(dataDir, baseDir + "/kernels/spk", lab);
745  }
746  // Load the DEM DB
747  loadKernelDbFiles(dataDir, baseDir + "/dems", lab);
748  // Load the mission specific spacecraft pointing DB
749  loadKernelDbFiles(dataDir, missionDir + "/kernels/ck", lab);
750  // Load the mission specific frame DB
751  loadKernelDbFiles(dataDir, missionDir + "/kernels/fk", lab);
752  // Load the mission specific instrument DB
753  loadKernelDbFiles(dataDir, missionDir + "/kernels/ik", lab);
754  // Load the mission specific spacecraft clock DB
755  loadKernelDbFiles(dataDir, missionDir + "/kernels/sclk", lab);
756  // Load the mission specific spacecraft position DB
757  loadKernelDbFiles(dataDir, missionDir + "/kernels/spk", lab);
758  // Load the mission specific instrument addendum DB
759  loadKernelDbFiles(dataDir, missionDir + "/kernels/iak", lab);
761  }
762 
792  QString directory, const Pvl &lab) {
793  // get most recent version of config file
794  FileName configFile = directory + "/kernels.????.conf";
795  bool noConfigFile = false;
796  // if there is no config file, default to the most recent kernel db file
797  try {
798  configFile = configFile.highestVersion();
799  }
800  catch (IException &e) {
801  noConfigFile = true;
802  }
803  if (noConfigFile) {
804  FileName kernelDb(directory + "/kernels.????.db");
805  m_kernelDbFiles.append(kernelDb.highestVersion());
806  }
807  else { // else, read in the appropriate database files from the config file
808  PvlObject inst = Pvl(configFile.expanded()).findObject("Instrument");
809  bool foundMatch = false;
810  // loop through each group until we find a match
811  for (int groupIndex = 0; groupIndex < inst.groups(); groupIndex++) {
812  if (!foundMatch) {
813  PvlGroup &grp = inst.group(groupIndex);
814  // Only add files in Selection groups with matching intrument id
815  if (grp.isNamed("Selection")
816  && KernelDb::matches(lab, grp, iTime(), 1)) {
817  foundMatch = true;
818  // add each File keywords in the matching group to the list
819  for (int keyIndex = 0; keyIndex < grp.keywords(); keyIndex++) {
820  PvlKeyword keyword = grp[keyIndex];
821  if (keyword.isNamed("File")) {
822  QString dir = dataDir[keyword[0]];
823  FileName kernelDb( dir + "/" + keyword[1]);
824  m_kernelDbFiles.append(kernelDb.highestVersion());
825  }
826  }
827  }
828  }
829  }
830  }
831  return;
832  }
833 
834 
853  // read each of the database files appended to the list into m_kernelData
854  foreach (FileName kernelDbFile, m_kernelDbFiles) {
855  try {
856  m_kernelData.read(kernelDbFile.expanded());
857  }
858  catch (IException &e) {
859  QString msg = "Unable to read kernel database file ["
860  + kernelDbFile.expanded() + "].";
861  throw IException(e, IException::Unknown, msg, _FILEINFO_);
862  }
863  }
864  }
865 
874  return m_kernelDbFiles;
875  }
876 
877 
889 
890  for (int i = 0; i < grp.keywords(); i++) {
891  PvlKeyword kfile = grp[i];
892  if (kfile.name() != "File") continue;
893 
894  // Two values in the "File" keyword from the DB,
895  // indicates an ISIS preference in the DataDirectory section
896  // and a filename
897  if (kfile.size() == 2) {
898  QString pref = kfile[0];
899  QString version = kfile[1];
900  FileName filename("$" + pref + "/" + version);
901  if (filename.isVersioned())
902  filename = filename.highestVersion();
903  files.push_back(filename.originalPath() + "/" + filename.name());
904  }
905  // One value in "File" indicates a full file spec
906  else if (kfile.size() == 1) {
907  FileName filename(kfile[0]);
908  if (filename.isVersioned())
909  filename = filename.highestVersion();
910  files.push_back(filename.originalPath() + "/" + filename.name());
911  }
912  else {
913  QString msg = "Invalid File keyword value in [Group = ";
914  msg += grp.name() + "] in database file [";
915  msg += m_filename + "]";
917  }
918  }
919 
920  return files;
921  }
922 } //end namespace isis
PvlObject & object(const int index)
Return the object at the specified index.
Definition: PvlObject.cpp:460
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:100
Kernel dem(Pvl &lab)
This method finds the highest version of all Digital Terrain Models (DEMs) found that match the crite...
Definition: KernelDb.cpp:334
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Kernel targetPosition(Pvl &lab)
This method finds the highest version of all Target Position kernels (tspk) identified by the databas...
Definition: KernelDb.cpp:189
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
Kernel findLast(const QString &entry, Pvl &lab)
Finds the highest priority Kernel object for the given entry based on the allowed Kernel types...
Definition: KernelDb.cpp:351
File name manipulation and expansion.
Definition: FileName.h:116
Parse and return pieces of a time string.
Definition: iTime.h:78
int objects() const
Returns the number of objects.
Definition: PvlObject.h:231
QList< std::priority_queue< Kernel > > spacecraftPointing(Pvl &lab)
This method finds a list of the highest versions of all Spacecraft Pointing kernels (ck) identified b...
Definition: KernelDb.cpp:210
KernelDb(const unsigned int allowedKernelTypes)
Constructs a new KernelDb object with a given integer value representing the Kernel::Type enumeration...
Definition: KernelDb.cpp:61
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
static int CameraVersion(Cube &cube)
This looks up the current camera model version from the cube.
~KernelDb()
Destructs KernelDb object.
Definition: KernelDb.cpp:128
Namespace for the standard library.
static bool matches(const Pvl &lab, PvlGroup &kernelDbGrp, iTime timeToMatch, int cameraVersion)
This static method determines whether the given cube label matches the given criteria.
Definition: KernelDb.cpp:583
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
QList< FileName > m_kernelDbFiles
List of the kernel database file names that were read in when the loadSystemDb() method is called...
Definition: KernelDb.h:154
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Definition: PvlObject.h:222
QString originalPath() const
Returns the path of the original file name.
Definition: FileName.cpp:100
int ToInteger() const
Returns the object string as an integer.
Definition: IString.cpp:733
bool isNamed(QString name) const
Determines whether two PvlKeywords have the same name or not.
Definition: PvlKeyword.h:126
Pvl m_kernelData
Pvl containing the information in the kernel database(s) that is read in from the constructor and whe...
Definition: KernelDb.h:165
Kernel spacecraftPosition(Pvl &lab)
This method finds the highest version of all Spacecraft Position kernels (spk) identified by the data...
Definition: KernelDb.cpp:251
QString m_filename
The name of the kernel database file.
Definition: KernelDb.h:152
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
Definition: PvlObject.h:335
QString name() const
Returns the container name.
Definition: PvlContainer.h:77
This class stores Kernel information, including Type and kernel file names.
Definition: Kernel.h:49
void loadSystemDb(const QString &mission, const Pvl &lab)
Loads the appropriate kernel database files with the defined BASE and MISSION info for each type of k...
Definition: KernelDb.cpp:719
static Type typeEnum(const QString &type)
Converts the given string to a character as follows.
Definition: Kernel.cpp:70
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:141
QStringList files(PvlGroup &grp)
This method retrieves the values of all of the "File" keywords in the given PvlGroup.
Definition: KernelDb.cpp:887
IString Token(const IString &separator)
Returns the first token in the IString.
Definition: IString.cpp:912
Kernel spacecraftClock(Pvl &lab)
This method finds the highest version of all Spacecraft Clock kernels (sclk) identified by the databa...
Definition: KernelDb.cpp:230
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
Kernel frame(Pvl &lab)
This method finds the highest version of all Frame kernels (fk) identified by the database and the al...
Definition: KernelDb.cpp:293
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
void loadKernelDbFiles(PvlGroup &dataDir, QString directory, const Pvl &lab)
This method is called by loadSystemDb() to create a list of all appropriate kernel database files to ...
Definition: KernelDb.cpp:791
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
Container for cube-like labels.
Definition: Pvl.h:135
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
Definition: PvlContainer.h:86
PvlGroup & group(const int index)
Return the group at the specified index.
Definition: PvlObject.cpp:423
FileName highestVersion() const
Searches the directory specified in the file name for the highest version of the file name...
Definition: FileName.cpp:329
QString name() const
Returns the keyword name.
Definition: PvlKeyword.h:114
Kernel leapSecond(Pvl &lab)
This method finds the top priority of all Leap Second kernels (lsk) identified by the database and th...
Definition: KernelDb.cpp:147
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
QList< FileName > kernelDbFiles()
Accessor method to retrieve the list of kernel database files that were read in when loadSystemDb() i...
Definition: KernelDb.cpp:873
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
unsigned int m_allowedKernelTypes
This integer value represents which Kernel::Types are allowed.
Definition: KernelDb.h:157
void readKernelDbFiles()
This method is called by loadSystemDb() to read kernel database file list compiled by loadKernelDbFil...
Definition: KernelDb.cpp:852
int groups() const
Returns the number of groups contained.
Definition: PvlObject.h:87
QList< std::priority_queue< Kernel > > findAll(const QString &entry, Pvl &lab)
Finds all of the Kernel objects for the given entry value based on the allowed Kernel types...
Definition: KernelDb.cpp:378
Kernel instrument(Pvl &lab)
This method finds the last Instrument kernel found that matches the (ik) criteria in the database and...
Definition: KernelDb.cpp:272
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
void read(const QString &file)
Loads PVL information from a stream.
Definition: Pvl.cpp:76
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
bool isVersioned() const
Checks to see if a file name is versioned by date or numerically.
Definition: FileName.cpp:297
Kernel targetAttitudeShape(Pvl &lab)
This method finds the highest version of all Target Attitude Shape kernels (pck) identified by the da...
Definition: KernelDb.cpp:168
Kernel instrumentAddendum(Pvl &lab)
This method finds the highest version of all Instrument Addendum kernels (iak) identified by the data...
Definition: KernelDb.cpp:313