From 6dafcfa00c225808f5dfd76aa940e08d584ae35c Mon Sep 17 00:00:00 2001
From: Kristin
Date: Fri, 10 Jan 2020 15:29:28 -0700
Subject: [PATCH 01/13] Update meta.yaml to rename conda package to isis from
isis3
---
recipe/meta.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/recipe/meta.yaml b/recipe/meta.yaml
index 7ec852a89b..3a47842618 100644
--- a/recipe/meta.yaml
+++ b/recipe/meta.yaml
@@ -26,7 +26,7 @@
{% set build_number = "0" %}
package:
- name: isis3
+ name: isis
version: {{ version }}
source:
From 834b5b538f2d10dfc72dcebb6588c34811c20efe Mon Sep 17 00:00:00 2001
From: Jesse Mapel
Date: Fri, 28 Feb 2020 10:59:04 -0700
Subject: [PATCH 02/13] Used CK quality for PCK selection in spiceinit (#3716)
* Changed PCK to use CK quality in spiceinit
* Added spiceinit history for change
---
isis/src/base/apps/spiceinit/spiceinit.cpp | 48 +++++++++++-----------
isis/src/base/apps/spiceinit/spiceinit.xml | 17 +++++---
2 files changed, 35 insertions(+), 30 deletions(-)
diff --git a/isis/src/base/apps/spiceinit/spiceinit.cpp b/isis/src/base/apps/spiceinit/spiceinit.cpp
index 97c7ea9347..9302fadd5e 100644
--- a/isis/src/base/apps/spiceinit/spiceinit.cpp
+++ b/isis/src/base/apps/spiceinit/spiceinit.cpp
@@ -23,7 +23,7 @@
using namespace std;
-namespace Isis {
+namespace Isis {
void getUserEnteredKernel(UserInterface &ui, const QString ¶m, Kernel &kernel);
bool tryKernels(Cube *icube, Process &p, UserInterface &ui, Pvl *log,
@@ -42,16 +42,16 @@ namespace Isis {
* @param ui The Application UI
* @param(out) log The Pvl that attempted kernel sets will be logged to
*/
- void spiceinit(UserInterface &ui, Pvl *log) {
+ void spiceinit(UserInterface &ui, Pvl *log) {
// Open the input cube
Process p;
-
+
CubeAttributeInput cai;
Cube *icube = p.SetInputCube(ui.GetFileName("FROM"), cai, ReadWrite);
spiceinit(icube, ui, log);
p.EndProcess();
}
-
+
/**
* Spiceinit a Cube
@@ -76,7 +76,7 @@ namespace Isis {
QString msg = "At least one SPK quality must be selected";
throw IException(IException::User, msg, _FILEINFO_);
}
-
+
// Make sure it is not projected
Projection *proj = NULL;
try {
@@ -92,7 +92,7 @@ namespace Isis {
}
Pvl lab = *icube->label();
-
+
// if cube has existing polygon delete it
if (icube->label()->hasObject("Polygon")) {
icube->label()->deleteObject("Polygon");
@@ -144,7 +144,7 @@ namespace Isis {
Kernel lk, pck, targetSpk, fk, ik, sclk, spk, iak, dem, exk;
QList< priority_queue > ck;
lk = baseKernels.leapSecond(lab);
- pck = baseKernels.targetAttitudeShape(lab);
+ pck = ckKernels.targetAttitudeShape(lab);
targetSpk = baseKernels.targetPosition(lab);
ik = baseKernels.instrument(lab);
sclk = baseKernels.spacecraftClock(lab);
@@ -152,7 +152,7 @@ namespace Isis {
fk = ckKernels.frame(lab);
ck = ckKernels.spacecraftPointing(lab);
spk = spkKernels.spacecraftPosition(lab);
-
+
if (ui.GetBoolean("CKNADIR")) {
// Only add nadir if no spacecraft pointing found, so we will set (priority) type to 0.
QStringList nadirCk;
@@ -198,7 +198,7 @@ namespace Isis {
_FILEINFO_);
}
else if (ui.WasEntered("CK")) {
- // if user entered ck
+ // if user entered ck
// empty ck queue list found in system
while (ck.size()) {
ck.pop_back();
@@ -209,10 +209,10 @@ namespace Isis {
emptyKernelQueue.push(Kernel());
ck.push_back(emptyKernelQueue);
}
-
+
// while the first queue is not empty, loop through it until tryKernels() succeeds
while (ck.at(0).size() != 0 && !kernelSuccess) {
- // create an empty kernel
+ // create an empty kernel
Kernel realCkKernel;
QStringList ckKernelList;
@@ -236,13 +236,13 @@ namespace Isis {
Kernel topPriority = ck.at(i).top();
ckKernelList.append(topPriority.kernels());
// set the type to equal the type of the to priority of the first
- //queue
- realCkKernel.setType(topPriority.type());
+ //queue
+ realCkKernel.setType(topPriority.type());
}
}
}
- // pop the top priority ck off only the first queue so that the next
+ // pop the top priority ck off only the first queue so that the next
// iteration will test the next highest priority of the first queue with
// the top priority of each of the other queues.
ck[0].pop();
@@ -267,14 +267,14 @@ namespace Isis {
}
/**
- * If the user entered the parameter param, then kernel is replaced by the
+ * If the user entered the parameter param, then kernel is replaced by the
* user's values and quality is reset to 0. Otherwise, the kernels loaded by the
* KernelDb class will be kept.
*
* @param param Name of the kernel input parameter
- *
- * @param kernel Kernel object to be overwritten if the specified user parameter
- * was entered.
+ *
+ * @param kernel Kernel object to be overwritten if the specified user parameter
+ * was entered.
*/
void getUserEnteredKernel(UserInterface &ui, const QString ¶m, Kernel &kernel) {
if (ui.WasEntered(param)) {
@@ -395,7 +395,7 @@ namespace Isis {
// Get rid of old keywords from previously inited cubes
if (currentKernels.hasKeyword("Source"))
currentKernels.deleteKeyword("Source");
-
+
if (currentKernels.hasKeyword("SpacecraftPointing"))
currentKernels.deleteKeyword("SpacecraftPointing");
@@ -450,7 +450,7 @@ namespace Isis {
try {
cam = icube->camera();
currentKernels = icube->group("Kernels");
-
+
PvlKeyword source("Source");
if (cam->isUsingAle()) {
@@ -461,11 +461,11 @@ namespace Isis {
}
currentKernels += source;
- icube->putGroup(currentKernels);
+ icube->putGroup(currentKernels);
if (log){
log->addGroup(currentKernels);
- }
-
+ }
+
}
catch(IException &e) {
Pvl errPvl = e.toPvl();
@@ -665,7 +665,7 @@ namespace Isis {
continue;
}
}
-
+
if (log) {
log->addGroup(logGrp);
}
diff --git a/isis/src/base/apps/spiceinit/spiceinit.xml b/isis/src/base/apps/spiceinit/spiceinit.xml
index 6ec49807cf..391fe2a9c4 100644
--- a/isis/src/base/apps/spiceinit/spiceinit.xml
+++ b/isis/src/base/apps/spiceinit/spiceinit.xml
@@ -90,9 +90,9 @@
not have their paths expanded. This is to allow variables like $msg/ to work correctly.
- The spiceinit program will also add the RayTraceEngine, OnError, and Tolerance keywords to the Kernels
- group if specified in the IsisPreferences file. If included, these keywords specify the ray-tracing engine to use and how to use it for shapemodels.
- Please see the IsisPreferences file for more details.
+ The spiceinit program will also add the RayTraceEngine, OnError, and Tolerance keywords to the Kernels
+ group if specified in the IsisPreferences file. If included, these keywords specify the ray-tracing engine to use and how to use it for shapemodels.
+ Please see the IsisPreferences file for more details.
Troubleshooting: If spiceinit is failing with the error
@@ -279,17 +279,22 @@
Updated spiceinit to retain ShapeModel-related keywords set by the ShapeModelFactory and add them to the kernel
- group. Like other keywords in the kernels group, if they are present at the beginning of a spiceinit run (if we are re-spiceiniting)
- they are removed.
+ group. Like other keywords in the kernels group, if they are present at the beginning of a spiceinit run (if we are re-spiceiniting)
+ they are removed.
- Updated spiceinit to remove code dealing with the CubeSupported Pvl Keyword, from the ShapeModel group in the IsisPreferences file,
+ Updated spiceinit to remove code dealing with the CubeSupported Pvl Keyword, from the ShapeModel group in the IsisPreferences file,
which has been removed.
Made change to camera construction error throw for better reporting on uninstantiated cameras.
Fixes #5163.
+
+ Changed PCK selection to use the same qualities as CK so that target body parameters
+ derived from bundle adjustment can be used alongside CKs derived from bundle adjustment.
+ Fixes #3669.
+
From 3b955cd8c89ca968f8ff7a683c4534763dbd05f9 Mon Sep 17 00:00:00 2001
From: Kristin
Date: Fri, 28 Feb 2020 15:59:50 -0700
Subject: [PATCH 03/13] Adds the ability to save and restore a greyscale
stretch to/from a Cube (#3717)
* Update meta.yaml to rename conda package to isis from isis3
* Initial stretch attempt
* Now will write a single stretch with a name and type to the cube
* Stretch updated to inherit from Blob, re-loading a saved stretch works but only if Linear right now
* Clean up Stretch class
* Completely move stretchTypes into stretch class, and some minor cleanup
* Fixed combo-box not updating bug and more cleanup
* Further cleanup of propagated earlier changes with types and names being removed from unnecessary classes
* Removed added unneeded member variables from StretchType
* Cleanup StretchTool class
* Update enter-text dialogs to drop down selection options
* Wrapped some long strings
* Initial commit to address most of review comments
* Removed buttons in case of RGB stretch and add a 'Color' PvlKeyword to Stretch output
Co-authored-by: Stuart Sides
---
isis/src/base/objs/Stretch/Stretch.cpp | 106 +++++++++-
isis/src/base/objs/Stretch/Stretch.h | 17 +-
.../objs/StretchTool/AdvancedStretch.cpp | 61 +++++-
.../qisis/objs/StretchTool/AdvancedStretch.h | 8 +-
.../StretchTool/AdvancedStretchDialog.cpp | 21 +-
.../objs/StretchTool/AdvancedStretchDialog.h | 4 +
.../objs/StretchTool/BinaryStretchType.cpp | 2 +
.../objs/StretchTool/LinearStretchType.cpp | 3 +-
.../objs/StretchTool/LinearStretchType.h | 1 -
.../objs/StretchTool/ManualStretchType.cpp | 2 +
.../objs/StretchTool/SawtoothStretchType.cpp | 2 +
.../objs/StretchTool/SawtoothStretchType.h | 1 -
.../qisis/objs/StretchTool/StretchTool.cpp | 181 ++++++++++++++++++
isis/src/qisis/objs/StretchTool/StretchTool.h | 3 +
.../qisis/objs/StretchTool/StretchType.cpp | 17 +-
isis/src/qisis/objs/StretchTool/StretchType.h | 6 +-
16 files changed, 416 insertions(+), 19 deletions(-)
diff --git a/isis/src/base/objs/Stretch/Stretch.cpp b/isis/src/base/objs/Stretch/Stretch.cpp
index 24458fd21e..a16f37379b 100644
--- a/isis/src/base/objs/Stretch/Stretch.cpp
+++ b/isis/src/base/objs/Stretch/Stretch.cpp
@@ -38,7 +38,7 @@ namespace Isis {
* Constructs a Stretch object with default mapping of special pixel values to
* themselves.
*/
- Stretch::Stretch() {
+ Stretch::Stretch() : Blob("ImageStretch", "Stretch") {
p_null = Isis::NULL8;
p_lis = Isis::LOW_INSTR_SAT8;
p_lrs = Isis::LOW_REPR_SAT8;
@@ -47,8 +47,29 @@ namespace Isis {
p_minimum = p_lrs;
p_maximum = p_hrs;
p_pairs = 0;
+ p_type = "None";
}
+
+ /**
+ * Constructs a Stretch object with default mapping of special pixel values to
+ * themselves and a provided name.
+ *
+ * @param name Name to use for Stretch
+ */
+ Stretch::Stretch(QString name) : Blob(name, "Stretch") {
+ p_null = Isis::NULL8;
+ p_lis = Isis::LOW_INSTR_SAT8;
+ p_lrs = Isis::LOW_REPR_SAT8;
+ p_his = Isis::HIGH_INSTR_SAT8;
+ p_hrs = Isis::HIGH_REPR_SAT8;
+ p_minimum = p_lrs;
+ p_maximum = p_hrs;
+ p_pairs = 0;
+ p_type = "None";
+ }
+
+
/**
* Adds a stretch pair to the list of pairs. Note that all input pairs must be
* in ascending order.
@@ -410,6 +431,89 @@ namespace Isis {
this->p_output = other.p_output;
}
+
+ /**
+ * Read saved Stretch data from a Cube into this object.
+ *
+ * This is called by Blob::Read() and is the actual data reading function
+ * ultimately called when running something like cube->read(stretch);
+ *
+ * @param is input stream containing the saved Stretch information
+ */
+ void Stretch::ReadData(std::istream &is) {
+ // Set the Stretch Type
+ p_type = p_blobPvl["StretchType"][0];
+
+ // Read in the Stretch Pairs
+ streampos sbyte = p_startByte - 1;
+ is.seekg(sbyte, std::ios::beg);
+ if (!is.good()) {
+ QString msg = "Error preparing to read data from " + p_type +
+ " [" + p_blobName + "]";
+ throw IException(IException::Io, msg, _FILEINFO_);
+ }
+
+ char *buf = new char[p_nbytes+1];
+ memset(buf, 0, p_nbytes + 1);
+
+ is.read(buf, p_nbytes);
+
+ // Read buffer data into a QString so we can call Parse()
+ std::string stringFromBuffer(buf);
+ QString qStringFromBuffer = QString::fromStdString(stringFromBuffer);
+ Parse(qStringFromBuffer);
+
+ delete [] buf;
+
+ if (!is.good()) {
+ QString msg = "Error reading data from " + p_type + " [" +
+ p_blobName + "]";
+ throw IException(IException::Io, msg, _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Get the Type of Stretch. This is only used by the AdvancedStretchTool.
+ *
+ * @return QString Type of Stretch.
+ */
+ QString Stretch::getType(){
+ return p_type;
+ }
+
+
+ /**
+ * Set the Type of Stretch. This is only used by the AdvancedStretchTool.
+ *
+ * @param stretchType The type of stretch.
+ */
+ void Stretch::setType(QString stretchType){
+ // check to see if valid input
+ p_type = stretchType;
+ }
+
+
+ /**
+ * Initializes for writing stretch to cube blob
+ */
+ void Stretch::WriteInit() {
+ p_nbytes = Text().toStdString().size();
+ }
+
+
+ /**
+ * Writes the stretch information to a cube.
+ *
+ * This is called by Blob::write() and is ultimately the function
+ * called when running something like cube->write(stretch);
+ *
+ * @param os output stream to write the stretch data to.
+ */
+ void Stretch::WriteData(std::fstream &os) {
+ os.write(Text().toStdString().c_str(), p_nbytes);
+ }
+
} // end namespace isis
diff --git a/isis/src/base/objs/Stretch/Stretch.h b/isis/src/base/objs/Stretch/Stretch.h
index 144bb41251..5da48bbe74 100644
--- a/isis/src/base/objs/Stretch/Stretch.h
+++ b/isis/src/base/objs/Stretch/Stretch.h
@@ -26,6 +26,7 @@
#include
#include "Pvl.h"
#include "Histogram.h"
+#include "Blob.h"
namespace Isis {
/**
@@ -67,9 +68,10 @@ namespace Isis {
* Created second Parse method for handling pairs where the
* input side is a perentage. Fixed Input and Output getters
* to check both sides of boundry condition for valid data
- *
+ * @history 2020-02-27 Kristin Berry - Updated to inherit from Blob so Stretches can be
+ * saved and restored from cubes.
*/
- class Stretch {
+ class Stretch : public Isis::Blob {
private:
std::vector p_input; //!< Array for input side of stretch pairs
std::vector p_output; //!< Array for output side of stretch pairs
@@ -88,10 +90,13 @@ namespace Isis {
double p_minimum; //! NextPair(QString &pairs);
public:
Stretch();
+ Stretch(QString name);
//! Destroys the Stretch object
~Stretch() {};
@@ -177,6 +182,9 @@ namespace Isis {
return p_pairs;
};
+ QString getType();
+ void setType(QString type);
+
double Input(const int index) const;
double Output(const int index) const;
@@ -188,6 +196,11 @@ namespace Isis {
};
void CopyPairs(const Stretch &other);
+
+ protected:
+ void WriteInit();
+ void ReadData(std::istream &is);
+ void WriteData(std::fstream &os);
};
};
diff --git a/isis/src/qisis/objs/StretchTool/AdvancedStretch.cpp b/isis/src/qisis/objs/StretchTool/AdvancedStretch.cpp
index ae237ddd05..6b41d0b892 100644
--- a/isis/src/qisis/objs/StretchTool/AdvancedStretch.cpp
+++ b/isis/src/qisis/objs/StretchTool/AdvancedStretch.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include "Stretch.h"
#include "IString.h"
@@ -35,40 +36,52 @@ namespace Isis {
typeSelectionArea->setLayout(new QHBoxLayout());
typeSelectionArea->layout()->addWidget(new QLabel("Stretch Type"));
- QComboBox *stretchTypeSelection = new QComboBox();
- stretchTypeSelection->addItem("Linear", 0);
- stretchTypeSelection->addItem("Sawtooth", 1);
- stretchTypeSelection->addItem("Binary", 2);
- stretchTypeSelection->addItem("Manual", 3);
+ p_stretchTypeSelection = new QComboBox();
+ p_stretchTypeSelection->addItem("Linear", 0);
+ p_stretchTypeSelection->addItem("Sawtooth", 1);
+ p_stretchTypeSelection->addItem("Binary", 2);
+ p_stretchTypeSelection->addItem("Manual", 3);
- typeSelectionArea->layout()->addWidget(stretchTypeSelection);
+ typeSelectionArea->layout()->addWidget(p_stretchTypeSelection);
layout()->addWidget(typeSelectionArea);
p_stretchTypeStack = new QStackedWidget();
LinearStretchType *linear = new LinearStretchType(hist, curStretch,
name, color);
connect(linear, SIGNAL(stretchChanged()), this, SIGNAL(stretchChanged()));
+ connect(linear, SIGNAL(saveToCube()), this, SIGNAL(saveToCube()));
+ connect(linear, SIGNAL(deleteFromCube()), this, SIGNAL(deleteFromCube()));
+ connect(linear, SIGNAL(loadStretch()), this, SIGNAL(loadStretch()));
p_stretchTypeStack->addWidget(linear);
SawtoothStretchType *sawtooth = new SawtoothStretchType(hist, curStretch,
name, color);
connect(sawtooth, SIGNAL(stretchChanged()), this, SIGNAL(stretchChanged()));
+ connect(sawtooth, SIGNAL(saveToCube()), this, SIGNAL(saveToCube()));
+ connect(sawtooth, SIGNAL(deleteFromCube()), this, SIGNAL(deleteFromCube()));
+ connect(sawtooth, SIGNAL(loadStretch()), this, SIGNAL(loadStretch()));
p_stretchTypeStack->addWidget(sawtooth);
BinaryStretchType *binary = new BinaryStretchType(hist, curStretch,
name, color);
connect(binary, SIGNAL(stretchChanged()), this, SIGNAL(stretchChanged()));
+ connect(binary, SIGNAL(saveToCube()), this, SIGNAL(saveToCube()));
+ connect(binary, SIGNAL(deleteFromCube()), this, SIGNAL(deleteFromCube()));
+ connect(binary, SIGNAL(loadStretch()), this, SIGNAL(loadStretch()));
p_stretchTypeStack->addWidget(binary);
ManualStretchType *manual = new ManualStretchType(hist, curStretch,
name, color);
connect(manual, SIGNAL(stretchChanged()), this, SIGNAL(stretchChanged()));
+ connect(manual, SIGNAL(saveToCube()), this, SIGNAL(saveToCube()));
+ connect(manual, SIGNAL(deleteFromCube()), this, SIGNAL(deleteFromCube()));
+ connect(manual, SIGNAL(loadStretch()), this, SIGNAL(loadStretch()));
p_stretchTypeStack->addWidget(manual);
layout()->addWidget(p_stretchTypeStack);
- connect(stretchTypeSelection, SIGNAL(currentIndexChanged(int)),
+ connect(p_stretchTypeSelection, SIGNAL(currentIndexChanged(int)),
p_stretchTypeStack, SLOT(setCurrentIndex(int)));
- connect(stretchTypeSelection, SIGNAL(currentIndexChanged(int)),
+ connect(p_stretchTypeSelection, SIGNAL(currentIndexChanged(int)),
this, SIGNAL(stretchChanged()));
}
@@ -105,6 +118,38 @@ namespace Isis {
}
+ /**
+ * Used to restore a saved Stretch from a cube. This function is
+ * distinct from setStretch in that setStretch deliberately _does not_
+ * change the stretch type, and this function does change the stretch type.
+ *
+ * @param newStretch saved stretch to restore
+ */
+ void AdvancedStretch::restoreSavedStretch(Stretch newStretch) {
+ QString stretchTypeName = newStretch.getType();
+
+ int index = 0;
+ if (stretchTypeName.compare("LinearStretch") == 0 ) {
+ index = 0;
+ }
+ else if (stretchTypeName.compare("SawtoothStretch") == 0 ) {
+ index = 1;
+ }
+ else if (stretchTypeName.compare("BinaryStretch") == 0) {
+ index = 2;
+ }
+ else if (stretchTypeName.compare("ManualStretch") == 0) {
+ index = 3;
+ }
+ // Fail by defaulting to Linear
+
+ p_stretchTypeSelection->setCurrentIndex(index);
+ StretchType *stretchType = (StretchType *)
+ p_stretchTypeStack->currentWidget();
+ stretchType->setStretch(newStretch);
+ }
+
+
/**
* This is called when the visible area changes, so that the
* histogram can be updated. It is essential that the stretch
diff --git a/isis/src/qisis/objs/StretchTool/AdvancedStretch.h b/isis/src/qisis/objs/StretchTool/AdvancedStretch.h
index acd80e8f32..3f49826e3c 100644
--- a/isis/src/qisis/objs/StretchTool/AdvancedStretch.h
+++ b/isis/src/qisis/objs/StretchTool/AdvancedStretch.h
@@ -4,6 +4,7 @@
#include
class QStackedWidget;
+class QComboBox;
class QLayout;
class QString;
class QColor;
@@ -36,16 +37,19 @@ namespace Isis {
~AdvancedStretch();
Stretch getStretch();
void setStretch(Stretch newStretch);
+ void restoreSavedStretch(Stretch newStretch);
void setHistogram(const Histogram &newHist);
signals:
//! Emitted when a new stretch is available
void stretchChanged();
-
- protected:
+ void saveToCube();
+ void deleteFromCube();
+ void loadStretch();
private:
QStackedWidget *p_stretchTypeStack; //!< StretchType's
+ QComboBox *p_stretchTypeSelection; //!< ComboBox of StretchTypes
};
};
diff --git a/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.cpp b/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.cpp
index 7055a49a2c..63a05e2fa2 100644
--- a/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.cpp
+++ b/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.cpp
@@ -21,7 +21,10 @@ namespace Isis {
p_bluStretch = NULL;
p_enabled = false;
+ setWindowTitle("Advanced Stretch Tool");
+
QHBoxLayout *layout = new QHBoxLayout();
+
setLayout(layout);
}
@@ -124,6 +127,22 @@ namespace Isis {
connect(p_grayStretch, SIGNAL(stretchChanged()),
this, SIGNAL(stretchChanged()));
+ connect(p_grayStretch, SIGNAL(saveToCube()),
+ this, SIGNAL(saveToCube()));
+ connect(p_grayStretch, SIGNAL(deleteFromCube()),
+ this, SIGNAL(deleteFromCube()));
+ connect(p_grayStretch, SIGNAL(loadStretch()),
+ this, SIGNAL(loadStretch()));
+ }
+
+
+ /**
+ * Restores a saved stretch from the cube
+ *
+ * @param stretch
+ */
+ void AdvancedStretchDialog::restoreSavedStretch(Stretch stretch){
+ p_grayStretch->restoreSavedStretch(stretch);
}
@@ -213,7 +232,7 @@ namespace Isis {
/**
- * This calls setHistogram on the gray advanced stretche. This
+ * This calls setHistogram on the gray advanced stretches. This
* should be called every time the visible area changes.
*
* @param grayHist Histogram of visible area on gray band
diff --git a/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.h b/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.h
index 2799f5a15f..24a41f331e 100644
--- a/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.h
+++ b/isis/src/qisis/objs/StretchTool/AdvancedStretchDialog.h
@@ -48,6 +48,7 @@ namespace Isis {
Histogram &grayHist);
void updateHistogram(const Histogram &grayHist);
bool isRgbMode() const;
+ void restoreSavedStretch(Stretch stretch);
Stretch getGrayStretch();
Stretch getRedStretch();
@@ -77,6 +78,9 @@ namespace Isis {
void stretchChanged();
//! Emitted when this dialog is shown or hidden
void visibilityChanged();
+ void saveToCube();
+ void deleteFromCube();
+ void loadStretch();
public slots:
void updateStretch(CubeViewport *);
diff --git a/isis/src/qisis/objs/StretchTool/BinaryStretchType.cpp b/isis/src/qisis/objs/StretchTool/BinaryStretchType.cpp
index d3c7b7e3f5..2e67c7011e 100644
--- a/isis/src/qisis/objs/StretchTool/BinaryStretchType.cpp
+++ b/isis/src/qisis/objs/StretchTool/BinaryStretchType.cpp
@@ -73,6 +73,8 @@ namespace Isis {
sliderWidget->setLayout(sliderLayout);
p_mainLayout->addWidget(sliderWidget, 1, 0);
+ p_stretch->setType("BinaryStretch");
+
setLayout(p_mainLayout);
setStretch(calculateNewStretch());
}
diff --git a/isis/src/qisis/objs/StretchTool/LinearStretchType.cpp b/isis/src/qisis/objs/StretchTool/LinearStretchType.cpp
index a1211598ed..66953c5320 100644
--- a/isis/src/qisis/objs/StretchTool/LinearStretchType.cpp
+++ b/isis/src/qisis/objs/StretchTool/LinearStretchType.cpp
@@ -71,6 +71,7 @@ namespace Isis {
sliderWidget->setLayout(sliderLayout);
p_mainLayout->addWidget(sliderWidget, 1, 0);
+ p_stretch->setType("LinearStretch");
setLayout(p_mainLayout);
setStretch(stretch);
@@ -254,8 +255,8 @@ namespace Isis {
}
}
-
Stretch LinearStretchType::getStretch() {
return *p_stretch;
}
+
}
diff --git a/isis/src/qisis/objs/StretchTool/LinearStretchType.h b/isis/src/qisis/objs/StretchTool/LinearStretchType.h
index 1ca66618ec..b41d46b8ef 100644
--- a/isis/src/qisis/objs/StretchTool/LinearStretchType.h
+++ b/isis/src/qisis/objs/StretchTool/LinearStretchType.h
@@ -36,7 +36,6 @@ namespace Isis {
virtual Stretch getStretch();
virtual void setStretch(Stretch);
-
private slots:
void startSliderMoved(int);
void startEditChanged(const QString &);
diff --git a/isis/src/qisis/objs/StretchTool/ManualStretchType.cpp b/isis/src/qisis/objs/StretchTool/ManualStretchType.cpp
index 4ae247c0c5..2c8d20f697 100644
--- a/isis/src/qisis/objs/StretchTool/ManualStretchType.cpp
+++ b/isis/src/qisis/objs/StretchTool/ManualStretchType.cpp
@@ -55,6 +55,8 @@ namespace Isis {
this, SLOT(readTable()));
disconnect(this, SIGNAL(stretchChanged()), this, SLOT(updateTable()));
+ p_stretch->setType("ManualStretch");
+
setLayout(p_mainLayout);
setStretch(stretch);
}
diff --git a/isis/src/qisis/objs/StretchTool/SawtoothStretchType.cpp b/isis/src/qisis/objs/StretchTool/SawtoothStretchType.cpp
index 5b1e46589c..2e97c93ed1 100644
--- a/isis/src/qisis/objs/StretchTool/SawtoothStretchType.cpp
+++ b/isis/src/qisis/objs/StretchTool/SawtoothStretchType.cpp
@@ -71,6 +71,8 @@ namespace Isis {
sliderWidget->setLayout(sliderLayout);
p_mainLayout->addWidget(sliderWidget, 1, 0);
+ p_stretch->setType("SawtoothStretch");
+
setLayout(p_mainLayout);
p_widthEdit->setText(QString::number(
diff --git a/isis/src/qisis/objs/StretchTool/SawtoothStretchType.h b/isis/src/qisis/objs/StretchTool/SawtoothStretchType.h
index 1da8bda35b..7801f8b114 100644
--- a/isis/src/qisis/objs/StretchTool/SawtoothStretchType.h
+++ b/isis/src/qisis/objs/StretchTool/SawtoothStretchType.h
@@ -39,7 +39,6 @@ namespace Isis {
virtual void setStretch(Stretch);
-
private slots:
void offsetSliderMoved(int);
void offsetEditChanged(const QString &);
diff --git a/isis/src/qisis/objs/StretchTool/StretchTool.cpp b/isis/src/qisis/objs/StretchTool/StretchTool.cpp
index 09660aecdb..466ade83fc 100644
--- a/isis/src/qisis/objs/StretchTool/StretchTool.cpp
+++ b/isis/src/qisis/objs/StretchTool/StretchTool.cpp
@@ -1,5 +1,7 @@
#include "StretchTool.h"
+#include
+
#include
#include
#include
@@ -13,9 +15,11 @@
#include
#include
#include
+#include
#include "AdvancedStretchDialog.h"
#include "Brick.h"
+#include "Blob.h"
#include "CubeViewport.h"
#include "Histogram.h"
#include "IException.h"
@@ -51,6 +55,12 @@ namespace Isis {
this, SLOT(advancedStretchChanged()));
connect(m_advancedStretch, SIGNAL(visibilityChanged()),
this, SLOT(updateTool()));
+ connect(m_advancedStretch, SIGNAL(saveToCube()),
+ this, SLOT(saveStretchToCube()));
+ connect(m_advancedStretch, SIGNAL(deleteFromCube()),
+ this, SLOT(deleteFromCube()));
+ connect(m_advancedStretch, SIGNAL(loadStretch()),
+ this, SLOT(loadStretchFromCube()));
QPushButton *hiddenButton = new QPushButton();
hiddenButton->setVisible(false);
@@ -370,6 +380,177 @@ namespace Isis {
}
}
+
+ /**
+ * Restores a saved stretch from the cube
+ */
+ void StretchTool::loadStretchFromCube(){
+ MdiCubeViewport *cvp = cubeViewport();
+ Cube* icube = cvp->cube();
+ Pvl* lab = icube->label();
+
+ // Create a list of existing Stretch names
+ QStringList namelist;
+ PvlObject::PvlObjectIterator objIter;
+ for (objIter=lab->beginObject(); objIterendObject(); objIter++) {
+ if (objIter->name() == "Stretch") {
+ PvlKeyword tempKeyword = objIter->findKeyword("Name");
+ QString tempName = tempKeyword[0];
+ namelist.append(tempName);
+ }
+ }
+
+ bool ok;
+ QString stretchName = QInputDialog::getItem(m_advancedStretch, tr("Load Stretch"),
+ tr("Name of Stretch to Load:"), namelist, 0,
+ false, &ok);
+
+ if (ok) {
+ Stretch stretch(stretchName);
+ icube->read(stretch);
+ m_advancedStretch->restoreSavedStretch(stretch);
+ }
+ }
+
+
+ /**
+ * Deletes a saved stretch from the cube
+ */
+ void StretchTool::deleteFromCube() {
+ MdiCubeViewport *cvp = cubeViewport();
+ Cube* icube = cvp->cube();
+ Pvl* lab = icube->label();
+
+ // Create a list of existing Stretch names
+ QStringList namelist;
+ PvlObject::PvlObjectIterator objIter;
+ for (objIter=lab->beginObject(); objIterendObject(); objIter++) {
+ if (objIter->name() == "Stretch") {
+ PvlKeyword tempKeyword = objIter->findKeyword("Name");
+ QString tempName = tempKeyword[0];
+ namelist.append(tempName);
+ }
+ }
+
+ bool ok;
+ QString toDelete = QInputDialog::getItem(m_advancedStretch, tr("Delete Stretch"),
+ tr("Name of Stretch to Delete:"), namelist, 0,
+ false, &ok);
+ if (ok) {
+ if (icube->isReadOnly()) {
+ try {
+ cvp->cube()->reopen("rw");
+ }
+ catch(IException &) {
+ cvp->cube()->reopen("r");
+ QMessageBox::information((QWidget *)parent(), "Error",
+ "Cannot open cube read/write to delete stretch");
+ return;
+ }
+ }
+
+ bool cubeDeleted = icube->deleteBlob("Stretch", toDelete);
+
+ if (!cubeDeleted) {
+ QMessageBox msgBox;
+ msgBox.setText("Stretch Could Not Be Deleted!");
+ msgBox.setInformativeText("A stretch with name: \"" + toDelete +
+ "\" Could not be found, so there was nothing to delete from the Cube.");
+ msgBox.setStandardButtons(QMessageBox::Ok);
+ msgBox.setIcon(QMessageBox::Critical);
+ msgBox.exec();
+ }
+
+ // Don't leave open rw -- not optimal.
+ cvp->cube()->reopen("r");
+ }
+ }
+
+
+ /**
+ * Saves a strech to the cube.
+ */
+ void StretchTool::saveStretchToCube() {
+ MdiCubeViewport *cvp = cubeViewport();
+ Cube* icube = cvp->cube();
+ Pvl* lab = icube->label();
+
+ // Create a list of existing Stretch names
+ QStringList namelist;
+ PvlObject::PvlObjectIterator objIter;
+ for (objIter=lab->beginObject(); objIterendObject(); objIter++) {
+ if (objIter->name() == "Stretch") {
+ PvlKeyword tempKeyword = objIter->findKeyword("Name");
+ QString tempName = tempKeyword[0];
+ namelist.append(tempName);
+ }
+ }
+
+ bool ok;
+ QString name;
+
+ // "Get the name for the stretch" dialog
+ QString text = QInputDialog::getText(m_advancedStretch, tr("Save Stretch"),
+ tr("Enter a name to save the stretch as:"), QLineEdit::Normal,
+ "stretch", &ok);
+
+ if (ok) {
+ // Stretch Name Already Exists Dialog!
+ if (namelist.contains(text)) {
+ QMessageBox msgBox;
+ msgBox.setText(tr("Stretch Name Already Exists!"));
+ msgBox.setInformativeText("A stretch pair with name: \"" + text + "\" already exists and "
+ "the existing saved data will be overwritten. Are you sure you "
+ "wish to proceed?");
+ msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.setDefaultButton(QMessageBox::Cancel);
+ int ret = msgBox.exec();
+
+ switch (ret) {
+ case QMessageBox::Save:
+ break;
+ case QMessageBox::Cancel:
+ // Cancel was clicked, exit this function
+ return;
+ break;
+ default:
+ // should never be reached
+ return;
+ break;
+ }
+ }
+
+ if (icube->isReadOnly()) {
+ // ReOpen cube as read/write
+ // If cube readonly print error
+ try {
+ cvp->cube()->reopen("rw");
+ }
+ catch(IException &) {
+ cvp->cube()->reopen("r");
+ QMessageBox::information((QWidget *)parent(), "Error", "Cannot open cube read/write to save stretch");
+ return;
+ }
+ }
+
+ Stretch stretch = m_advancedStretch->getGrayStretch();
+
+ // consider moving into Stretch::WriteInit()
+ stretch.Label()["Name"] = text;
+ stretch.Label() += PvlKeyword("StretchType", stretch.getType());
+
+ // Greyscale is only available option for now
+ stretch.Label() += PvlKeyword("Color", "Greyscale");
+
+ icube->write(stretch);
+
+ // Don't leave open rw -- not optimal.
+ cvp->cube()->reopen("r");
+ }
+ }
+
+
/**
* This is called when the visible area changes.
*/
diff --git a/isis/src/qisis/objs/StretchTool/StretchTool.h b/isis/src/qisis/objs/StretchTool/StretchTool.h
index cfa9cb0f40..13a5e938ec 100644
--- a/isis/src/qisis/objs/StretchTool/StretchTool.h
+++ b/isis/src/qisis/objs/StretchTool/StretchTool.h
@@ -171,6 +171,9 @@ namespace Isis {
protected slots:
void mouseButtonRelease(QPoint p, Qt::MouseButton s);
+ void saveStretchToCube();
+ void deleteFromCube();
+ void loadStretchFromCube();
void enableRubberBandTool();
void screenPixelsChanged();
void updateHistograms();
diff --git a/isis/src/qisis/objs/StretchTool/StretchType.cpp b/isis/src/qisis/objs/StretchTool/StretchType.cpp
index 87a93dba2e..2e69622a04 100644
--- a/isis/src/qisis/objs/StretchTool/StretchType.cpp
+++ b/isis/src/qisis/objs/StretchTool/StretchType.cpp
@@ -55,10 +55,25 @@ namespace Isis {
connect(this, SIGNAL(stretchChanged()), this, SLOT(updateTable()));
p_mainLayout->addWidget(p_table, 2, 0);
- QPushButton *saveAsButton = new QPushButton("Save Stretch Pairs...");
+ QPushButton *saveAsButton = new QPushButton("Save Stretch Pairs to File...");
connect(saveAsButton, SIGNAL(clicked(bool)), this, SLOT(savePairs()));
p_mainLayout->addWidget(saveAsButton, 3, 0);
+ // Save/Restore strech only supported for Grayscale images. Hide buttons if in RGB.
+ if (name.compare("Gray") == 0) {
+ QPushButton *saveToCubeButton = new QPushButton("Save Stretch Pairs to Cube...");
+ connect(saveToCubeButton, SIGNAL(clicked(bool)), this, SIGNAL(saveToCube()));
+ p_mainLayout->addWidget(saveToCubeButton, 4, 0);
+
+ QPushButton *deleteFromCubeButton = new QPushButton("Delete Stretch Pairs from Cube...");
+ connect(deleteFromCubeButton, SIGNAL(clicked(bool)), this, SIGNAL(deleteFromCube()));
+ p_mainLayout->addWidget(deleteFromCubeButton, 5, 0);
+
+ QPushButton *loadStretchButton = new QPushButton("Load Saved Stretch from Cube...");
+ connect(loadStretchButton, SIGNAL(clicked(bool)), this, SIGNAL(loadStretch()));
+ p_mainLayout->addWidget(loadStretchButton, 6, 0);
+ }
+
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
sizePolicy.setHeightForWidth(true);
p_graph->setSizePolicy(sizePolicy);
diff --git a/isis/src/qisis/objs/StretchTool/StretchType.h b/isis/src/qisis/objs/StretchTool/StretchType.h
index 00808f2677..d54979dfa5 100644
--- a/isis/src/qisis/objs/StretchTool/StretchType.h
+++ b/isis/src/qisis/objs/StretchTool/StretchType.h
@@ -45,6 +45,7 @@ namespace Isis {
virtual ~StretchType();
virtual Stretch getStretch();
+
/**
* Children must re-implement this to update their stretch pairs and GUI
* elements appropriately. This could be called with a
@@ -72,11 +73,14 @@ namespace Isis {
signals:
//! Emitted when a new Stretch object is available
+ void saveToCube();
+ void deleteFromCube();
void stretchChanged();
-
+ void loadStretch();
private slots:
void savePairs();
+
};
};
From 3eec82d1bf19a91f8a31fe59fba7669a71bc82f9 Mon Sep 17 00:00:00 2001
From: AustinSanders
Date: Fri, 28 Feb 2020 16:00:18 -0700
Subject: [PATCH 04/13] Updated kaguyatc2isis to allow ingestion of data
provided by JAXA online archive (#3713)
* Updated to allow ingestion of data provided by JAXA online archive
* Listed SLN-L-TC-5-MORNING-MAP-V4.0 as a supported format.
* Added tests + testing data
* Replaced several label parsing tests with cube attribute tests.
---
.../apps/kaguyatc2isis/kaguyatc2isis.cpp | 292 ++++++++++++++++++
.../kaguya/apps/kaguyatc2isis/kaguyatc2isis.h | 11 +
isis/src/kaguya/apps/kaguyatc2isis/main.cpp | 283 +----------------
isis/tests/FunctionalTestsKaguyatc2isis.cpp | 88 ++++++
.../TC1S2B0_01_05186N225E0040_mini.img | Bin 0 -> 19248 bytes
.../TC1S2B0_01_05186N225E0040_mini.lbl | 131 ++++++++
6 files changed, 533 insertions(+), 272 deletions(-)
create mode 100644 isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.cpp
create mode 100644 isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.h
create mode 100644 isis/tests/FunctionalTestsKaguyatc2isis.cpp
create mode 100644 isis/tests/data/kaguyatc2isis/TC1S2B0_01_05186N225E0040_mini.img
create mode 100644 isis/tests/data/kaguyatc2isis/TC1S2B0_01_05186N225E0040_mini.lbl
diff --git a/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.cpp b/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.cpp
new file mode 100644
index 0000000000..f80d772d56
--- /dev/null
+++ b/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.cpp
@@ -0,0 +1,292 @@
+#include "kaguyatc2isis.h"
+
+#include
+#include
+
+#include "FileName.h"
+#include "ProcessImportPds.h"
+#include "UserInterface.h"
+#include "Pvl.h"
+
+using namespace std;
+
+namespace Isis {
+ void kaguyatc2isis(UserInterface &ui, Pvl *log) {
+ ProcessImportPds importPds;
+ FileName inFile = ui.GetFileName("FROM");
+ QString labelFile = inFile.expanded();
+ Pvl label(labelFile);
+
+ QString dataFile = "";
+ if ( inFile.extension().toLower() == "lbl" ) {
+ dataFile = inFile.path() + "/" + (QString) label.findKeyword("FILE_NAME");
+ }
+ else {
+ dataFile = labelFile;
+ }
+
+ QString id = "";
+ try {
+ id = (QString) label.findKeyword("DATA_SET_ID");
+ }
+ catch(IException &e) {
+ QString msg = "Unable to read [DATA_SET_ID] from label file ["
+ + labelFile + "]";
+ throw IException(e, IException::Unknown, msg, _FILEINFO_);
+ }
+
+ id = id.simplified().trimmed();
+ if (id != "TC_MAP"
+ && id != "TCO_MAP"
+ && id != "TC1_Level2B"
+ && id != "TC2_Level2B"
+ && id != "SLN-L-TC-3-S-LEVEL2B0-V1.0"
+ && id != "SLN-L-TC-5-MORNING-MAP-V4.0") {
+ QString msg = "Input file [" + labelFile + "] does not appear to be " +
+ "a supported Kaguya Terrain Camera format. " +
+ "DATA_SET_ID is [" + id + "]" +
+ "Valid formats include [TC_MAP, TCO_MAP, TC1_Level2B, " +
+ "SLN-L-TC-3-S-LEVEL2B0-V1.0, SLN-L-TC-5-MORNING-MAP-V4.0]";
+ throw IException(IException::Unknown, msg, _FILEINFO_);
+ }
+
+ if (!label.hasKeyword("TARGET_NAME")) {
+ label.addKeyword(PvlKeyword("TARGET_NAME", "MOON"), Pvl::Replace);
+ }
+
+ importPds.SetPdsFile(label, dataFile);
+
+ CubeAttributeOutput &att = ui.GetOutputAttribute("TO");
+ Cube *outcube = importPds.SetOutputCube(ui.GetFileName("TO"), att);
+
+ // Get user entered special pixel ranges
+ if (ui.GetBoolean("SETNULLRANGE")) {
+ importPds.SetNull(ui.GetDouble("NULLMIN"), ui.GetDouble("NULLMAX"));
+ }
+ if (ui.GetBoolean("SETHRSRANGE")) {
+ importPds.SetHRS(ui.GetDouble("HRSMIN"), ui.GetDouble("HRSMAX"));
+ }
+ if (ui.GetBoolean("SETHISRANGE")) {
+ importPds.SetHIS(ui.GetDouble("HISMIN"), ui.GetDouble("HISMAX"));
+ }
+ if (ui.GetBoolean("SETLRSRANGE")) {
+ importPds.SetLRS(ui.GetDouble("LRSMIN"), ui.GetDouble("LRSMAX"));
+ }
+ if (ui.GetBoolean("SETLISRANGE")) {
+ importPds.SetLIS(ui.GetDouble("LISMIN"), ui.GetDouble("LISMAX"));
+ }
+
+ importPds.SetOrganization(Isis::ProcessImport::BSQ);
+
+ importPds.StartProcess();
+
+ // Get the mapping labels
+ Pvl otherLabels;
+ importPds.TranslatePdsProjection(otherLabels);
+
+ // Translate the remaining MI MAP labels
+ PvlGroup dataDir(Preference::Preferences().findGroup("DataDirectory"));
+ QString transDir = (QString) dataDir["Kaguya"] + "/translations/";
+
+ FileName transFile(transDir + "kaguyaTcBandBin.trn");
+ PvlToPvlTranslationManager bandBinXlater(label, transFile.expanded());
+ bandBinXlater.Auto(otherLabels);
+
+ transFile = transDir + "kaguyaTcInstrument.trn";
+ PvlToPvlTranslationManager instXlater(label, transFile.expanded());
+ instXlater.Auto(otherLabels);
+
+ transFile = transDir + "kaguyaTcArchive.trn";
+ PvlToPvlTranslationManager archiveXlater(label, transFile.expanded());
+ archiveXlater.Auto(otherLabels);
+
+ transFile = transDir + "kaguyaTcKernels.trn";
+ PvlToPvlTranslationManager kernelsXlater(label, transFile.expanded());
+ kernelsXlater.Auto(otherLabels);
+
+ if ( otherLabels.hasGroup("Mapping")
+ && otherLabels.findGroup("Mapping").keywords() > 0 ) {
+ outcube->putGroup(otherLabels.findGroup("Mapping"));
+ }
+ if ( otherLabels.hasGroup("Instrument")
+ && otherLabels.findGroup("Instrument").keywords() > 0 ) {
+ PvlGroup &inst = otherLabels.findGroup("Instrument", Pvl::Traverse);
+ if (inst.hasKeyword("StartTime")) {
+ // Remove trailing "Z" from keyword
+ PvlKeyword &startTime = inst["StartTime"];
+ QString startTimeString = startTime[0];
+ if (QString::compare(startTimeString.at(startTimeString.size() - 1), "Z", Qt::CaseInsensitive) == 0){
+ startTimeString = startTimeString.left(startTimeString.length() - 1);
+ startTime.setValue(startTimeString);
+ }
+ }
+ if (inst.hasKeyword("StopTime")) {
+ // Remove trailing "Z" from keyword
+ PvlKeyword &stopTime = inst["StopTime"];
+ QString stopTimeString = stopTime[0];
+ if (QString::compare(stopTimeString.at(stopTimeString.size() - 1), "Z", Qt::CaseInsensitive) == 0){
+ stopTimeString = stopTimeString.left(stopTimeString.length() - 1);
+ stopTime.setValue(stopTimeString);
+ }
+ }
+ outcube->putGroup(otherLabels.findGroup("Instrument"));
+ /*
+ // This code is not needed now, but is included here commented-out in case it becomes necessary
+ // to support the swath modes by setting their NaifFrameCodes in the future. The swath mode
+ // setting is currently handled entirely via the camera model.
+
+ // add kernels group
+ QString instId = inst["InstrumentId"];
+ QString encoding = inst["EncodingType"];
+ QString swath = inst["SwathModeId"];
+ PvlGroup kern("Kernels");
+ if (instId == "TC1") {
+ if (swath == "Full") {
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131352));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131353));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131354));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131355));
+ }
+ }
+ }
+ else if (swath == "Nominal") {
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131356));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131357));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131358));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131359));
+ }
+ }
+ }
+ else { // swath == "Half"
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131360));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131361));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131362));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131363));
+ }
+ }
+ }
+ }
+ if (instId == "TC2") {
+ if (swath == "Full") {
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131372));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131373));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131374));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131375));
+ }
+ }
+ }
+ else if (swath == "Nominal") {
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131376));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131377));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131378));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131379));
+ }
+ }
+ }
+ else { // swath == "Half"
+ if (productSetId == "TC_w_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131380));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131381));
+ }
+ }
+ else if (productSetId == "TC_s_Level2B0") {
+ if (encoding == "DCT") {
+ kern += PvlKeyword("NaifFrameCode", toString(-131382));
+ }
+ else { // encoding == "N/A" so no compression
+ kern += PvlKeyword("NaifFrameCode", toString(-131383));
+ }
+ }
+ }
+ }
+ */
+ }
+ if ( otherLabels.hasGroup("BandBin")
+ && otherLabels.findGroup("BandBin").keywords() > 0 ) {
+
+ PvlGroup &bandBinGroup = otherLabels.findGroup("BandBin");
+ if (!bandBinGroup.hasKeyword("FilterName")) {
+ bandBinGroup += PvlKeyword("FilterName", "BroadBand");
+ }
+ if (!bandBinGroup.hasKeyword("Center")) {
+ bandBinGroup += PvlKeyword("Center", "640", "nanometers");
+ }
+ if (!bandBinGroup.hasKeyword("Width")) {
+ bandBinGroup += PvlKeyword("Width", "420", "nanometers");
+ }
+ outcube->putGroup(bandBinGroup);
+ }
+ else {
+ // Add the BandBin group
+ PvlGroup bandBinGroup("BandBin");
+ bandBinGroup += PvlKeyword("FilterName", "BroadBand");
+ bandBinGroup += PvlKeyword("Center", "640nm");
+ bandBinGroup += PvlKeyword("Width", "420nm");
+ outcube->putGroup(bandBinGroup);
+ }
+
+ if ( otherLabels.hasGroup("Archive")
+ && otherLabels.findGroup("Archive").keywords() > 0 ) {
+ outcube->putGroup(otherLabels.findGroup("Archive"));
+ }
+ if ( otherLabels.hasGroup("Kernels")
+ && otherLabels.findGroup("Kernels").keywords() > 0 ) {
+ outcube->putGroup(otherLabels.findGroup("Kernels", Pvl::Traverse));
+ }
+
+ importPds.EndProcess();
+ }
+}
diff --git a/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.h b/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.h
new file mode 100644
index 0000000000..9c2db22777
--- /dev/null
+++ b/isis/src/kaguya/apps/kaguyatc2isis/kaguyatc2isis.h
@@ -0,0 +1,11 @@
+#ifndef kaguyatc2isis_h
+#define kaguyatc2isis_h
+
+#include "UserInterface.h"
+#include "Pvl.h"
+
+namespace Isis {
+ extern void kaguyatc2isis(UserInterface &ui, Pvl *log);
+}
+
+#endif
diff --git a/isis/src/kaguya/apps/kaguyatc2isis/main.cpp b/isis/src/kaguya/apps/kaguyatc2isis/main.cpp
index 86e995041b..c92d257f8f 100644
--- a/isis/src/kaguya/apps/kaguyatc2isis/main.cpp
+++ b/isis/src/kaguya/apps/kaguyatc2isis/main.cpp
@@ -1,288 +1,27 @@
#include "Isis.h"
-#include
-#include
+#include "kaguyatc2isis.h"
-#include "FileName.h"
-#include "ProcessImportPds.h"
-#include "UserInterface.h"
+#include "Application.h"
+#include "Pvl.h"
using namespace std;
using namespace Isis;
void IsisMain() {
- ProcessImportPds importPds;
UserInterface &ui = Application::GetUserInterface();
-
- FileName inFile = ui.GetFileName("FROM");
- QString labelFile = inFile.expanded();
- Pvl label(labelFile);
-
- QString dataFile = "";
- if ( inFile.extension().toLower() == "lbl" ) {
- dataFile = inFile.path() + (QString) label.findKeyword("FILE_NAME");
- }
- else {
- dataFile = labelFile;
- }
-
- QString id = "";
+ Pvl appLog;
try {
- id = (QString) label.findKeyword("DATA_SET_ID");
- }
- catch(IException &e) {
- QString msg = "Unable to read [DATA_SET_ID] from label file ["
- + labelFile + "]";
- throw IException(e, IException::Unknown, msg, _FILEINFO_);
- }
-
- id = id.simplified().trimmed();
- if (id != "TC_MAP"
- && id != "TCO_MAP"
- && id != "TC1_Level2B"
- && id != "TC2_Level2B") {
- QString msg = "Input file [" + labelFile + "] does not appear to be " +
- "a supported Kaguya Terrain Camera format. " +
- "DATA_SET_ID is [" + id + "]" +
- "Valid formats include [TC_MAP, TCO_MAP, TC1_Level2B]";
- throw IException(IException::Unknown, msg, _FILEINFO_);
- }
-
- if (!label.hasKeyword("TARGET_NAME")) {
- label.addKeyword(PvlKeyword("TARGET_NAME", "MOON"), Pvl::Replace);
- }
-
- importPds.SetPdsFile(label, dataFile);
-
- Cube *outcube = importPds.SetOutputCube("TO");
-
- // Get user entered special pixel ranges
- if (ui.GetBoolean("SETNULLRANGE")) {
- importPds.SetNull(ui.GetDouble("NULLMIN"), ui.GetDouble("NULLMAX"));
- }
- if (ui.GetBoolean("SETHRSRANGE")) {
- importPds.SetHRS(ui.GetDouble("HRSMIN"), ui.GetDouble("HRSMAX"));
- }
- if (ui.GetBoolean("SETHISRANGE")) {
- importPds.SetHIS(ui.GetDouble("HISMIN"), ui.GetDouble("HISMAX"));
- }
- if (ui.GetBoolean("SETLRSRANGE")) {
- importPds.SetLRS(ui.GetDouble("LRSMIN"), ui.GetDouble("LRSMAX"));
- }
- if (ui.GetBoolean("SETLISRANGE")) {
- importPds.SetLIS(ui.GetDouble("LISMIN"), ui.GetDouble("LISMAX"));
+ kaguyatc2isis(ui, &appLog);
}
-
- importPds.SetOrganization(Isis::ProcessImport::BSQ);
-
- importPds.StartProcess();
-
- // Get the mapping labels
- Pvl otherLabels;
- importPds.TranslatePdsProjection(otherLabels);
-
- // Translate the remaining MI MAP labels
- PvlGroup dataDir(Preference::Preferences().findGroup("DataDirectory"));
- QString transDir = (QString) dataDir["Kaguya"] + "/translations/";
-
- FileName transFile(transDir + "kaguyaTcBandBin.trn");
- PvlToPvlTranslationManager bandBinXlater(label, transFile.expanded());
- bandBinXlater.Auto(otherLabels);
-
- transFile = transDir + "kaguyaTcInstrument.trn";
- PvlToPvlTranslationManager instXlater(label, transFile.expanded());
- instXlater.Auto(otherLabels);
-
- transFile = transDir + "kaguyaTcArchive.trn";
- PvlToPvlTranslationManager archiveXlater(label, transFile.expanded());
- archiveXlater.Auto(otherLabels);
-
- transFile = transDir + "kaguyaTcKernels.trn";
- PvlToPvlTranslationManager kernelsXlater(label, transFile.expanded());
- kernelsXlater.Auto(otherLabels);
-
- if ( otherLabels.hasGroup("Mapping")
- && otherLabels.findGroup("Mapping").keywords() > 0 ) {
- outcube->putGroup(otherLabels.findGroup("Mapping"));
- }
- if ( otherLabels.hasGroup("Instrument")
- && otherLabels.findGroup("Instrument").keywords() > 0 ) {
- PvlGroup &inst = otherLabels.findGroup("Instrument", Pvl::Traverse);
- if (inst.hasKeyword("StartTime")) {
- // Remove trailing "Z" from keyword
- PvlKeyword &startTime = inst["StartTime"];
- QString startTimeString = startTime[0];
- if (QString::compare(startTimeString.at(startTimeString.size() - 1), "Z", Qt::CaseInsensitive) == 0){
- startTimeString = startTimeString.left(startTimeString.length() - 1);
- startTime.setValue(startTimeString);
- }
- }
- if (inst.hasKeyword("StopTime")) {
- // Remove trailing "Z" from keyword
- PvlKeyword &stopTime = inst["StopTime"];
- QString stopTimeString = stopTime[0];
- if (QString::compare(stopTimeString.at(stopTimeString.size() - 1), "Z", Qt::CaseInsensitive) == 0){
- stopTimeString = stopTimeString.left(stopTimeString.length() - 1);
- stopTime.setValue(stopTimeString);
- }
- }
- outcube->putGroup(otherLabels.findGroup("Instrument"));
-/*
- // This code is not needed now, but is included here commented-out in case it becomes necessary
- // to support the swath modes by setting their NaifFrameCodes in the future. The swath mode
- // setting is currently handled entirely via the camera model.
-
- // add kernels group
- QString instId = inst["InstrumentId"];
- QString encoding = inst["EncodingType"];
- QString swath = inst["SwathModeId"];
- PvlGroup kern("Kernels");
- if (instId == "TC1") {
- if (swath == "Full") {
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131352));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131353));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131354));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131355));
- }
- }
- }
- else if (swath == "Nominal") {
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131356));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131357));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131358));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131359));
- }
- }
- }
- else { // swath == "Half"
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131360));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131361));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131362));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131363));
- }
- }
- }
- }
- if (instId == "TC2") {
- if (swath == "Full") {
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131372));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131373));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131374));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131375));
- }
- }
- }
- else if (swath == "Nominal") {
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131376));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131377));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131378));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131379));
- }
- }
- }
- else { // swath == "Half"
- if (productSetId == "TC_w_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131380));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131381));
- }
- }
- else if (productSetId == "TC_s_Level2B0") {
- if (encoding == "DCT") {
- kern += PvlKeyword("NaifFrameCode", toString(-131382));
- }
- else { // encoding == "N/A" so no compression
- kern += PvlKeyword("NaifFrameCode", toString(-131383));
- }
- }
- }
+ catch (...) {
+ for (auto grpIt = appLog.beginGroup(); grpIt != appLog.endGroup(); grpIt++) {
+ Application::Log(*grpIt);
}
- */
+ throw;
}
- if ( otherLabels.hasGroup("BandBin")
- && otherLabels.findGroup("BandBin").keywords() > 0 ) {
- PvlGroup &bandBinGroup = otherLabels.findGroup("BandBin");
- if (!bandBinGroup.hasKeyword("FilterName")) {
- bandBinGroup += PvlKeyword("FilterName", "BroadBand");
- }
- if (!bandBinGroup.hasKeyword("Center")) {
- bandBinGroup += PvlKeyword("Center", "640", "nanometers");
- }
- if (!bandBinGroup.hasKeyword("Width")) {
- bandBinGroup += PvlKeyword("Width", "420", "nanometers");
- }
- outcube->putGroup(bandBinGroup);
- }
- else {
- // Add the BandBin group
- PvlGroup bandBinGroup("BandBin");
- bandBinGroup += PvlKeyword("FilterName", "BroadBand");
- bandBinGroup += PvlKeyword("Center", "640nm");
- bandBinGroup += PvlKeyword("Width", "420nm");
- outcube->putGroup(bandBinGroup);
+ for (auto grpIt = appLog.beginGroup(); grpIt != appLog.endGroup(); grpIt++){
+ Application::Log(*grpIt);
}
-
- if ( otherLabels.hasGroup("Archive")
- && otherLabels.findGroup("Archive").keywords() > 0 ) {
- outcube->putGroup(otherLabels.findGroup("Archive"));
- }
- if ( otherLabels.hasGroup("Kernels")
- && otherLabels.findGroup("Kernels").keywords() > 0 ) {
- outcube->putGroup(otherLabels.findGroup("Kernels", Pvl::Traverse));
- }
-
- importPds.EndProcess();
}
diff --git a/isis/tests/FunctionalTestsKaguyatc2isis.cpp b/isis/tests/FunctionalTestsKaguyatc2isis.cpp
new file mode 100644
index 0000000000..a6927ebbc3
--- /dev/null
+++ b/isis/tests/FunctionalTestsKaguyatc2isis.cpp
@@ -0,0 +1,88 @@
+#include
+
+#include "kaguyatc2isis.h"
+#include "Fixtures.h"
+#include "Pvl.h"
+#include "PvlGroup.h"
+#include "TestUtilities.h"
+#include "Endian.h"
+#include "PixelType.h"
+
+#include "gtest/gtest.h"
+
+using namespace Isis;
+
+static QString APP_XML = FileName("$ISISROOT/bin/xml/kaguyatc2isis.xml").expanded();
+
+TEST(kaguyatc2isisTest, kaguyatc2isisTestDefault) {
+ Pvl appLog;
+ QTemporaryDir prefix;
+ QString cubeFileName = prefix.path() + "/kaguyatc2isisTEMP.cub";
+ QVector args = {"from=data/kaguyatc2isis/TC1S2B0_01_05186N225E0040_mini.lbl", "to="+cubeFileName};
+
+ UserInterface options(APP_XML, args);
+ try {
+ kaguyatc2isis(options, &appLog);
+ }
+ catch (IException &e) {
+ FAIL() << "Unable to ingest Kaguya TC image: " <findGroup("Instrument", Pvl::Traverse);
+ ASSERT_EQ(inst["MissionName"][0].toStdString(), "SELENE");
+ ASSERT_EQ(inst["SpacecraftName"][0].toStdString(), "KAGUYA");
+ ASSERT_EQ(inst["InstrumentName"][0].toStdString(), "TERRAIN CAMERA 1");
+ ASSERT_EQ(inst["InstrumentId"][0].toStdString(), "TC1");
+ ASSERT_EQ(inst["TargetName"][0].toStdString(), "MOON");
+ ASSERT_EQ(inst["StartTime"][0].toStdString(), "2008-12-07T05:04:34.458542");
+ ASSERT_EQ(inst["StopTime"][0].toStdString(), "2008-12-07T05:05:04.715727");
+ ASSERT_EQ(inst["SpacecraftClockStartCount"][0].toStdString(), "912661463.551562");
+ ASSERT_EQ(inst["SpacecraftClockStopCount"][0].toStdString(), "912661493.808747");
+ ASSERT_DOUBLE_EQ(inst["ExposureDuration"], 3.25);
+ ASSERT_EQ(inst["ExposureDuration"].unit(), "ms");
+ ASSERT_DOUBLE_EQ(inst["LineSamplingInterval"], 6.499932);
+ ASSERT_EQ(inst["LineSamplingInterval"].unit(), "ms");
+ ASSERT_EQ(inst["IlluminationCondition"][0].toStdString(), "MORNING");
+
+ // Archive Group
+ PvlGroup &arch = isisLabel->findGroup("Archive", Pvl::Traverse);
+
+ ASSERT_EQ(arch["DataSetId"][0].toStdString(), "SLN-L-TC-3-S-LEVEL2B0-V1.0");
+ ASSERT_EQ(arch["ImageValueType"][0].toStdString(), "RADIANCE");
+ ASSERT_EQ(int(arch["SceneMaximumDn"]), 3913);
+ ASSERT_EQ(int(arch["SceneMinimumDn"]), 30);
+ ASSERT_DOUBLE_EQ(double(arch["SceneAverageDn"]), 868.1);
+ ASSERT_DOUBLE_EQ(double(arch["UpperLeftLatitude"]), 21.694101);
+ ASSERT_DOUBLE_EQ(double(arch["UpperLeftLongitude"]), 3.476042);
+ ASSERT_DOUBLE_EQ(double(arch["UpperRightLatitude"]), 21.711476);
+ ASSERT_DOUBLE_EQ(double(arch["UpperRightLongitude"]), 4.636101);
+ ASSERT_DOUBLE_EQ(double(arch["LowerLeftLatitude"]), 23.230896);
+ ASSERT_DOUBLE_EQ(double(arch["LowerLeftLongitude"]), 3.440187);
+ ASSERT_DOUBLE_EQ(double(arch["LowerRightLatitude"]), 23.248459);
+ ASSERT_DOUBLE_EQ(double(arch["LowerRightLongitude"]), 4.613281);
+
+ // Bandbin Group
+ PvlGroup &bandbin = isisLabel->findGroup("BandBin", Pvl::Traverse);
+ ASSERT_EQ(bandbin["Center"][0], "640nm");
+ ASSERT_EQ(bandbin["Width"][0], "420nm");
+
+ // Kernels Group
+ PvlGroup &kern = isisLabel->findGroup("Kernels", Pvl::Traverse);
+ ASSERT_EQ(int(kern["NaifCkCode"]), -131350);
+ ASSERT_EQ(int(kern["NaifFrameCode"]), -131351);
+}
diff --git a/isis/tests/data/kaguyatc2isis/TC1S2B0_01_05186N225E0040_mini.img b/isis/tests/data/kaguyatc2isis/TC1S2B0_01_05186N225E0040_mini.img
new file mode 100644
index 0000000000000000000000000000000000000000..eaad94a387ea4c9ddfe89ffc4125d0d3da6b96b0
GIT binary patch
literal 19248
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
qKas-|8<)
+MISSION_NAME = SELENE
+DATA_SET_ID = SLN-L-TC-3-S-LEVEL2B0-V1.0
+DATA_SET_NAME = "SELENE MOON TC 3 MONO LEVEL2B0 V1.0"
+L2DB_ORIGINAL_ID = TC_s_Level2B0
+PRODUCT_ID = TC1S2B0_01_05186N225E0040
+INSTRUMENT_TYPE = IMAGER
+INSTRUMENT_ID = TC1
+INSTRUMENT_NAME = "TERRAIN CAMERA 1"
+INSTRUMENT_HOST_NAME = "SELENE MAIN ORBITER"
+TARGET_TYPE = SATELLITE
+TARGET_NAME = MOON
+START_TIME = 2008-12-07T05:04:34.460480
+STOP_TIME = 2008-12-07T05:05:04.717980
+SOFTWARE_NAME = RGC_TC_s_Level2B0
+SOFTWARE_VERSION = 1.0.0
+PROCESS_VERSION_ID = L2B
+PRODUCT_CREATION_TIME = 2013-06-08T12:58:16
+PROGRAM_START_TIME = 2013-06-08T12:58:01
+PRODUCER_ID = LISM
+PRODUCT_SET_ID = TC_s_Level2B0
+PRODUCT_VERSION_ID = "01"
+REGISTERED_PRODUCT = Y
+ILLUMINATION_CONDITION = MORNING
+LEVEL2A_FILE_NAME = TC1S2A0_02TMF05186_004_0002.img
+SPICE_METAKERNEL_FILE_NAME = RGC_INF_TCv401IK_MIv200IK_SPv105IK_RISE100i_05_LongCK_D_V02_de421_110706.mk
+MISSION_PHASE_NAME = Extended
+REVOLUTION_NUMBER = 5186
+STRIP_SEQUENCE_NUMBER = 4
+SCENE_SEQUENCE_NUMBER = 2
+UPPER_LEFT_DAYTIME_FLAG = Day
+UPPER_RIGHT_DAYTIME_FLAG = Day
+LOWER_LEFT_DAYTIME_FLAG = Day
+LOWER_RIGHT_DAYTIME_FLAG = Day
+OBSERVATION_MODE_ID = NORMAL
+SENSOR_DESCRIPTION = "Imagery type:Pushbroom. ImageryMode:Mono,Stereo. ExposureTimeMode:Long,Middle,Short. CompressionMode:NonComp,DCT. Q-table:32 patterns. H-table:4 patterns. SwathMode:F(Full),N(Nominal),H(Half). First pixel number:1(F),297(N),1172(H)."
+SENSOR_DESCRIPTION2 = "Pixel size:7x7[micron^2](TC1/TC2). Wavelength range:430-850[nm](TC1/TC2). A/D rate:10[bit](TC1/TC2). Slant angle:+/-15[degree] (from nadir to +x of S/C)(TC1/TC2). Focal length:72.45/72.63[mm](TC1/TC2). F number:3.97/3.98(TC1/TC2)."
+DETECTOR_STATUS = (TC1:ON, TC2:OFF, MV:OFF, MN:OFF, SP:ON)
+EXPOSURE_MODE_ID = MIDDLE
+LINE_EXPOSURE_DURATION = (3.25 )
+SPACECRAFT_CLOCK_START_COUNT = "912661463.5535 "
+SPACECRAFT_CLOCK_STOP_COUNT = "912661493.8110 "
+CORRECTED_SC_CLOCK_START_COUNT = 912661463.551562
+CORRECTED_SC_CLOCK_STOP_COUNT = 912661493.808747
+CORRECTED_START_TIME = 2008-12-07T05:04:34.458542
+CORRECTED_STOP_TIME = 2008-12-07T05:05:04.715727
+LINE_SAMPLING_INTERVAL = 6.5
+CORRECTED_SAMPLING_INTERVAL = (6.499932 )
+UPPER_LEFT_LATITUDE = 21.694101
+UPPER_LEFT_LONGITUDE = 3.476042
+UPPER_RIGHT_LATITUDE = 21.711476
+UPPER_RIGHT_LONGITUDE = 4.636101
+LOWER_LEFT_LATITUDE = 23.230896
+LOWER_LEFT_LONGITUDE = 3.440187
+LOWER_RIGHT_LATITUDE = 23.248459
+LOWER_RIGHT_LONGITUDE = 4.613281
+LOCATION_FLAG = A
+ROLL_CANT = NO
+SCENE_CENTER_LATITUDE = 22.472717
+SCENE_CENTER_LONGITUDE = 4.042497
+INCIDENCE_ANGLE = 65.012
+EMISSION_ANGLE = 15.912
+PHASE_ANGLE = 67.161
+SOLAR_AZIMUTH_ANGLE = 102.71
+FOCAL_PLANE_TEMPERATURE = (18.08 )
+TELESCOPE_TEMPERATURE = (17.82 )
+SATELLITE_MOVING_DIRECTION = -1
+FIRST_SAMPLED_LINE_POSITION = UPPERMOST
+FIRST_DETECTOR_ELEM_POSITION = LEFT
+A_AXIS_RADIUS = 1737.4
+B_AXIS_RADIUS = 1737.4
+C_AXIS_RADIUS = 1737.4
+DEFECT_PIXEL_POSITION = N/A
+SWATH_MODE_ID = FULL
+FIRST_PIXEL_NUMBER = 1
+LAST_PIXEL_NUMBER = 3208
+SPACECRAFT_ALTITUDE = 101.768
+SPACECRAFT_GROUND_SPEED = 1.54
+TC1_TELESCOPE_TEMPERATURE = 18.01
+TC2_TELESCOPE_TEMPERATURE = 18.01
+DPU_TEMPERATURE = 13.3
+TM_TEMPERATURE = 16.99
+TM_RADIATOR_TEMPERATURE = 14.6
+Q_TABLE_ID = N/A
+HUFFMAN_TABLE_ID = N/A
+DATA_COMPRESSION_PERCENT_MEAN = 100.0
+DATA_COMPRESSION_PERCENT_MAX = 100.0
+DATA_COMPRESSION_PERCENT_MIN = 100.0
+Object = IMAGE
+ COMPRESSION_TYPE = N/A
+ COMPRESSION_PERCENT = 100.0
+ NOMINAL_LINE_NUMBER = 4088
+ NOMINAL_OVERLAP_LINE_NUMBER = 568
+ OVERLAP_LINE_NUMBER = 568
+ LINES = 3
+ LINE_SAMPLES = 3208
+ SAMPLE_TYPE = MSB_INTEGER
+ SAMPLE_BITS = 16
+ IMAGE_VALUE_TYPE = RADIANCE
+ UNIT = W/m**2/micron/sr
+ SCALING_FACTOR = 0.013
+ OFFSET = 0.0
+ MIN_FOR_STATISTICAL_EVALUATION = 0
+ MAX_FOR_STATISTICAL_EVALUATION = 32767
+ SCENE_MAXIMUM_DN = 3913
+ SCENE_MINIMUM_DN = 30
+ SCENE_AVERAGE_DN = 868.1
+ SCENE_STDEV_DN = 236.6
+ SCENE_MODE_DN = 833
+ SHADOWED_AREA_MINIMUM = 0
+ SHADOWED_AREA_MAXIMUM = 0
+ SHADOWED_AREA_PERCENTAGE = 0
+ INVALID_TYPE = (SATURATION, MINUS, DUMMY_DEFECT, OTHER)
+ INVALID_VALUE = (-20000, -21000, -22000, -23000)
+ INVALID_PIXELS = (0, 0, 0, 0)
+End_Object
+Object = PROCESSING_PARAMETERS
+ DARK_FILE_NAME = TC1_DRK_04740_07463_M_N_b05.csv
+ FLAT_FILE_NAME = TC1_FLT_04740_07536_N_N_b05.csv
+ EFFIC_FILE_NAME = TC1_EFF_PRFLT_N_N_v01.csv
+ NONLIN_FILE_NAME = TC1_NLT_PRFLT_N_N_v01.csv
+ RAD_CNV_COEF = (3.790009 )
+ L2A_DEAD_PIXEL_THRESHOLD = 30
+ L2A_SATURATION_THRESHOLD = 1023
+ DARK_VALID_MINIMUM = -5
+ RADIANCE_SATURATION_THRESHOLD = 425.971
+End_Object
+End
\ No newline at end of file
From b59f3b2497f6012b624251c853b6baf05ce4a95b Mon Sep 17 00:00:00 2001
From: acpaquette
Date: Fri, 28 Feb 2020 16:24:15 -0700
Subject: [PATCH 05/13] Fixes ddd2isis to support updated uvflat files (#3719)
* Fixes ddd2isis to support updated uvflat files
* Added history comment
---
isis/src/base/apps/ddd2isis/ddd2isis.xml | 4 ++++
isis/src/base/apps/ddd2isis/main.cpp | 7 ++++++
.../apps/ddd2isis/tsts/badBandBit/Makefile | 24 +++++++++++++++++++
3 files changed, 35 insertions(+)
create mode 100644 isis/src/base/apps/ddd2isis/tsts/badBandBit/Makefile
diff --git a/isis/src/base/apps/ddd2isis/ddd2isis.xml b/isis/src/base/apps/ddd2isis/ddd2isis.xml
index 19548a0aff..bd072e3cc0 100644
--- a/isis/src/base/apps/ddd2isis/ddd2isis.xml
+++ b/isis/src/base/apps/ddd2isis/ddd2isis.xml
@@ -41,6 +41,10 @@
bands. Removed the internal default of the output parameter set to None so
that an output file is now requried. Fixes #703.
+
+ Updated the dataTypes QMap with a new mapping (32, 4) to handle ingesting
+ the updated uvflat files from malin. Fixes #3715.
+
diff --git a/isis/src/base/apps/ddd2isis/main.cpp b/isis/src/base/apps/ddd2isis/main.cpp
index efae0dc7aa..ec6121a2e4 100644
--- a/isis/src/base/apps/ddd2isis/main.cpp
+++ b/isis/src/base/apps/ddd2isis/main.cpp
@@ -100,6 +100,7 @@ void IsisMain() {
dataTypes.insert(1450903360, 8);
dataTypes.insert(8, 1);
dataTypes.insert(16, 2);
+ dataTypes.insert(32, 4);
dataTypes.insert(48, 2);
// Read bytes 16-19 to get the bit type
@@ -130,6 +131,12 @@ void IsisMain() {
nOffset = 1024;
}
+ if (dataTypeBytes == 0) {
+ string msg = "The value totalBandBits [" + to_string(totalBandBits) + "] does not map " +
+ "to any byte size in the dataTypes table.";
+ throw IException(IException::Programmer, msg, _FILEINFO_);
+ }
+
fin.close();
PvlGroup results("FileInfo");
diff --git a/isis/src/base/apps/ddd2isis/tsts/badBandBit/Makefile b/isis/src/base/apps/ddd2isis/tsts/badBandBit/Makefile
new file mode 100644
index 0000000000..5dea576ab3
--- /dev/null
+++ b/isis/src/base/apps/ddd2isis/tsts/badBandBit/Makefile
@@ -0,0 +1,24 @@
+APPNAME = ddd2isis
+
+include $(ISISROOT)/make/isismake.tsts
+
+commands:
+ # TEST: Throws an error when trying to open the file
+ if [ `$(APPNAME) \
+ FROM=$(INPUT)/bad_flat.ddd \
+ TO=$(OUTPUT)/bad_flat.cub \
+ 2> $(OUTPUT)/temp.txt > /dev/null` ]; \
+ then true; \
+ fi;
+
+ # TEST: Throws an error when trying to read from a cub instead of ddd
+ if [ `$(APPNAME) \
+ FROM=$(INPUT)/bad_flat.cub \
+ TO=$(OUTPUT)/bad_flat.cub \
+ 2>> $(OUTPUT)/temp.txt > /dev/null` ]; \
+ then true; \
+ fi;
+
+ # Removes input file path up until input
+ $(SED) 's+\[.*/input+[input+' $(OUTPUT)/temp.txt > $(OUTPUT)/errorTruth.txt;
+ $(RM) $(OUTPUT)/temp.txt
From e1e2903496d176e2728d0dcd4c0381931e432db5 Mon Sep 17 00:00:00 2001
From: Jesse Mapel
Date: Mon, 2 Mar 2020 17:00:13 -0700
Subject: [PATCH 06/13] Changed version numbers for 4.1 RC (#3722)
---
isis/CMakeLists.txt | 2 +-
recipe/meta.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index 24f7a2a986..75749b7452 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -33,7 +33,7 @@ set(PACKAGE "ISIS")
set(PACKAGE_NAME "USGS ISIS")
# Version number
-set(VERSION "4.0.0")
+set(VERSION "4.1.0")
set(PACKAGE_VERSION ${VERSION})
# Full name and version number
diff --git a/recipe/meta.yaml b/recipe/meta.yaml
index 7836c1dbb5..f35759f302 100644
--- a/recipe/meta.yaml
+++ b/recipe/meta.yaml
@@ -18,7 +18,7 @@
# A Public Release for ISIS3.6.1: {% set version = "3.6.1" %}
# A Release Candidate for ISIS3.6.1: {% set version = "3.6.1_RC" %}
# A custom build of ISIS3.6.1 for the CaSSIS mission: {% set version = "3.6.1_cassis" %}
-{% set version = "4.0.0_RC1" %}
+{% set version = "4.1.0_RC1" %}
# This is the build number for the current version you are building. If this is the first build of
# this version, the build number will be 0. It is incremented by 1 with every consecutive build of
From 08fcba24171c8cf3c350e3decf07e3154a9f70d7 Mon Sep 17 00:00:00 2001
From: Kristin
Date: Mon, 2 Mar 2020 17:07:15 -0700
Subject: [PATCH 07/13] Add directory structure for appdata in source
---
isis/appdata/autoreg/DELETEME.txt | 0
isis/appdata/images/icons/DELETEME.txt | 0
isis/appdata/images/targets/DELETEME.txt | 0
isis/appdata/labels/DELETEME.txt | 0
isis/appdata/maps/DELETEME.txt | 0
isis/appdata/serialnumbers/DELETEME.txt | 0
6 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 isis/appdata/autoreg/DELETEME.txt
create mode 100644 isis/appdata/images/icons/DELETEME.txt
create mode 100644 isis/appdata/images/targets/DELETEME.txt
create mode 100644 isis/appdata/labels/DELETEME.txt
create mode 100644 isis/appdata/maps/DELETEME.txt
create mode 100644 isis/appdata/serialnumbers/DELETEME.txt
diff --git a/isis/appdata/autoreg/DELETEME.txt b/isis/appdata/autoreg/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/isis/appdata/images/icons/DELETEME.txt b/isis/appdata/images/icons/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/isis/appdata/images/targets/DELETEME.txt b/isis/appdata/images/targets/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/isis/appdata/labels/DELETEME.txt b/isis/appdata/labels/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/isis/appdata/maps/DELETEME.txt b/isis/appdata/maps/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/isis/appdata/serialnumbers/DELETEME.txt b/isis/appdata/serialnumbers/DELETEME.txt
new file mode 100644
index 0000000000..e69de29bb2
From 9a72acde7c05e90215eeb0cc4a9cebadeeb0ac2c Mon Sep 17 00:00:00 2001
From: Kristin
Date: Tue, 3 Mar 2020 13:09:04 -0700
Subject: [PATCH 08/13] Update cmakelists to copy translation files over into
the appdata/translations area in the build directory.
---
isis/CMakeLists.txt | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index 75749b7452..3a6d7c4f7d 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -446,9 +446,13 @@ endif()
file(WRITE "${CMAKE_BINARY_DIR}/qt.conf" "[Paths]\nPlugins=../3rdParty/plugins/\n")
install(FILES "${CMAKE_BINARY_DIR}/qt.conf" DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/xml)
-#Create the inc directory
+# Create the inc directory
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/inc)
+# Create the appdata directory and translations directory
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/translations)
+
# Create an xml folder in the source directory that we will need later
set(sourceXmlFolder ${CMAKE_BINARY_DIR}/bin/xml)
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/bin/xml)
@@ -490,6 +494,13 @@ add_custom_target(incs ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/src/*/apps/*/*.h ${CMAKE_BINARY_DIR}/inc)
add_dependencies(isis3 incs)
+# Add custom build target to copy modified translation files to the build/appdata/translations
+# directory. (As above - may need to be updated)
+add_custom_target(appdata ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/serialnumbers/*.trn ${CMAKE_SOURCE_DIR}/src/*/apps/*/*.trn
+ ${CMAKE_BINARY_DIR}/appdata/translations)
+add_dependencies(isis3 appdata)
+
# Add a custom build target to clean out everything that gets added to the source
# directory during the build process.
# - Only a few things are added in order to make the tests work properly so
From eb6eb799b4bb28906f8e75793049b74816c9372c Mon Sep 17 00:00:00 2001
From: Kristin
Date: Tue, 3 Mar 2020 13:50:58 -0700
Subject: [PATCH 09/13] Update to install appdata
---
isis/CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index 3a6d7c4f7d..176b678107 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -466,6 +466,9 @@ install(DIRECTORY ${CMAKE_SOURCE_DIR}/templates DESTINATION .)
# Set up install of the make folder.
install(DIRECTORY ${CMAKE_SOURCE_DIR}/make DESTINATION ${CMAKE_INSTALL_PREFIX})
+# Set up install of appdata folder
+install(DIRECTORY ${CMAKE_BINARY_DIR}/appdata DESTINATION ${CMAKE_INSTALL_PREFIX})
+
# Have CMake process all of the source code and tests.
add_subdirectory(src objects)
From 35eb12260278e18b0933ac42be5e575371109412 Mon Sep 17 00:00:00 2001
From: Kristin
Date: Tue, 3 Mar 2020 14:30:08 -0700
Subject: [PATCH 10/13] Add appdata/templates directory needed for apollo work.
---
isis/CMakeLists.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index 176b678107..c53dca1085 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -450,8 +450,8 @@ install(FILES "${CMAKE_BINARY_DIR}/qt.conf" DESTINATION ${CMAKE_INSTALL_PREFIX}/
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/inc)
# Create the appdata directory and translations directory
-execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata)
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/translations)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/templates)
# Create an xml folder in the source directory that we will need later
set(sourceXmlFolder ${CMAKE_BINARY_DIR}/bin/xml)
@@ -504,6 +504,12 @@ add_custom_target(appdata ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_BINARY_DIR}/appdata/translations)
add_dependencies(isis3 appdata)
+# Add custom build target to copy modified template files to the build/appdata/templates
+# directory. (As above - may need to be updated)
+add_custom_target(templates ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/templates/*.pvl ${CMAKE_BINARY_DIR}/appdata/templates)
+add_dependencies(isis3 templates)
+
# Add a custom build target to clean out everything that gets added to the source
# directory during the build process.
# - Only a few things are added in order to make the tests work properly so
From 6759ea31860fc926d2620c8c5efece01c73faf89 Mon Sep 17 00:00:00 2001
From: Kristin
Date: Wed, 4 Mar 2020 16:15:39 -0700
Subject: [PATCH 11/13] Migrates everything in maps, labels, and and autoreg
into source, adds placeholders for cmake for images and templates, and adds
two actual base translation files and associated changes
---
isis/CMakeLists.txt | 33 ++-
.../autoreg/coreg.adaptgruen.p1515s3030.def | 256 ++++++++++++++++++
.../autoreg/coreg.maxcor.p1515.s3030.def | 163 +++++++++++
.../autoreg/coreg.maxcor.p2020.s5050.def | 163 +++++++++++
.../autoreg/coreg.mindif.p1515.s3030.def | 168 ++++++++++++
.../autoreg/coreg.mindif.p2020.s5050.def | 168 ++++++++++++
isis/appdata/autoreg/default.def | 31 +++
isis/appdata/autoreg/findrx.def | 22 ++
isis/appdata/autoreg/gruen_default.def | 29 ++
isis/appdata/autoreg/qnetReg.def | 21 ++
.../icons/DELETEME.png} | 0
.../DELETEME.txt => targets/DELETEME.png} | 0
isis/appdata/labels/CubeFormatTemplate.pft | 42 +++
isis/appdata/labels/MappingGroupKeywords.pft | 19 ++
isis/appdata/labels/pdsExportAllMapping.pft | 30 ++
isis/appdata/maps/DELETEME.txt | 0
.../maps/ellipsoidtransverseazimuthal.map | 48 ++++
isis/appdata/maps/equirectangular.map | 38 +++
.../maps/lambertazimuthalequalarea.map | 38 +++
isis/appdata/maps/lambertconformal.map | 57 ++++
isis/appdata/maps/mercator.map | 38 +++
isis/appdata/maps/mollweide.map | 36 +++
isis/appdata/maps/obliquecylindrical.map | 39 +++
isis/appdata/maps/orthographic.map | 38 +++
isis/appdata/maps/planar.map | 35 +++
isis/appdata/maps/pointperspective.map | 44 +++
isis/appdata/maps/polarstereographic.map | 38 +++
isis/appdata/maps/ringcylindrical.map | 36 +++
isis/appdata/maps/robinson.map | 37 +++
isis/appdata/maps/simplecylindrical.map | 37 +++
isis/appdata/maps/sinusoidal.map | 37 +++
isis/appdata/maps/transversemercator.map | 42 +++
.../DELETEME.txt => templates/DELETEME.pvl} | 0
isis/appdata/translations/Instruments.trn | 156 +++++++++++
.../translations/MissionName2DataDir.trn | 93 +++++++
.../ObservationNumber/ObservationNumber.cpp | 4 +-
.../ObservationNumber/ObservationNumber.h | 2 +
.../base/objs/SerialNumber/SerialNumber.cpp | 4 +-
.../src/base/objs/SerialNumber/SerialNumber.h | 2 +
39 files changed, 2039 insertions(+), 5 deletions(-)
create mode 100644 isis/appdata/autoreg/coreg.adaptgruen.p1515s3030.def
create mode 100644 isis/appdata/autoreg/coreg.maxcor.p1515.s3030.def
create mode 100644 isis/appdata/autoreg/coreg.maxcor.p2020.s5050.def
create mode 100644 isis/appdata/autoreg/coreg.mindif.p1515.s3030.def
create mode 100644 isis/appdata/autoreg/coreg.mindif.p2020.s5050.def
create mode 100644 isis/appdata/autoreg/default.def
create mode 100644 isis/appdata/autoreg/findrx.def
create mode 100644 isis/appdata/autoreg/gruen_default.def
create mode 100644 isis/appdata/autoreg/qnetReg.def
rename isis/appdata/{autoreg/DELETEME.txt => images/icons/DELETEME.png} (100%)
rename isis/appdata/images/{icons/DELETEME.txt => targets/DELETEME.png} (100%)
create mode 100644 isis/appdata/labels/CubeFormatTemplate.pft
create mode 100644 isis/appdata/labels/MappingGroupKeywords.pft
create mode 100644 isis/appdata/labels/pdsExportAllMapping.pft
delete mode 100644 isis/appdata/maps/DELETEME.txt
create mode 100644 isis/appdata/maps/ellipsoidtransverseazimuthal.map
create mode 100644 isis/appdata/maps/equirectangular.map
create mode 100644 isis/appdata/maps/lambertazimuthalequalarea.map
create mode 100644 isis/appdata/maps/lambertconformal.map
create mode 100644 isis/appdata/maps/mercator.map
create mode 100644 isis/appdata/maps/mollweide.map
create mode 100644 isis/appdata/maps/obliquecylindrical.map
create mode 100644 isis/appdata/maps/orthographic.map
create mode 100644 isis/appdata/maps/planar.map
create mode 100644 isis/appdata/maps/pointperspective.map
create mode 100644 isis/appdata/maps/polarstereographic.map
create mode 100644 isis/appdata/maps/ringcylindrical.map
create mode 100644 isis/appdata/maps/robinson.map
create mode 100644 isis/appdata/maps/simplecylindrical.map
create mode 100644 isis/appdata/maps/sinusoidal.map
create mode 100644 isis/appdata/maps/transversemercator.map
rename isis/appdata/{labels/DELETEME.txt => templates/DELETEME.pvl} (100%)
create mode 100644 isis/appdata/translations/Instruments.trn
create mode 100644 isis/appdata/translations/MissionName2DataDir.trn
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index c53dca1085..f10d08c025 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -452,6 +452,11 @@ execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/inc)
# Create the appdata directory and translations directory
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/translations)
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/templates)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/maps)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/images/icons)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/images/targets)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/labels)
+execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/appdata/autoreg)
# Create an xml folder in the source directory that we will need later
set(sourceXmlFolder ${CMAKE_BINARY_DIR}/bin/xml)
@@ -500,7 +505,8 @@ add_dependencies(isis3 incs)
# Add custom build target to copy modified translation files to the build/appdata/translations
# directory. (As above - may need to be updated)
add_custom_target(appdata ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
- ${CMAKE_SOURCE_DIR}/appdata/serialnumbers/*.trn ${CMAKE_SOURCE_DIR}/src/*/apps/*/*.trn
+ ${CMAKE_SOURCE_DIR}/appdata/serialnumbers/*.trn ${CMAKE_SOURCE_DIR}/appdata/translations/*.trn
+ ${CMAKE_SOURCE_DIR}/src/*/apps/*/*.trn
${CMAKE_BINARY_DIR}/appdata/translations)
add_dependencies(isis3 appdata)
@@ -510,6 +516,31 @@ add_custom_target(templates ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/appdata/templates/*.pvl ${CMAKE_BINARY_DIR}/appdata/templates)
add_dependencies(isis3 templates)
+# Either add these for maps, labels, autoreg, images or approach in a different way.
+
+# Add custom build target to copy modified template files to the build/appdata/templates
+# directory. (As above - may need to be updated)
+
+add_custom_target(icons ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/images/icons/* ${CMAKE_BINARY_DIR}/appdata/images/icons)
+add_dependencies(isis3 icons)
+
+add_custom_target(targets ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/images/targets/* ${CMAKE_BINARY_DIR}/appdata/images/targets)
+add_dependencies(isis3 targets)
+
+add_custom_target(maps ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/maps/*.map ${CMAKE_BINARY_DIR}/appdata/maps)
+add_dependencies(isis3 maps)
+
+add_custom_target(labels ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/labels/*.pft ${CMAKE_BINARY_DIR}/appdata/labels)
+add_dependencies(isis3 labels)
+
+add_custom_target(autoreg ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_SOURCE_DIR}/appdata/autoreg/*.def ${CMAKE_BINARY_DIR}/appdata/autoreg)
+add_dependencies(isis3 autoreg)
+
# Add a custom build target to clean out everything that gets added to the source
# directory during the build process.
# - Only a few things are added in order to make the tests work properly so
diff --git a/isis/appdata/autoreg/coreg.adaptgruen.p1515s3030.def b/isis/appdata/autoreg/coreg.adaptgruen.p1515s3030.def
new file mode 100644
index 0000000000..0519b54127
--- /dev/null
+++ b/isis/appdata/autoreg/coreg.adaptgruen.p1515s3030.def
@@ -0,0 +1,256 @@
+ Object = AutoRegistration
+ Group = Algorithm
+ # This is the adaptive gruen algorithm, which provides adaptive image
+ # (chip) registration using an Affine transform to iteratively adjust
+ # the search chip at each iteration. Each iteration solves for new
+ # adjustments to the Affine transform until the 6 affine parameters
+ # fall below the tolerances as specified by the following parameters.
+ #REQUIRED
+ Name = AdaptiveGruen
+
+ # The tolerance for the goodness-of-fit. For the
+ # AdaptiveGruen algorithm, the goodness-of-fit value must
+ # be less than Tolerance before the algorithm is considered
+ # to have converged to a user-acceptable solution.
+ #Possible Values: [0,infinity)
+ #REQUIRED
+ Tolerance = 0.1
+
+ # The Maximum number of iterations the algorithm is allowed to perform
+ # in an attempt to converge before failing and returning no registration.
+ #Possible Values: [1,infinity), integer
+ #REQUIRED
+ MaximumIterations = 30
+
+ # The AffineTolerance specifies the amount of offset in pixels an affine
+ # derived point is allowed to deviate from the orginal match point.
+ #Possible Values: [0,infinity)
+ #OPTIONAL
+ AffineTolerance = 5.0
+
+ # The AffineTranslationTolerance specifies the threshold convergence value
+ # of the affine translation shift in line/sample between each Gruen match
+ # iteration. If the amount of affine translation computed in the Gruen
+ # algorithm is less than the AffineTranslationTolerance, that point is
+ # deemed a match point for the purposes of the translation portion of the
+ # registered point.
+ #Possible Values: [0,infinity)
+ #OPTIONAL
+ AffineTranslationTolerance = 0.2
+
+ # The AffineScaleTolerance specifies the threshold convergence value of the
+ # affine scale in line/sample between each Gruen match iteration. If the
+ # amount of the affine translation computed in the Gruen algorithm is
+ # less than the AffineScaleTolerance, that point is deemed a match point
+ # for the purposes of the scaling portion of the registered point.
+ #Possible Values: [0,infinity)
+ #OPTIONAL
+ AffineScaleTolerance = 0.7
+
+ # The AffineShearTolerance specifies the threshold convergence value of the
+ # affine scale in line/sample between each Gruen match iteration. If the
+ # amount of the affine translation computed in the Gruen algorithm is
+ # less than the AffineShearTolerance, that point is deemed a match point
+ # for the purposes of the shear portion of the registered point.
+ #Possible Values: [0,infinity)
+ #OPTIONAL
+ #AffineShearTolerance = 0.7
+
+ #The SpiceTolerance defines the amount of offset in pixels a registration
+ # is allowed to deviate from a registered point.
+ #Possible Values: [0,infinity)
+ #OPTIONAL
+ #SpiceTolerance = 7.0
+
+ #The RadioShiftTolerance specifies the threshold convergence value for the
+ # radiometric shift of the pixel value between each Gruen match iteration.
+ # If the amount of the radiometric shift computed in the Gruen algorithm is
+ # less than the RadioShiftTolerance, that point is deemed a match point
+ # for the purposes of the radiometric shift portion of the registered point.
+ # This tolerance value depends heavily on the radiometric properties of
+ # your images.
+ #Possible Values: (-infinity,infinity)
+ #OPTIONAL
+ #RadioShiftTolerance = 256
+
+ #The RadioGainMinTolerance specifies the minimum value for the
+ # radiometric gain of the pixel value between each Gruen match iteration.
+ # If the amount of the radiometric gain computed in the Gruen algorithm is
+ # greater than the RadioGainMinTolerance and is less than
+ # RadioGainMaxTolerance, that point is deemed a match point for the
+ # purposes of the radiometric gain portion of the registered point.
+ # This tolerance value depends heavily on the radiometric properties of
+ # your images.
+ #Possible Values: (-infinity,infinity)
+ #OPTIONAL
+ #RadioGainMinTolerance = -0.75
+
+ #The RadioGainMaxTolerance specifies the maximum value for the
+ # radiometric gain of the pixel value between each Gruen match iteration.
+ # If the amount of the radiometric gain computed in the Gruen algorithm is
+ # greater than the RadioGainMinTolerance and is less than
+ # RadioGainMaxTolerance, that point is deemed a match point for the
+ # purposes of the radiometric gain portion of the registered point.
+ # This tolerance value depends heavily on the radiometric properties of
+ # your images.
+ #Possible Values: (-infinity,infinity)
+ #OPTIONAL
+ #RadioGainMaxTolerance = 3.0
+
+ #FitChipScale = 0.1
+
+ #The DefaultRadioShift sets the default value for the radiometric shift
+ # value used as a starting point in the Gruen algorithm.
+ #Possible Values: (-infinity,infinity)
+ #OPTIONAL
+ #DefaultRadioShift = 0.0
+
+ #The DefaultRadioGain sets the default value for the radiometric gain
+ # value used as a starting point in the Gruen algorithm.
+ #Possible Values: (-infinity,infinity)
+ #OPTIONAL
+ #DefaultRadioGain = 0.0
+
+ # Calculate the registration to subpixel accuracy. This is a
+ # boolean (True or False).
+ #Possible Values: {True, False}
+ #OPTIONAL
+ #SubPixelAccuracy = True
+
+ # Reduce the size of of the Pattern and Search chips by a
+ # the ReductionFactor for a first-run through the data
+ # to find a low-accuracy match. Then focus the
+ # full-accuracy match to the surrounding area.
+ #Possible Values: Natural Numbers
+ #OPTIONAL
+ #ReductionFactor = 1
+
+ # Apply a Sobel gradient filter to the chips before running the
+ # pattern matching Algorithm. This essentially highlights
+ # edges within the chips, possibly increasing the chance of
+ # finding a good match between the search and pattern chips.
+ #Possible Values: {None, Sobel}
+ #OPTIONAL
+ #Gradient = None
+
+ # If the two images to be registered do not have the same
+ # geometry, pattern matching becomes more difficult. This
+ # option informs the algorithm to warp the pattern cube to
+ # match the geometry of the search cube by using map
+ # projections and/or camera models. The warping requires
+ # interpolation, and the type of interpolation is chosen here.
+ #Possible Values: {NearestNeighborType, BiLinearType, CubicConvolutionType}
+ #OPTIONAL
+ #ChipInterpolator = NearestNeighborType
+ EndGroup
+
+ #Pattern Chip Definitions
+ Group = PatternChip
+ #Size of the PatternChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 15
+ Lines = 15
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The MinimumZScore is used to guarantee that the pattern chip has
+ # enough variability--if the chip is too smooth, spurious matches
+ # are likely to occur.
+ #Possible Values: (0.0,infinity)
+ #OPTIONAL
+ #MinimumZScore = 1.0
+
+ #The ValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the chip before the chip is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0,100.0]
+ #OPTIONAL
+ #ValidPercent = 50.0
+ EndGroup
+
+ #Search Chip Definitions
+ Group = SearchChip
+ #Size of the SearchChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 30
+ Lines = 30
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The SubchipValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the subchip before it is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0, 100.0]
+ #OPTIONAL
+ #SubchipValidPercent = 50.0
+ EndGroup
+
+ #If the SubPixelAccuracy parameter is TRUE, then a continuous surface
+ # based on the fit chip is generated. A least squares fit is then used
+ # to estimate the true registration position (likely to be between pixels).
+ Group = SurfaceModel
+ #The result of a sub-pixel accuracy computation is likely to move
+ # the result away from its original whole-pixel fit. However,
+ # sometimes the move could be so drastic that it calls into
+ # question the validity of the match. This tolerance value
+ # thus specifies the max number of pixels the sub-pixel accuracy
+ # computation can move the best fit before the registration is rejected
+ # entirely.
+ #Possible Values (0.0, infinity)
+ #OPTIONAL
+ #DistanceTolerance = 1.5
+
+ #When refining a whole-pixel match to sub-pixel accuracy, it is important
+ # to consider how much area around that best whole-pixel fit to sample
+ # for constructing a surface model. The WindowSize keyword defines the
+ # size of the window, centered on the best whole-pixel match, that will
+ # be used for modelling the surface. Values for WindowSize specify the
+ # N of an NxN chip, and must be odd numbers greater than or equal to 3.
+ #Possible Values: [3, infinity), odd integer
+ #OPTIONAL
+ #WindowSize = 5
+
+ #After the least squares fit is performed to model a surface, the
+ # ideal result is a circular formation of goodness-of-fit values
+ # improving towards the center of the surface. The less circular,
+ # or more "eccentric", the formation of goodness-of-fit values,
+ # the less likely the modelling result is accurate. The
+ # conditions under which a high ratio occurs is when there are
+ # primiarily linear features in the search and pattern chips.
+ # In an attempt to let the user define what constitutes a tolerable
+ # amount of eccentricity in their surface models, we introduce the
+ # notion of an "Eccentricity Ratio". Here we think of eccentricity
+ # as a ratio between the semi-major and semi-minor axes of an ellipse.
+ #Possible Values [1.0, infinity]
+ #OPTIONAL
+ #EccentricityRatio = 1.0
+
+ #The least squares fit performed to construct the surface model
+ # takes discrete data from the whole-pixels around the best-fit.
+ # When these discrete data are fit with a continuous function,
+ # there is likely going to be some amount of error between the
+ # original value for some pixel and its interpolated value in the
+ # least squares solution. The ResidualTolerance keyword thus
+ # allows the user to specify the maximum average residual, or
+ # mean absolute error, for all pixels in the surface model area,
+ # that will be tolerated before the sub-pixel accuracy computation
+ # is rejected and the registration fails for that point.
+ #Possible Values: [0.0, infinity]
+ #OPTIONAL
+ #ResidualTolerance = 0.0
+ EndGroup
+ EndObject
diff --git a/isis/appdata/autoreg/coreg.maxcor.p1515.s3030.def b/isis/appdata/autoreg/coreg.maxcor.p1515.s3030.def
new file mode 100644
index 0000000000..03c84ab9b1
--- /dev/null
+++ b/isis/appdata/autoreg/coreg.maxcor.p1515.s3030.def
@@ -0,0 +1,163 @@
+ Object = AutoRegistration
+ # Algorithm specification.
+ Group = Algorithm
+
+ # This is the maximum correlation algorithm, which
+ # computes the correlation coefficient, -1.0 <= R <= 1.0
+ # between the pattern chip and sub-region of the search chip.
+ # The goodness-of-fit is defined as the absolute value
+ # of R.
+ #REQUIRED
+ Name = MaximumCorrelation
+
+ # The tolerance for the goodness-of-fit. For the
+ # MaximumCorrelation algorithm, the goodness-of-fit value must
+ # be greater than Tolerance, before the algorithm is considered
+ # to have converged to a user-acceptable solution.
+ #Possible Values: [0,1.0)
+ #REQUIRED
+ Tolerance = 0.7
+
+ # Calculate the registration to subpixel accuracy. This is a
+ # boolean (True or False).
+ #Possible Values: {True, False}
+ #OPTIONAL
+ #SubPixelAccuracy = True
+
+ # Reduce the size of of the Pattern and Search chips by a
+ # the ReductionFactor for a first-run through the data
+ # to find a low-accuracy match. Then focus the
+ # full-accuracy match to the surrounding area.
+ #Possible Values: Natural Numbers
+ #OPTIONAL
+ #ReductionFactor = 1
+
+ # Apply a Sobel gradient filter to the chips before running the
+ # pattern matching Algorithm. This essentially highlights
+ # edges within the chips, possibly increasing the chance of
+ # finding a good match between the search and pattern chips.
+ #Possible Values: {None, Sobel}
+ #OPTIONAL
+ #Gradient = None
+
+ # If the two images to be registered do not have the same
+ # geometry, pattern matching becomes more difficult. This
+ # option informs the algorithm to warp the pattern cube to
+ # match the geometry of the search cube by using map
+ # projections and/or camera models. The warping requires
+ # interpolation, and the type of interpolation is chosen here.
+ #Possible Values: {NearestNeighborType, BiLinearType, CubicConvolutionType}
+ #OPTIONAL
+ #ChipInterpolator = NearestNeighborType
+ EndGroup
+
+ #Pattern Chip Definitions
+ Group = PatternChip
+ #Size of the PatternChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 15
+ Lines = 15
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The MinimumZScore is used to guarantee that the pattern chip has
+ # enough variability--if the chip is too smooth, spurious matches
+ # are likely to occur.
+ #Possible Values: (0.0,infinity)
+ #OPTIONAL
+ #MinimumZScore = 1.0
+
+ #The ValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the chip before the chip is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0,100.0]
+ #OPTIONAL
+ #ValidPercent = 50.0
+ EndGroup
+
+ #Search Chip Definitions
+ Group = SearchChip
+ #Size of the SearchChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 30
+ Lines = 30
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The SubchipValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the subchip before it is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0, 100.0]
+ #OPTIONAL
+ #SubchipValidPercent = 50.0
+ EndGroup
+
+ #If the SubPixelAccuracy parameter is TRUE, then a continuous surface
+ # based on the fit chip is generated. A least squares fit is then used
+ # to estimate the true registration position (likely to be between pixels).
+ Group = SurfaceModel
+ #The result of a sub-pixel accuracy computation is likely to move
+ # the result away from its original whole-pixel fit. However,
+ # sometimes the move could be so drastic that it calls into
+ # question the validity of the match. This tolerance value
+ # thus specifies the max number of pixels the sub-pixel accuracy
+ # computation can move the best fit before the registration is rejected
+ # entirely.
+ #Possible Values (0.0, infinity)
+ #OPTIONAL
+ #DistanceTolerance = 1.5
+
+ #When refining a whole-pixel match to sub-pixel accuracy, it is important
+ # to consider how much area around that best whole-pixel fit to sample
+ # for constructing a surface model. The WindowSize keyword defines the
+ # size of the window, centered on the best whole-pixel match, that will
+ # be used for modelling the surface. Values for WindowSize specify the
+ # N of an NxN chip, and must be odd numbers greater than or equal to 3.
+ #Possible Values: [3, infinity), odd integer
+ #OPTIONAL
+ #WindowSize = 5
+
+ #After the least squares fit is performed to model a surface, the
+ # ideal result is a circular formation of goodness-of-fit values
+ # improving towards the center of the surface. The less circular,
+ # or more "eccentric", the formation of goodness-of-fit values,
+ # the less likely the modelling result is accurate. The
+ # conditions under which a high ratio occurs is when there are
+ # primiarily linear features in the search and pattern chips.
+ # In an attempt to let the user define what constitutes a tolerable
+ # amount of eccentricity in their surface models, we introduce the
+ # notion of an "Eccentricity Ratio". Here we think of eccentricity
+ # as a ratio between the semi-major and semi-minor axes of an ellipse.
+ #Possible Values [1.0, infinity]
+ #OPTIONAL
+ #EccentricityRatio = 1.0
+
+ #The least squares fit performed to construct the surface model
+ # takes discrete data from the whole-pixels around the best-fit.
+ # When these discrete data are fit with a continuous function,
+ # there is likely going to be some amount of error between the
+ # original value for some pixel and its interpolated value in the
+ # least squares solution. The ResidualTolerance keyword thus
+ # allows the user to specify the maximum average residual, or
+ # mean absolute error, for all pixels in the surface model area,
+ # that will be tolerated before the sub-pixel accuracy computation
+ # is rejected and the registration fails for that point.
+ #Possible Values: [0.0, infinity]
+ #OPTIONAL
+ #ResidualTolerance = 0.0
+ EndGroup
+ EndObject
diff --git a/isis/appdata/autoreg/coreg.maxcor.p2020.s5050.def b/isis/appdata/autoreg/coreg.maxcor.p2020.s5050.def
new file mode 100644
index 0000000000..216c11d377
--- /dev/null
+++ b/isis/appdata/autoreg/coreg.maxcor.p2020.s5050.def
@@ -0,0 +1,163 @@
+ Object = AutoRegistration
+ # Algorithm specification.
+ Group = Algorithm
+
+ # This is the maximum correlation algorithm, which
+ # computes the correlation coefficient, -1.0 <= R <= 1.0
+ # between the pattern chip and sub-region of the search chip.
+ # The goodness-of-fit is defined as the absolute value
+ # of R.
+ #REQUIRED
+ Name = MaximumCorrelation
+
+ # The tolerance for the goodness-of-fit. For the
+ # MaximumCorrelation algorithm, the goodness-of-fit value must
+ # be greater than Tolerance, before the algorithm is considered
+ # to have converged to a user-acceptable solution.
+ #Possible Values: [0,1.0)
+ #REQUIRED
+ Tolerance = 0.7
+
+ # Calculate the registration to subpixel accuracy. This is a
+ # boolean (True or False).
+ #Possible Values: {True, False}
+ #OPTIONAL
+ #SubPixelAccuracy = True
+
+ # Reduce the size of of the Pattern and Search chips by a
+ # the ReductionFactor for a first-run through the data
+ # to find a low-accuracy match. Then focus the
+ # full-accuracy match to the surrounding area.
+ #Possible Values: Natural Numbers
+ #OPTIONAL
+ #ReductionFactor = 1
+
+ # Apply a Sobel gradient filter to the chips before running the
+ # pattern matching Algorithm. This essentially highlights
+ # edges within the chips, possibly increasing the chance of
+ # finding a good match between the search and pattern chips.
+ #Possible Values: {None, Sobel}
+ #OPTIONAL
+ #Gradient = None
+
+ # If the two images to be registered do not have the same
+ # geometry, pattern matching becomes more difficult. This
+ # option informs the algorithm to warp the pattern cube to
+ # match the geometry of the search cube by using map
+ # projections and/or camera models. The warping requires
+ # interpolation, and the type of interpolation is chosen here.
+ #Possible Values: {NearestNeighborType, BiLinearType, CubicConvolutionType}
+ #OPTIONAL
+ #ChipInterpolator = NearestNeighborType
+ EndGroup
+
+ #Pattern Chip Definitions
+ Group = PatternChip
+ #Size of the PatternChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 20
+ Lines = 20
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The MinimumZScore is used to guarantee that the pattern chip has
+ # enough variability--if the chip is too smooth, spurious matches
+ # are likely to occur.
+ #Possible Values: (0.0,infinity)
+ #OPTIONAL
+ #MinimumZScore = 1.0
+
+ #The ValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the chip before the chip is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0,100.0]
+ #OPTIONAL
+ #ValidPercent = 50.0
+ EndGroup
+
+ #Search Chip Definitions
+ Group = SearchChip
+ #Size of the SearchChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 50
+ Lines = 50
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The SubchipValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the subchip before it is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0, 100.0]
+ #OPTIONAL
+ #SubchipValidPercent = 50.0
+ EndGroup
+
+ #If the SubPixelAccuracy parameter is TRUE, then a continuous surface
+ # based on the fit chip is generated. A least squares fit is then used
+ # to estimate the true registration position (likely to be between pixels).
+ Group = SurfaceModel
+ #The result of a sub-pixel accuracy computation is likely to move
+ # the result away from its original whole-pixel fit. However,
+ # sometimes the move could be so drastic that it calls into
+ # question the validity of the match. This tolerance value
+ # thus specifies the max number of pixels the sub-pixel accuracy
+ # computation can move the best fit before the registration is rejected
+ # entirely.
+ #Possible Values (0.0, infinity)
+ #OPTIONAL
+ #DistanceTolerance = 1.5
+
+ #When refining a whole-pixel match to sub-pixel accuracy, it is important
+ # to consider how much area around that best whole-pixel fit to sample
+ # for constructing a surface model. The WindowSize keyword defines the
+ # size of the window, centered on the best whole-pixel match, that will
+ # be used for modelling the surface. Values for WindowSize specify the
+ # N of an NxN chip, and must be odd numbers greater than or equal to 3.
+ #Possible Values: [3, infinity), odd integer
+ #OPTIONAL
+ #WindowSize = 5
+
+ #After the least squares fit is performed to model a surface, the
+ # ideal result is a circular formation of goodness-of-fit values
+ # improving towards the center of the surface. The less circular,
+ # or more "eccentric", the formation of goodness-of-fit values,
+ # the less likely the modelling result is accurate. The
+ # conditions under which a high ratio occurs is when there are
+ # primiarily linear features in the search and pattern chips.
+ # In an attempt to let the user define what constitutes a tolerable
+ # amount of eccentricity in their surface models, we introduce the
+ # notion of an "Eccentricity Ratio". Here we think of eccentricity
+ # as a ratio between the semi-major and semi-minor axes of an ellipse.
+ #Possible Values [1.0, infinity]
+ #OPTIONAL
+ #EccentricityRatio = 1.0
+
+ #The least squares fit performed to construct the surface model
+ # takes discrete data from the whole-pixels around the best-fit.
+ # When these discrete data are fit with a continuous function,
+ # there is likely going to be some amount of error between the
+ # original value for some pixel and its interpolated value in the
+ # least squares solution. The ResidualTolerance keyword thus
+ # allows the user to specify the maximum average residual, or
+ # mean absolute error, for all pixels in the surface model area,
+ # that will be tolerated before the sub-pixel accuracy computation
+ # is rejected and the registration fails for that point.
+ #Possible Values: [0.0, infinity]
+ #OPTIONAL
+ #ResidualTolerance = 0.0
+ EndGroup
+ EndObject
diff --git a/isis/appdata/autoreg/coreg.mindif.p1515.s3030.def b/isis/appdata/autoreg/coreg.mindif.p1515.s3030.def
new file mode 100644
index 0000000000..fd968d345b
--- /dev/null
+++ b/isis/appdata/autoreg/coreg.mindif.p1515.s3030.def
@@ -0,0 +1,168 @@
+ Object = AutoRegistration
+ # Algorithm specification.
+ Group = Algorithm
+
+ # This is the minimum difference algorithm, which
+ # defines goodness-of-fit as the average difference
+ # per pixel between the pattern chip and the search
+ # sub-region. A value of 0 in the goodness-of-fit
+ # result implies a perfect match.
+ #REQUIRED
+ Name = MinimumDifference
+
+ # The tolerance for the goodness-of-fit. For the
+ # MinimumDifference algorithm, the goodness-of-fit value must
+ # be less than Tolerance, before the algorithm is considered
+ # to have converged to a user-acceptable solution. In addition,
+ # the tolerance value is dependent on the images being
+ # matched. For example, 100 might work for DN values in
+ # an image pair that have not been radiometrically
+ # calibrated, but 0.1 may be necessary for an image pair
+ # that have radiometrically calibrated values of I/F.
+ #Possible Values: [0,infinity)
+ #REQUIRED
+ Tolerance = 100
+
+ # Calculate the registration to subpixel accuracy. This is a
+ # boolean (True or False).
+ #Possible Values: {True, False}
+ #OPTIONAL
+ #SubPixelAccuracy = True
+
+ # Reduce the size of of the Pattern and Search chips by a
+ # the ReductionFactor for a first-run through the data
+ # to find a low-accuracy match. Then focus the
+ # full-accuracy match to the surrounding area.
+ #Possible Values: Natural Numbers
+ #OPTIONAL
+ #ReductionFactor = 1
+
+ # Apply a Sobel gradient filter to the chips before running the
+ # pattern matching Algorithm. This essentially highlights
+ # edges within the chips, possibly increasing the chance of
+ # finding a good match between the search and pattern chips.
+ #Possible Values: {None, Sobel}
+ #OPTIONAL
+ #Gradient = None
+
+ # If the two images to be registered do not have the same
+ # geometry, pattern matching becomes more difficult. This
+ # option informs the algorithm to warp the pattern cube to
+ # match the geometry of the search cube by using map
+ # projections and/or camera models. The warping requires
+ # interpolation, and the type of interpolation is chosen here.
+ #Possible Values: {NearestNeighborType, BiLinearType, CubicConvolutionType}
+ #OPTIONAL
+ #ChipInterpolator = NearestNeighborType
+ EndGroup
+
+ #Pattern Chip Definitions
+ Group = PatternChip
+ #Size of the PatternChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 15
+ Lines = 15
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The MinimumZScore is used to guarantee that the pattern chip has
+ # enough variability--if the chip is too smooth, spurious matches
+ # are likely to occur.
+ #Possible Values: (0.0,infinity)
+ #OPTIONAL
+ #MinimumZScore = 1.0
+
+ #The ValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the chip before the chip is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0,100.0]
+ #OPTIONAL
+ #ValidPercent = 50.0
+ EndGroup
+
+ #Search Chip Definitions
+ Group = SearchChip
+ #Size of the SearchChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 30
+ Lines = 30
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The SubchipValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the subchip before it is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0, 100.0]
+ #OPTIONAL
+ #SubchipValidPercent = 50.0
+ EndGroup
+
+ #If the SubPixelAccuracy parameter is TRUE, then a continuous surface
+ # based on the fit chip is generated. A least squares fit is then used
+ # to estimate the true registration position (likely to be between pixels).
+ Group = SurfaceModel
+ #The result of a sub-pixel accuracy computation is likely to move
+ # the result away from its original whole-pixel fit. However,
+ # sometimes the move could be so drastic that it calls into
+ # question the validity of the match. This tolerance value
+ # thus specifies the max number of pixels the sub-pixel accuracy
+ # computation can move the best fit before the registration is rejected
+ # entirely.
+ #Possible Values (0.0, infinity)
+ #OPTIONAL
+ #DistanceTolerance = 1.5
+
+ #When refining a whole-pixel match to sub-pixel accuracy, it is important
+ # to consider how much area around that best whole-pixel fit to sample
+ # for constructing a surface model. The WindowSize keyword defines the
+ # size of the window, centered on the best whole-pixel match, that will
+ # be used for modelling the surface. Values for WindowSize specify the
+ # N of an NxN chip, and must be odd numbers greater than or equal to 3.
+ #Possible Values: [3, infinity), odd integer
+ #OPTIONAL
+ #WindowSize = 5
+
+ #After the least squares fit is performed to model a surface, the
+ # ideal result is a circular formation of goodness-of-fit values
+ # improving towards the center of the surface. The less circular,
+ # or more "eccentric", the formation of goodness-of-fit values,
+ # the less likely the modelling result is accurate. The
+ # conditions under which a high ratio occurs is when there are
+ # primiarily linear features in the search and pattern chips.
+ # In an attempt to let the user define what constitutes a tolerable
+ # amount of eccentricity in their surface models, we introduce the
+ # notion of an "Eccentricity Ratio". Here we think of eccentricity
+ # as a ratio between the semi-major and semi-minor axes of an ellipse.
+ #Possible Values [1.0, infinity]
+ #OPTIONAL
+ #EccentricityRatio = 1.0
+
+ #The least squares fit performed to construct the surface model
+ # takes discrete data from the whole-pixels around the best-fit.
+ # When these discrete data are fit with a continuous function,
+ # there is likely going to be some amount of error between the
+ # original value for some pixel and its interpolated value in the
+ # least squares solution. The ResidualTolerance keyword thus
+ # allows the user to specify the maximum average residual, or
+ # mean absolute error, for all pixels in the surface model area,
+ # that will be tolerated before the sub-pixel accuracy computation
+ # is rejected and the registration fails for that point.
+ #Possible Values: [0.0, infinity]
+ #OPTIONAL
+ #ResidualTolerance = 0.0
+ EndGroup
+ EndObject
diff --git a/isis/appdata/autoreg/coreg.mindif.p2020.s5050.def b/isis/appdata/autoreg/coreg.mindif.p2020.s5050.def
new file mode 100644
index 0000000000..6614c9fca7
--- /dev/null
+++ b/isis/appdata/autoreg/coreg.mindif.p2020.s5050.def
@@ -0,0 +1,168 @@
+ Object = AutoRegistration
+ # Algorithm specification.
+ Group = Algorithm
+
+ # This is the minimum difference algorithm, which
+ # defines goodness-of-fit as the average difference
+ # per pixel between the pattern chip and the search
+ # sub-region. A value of 0 in the goodness-of-fit
+ # result implies a perfect match.
+ #REQUIRED
+ Name = MinimumDifference
+
+ # The tolerance for the goodness-of-fit. For the
+ # MinimumDifference algorithm, the goodness-of-fit value must
+ # be less than Tolerance, before the algorithm is considered
+ # to have converged to a user-acceptable solution. In addition,
+ # the tolerance value is dependent on the images being
+ # matched. For example, 100 might work for DN values in
+ # an image pair that have not been radiometrically
+ # calibrated, but 0.1 may be necessary for an image pair
+ # that have radiometrically calibrated values of I/F.
+ #Possible Values: [0,infinity)
+ #REQUIRED
+ Tolerance = 100
+
+ # Calculate the registration to subpixel accuracy. This is a
+ # boolean (True or False).
+ #Possible Values: {True, False}
+ #OPTIONAL
+ #SubPixelAccuracy = True
+
+ # Reduce the size of of the Pattern and Search chips by a
+ # the ReductionFactor for a first-run through the data
+ # to find a low-accuracy match. Then focus the
+ # full-accuracy match to the surrounding area.
+ #Possible Values: Natural Numbers
+ #OPTIONAL
+ #ReductionFactor = 1
+
+ # Apply a Sobel gradient filter to the chips before running the
+ # pattern matching Algorithm. This essentially highlights
+ # edges within the chips, possibly increasing the chance of
+ # finding a good match between the search and pattern chips.
+ #Possible Values: {None, Sobel}
+ #OPTIONAL
+ #Gradient = None
+
+ # If the two images to be registered do not have the same
+ # geometry, pattern matching becomes more difficult. This
+ # option informs the algorithm to warp the pattern cube to
+ # match the geometry of the search cube by using map
+ # projections and/or camera models. The warping requires
+ # interpolation, and the type of interpolation is chosen here.
+ #Possible Values: {NearestNeighborType, BiLinearType, CubicConvolutionType}
+ #OPTIONAL
+ #ChipInterpolator = NearestNeighborType
+ EndGroup
+
+ #Pattern Chip Definitions
+ Group = PatternChip
+ #Size of the PatternChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 20
+ Lines = 20
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The MinimumZScore is used to guarantee that the pattern chip has
+ # enough variability--if the chip is too smooth, spurious matches
+ # are likely to occur.
+ #Possible Values: (0.0,infinity)
+ #OPTIONAL
+ #MinimumZScore = 1.0
+
+ #The ValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the chip before the chip is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0,100.0]
+ #OPTIONAL
+ #ValidPercent = 50.0
+ EndGroup
+
+ #Search Chip Definitions
+ Group = SearchChip
+ #Size of the SearchChip in Samples and Lines
+ #Possible Values: Natural Numbers
+ #REQUIRED
+ Samples = 50
+ Lines = 50
+
+ #The minimum/maximum pixel value the algorithm should use for registration.
+ # If a pixel is outside of this range, then it will not be used in the
+ # registration calculations.
+ #Possible Values: (-infinity, infinity), ValidMinimum < ValidMaximum
+ #OPTIONAL
+ #ValidMinimum = -100
+ #ValidMaximum = 100
+
+ #The SubchipValidPercent parameter specifies how many invalid pixels
+ # (NULL, HIS, etc.) are allowed in the subchip before it is
+ # considered invalid and the match fails.
+ #Possible Values: (0.0, 100.0]
+ #OPTIONAL
+ #SubchipValidPercent = 50.0
+ EndGroup
+
+ #If the SubPixelAccuracy parameter is TRUE, then a continuous surface
+ # based on the fit chip is generated. A least squares fit is then used
+ # to estimate the true registration position (likely to be between pixels).
+ Group = SurfaceModel
+ #The result of a sub-pixel accuracy computation is likely to move
+ # the result away from its original whole-pixel fit. However,
+ # sometimes the move could be so drastic that it calls into
+ # question the validity of the match. This tolerance value
+ # thus specifies the max number of pixels the sub-pixel accuracy
+ # computation can move the best fit before the registration is rejected
+ # entirely.
+ #Possible Values (0.0, infinity)
+ #OPTIONAL
+ #DistanceTolerance = 1.5
+
+ #When refining a whole-pixel match to sub-pixel accuracy, it is important
+ # to consider how much area around that best whole-pixel fit to sample
+ # for constructing a surface model. The WindowSize keyword defines the
+ # size of the window, centered on the best whole-pixel match, that will
+ # be used for modelling the surface. Values for WindowSize specify the
+ # N of an NxN chip, and must be odd numbers greater than or equal to 3.
+ #Possible Values: [3, infinity), odd integer
+ #OPTIONAL
+ #WindowSize = 5
+
+ #After the least squares fit is performed to model a surface, the
+ # ideal result is a circular formation of goodness-of-fit values
+ # improving towards the center of the surface. The less circular,
+ # or more "eccentric", the formation of goodness-of-fit values,
+ # the less likely the modelling result is accurate. The
+ # conditions under which a high ratio occurs is when there are
+ # primiarily linear features in the search and pattern chips.
+ # In an attempt to let the user define what constitutes a tolerable
+ # amount of eccentricity in their surface models, we introduce the
+ # notion of an "Eccentricity Ratio". Here we think of eccentricity
+ # as a ratio between the semi-major and semi-minor axes of an ellipse.
+ #Possible Values [1.0, infinity]
+ #OPTIONAL
+ #EccentricityRatio = 1.0
+
+ #The least squares fit performed to construct the surface model
+ # takes discrete data from the whole-pixels around the best-fit.
+ # When these discrete data are fit with a continuous function,
+ # there is likely going to be some amount of error between the
+ # original value for some pixel and its interpolated value in the
+ # least squares solution. The ResidualTolerance keyword thus
+ # allows the user to specify the maximum average residual, or
+ # mean absolute error, for all pixels in the surface model area,
+ # that will be tolerated before the sub-pixel accuracy computation
+ # is rejected and the registration fails for that point.
+ #Possible Values: [0.0, infinity]
+ #OPTIONAL
+ #ResidualTolerance = 0.0
+ EndGroup
+ EndObject
diff --git a/isis/appdata/autoreg/default.def b/isis/appdata/autoreg/default.def
new file mode 100644
index 0000000000..7641c11e6f
--- /dev/null
+++ b/isis/appdata/autoreg/default.def
@@ -0,0 +1,31 @@
+Object = AutoRegistration
+ Group = Algorithm
+ Name = MaximumCorrelation
+ Tolerance = 0.7
+ ReductionFactor = 1
+ SubpixelAccuracy = True
+
+ # Valid gradient value is Sobel.
+ # Gradient = Sobel
+ End_Group
+
+ Group = PatternChip
+ Samples = 3
+ Lines = 3
+ MinimumZScore = 1.0
+ End_Group
+
+ Group = SearchChip
+ Samples = 5
+ Lines = 5
+ ValidPercent = 50.0
+ End_Group
+
+ Group = SurfaceModel
+ DistanceTolerance = 1.5
+ WindowSize = 5
+ EccentricityRatio = 2.0
+ ResidualTolerance = 0.1
+ End_Group
+End_Object
+End
diff --git a/isis/appdata/autoreg/findrx.def b/isis/appdata/autoreg/findrx.def
new file mode 100644
index 0000000000..a0ecc3b7a0
--- /dev/null
+++ b/isis/appdata/autoreg/findrx.def
@@ -0,0 +1,22 @@
+ Object = AutoRegistration
+ Group = Algorithm
+ Name = MaximumCorrelation
+ Tolerance = 0.7
+
+ # Valid gradient value is Sobel.
+ # Gradient = Sobel
+ EndGroup
+
+ Group = PatternChip
+ Samples = 9
+ Lines = 9
+ MinimumZScore = .5
+ EndGroup
+
+ Group = SearchChip
+ Samples = 21
+ Lines = 21
+ EndGroup
+ EndObject
+
+
diff --git a/isis/appdata/autoreg/gruen_default.def b/isis/appdata/autoreg/gruen_default.def
new file mode 100644
index 0000000000..cab72f8c50
--- /dev/null
+++ b/isis/appdata/autoreg/gruen_default.def
@@ -0,0 +1,29 @@
+ Object = AutoRegistration
+ Group = Algorithm
+ Name = AdaptiveGruen
+ Tolerance = 99.0
+ MaximumIterations = 25
+ AffineTolerance = 8.0
+ SpiceTolerance = 20.0
+ AffineTranslationTolerance = 0.1
+ AffineScaleTolerance = 0.3
+ AffineShearTolerance = 0.3
+
+# RadioShiftTolerance = 256
+# RadioGainMinTolerance = -0.75
+# RadioGainMaxTolerance = 3.0
+# DefaultRadioShift = 0.0
+# DefaultRadioGain = 0.0
+ EndGroup
+
+ Group = PatternChip
+ Samples = 19
+ Lines = 19
+ EndGroup
+
+ Group = SearchChip
+ Samples = 31
+ Lines = 31
+ EndGroup
+ EndObject
+End
diff --git a/isis/appdata/autoreg/qnetReg.def b/isis/appdata/autoreg/qnetReg.def
new file mode 100644
index 0000000000..99d9d6caee
--- /dev/null
+++ b/isis/appdata/autoreg/qnetReg.def
@@ -0,0 +1,21 @@
+ Object = AutoRegistration
+ Group = Algorithm
+ Name = MaximumCorrelation
+ Tolerance = 0.7
+
+ # Valid gradient value is Sobel.
+ # Gradient = Sobel
+ EndGroup
+
+ Group = PatternChip
+ Samples = 15
+ Lines = 15
+ EndGroup
+
+ Group = SearchChip
+ Samples = 30
+ Lines = 30
+ EndGroup
+ EndObject
+
+
diff --git a/isis/appdata/autoreg/DELETEME.txt b/isis/appdata/images/icons/DELETEME.png
similarity index 100%
rename from isis/appdata/autoreg/DELETEME.txt
rename to isis/appdata/images/icons/DELETEME.png
diff --git a/isis/appdata/images/icons/DELETEME.txt b/isis/appdata/images/targets/DELETEME.png
similarity index 100%
rename from isis/appdata/images/icons/DELETEME.txt
rename to isis/appdata/images/targets/DELETEME.png
diff --git a/isis/appdata/labels/CubeFormatTemplate.pft b/isis/appdata/labels/CubeFormatTemplate.pft
new file mode 100644
index 0000000000..6bd1e6d85c
--- /dev/null
+++ b/isis/appdata/labels/CubeFormatTemplate.pft
@@ -0,0 +1,42 @@
+
+Object = IsisCube
+ Object = Core
+ Group = Dimensions
+ End_Group
+
+ Group = Pixels
+ End_Group
+ End_Object
+
+ Group = Instrument
+ End_Group
+
+ Group = Archive
+ End_Group
+
+ Group = BandBin
+ End_Group
+
+ Group = Kernels
+ End_Group
+
+ Group = Radiometry
+ End_Group
+
+ Group = Mapping
+ Isis:PvlTemplate:File = $base/templates/labels/MappingGroupKeywords.pft
+ End_Group
+
+ Group = AlphaCube
+ End_Group
+End_Object
+
+Object = Label
+End_Object
+
+Object = Table
+End_Object
+
+Object = History
+End_Object
+End
diff --git a/isis/appdata/labels/MappingGroupKeywords.pft b/isis/appdata/labels/MappingGroupKeywords.pft
new file mode 100644
index 0000000000..35624da362
--- /dev/null
+++ b/isis/appdata/labels/MappingGroupKeywords.pft
@@ -0,0 +1,19 @@
+ProjectionName
+CenterLongitude
+TargetName
+EquatorialRadius
+PolarRadius
+LatitudeType
+LongitudeDirection
+LongitudeDomain
+MinimumLatitude
+MaximumLatitude
+MinimumLongitude
+MaximumLongitude
+UpperLeftCornerX
+UpperLeftCornerY
+PixelResolution
+Scale
+TrueScaleLatitude
+LineProjectionOffset
+SampleProjectionOffset
diff --git a/isis/appdata/labels/pdsExportAllMapping.pft b/isis/appdata/labels/pdsExportAllMapping.pft
new file mode 100644
index 0000000000..3039ed2c41
--- /dev/null
+++ b/isis/appdata/labels/pdsExportAllMapping.pft
@@ -0,0 +1,30 @@
+
+^DATA_SET_MAP_PROJECTION = String
+NOT_APPLICABLE_CONSTANT = Integer
+MAP_PROJECTION_TYPE = String
+PROJECTION_LATITUDE_TYPE = Enum
+A_AXIS_RADIUS = Real
+B_AXIS_RADIUS = Real
+C_AXIS_RADIUS = Real
+FIRST_STANDARD_PARALLEL = Real
+SECOND_STANDARD_PARALLEL = Real
+COORDINATE_SYSTEM_NAME = Enum
+POSITIVE_LONGITUDE_DIRECTION = Enum
+KEYWORD_LATITUDE_TYPE = Enum
+CENTER_LATITUDE = Real
+CENTER_LONGITUDE = Real
+REFERENCE_LATITUDE = Real
+REFERENCE_LONGITUDE = Real
+LINE_FIRST_PIXEL = Integer
+LINE_LAST_PIXEL = Integer
+SAMPLE_FIRST_PIXEL = Integer
+SAMPLE_LAST_PIXEL = Integer
+MAP_PROJECTION_ROTATION = Real
+MAP_RESOLUTION = Real
+MAP_SCALE = Real
+MAXIMUM_LATITUDE = Real
+MINIMUM_LATITUDE = Real
+LINE_PROJECTION_OFFSET = Real
+SAMPLE_PROJECTION_OFFSET = Real
+EASTERNMOST_LONGITUDE = Real
+WESTERNMOST_LONGITUDE = Real
diff --git a/isis/appdata/maps/DELETEME.txt b/isis/appdata/maps/DELETEME.txt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/isis/appdata/maps/ellipsoidtransverseazimuthal.map b/isis/appdata/maps/ellipsoidtransverseazimuthal.map
new file mode 100644
index 0000000000..bd11c8e0e1
--- /dev/null
+++ b/isis/appdata/maps/ellipsoidtransverseazimuthal.map
@@ -0,0 +1,48 @@
+#****************************************************************************
+# This is a map template file for the upturned ellipsoid transverse azimuthal
+# projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The upturned ellipsoid transverse azimuthal projection has
+# two required parameters: CenterLongitude and CenterLatitude
+# which you must uncomment and supply.
+#
+# If the CenterLongitude is not entered, a default of 0.0 will be used.
+# The MinimumLongitude and MaximumLongitude must be within 90 degrees
+# of the CenterLongitude.
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = UpturnedEllipsoidTransverseAzimuthal
+
+# CenterLatitude = 0.0
+# CenterLongitude = 180.0
+
+# TargetName = ITOKAWA
+# EquatorialRadius = 274.0
+# PolarRadius = 138.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = -90.0
+# MaximumLatitude = 90.0
+# MinimumLongitude = 100.0
+# MaximumLongitude = 230.0
+
+# PixelResolution = 1.07
+
+End_Group
+
+
+
+
diff --git a/isis/appdata/maps/equirectangular.map b/isis/appdata/maps/equirectangular.map
new file mode 100644
index 0000000000..bed67dd029
--- /dev/null
+++ b/isis/appdata/maps/equirectangular.map
@@ -0,0 +1,38 @@
+#****************************************************************************
+# This is a map template file for the equirectangular projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The equirectangular projection has two required parameters CenterLatitude
+# and CenterLongitude. If not uncommented in this file programs usually
+# compute them to be the average of the latitude/longitude range.
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = Equirectangular
+# CenterLatitude = 0.0
+# CenterLongitude = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/lambertazimuthalequalarea.map b/isis/appdata/maps/lambertazimuthalequalarea.map
new file mode 100644
index 0000000000..9836278ca1
--- /dev/null
+++ b/isis/appdata/maps/lambertazimuthalequalarea.map
@@ -0,0 +1,38 @@
+#****************************************************************************
+# This is a map template file for the Lambert azimuthal equal-area projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The Lambert azimuthal equal-area projection has two required parameters:
+# CenterLatitude and CenterLongitude
+# If not uncommented in this file, these will usually be computed by programs
+# to be the average of the latitude and longitude ranges, respectively.
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = LambertAzimuthalEqualArea
+# CenterLatitude = 0.0
+# CenterLongitude = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/lambertconformal.map b/isis/appdata/maps/lambertconformal.map
new file mode 100644
index 0000000000..4ee0302b3a
--- /dev/null
+++ b/isis/appdata/maps/lambertconformal.map
@@ -0,0 +1,57 @@
+#****************************************************************************
+# This is a map template file for the lambert conformal projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The lambert conformal projection has four required parameters.
+# Two, CenterLatitude and CenterLongitude, if not uncommented in this
+# file will usually be computed by programs to be the average of the
+# latitude/longitude range.
+#
+# The third and fourth parameters are the standard parallels which
+# you must supply by uncommenting and adding a number
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = LambertConformal
+# CenterLatitude = 0.0
+# CenterLongitude = 0.0
+# Earth (ographic)
+# FirstStandardParallel = 33.0
+# SecondStandardParallel = 45.0
+
+# Mars (ographic)
+# FirstStandardParallel = 35.83
+# SecondStandardParallel = 59.17
+
+# Venus
+# FirstStandardParallel = 34.0
+# SecondStandardParallel = 73.0
+
+# Ganymede & Callisto
+# FirstStandardParallel = 30.0
+# SecondStandardParallel = 58.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/mercator.map b/isis/appdata/maps/mercator.map
new file mode 100644
index 0000000000..fe435f0c95
--- /dev/null
+++ b/isis/appdata/maps/mercator.map
@@ -0,0 +1,38 @@
+#****************************************************************************
+# This is a map template file for the mercator projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The mercator projection has two required parameters CenterLatitude
+# and CenterLongitude. If not uncommented in this file programs usually
+# compute them to be the average of the latitude/longitude range.
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = Mercator
+# CenterLatitude = 0.0
+# CenterLongitude = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/mollweide.map b/isis/appdata/maps/mollweide.map
new file mode 100644
index 0000000000..aae2a3c754
--- /dev/null
+++ b/isis/appdata/maps/mollweide.map
@@ -0,0 +1,36 @@
+#****************************************************************************
+# This is a map template file for the Mollweide projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The Mollweide projection has two required parameters: CenterLongitude
+# and EquatorialRadius.
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = Mollweide
+# CenterLongitude = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/obliquecylindrical.map b/isis/appdata/maps/obliquecylindrical.map
new file mode 100644
index 0000000000..de6d810830
--- /dev/null
+++ b/isis/appdata/maps/obliquecylindrical.map
@@ -0,0 +1,39 @@
+#****************************************************************************
+# This is a map template file for the oblique cylindrical projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The oblique cylindricalprojection has three required parameters
+# PoleLatitude, PoleLongitude, and PoleRotation which you must uncomment
+# and supply
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = ObliqueCylindrical
+# PoleLatitude = 0.0
+# PoleLongitude = 0.0
+# PoleRotation = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021
+# Scale = 512.0
+End_Group
diff --git a/isis/appdata/maps/orthographic.map b/isis/appdata/maps/orthographic.map
new file mode 100644
index 0000000000..6882d50e7e
--- /dev/null
+++ b/isis/appdata/maps/orthographic.map
@@ -0,0 +1,38 @@
+#****************************************************************************
+# This is a map template file for the orthographic projection.
+#
+# Most of the parameters are commented (#) which means a program will try
+# to determine a good value. For example, a program will look at cube
+# labels to determine the target name and then read system radii values.
+#
+# If you want to use something other than a system default uncomment the
+# approriate line and give the parameter your value. For example,
+# PixelResolution = 10
+#
+# The orthographic projection has two required parameters CenterLatitude
+# and CenterLongitude. If not uncommented in this file programs usually
+# compute them to be the average of the latitude/longitude range.
+#
+#****************************************************************************
+
+Group = Mapping
+ ProjectionName = Orthographic
+# CenterLatitude = 0.0
+# CenterLongitude = 0.0
+
+# TargetName = Mars
+# EquatorialRadius = 3396190.0
+# PolarRadius = 3376200.0
+
+# LatitudeType = Planetocentric
+# LongitudeDirection = PositiveEast
+# LongitudeDomain = 360
+
+# MinimumLatitude = 47.431079407022
+# MaximumLatitude = 49.323205331047
+# MinimumLongitude = 276.4825037824
+# MaximumLongitude = 279.27207041615
+
+# PixelResolution = 115.77089360021