Skip to content

Commit

Permalink
Update Hayabusa2 translation (DOI-USGS#5433)
Browse files Browse the repository at this point in the history
* Add spacecraft name trn

* Update changelog

* Added hyb2onc2isis test

---------

Co-authored-by: Kelvin Rodriguez <[email protected]>
  • Loading branch information
chkim-usgs and Kelvinrr authored Apr 5, 2024
1 parent 3fe2d96 commit da7d0e0
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 118 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ release.
- Added new option in `ctxcal` to use monthly computed flatfield files for "Frown" removal in CTX images. [#5338](https://github.com/DOI-USGS/ISIS3/pull/5338)
- CSMCamera can now read and use the body rotation from ALE produced ISDs [#5072](https://github.com/DOI-USGS/ISIS3/pull/5072)
- CSMSkyMap added to CSMCamera for use with local rover projections in ISIS [#5072](https://github.com/DOI-USGS/ISIS3/pull/5072)
- Added new Hayabusa2 translation for `SpacecraftName` to accept `HAYABUSA2` [#5395](https://github.com/DOI-USGS/ISIS3/issues/5395)
- Added ALLOWERROR parameter to campt [#5393](https://github.com/DOI-USGS/ISIS3/pull/5393)
- OSIRIS-REx Tagcams instrument support, tests, and test data added [#5424](https://github.com/DOI-USGS/ISIS3/issues/5424)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Group = SpacecraftName
InputPosition = FitsLabels
OutputName = SpacecraftName
OutputPosition = (Object, IsisCube, Group, Instrument)
Translation = (HAYABUSA-2, HAYABUSA2)
Translation = (*, *)
End_Group

Expand Down
136 changes: 136 additions & 0 deletions isis/src/hayabusa2/apps/hyb2onc2isis/hyb2onc2isis.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/** This is free and unencumbered software released into the public domain.
The authors of ISIS do not claim copyright on the contents of this file.
For more details about the LICENSE terms and the AUTHORS, you will
find files of those names at the top level of this repository. **/

/* SPDX-License-Identifier: CC0-1.0 */

#include <QString>

#include "FileName.h"
#include "iTime.h"
#include "OriginalLabel.h"
#include "ProcessImportFits.h"
#include "Pvl.h"
#include "PvlGroup.h"
#include "PvlKeyword.h"
#include "PvlObject.h"
#include "PvlToPvlTranslationManager.h"
#include "UserInterface.h"

using namespace std;

namespace Isis {

// Cube *outputCube = NULL;

void hyb2onc2isis(UserInterface &ui) {
ProcessImportFits importFits;
importFits.setFitsFile(FileName(ui.GetFileName("FROM")));
importFits.setProcessFileStructure(0);

CubeAttributeOutput &att = ui.GetOutputAttribute("TO");
Cube *outputCube = importFits.SetOutputCube(ui.GetCubeName("TO"), att);

// Get the directory where the Hayabusa translation tables are.
QString transDir = "$ISISROOT/appdata/translations/";

// Create a PVL to store the translated labels in
Pvl outputLabel;

// Get the FITS label
Pvl fitsLabel;
fitsLabel.addGroup(importFits.fitsImageLabel(0));

try {
fitsLabel.addGroup(importFits.extraFitsLabel(0));
}
catch (IException &e) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2/ONC label file.";
throw IException(e, IException::Unknown, msg, _FILEINFO_);
}

QString instid;
QString missid;
try {
instid = fitsLabel.findGroup("FitsLabels").findKeyword("INSTRUME")[0];
missid = fitsLabel.findGroup("FitsLabels").findKeyword ("SPCECRFT")[0];
}
catch (IException &e) {
QString msg = "Unable to read instrument ID, [INSTRUME], or spacecraft ID, [SPCECRFT], "
"from input file [" + FileName(ui.GetFileName("FROM")).expanded() + "]";
throw IException(e, IException::Io,msg, _FILEINFO_);
}

missid = missid.simplified().trimmed();
if ((QString::compare(missid, "HAYABUSA2", Qt::CaseInsensitive) != 0) && (QString::compare(missid, "HAYABUSA-2", Qt::CaseInsensitive) != 0)) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2 label file.";
throw IException(IException::Unknown, msg, _FILEINFO_);
}
instid = instid.simplified().trimmed();
if (QString::compare(instid, "Optical Navigation Camera", Qt::CaseInsensitive) != 0) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2/ONC label file.";
throw IException(IException::Unknown, msg, _FILEINFO_);
}

// Translate the Instrument group
FileName transFile(transDir + "Hayabusa2OncInstrument.trn");
PvlToPvlTranslationManager instrumentXlater (fitsLabel, transFile.expanded());
instrumentXlater.Auto(outputLabel);

// Update target if user specifies it
PvlGroup &instGrp = outputLabel.findGroup("Instrument",Pvl::Traverse);
QString target;
if (ui.WasEntered("TARGET")) {
instGrp["TargetName"] = ui.GetString("TARGET");
}
instGrp["ExposureDuration"].setUnits("seconds");
outputCube->putGroup(instGrp);

// Translate the BandBin group
transFile = transDir + "Hayabusa2OncBandBin.trn";
PvlToPvlTranslationManager bandBinXlater (fitsLabel, transFile.expanded());
bandBinXlater.Auto(outputLabel);
PvlGroup &bandGrp = outputLabel.findGroup("BandBin",Pvl::Traverse);
if (bandGrp.hasKeyword("Width")) { // if width exists, then so must center
bandGrp["Width"].setUnits("nanometers");
bandGrp["Center"].setUnits("nanometers");
}
outputCube->putGroup(outputLabel.findGroup("BandBin",Pvl::Traverse));

// Translate the Archive group
transFile = transDir + "Hayabusa2OncArchive.trn";
PvlToPvlTranslationManager archiveXlater (fitsLabel, transFile.expanded());
archiveXlater.Auto(outputLabel);
PvlGroup &archGrp = outputLabel.findGroup("Archive", Pvl::Traverse);
QString source = archGrp.findKeyword("SourceProductId")[0];
archGrp["SourceProductId"].setValue(FileName(source).baseName());

// Create YearDoy keyword in Archive group
iTime stime(outputLabel.findGroup("Instrument", Pvl::Traverse)["StartTime"][0]);
PvlKeyword yeardoy("YearDoy", toString(stime.Year()*1000 + stime.DayOfYear()));
archGrp.addKeyword(yeardoy);
outputCube->putGroup(archGrp);


// Create a Kernels group
transFile = transDir + "Hayabusa2OncKernels.trn";
PvlToPvlTranslationManager kernelsXlater(fitsLabel, transFile.expanded());
kernelsXlater.Auto(outputLabel);
outputCube->putGroup(outputLabel.findGroup("Kernels", Pvl::Traverse));

// Now write the FITS augmented label as the original label
// Save the input FITS label in the Cube original labels
OriginalLabel originalLabel(fitsLabel);
outputCube->write(originalLabel);

// Convert the image data
importFits.Progress()->SetText("Importing Hayabusa2 image");
importFits.StartProcess();
importFits.Finalize();
}
}
18 changes: 18 additions & 0 deletions isis/src/hayabusa2/apps/hyb2onc2isis/hyb2onc2isis.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef hyb2onc2isis_h
#define hyb2onc2isis_h

/** This is free and unencumbered software released into the public domain.
The authors of ISIS do not claim copyright on the contents of this file.
For more details about the LICENSE terms and the AUTHORS, you will
find files of those names at the top level of this repository. **/

/* SPDX-License-Identifier: CC0-1.0 */

#include "UserInterface.h"

namespace Isis {
extern void hyb2onc2isis(UserInterface &ui);
}

#endif
122 changes: 4 additions & 118 deletions isis/src/hayabusa2/apps/hyb2onc2isis/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,128 +8,14 @@ find files of those names at the top level of this repository. **/

#include "Isis.h"

#include <QString>

#include "FileName.h"
#include "iTime.h"
#include "OriginalLabel.h"
#include "ProcessImportFits.h"
#include "Pvl.h"
#include "PvlGroup.h"
#include "PvlKeyword.h"
#include "PvlObject.h"
#include "PvlToPvlTranslationManager.h"
#include "UserInterface.h"
#include "Application.h"
#include "hyb2onc2isis.h"

using namespace std;
using namespace Isis;

void IsisMain () {

ProcessImportFits importFits;
void IsisMain() {
UserInterface &ui = Application::GetUserInterface();
importFits.setFitsFile(FileName(ui.GetFileName("FROM")));
importFits.setProcessFileStructure(0);

Cube *outputCube = importFits.SetOutputCube("TO");

// Get the directory where the Hayabusa translation tables are.
QString transDir = "$ISISROOT/appdata/translations/";

// Create a PVL to store the translated labels in
Pvl outputLabel;

// Get the FITS label
Pvl fitsLabel;
fitsLabel.addGroup(importFits.fitsImageLabel(0));
try {
fitsLabel.addGroup(importFits.extraFitsLabel(0));
}
catch (IException &e) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2/ONC label file.";
throw IException(e, IException::Unknown, msg, _FILEINFO_);
}

QString instid;
QString missid;
try {
instid = fitsLabel.findGroup("FitsLabels").findKeyword("INSTRUME")[0];
missid = fitsLabel.findGroup("FitsLabels").findKeyword ("SPCECRFT")[0];
}
catch (IException &e) {
QString msg = "Unable to read instrument ID, [INSTRUME], or spacecraft ID, [SPCECRFT], "
"from input file [" + FileName(ui.GetFileName("FROM")).expanded() + "]";
throw IException(e, IException::Io,msg, _FILEINFO_);
}

missid = missid.simplified().trimmed();
if ((QString::compare(missid, "HAYABUSA2", Qt::CaseInsensitive) != 0) && (QString::compare(missid, "HAYABUSA-2", Qt::CaseInsensitive) != 0)) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2 label file.";
throw IException(IException::Unknown, msg, _FILEINFO_);
}
instid = instid.simplified().trimmed();
if (QString::compare(instid, "Optical Navigation Camera", Qt::CaseInsensitive) != 0) {
QString msg = "Input file [" + FileName(ui.GetFileName("FROM")).expanded() +
"] does not appear to be a Hayabusa2/ONC label file.";
throw IException(IException::Unknown, msg, _FILEINFO_);
}

// Translate the Instrument group
FileName transFile(transDir + "Hayabusa2OncInstrument.trn");
PvlToPvlTranslationManager instrumentXlater (fitsLabel, transFile.expanded());
instrumentXlater.Auto(outputLabel);

// Update target if user specifies it
PvlGroup &instGrp = outputLabel.findGroup("Instrument",Pvl::Traverse);
QString target;
if (ui.WasEntered("TARGET")) {
instGrp["TargetName"] = ui.GetString("TARGET");
}
instGrp["ExposureDuration"].setUnits("seconds");
outputCube->putGroup(instGrp);

// Translate the BandBin group
transFile = transDir + "Hayabusa2OncBandBin.trn";
PvlToPvlTranslationManager bandBinXlater (fitsLabel, transFile.expanded());
bandBinXlater.Auto(outputLabel);
PvlGroup &bandGrp = outputLabel.findGroup("BandBin",Pvl::Traverse);
if (bandGrp.hasKeyword("Width")) { // if width exists, then so must center
bandGrp["Width"].setUnits("nanometers");
bandGrp["Center"].setUnits("nanometers");
}
outputCube->putGroup(outputLabel.findGroup("BandBin",Pvl::Traverse));

// Translate the Archive group
transFile = transDir + "Hayabusa2OncArchive.trn";
PvlToPvlTranslationManager archiveXlater (fitsLabel, transFile.expanded());
archiveXlater.Auto(outputLabel);
PvlGroup &archGrp = outputLabel.findGroup("Archive", Pvl::Traverse);
QString source = archGrp.findKeyword("SourceProductId")[0];
archGrp["SourceProductId"].setValue(FileName(source).baseName());

// Create YearDoy keyword in Archive group
iTime stime(outputLabel.findGroup("Instrument", Pvl::Traverse)["StartTime"][0]);
PvlKeyword yeardoy("YearDoy", toString(stime.Year()*1000 + stime.DayOfYear()));
archGrp.addKeyword(yeardoy);
outputCube->putGroup(archGrp);


// Create a Kernels group
transFile = transDir + "Hayabusa2OncKernels.trn";
PvlToPvlTranslationManager kernelsXlater(fitsLabel, transFile.expanded());
kernelsXlater.Auto(outputLabel);
outputCube->putGroup(outputLabel.findGroup("Kernels", Pvl::Traverse));

// Now write the FITS augmented label as the original label
// Save the input FITS label in the Cube original labels
OriginalLabel originalLabel(fitsLabel);
outputCube->write(originalLabel);

// Convert the image data
importFits.Progress()->SetText("Importing Hayabusa2 image");
importFits.StartProcess();
importFits.Finalize();

hyb2onc2isis(ui);
}
77 changes: 77 additions & 0 deletions isis/tests/FunctionalTestsHyb2onc2isis.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include <QTemporaryDir>
#include <QFile>

#include "hyb2onc2isis.h"
#include "Pvl.h"
#include "PvlGroup.h"
#include "TestUtilities.h"
#include "Histogram.h"
#include "OriginalLabel.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

using namespace Isis;
using ::testing::HasSubstr;

static QString APP_XML = FileName("$ISISROOT/bin/xml/hyb2onc2isis.xml").expanded();

TEST(Hyb2onc2isis, Hyb2onc2isisTestDefault) {
QTemporaryDir prefix;
QString cubeFileName = prefix.path() + "/hyb2onc2isisTEMP.cub";
QVector<QString> args = {"from=data/hyb2onc2isis/hyb2_onc_20151203_000006_w2f_l2a.fit",
"to=" + cubeFileName };

UserInterface options(APP_XML, args);
try {
hyb2onc2isis(options);
}
catch (IException &e) {
FAIL() << "Unable to ingest HYB2ONC image: " << e.toString().toStdString().c_str() << std::endl;
}
Cube cube(cubeFileName);
Pvl *isisLabel = cube.label();

// Dimensions Group
ASSERT_EQ(cube.sampleCount(), 1024);
ASSERT_EQ(cube.lineCount(), 1024);
ASSERT_EQ(cube.bandCount(), 1);

// Pixels Group
ASSERT_EQ(PixelTypeName(cube.pixelType()), "Real");
ASSERT_EQ(ByteOrderName(cube.byteOrder()), "Lsb");
ASSERT_DOUBLE_EQ(cube.base(), 0.0);
ASSERT_DOUBLE_EQ(cube.multiplier(), 1.0);

// Instrument Group
PvlGroup &inst = isisLabel->findGroup("Instrument", Pvl::Traverse);
ASSERT_EQ(inst["SpacecraftName"][0].toStdString(), "HAYABUSA-2");
ASSERT_EQ(inst["InstrumentId"][0].toStdString(), "ONC-W2" );
ASSERT_EQ(inst["StartTime"][0].toStdString(), "2015-12-03T00:00:06.637" );
ASSERT_EQ(inst["StopTime"][0].toStdString(), "2015-12-03T00:00:06.641" );
ASSERT_EQ(inst["SpacecraftClockStartCount"][0].toStdString(), "1/1009473117" );
ASSERT_EQ(inst["TargetName"][0].toStdString(), "Earth" );

// Archive Group
PvlGroup &archive = isisLabel->findGroup("Archive", Pvl::Traverse);
ASSERT_EQ(archive["ProducerId"][0].toStdString(), "ISAS/JAXA" );
ASSERT_EQ(archive["FormatType"][0].toStdString(), "HAYABUSA2 IMAGE ONC L2a" );
ASSERT_EQ(archive["Contenttype"][0].toStdString(), "ONC-W2 NON SMEARCORRECTED");
ASSERT_EQ(archive["SourceProductId"][0].toStdString(), "hyb2_onc_20151203_000006_w2f_l2a" );

// Kernels Group
PvlGroup &kernel = isisLabel->findGroup("Kernels", Pvl::Traverse);
ASSERT_EQ(int(kernel["NaifFrameCode"]), -37120);

std::unique_ptr<Histogram> hist (cube.histogram());

ASSERT_NEAR(hist->Average(), 297.8918, .0001);
ASSERT_DOUBLE_EQ(hist->Sum(), 312362230);
ASSERT_EQ(hist->ValidPixels(), 1048576);
ASSERT_NEAR(hist->StandardDeviation(), 65.75840, .00001);

// check original label exists
Pvl ogLabel = cube.readOriginalLabel().ReturnLabels();
PvlGroup &fitsLabel = ogLabel.findGroup("FitsLabels", Pvl::Traverse);
ASSERT_EQ(fitsLabel["SPCECRFT"][0].toStdString(), "HAYABUSA2" );
}
61 changes: 61 additions & 0 deletions isis/tests/data/hyb2onc2isis/hyb2_onc_20151203_000006_w2f_l2a.fit

Large diffs are not rendered by default.

0 comments on commit da7d0e0

Please sign in to comment.