Loading [MathJax]/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
KernelDb.cpp
1
6
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "KernelDb.h"
10
11#include <iomanip>
12#include <queue>
13
14#include "CameraFactory.h"
15#include "FileName.h"
16#include "IException.h"
17#include "IString.h"
18#include "iTime.h"
19#include "Kernel.h"
20#include "Preference.h"
21#include "Preference.h"
22#include "PvlGroup.h"
23#include "PvlKeyword.h"
24#include "PvlObject.h"
25
26using namespace std;
27namespace Isis {
48 KernelDb::KernelDb(const unsigned int allowedKernelTypes) {
49 m_filename = "None";
50 m_allowedKernelTypes = allowedKernelTypes;
51 m_kernelDbFiles.clear();
52 }
53
54
76 KernelDb::KernelDb(const QString &dbName, const unsigned int allowedKernelTypes) :
77 m_kernelData(dbName) {
78 m_filename = dbName;
79 m_allowedKernelTypes = allowedKernelTypes;
80 m_kernelDbFiles.clear();
81 }
82
83
105 KernelDb::KernelDb(std::istream &dbStream, const unsigned int allowedKernelTypes) {
106 dbStream >> m_kernelData;
107 m_filename = "internal stream";
108 m_allowedKernelTypes = allowedKernelTypes;
109 m_kernelDbFiles.clear();
110 }
111
117
135 return findLast("LeapSecond", lab);
136 }
137
138
156 return findLast("TargetAttitudeShape", lab);
157 }
158
159
177 return findLast("TargetPosition", lab);
178 }
179
180
198 return findAll("SpacecraftPointing", lab);
199 }
200
201
218 return findLast("SpacecraftClock", lab);
219 }
220
221
239 return findLast("SpacecraftPosition", lab);
240 }
241
242
260 return findLast("Instrument", lab);
261 }
262
263
281 return findLast("Frame", lab);
282 }
283
301 return findLast("InstrumentAddendum", lab);
302 }
303
304
322 return findLast("Dem", lab);
323 }
324
338 Kernel KernelDb::findLast(const QString &entry, Pvl &lab) {
339
340 QList< priority_queue<Kernel> > queues = findAll(entry, lab);
341 Kernel lastKernel;
342
343 if (queues.size() > 0 && queues.at(0).size() > 0) {
344 lastKernel = queues.at(0).top();
345 }
346
347 return lastKernel;
348 }
349
366 Pvl &lab) {
367
369 PvlObject &cube = lab.findObject("IsisCube");
370 int cameraVersion = -1;
371
372 try {
373 cameraVersion = CameraFactory::CameraVersion(lab);
374 }
375 catch (IException &) {
376 }
377
378 // Make sure the entry has been loaded into memory
379 if (!m_kernelData.hasObject(entry)) {
380 priority_queue<Kernel> emptyKernelQueue;
381 emptyKernelQueue.push(Kernel());
382 queues.push_back(emptyKernelQueue);
383 return queues;
384 }
385
386 // Get the start and end time for the cube
387 iTime start;
388 iTime end;
389
390 if (cube.hasGroup("Instrument")) {
391 start = (QString) cube.findGroup("Instrument")["StartTime"];
392
393 if (cube.findGroup("Instrument").hasKeyword("StopTime")) {
394 end = ((QString) cube.findGroup("Instrument")["StopTime"]);
395 }
396 else {
397 end = ((QString) cube.findGroup("Instrument")["StartTime"]);
398 }
399 }
400
401 // Loop through the objects to look for all matches to the entry value
402 for (int i = 0; i < m_kernelData.objects(); i++) {
403 if (m_kernelData.object(i).isNamed(entry)) {
404 priority_queue<Kernel> filesFound;
405 PvlObject &obj = m_kernelData.object(i);
406
407 for (int groupIndex = obj.groups() - 1; groupIndex >= 0; groupIndex--) {
408 // Get the group and start testing the cases in the keywords
409 // to see if they all match this cube
410 PvlGroup &grp = obj.group(groupIndex);
411
412 // If the group name isn't selection, skip it.
413 if (!grp.isNamed("Selection")) continue;
414
415 QString type = "";
416
417 // Make sure the type is allowed
418 if (grp.hasKeyword("Type")) {
419 type = (QString) grp["Type"];
420 if (!(Kernel::typeEnum(type) & m_allowedKernelTypes)) {
421 // will return 1 for each bit that has 1 in both type and allowed and
422 // return 0 for all other bits
423 //
424 // so, if Type = 0010 and allowed = 1010, then this bitwise operator
425 // (type & allowed) returns 0010 and is true.
426 // That is, this type is allowed.
427 continue;
428 }
429 }
430
431
432 bool startMatches = matches(lab, grp, start, cameraVersion);
433 bool endMatches = matches(lab, grp, end, cameraVersion);
434
435 if (startMatches && endMatches) {
436 // Simple case - the selection simply matches
437 filesFound.push(Kernel(Kernel::typeEnum(type), files(grp)));
438 QStringList kernelfiles = files(grp);
439 }
440 else if (startMatches) {
441 // Well, the selection start matched but not the end.
442 // Let's look for a second selection to handle overlap areas.
443 for (int endTimeIndex = obj.groups() - 1;
444 endTimeIndex >= 0;
445 endTimeIndex--) {
446
447 PvlGroup &endTimeGrp = obj.group(endTimeIndex);
448
449 // The second selection must:
450 // Not be the current selection
451 // Be a selection
452 // Be of the same quality
453 // Match the end time
454 //
455 // *If start time is also matched, do not merge and simply take the
456 // secondary match
457 if (endTimeIndex == groupIndex) continue;
458 if (!endTimeGrp.isNamed("Selection")) continue;
459 if (grp.hasKeyword("Type") != endTimeGrp.hasKeyword("Type")) continue;
460 if (grp.hasKeyword("Type") &&
461 grp["Type"] != endTimeGrp["Type"]) continue;
462 if (!matches(lab, endTimeGrp, end, cameraVersion)) continue;
463
464 // Better match is true if we find a full overlap
465 bool betterMatch = false;
466
467 // True if we have matching time ranges = we want to merge
468 bool endTimesMatch = true;
469
470 // Check for matching time ranges
471 for (int keyIndex = 0;
472 !betterMatch && keyIndex < grp.keywords();
473 keyIndex++) {
474 PvlKeyword &key = grp[keyIndex];
475
476 if (!key.isNamed("Time")) continue;
477
478 iTime timeRangeStart((QString)key[0]);
479 iTime timeRangeEnd((QString)key[1]);
480
481 bool thisEndMatches = matches(lab, endTimeGrp,
482 timeRangeEnd, cameraVersion);
483 endTimesMatch = endTimesMatch && thisEndMatches;
484
485 if (matches(lab, endTimeGrp, start, cameraVersion)
486 && matches(lab, endTimeGrp, end, cameraVersion)) {
487 // If we run into a continuous kernel, we want to take that in all
488 // cases.
489 betterMatch = true;
490 }
491 }
492
493 // No exact match but time ranges overlap, merge the selections
494 if (!betterMatch && endTimesMatch) {
495 QStringList startMatchFiles = files(grp);
496 QStringList endMatchFiles = files(endTimeGrp);
497
498 while (endMatchFiles.size()) {
499 startMatchFiles.push_back(endMatchFiles[endMatchFiles.size() - 1]);
500 endMatchFiles.pop_back();
501 }
502
503 filesFound.push(
504 Kernel(Kernel::typeEnum(type), startMatchFiles));
505 }
506 // Found an exact match, use it
507 else if (betterMatch) {
508 filesFound.push(Kernel(Kernel::typeEnum(type), files(endTimeGrp)));
509 QStringList kernelfiles = files(endTimeGrp);
510 }
511 }
512 }
513 }
514
515 queues.push_back(filesFound);
516 }
517 }
518
519 if (queues.size() == 0) {
520 priority_queue<Kernel> emptyKernelQueue;
521 emptyKernelQueue.push(Kernel());
522 queues.push_back(emptyKernelQueue);
523 }
524
525 return queues;
526 }
527
571 bool KernelDb::matches(const Pvl &lab, PvlGroup &grp,
572 iTime timeToMatch, int cameraVersion) {
573 // These are the conditions that make this test pass:
574 // 1) No time OR At least one matching time
575 // 2) All keyword matches are true OR No keyword matches present
576 //
577 // In order to accomplish this, matchTime is initialized to true and remains
578 // as such if and only if there are no time conditionals. If Time keywords
579 // exist, one of them has to set matchTime to true. The matchKeywords is
580 // true until a mismatch is found.
581 const PvlObject &cube = lab.findObject("IsisCube");
582 bool matchTime = !grp.hasKeyword("Time");
583 bool matchKeywords = true;
584 double startOffset = 0;
585 double endOffset = 0;
586 QString instrument = "";
587
588 if (grp.hasKeyword("StartOffset")){
589 startOffset = (double) grp["StartOffset"] + 0.001;
590 }
591 if (grp.hasKeyword("EndOffset")){
592 endOffset = (double) grp["EndOffset"] + 0.001;
593 }
594 if (grp.hasKeyword("Instrument")){
595 instrument = (QString) grp["Instrument"];
596 }
597
598 // First, the time search. Loop through the keywords, if the name isn't
599 // Time then skip it. If it is, then get the start/end times and keep
600 // looking until one is found.
601 for (int keyword = 0; keyword < grp.keywords(); keyword++) {
602 PvlKeyword key = grp[keyword];
603
604 if (key.isNamed("Time")) {
605
606 // Pull the selections start and end time out
607 iTime kernelStart = (QString) key[0];
608 iTime kernelEnd = (QString) key[1];
609
610 // If the kernel times inside of the requested times we
611 // set the matchTime to be true.
612 if ((kernelStart - startOffset <= timeToMatch) && (kernelEnd + endOffset >= timeToMatch)) {
613 matchTime = true;
614 }
615 // If the kernel segment has an instrument specification that doesn't match
616 // the instrument id in the label then the timing is always invalid
617 if (!instrument.isEmpty()) {
618 const PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
619 QString instId = (QString) inst.findKeyword("InstrumentId");
620 if (instId.compare(instrument) != 0) {
621 matchTime = false;
622 }
623 }
624 }
625
626 else if (key.isNamed("Match")) {
627 try {
628 QString matchGroup = key[0];
629 QString matchKey = key[1];
630 QString matchValue = key[2];
631
632 QString cubeValue = cube.findGroup(matchGroup)[matchKey];
633 cubeValue = cubeValue.simplified().trimmed().toUpper();
634 matchValue = matchValue.simplified().trimmed().toUpper();
635
636 // If QStrings are not the same, match automatically fails
637 if (cubeValue.compare(matchValue) != 0) {
638 matchKeywords = false;
639 }
640 }
641 catch (IException &e) {
642 // This error is thrown if the group or keyword do not exist in 'lab'
643 matchKeywords = false;
644 }
645 }
646 else if (key.isNamed("CameraVersion")) {
647 try {
648 for (int camVersionKeyIndex = 0;
649 camVersionKeyIndex < key.size();
650 camVersionKeyIndex++) {
651
652 bool versionMatch = false;
653 IString val = key[camVersionKeyIndex];
654 IString commaTok;
655
656 while ((commaTok = val.Token(",")).ToQt().length() > 0) {
657 if (commaTok.find('-') != string::npos) {
658 QString dashTok;
659 int start = commaTok.Token("-").ToInteger();
660 int end = commaTok.Token("-").ToInteger();
661 int direction;
662 direction = (start <= end) ? 1 : -1;
663 // Save the entire range of bands
664 for (int version = start;
665 version != end + direction;
666 version += direction) {
667 if (version == cameraVersion) {
668 versionMatch = true;
669 }
670 }
671 }
672 // This token is a single band specification
673 else {
674 if (commaTok.ToInteger() == cameraVersion) {
675 versionMatch = true;
676 }
677 }
678 }
679
680 if (!versionMatch) {
681 matchKeywords = false;
682 }
683 }
684 }
685 catch (IException &) {
686 matchKeywords = false;
687 }
688 }
689 }
690
691 return matchKeywords && matchTime;
692 }
693
731 void KernelDb::loadSystemDb(const QString &mission, const Pvl &lab) {
732
733 // Get the base DataDirectory
734 PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory");
735 QString baseDir = dataDir["Base"];
736
737 // Get the mission DataDirectory
738 QString missionDir = dataDir[mission];
739
740 // Load the leapsecond DB
741 loadKernelDbFiles(dataDir, baseDir + "/kernels/lsk", lab);
742 // Load the target attitude shape DB
743 // Try to get mission specific pck data, if that
744 // fails, fallback to the base pck data
745 try {
746 loadKernelDbFiles(dataDir, missionDir + "/kernels/pck", lab);
747 }
748 catch (IException &e) {
749 loadKernelDbFiles(dataDir, baseDir + "/kernels/pck", lab);
750 }
751 // Load the target position DB
752 FileName tpDbPath(missionDir + "/kernels/tspk");
753 if (tpDbPath.fileExists()) {
754 loadKernelDbFiles(dataDir, missionDir + "/kernels/tspk", lab);
755 }
756 else {
757 loadKernelDbFiles(dataDir, baseDir + "/kernels/spk", lab);
758 }
759 // Load the DEM DB
760 loadKernelDbFiles(dataDir, baseDir + "/dems", lab);
761 // Load the mission specific spacecraft pointing DB
762 loadKernelDbFiles(dataDir, missionDir + "/kernels/ck", lab);
763 // Load the mission specific frame DB
764 loadKernelDbFiles(dataDir, missionDir + "/kernels/fk", lab);
765 // Load the mission specific instrument DB
766 loadKernelDbFiles(dataDir, missionDir + "/kernels/ik", lab);
767 // Load the mission specific spacecraft clock DB
768 loadKernelDbFiles(dataDir, missionDir + "/kernels/sclk", lab);
769 // Load the mission specific spacecraft position DB
770 loadKernelDbFiles(dataDir, missionDir + "/kernels/spk", lab);
771 // Load the mission specific instrument addendum DB
772 loadKernelDbFiles(dataDir, missionDir + "/kernels/iak", lab);
774 }
775
805 QString directory, const Pvl &lab) {
806 // get most recent version of config file
807 FileName configFile = directory + "/kernels.????.conf";
808 bool noConfigFile = false;
809 // if there is no config file, default to the most recent kernel db file
810 try {
811 configFile = configFile.highestVersion();
812 }
813 catch (IException &e) {
814 noConfigFile = true;
815 }
816 if (noConfigFile) {
817 FileName kernelDb(directory + "/kernels.????.db");
818 m_kernelDbFiles.append(kernelDb.highestVersion());
819 }
820 else { // else, read in the appropriate database files from the config file
821 PvlObject inst = Pvl(configFile.expanded()).findObject("Instrument");
822 bool foundMatch = false;
823 // loop through each group until we find a match
824 for (int groupIndex = 0; groupIndex < inst.groups(); groupIndex++) {
825 if (!foundMatch) {
826 PvlGroup &grp = inst.group(groupIndex);
827 // Only add files in Selection groups with matching intrument id
828 if (grp.isNamed("Selection")
829 && KernelDb::matches(lab, grp, iTime(), 1)) {
830 foundMatch = true;
831 // add each File keywords in the matching group to the list
832 for (int keyIndex = 0; keyIndex < grp.keywords(); keyIndex++) {
833 PvlKeyword keyword = grp[keyIndex];
834 if (keyword.isNamed("File")) {
835 QString dir = dataDir[keyword[0]];
836 FileName kernelDb( dir + "/" + keyword[1]);
837 m_kernelDbFiles.append(kernelDb.highestVersion());
838 }
839 }
840 }
841 }
842 }
843 }
844 return;
845 }
846
847
866 // read each of the database files appended to the list into m_kernelData
867 foreach (FileName kernelDbFile, m_kernelDbFiles) {
868 try {
869 m_kernelData.read(kernelDbFile.expanded());
870 }
871 catch (IException &e) {
872 QString msg = "Unable to read kernel database file ["
873 + kernelDbFile.expanded() + "].";
874 throw IException(e, IException::Unknown, msg, _FILEINFO_);
875 }
876 }
877 }
878
889
890
902
903 for (int i = 0; i < grp.keywords(); i++) {
904 PvlKeyword kfile = grp[i];
905 if (kfile.name() != "File") continue;
906
907 // Two values in the "File" keyword from the DB,
908 // indicates an ISIS preference in the DataDirectory section
909 // and a filename
910 if (kfile.size() == 2) {
911 QString pref = kfile[0];
912 QString version = kfile[1];
913 FileName filename("$" + pref + "/" + version);
914 if (filename.isVersioned())
915 filename = filename.highestVersion();
916 files.push_back(filename.originalPath() + "/" + filename.name());
917 }
918 // One value in "File" indicates a full file spec
919 else if (kfile.size() == 1) {
920 FileName filename(kfile[0]);
921 if (filename.isVersioned())
922 filename = filename.highestVersion();
923 files.push_back(filename.originalPath() + "/" + filename.name());
924 }
925 else {
926 QString msg = "Invalid File keyword value in [Group = ";
927 msg += grp.name() + "] in database file [";
928 msg += m_filename + "]";
929 throw IException(IException::Unknown, msg, _FILEINFO_);
930 }
931 }
932
933 return files;
934 }
935} //end namespace isis
static int CameraVersion(Cube &cube)
This looks up the current camera model version from the cube.
File name manipulation and expansion.
Definition FileName.h:100
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition FileName.cpp:449
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
FileName highestVersion() const
Searches the directory specified in the file name for the highest version of the file name.
Definition FileName.cpp:313
QString originalPath() const
Returns the path of the original file name.
Definition FileName.cpp:84
bool isVersioned() const
Checks to see if a file name is versioned by date or numerically.
Definition FileName.cpp:281
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
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 Token(const IString &separator)
Returns the first token in the IString.
Definition IString.cpp:897
Kernel instrumentAddendum(Pvl &lab)
This method finds the highest version of all Instrument Addendum kernels (iak) identified by the data...
Definition KernelDb.cpp:300
QStringList files(PvlGroup &grp)
This method retrieves the values of all of the "File" keywords in the given PvlGroup.
Definition KernelDb.cpp:900
Kernel spacecraftClock(Pvl &lab)
This method finds the highest version of all Spacecraft Clock kernels (sclk) identified by the databa...
Definition KernelDb.cpp:217
Kernel targetAttitudeShape(Pvl &lab)
This method finds the highest version of all Target Attitude Shape kernels (pck) identified by the da...
Definition KernelDb.cpp:155
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:804
QList< FileName > m_kernelDbFiles
List of the kernel database file names that were read in when the loadSystemDb() method is called.
Definition KernelDb.h:145
Kernel instrument(Pvl &lab)
This method finds the last Instrument kernel found that matches the (ik) criteria in the database and...
Definition KernelDb.cpp:259
~KernelDb()
Destructs KernelDb object.
Definition KernelDb.cpp:115
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:731
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:571
Kernel targetPosition(Pvl &lab)
This method finds the highest version of all Target Position kernels (tspk) identified by the databas...
Definition KernelDb.cpp:176
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:338
Pvl m_kernelData
Pvl containing the information in the kernel database(s) that is read in from the constructor and whe...
Definition KernelDb.h:156
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:365
QString m_filename
The name of the kernel database file.
Definition KernelDb.h:143
Kernel spacecraftPosition(Pvl &lab)
This method finds the highest version of all Spacecraft Position kernels (spk) identified by the data...
Definition KernelDb.cpp:238
unsigned int m_allowedKernelTypes
This integer value represents which Kernel::Types are allowed.
Definition KernelDb.h:148
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:280
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:197
QList< FileName > kernelDbFiles()
Accessor method to retrieve the list of kernel database files that were read in when loadSystemDb() i...
Definition KernelDb.cpp:886
Kernel dem(Pvl &lab)
This method finds the highest version of all Digital Terrain Models (DEMs) found that match the crite...
Definition KernelDb.cpp:321
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:134
void readKernelDbFiles()
This method is called by loadSystemDb() to read kernel database file list compiled by loadKernelDbFil...
Definition KernelDb.cpp:865
KernelDb(const unsigned int allowedKernelTypes)
Constructs a new KernelDb object with a given integer value representing the Kernel::Type enumeration...
Definition KernelDb.cpp:48
This class stores Kernel information, including Type and kernel file names.
Definition Kernel.h:36
static Type typeEnum(const QString &type)
Converts the given string to a character as follows.
Definition Kernel.cpp:57
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
QString name() const
Returns the container name.
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
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
QString name() const
Returns the keyword name.
Definition PvlKeyword.h:103
int size() const
Returns the number of values stored in this keyword.
Definition PvlKeyword.h:133
bool isNamed(QString name) const
Determines whether two PvlKeywords have the same name or not.
Definition PvlKeyword.h:115
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
PvlGroup & group(const int index)
Return the group at the specified index.
int groups() const
Returns the number of groups contained.
Definition PvlObject.h:75
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:274
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Definition PvlObject.h:210
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
Parse and return pieces of a time string.
Definition iTime.h:65
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.