7#include "ProcessExportPds4.h"
13#include <QDomDocument>
15#include <QRegularExpression>
18#include "Application.h"
20#include "IException.h"
21#include "Projection.h"
22#include "ProjectionFactory.h"
24#include "PvlToXmlTranslationManager.h"
43 qSetGlobalQHashSeed(0);
49 QString xmlVersion =
"version=\"1.0\" encoding=\"utf-8\"";
50 QDomProcessingInstruction xmlHeader =
51 m_domDoc->createProcessingInstruction(
"xml", xmlVersion);
55 m_schemaLocation =
"http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1B00.xsd";
58 xmlModel +=
"href=\"http://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1B00.sch\" ";
59 xmlModel +=
"schematypens=\"http://purl.oclc.org/dsdl/schematron\"";
60 QDomProcessingInstruction header =
61 m_domDoc->createProcessingInstruction(
"xml-model", xmlModel);
110 QString msg(
"Must set an input cube before creating a PDS4 label.");
113 if (
m_domDoc->documentElement().isNull()) {
114 QDomElement root =
m_domDoc->createElement(
"Product_Observational");
115 root.setAttribute(
"xmlns",
"http://pds.nasa.gov/pds4/pds/v1");
116 root.setAttribute(
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
117 root.setAttribute(
"xsi:schemaLocation",
118 "http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1");
128 QString msg =
"Unable to translate and export identification information.";
137 QString msg =
"Unable to translate and export instrument information.";
148 QString msg =
"Unable to translate and export display settings.";
160 QString msg =
"Unable to translate and export spectral information.";
172 QString msg =
"Unable to translate and export mapping group.";
181 QString msg =
"Unable to translate and export standard image information.";
195 if (inputLabel->findObject(
"IsisCube").hasGroup(
"Instrument")) {
198 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportInstrument.trn";
203 QDomElement obsAreaNode =
m_domDoc->documentElement().firstChildElement(
"Observation_Area");
205 if ( !obsAreaNode.isNull() ) {
208 QDomElement timeNode = obsAreaNode.firstChildElement(
"Time_Coordinates");
209 if (!timeNode.isNull()) {
210 QDomElement startTime = timeNode.firstChildElement(
"start_date_time");
211 if (startTime.text() ==
"") {
212 startTime.setAttribute(
"xsi:nil",
"true");
215 QString timeValue = startTime.text();
218 QDomElement stopTime = timeNode.firstChildElement(
"stop_date_time");
219 if (stopTime.text() ==
"") {
220 stopTime.setAttribute(
"xsi:nil",
"true");
223 QString timeValue = stopTime.text();
228 QDomElement obsSysNode = obsAreaNode.firstChildElement(
"Observing_System");
229 if ( !obsSysNode.isNull() ) {
230 QString instrumentName;
231 QString spacecraftName;
232 QDomElement obsSysCompNode = obsSysNode.firstChildElement(
"Observing_System_Component");
233 while ( !obsSysCompNode.isNull()) {
234 QDomElement compTypeNode = obsSysCompNode.firstChildElement(
"type");
235 if ( compTypeNode.text().compare(
"Spacecraft") == 0 ) {
236 QString componentName = obsSysCompNode.firstChildElement(
"name").text();
237 if (QString::compare(componentName,
"TBD", Qt::CaseInsensitive) != 0) {
238 spacecraftName = componentName;
241 else if ( compTypeNode.text().compare(
"Instrument") == 0 ) {
242 QString componentName = obsSysCompNode.firstChildElement(
"name").text();
243 if (QString::compare(componentName,
"TBD", Qt::CaseInsensitive) != 0) {
244 instrumentName = componentName;
247 obsSysCompNode = obsSysCompNode.nextSiblingElement(
"Observing_System_Component");
249 QDomElement combinedNode =
m_domDoc->createElement(
"name");
250 QString combinedValue =
"TBD";
251 if ( !instrumentName.isEmpty() && !spacecraftName.isEmpty() ) {
252 combinedValue = spacecraftName +
" " + instrumentName;
254 combinedNode.appendChild(
m_domDoc->createTextNode(combinedValue) );
255 obsSysNode.insertBefore( combinedNode, obsSysNode.firstChild() );
260 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportTargetFromInstrument.trn";
265 QDomElement targetIdNode = obsAreaNode.firstChildElement(
"Target_Identification");
266 obsAreaNode.insertAfter(targetIdNode, obsAreaNode.firstChildElement(
"Observing_System"));
268 else if (inputLabel->findObject(
"IsisCube").hasGroup(
"Mapping")) {
270 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportTargetFromMapping.trn";
285 QDomElement obsAreaNode =
m_domDoc->documentElement().firstChildElement(
"Observation_Area");
286 if ( !obsAreaNode.isNull() ) {
289 QDomElement timeNode = obsAreaNode.firstChildElement(
"Time_Coordinates");
290 if (!timeNode.isNull()) {
291 QDomElement startTime = timeNode.firstChildElement(
"start_date_time");
292 if (startTime.text() ==
"") {
293 startTime.setAttribute(
"xsi:nil",
"true");
296 QString timeValue = startTime.text();
297 if (!timeValue.contains(
"Z")) {
302 QDomElement stopTime = timeNode.firstChildElement(
"stop_date_time");
303 if (stopTime.text() ==
"") {
304 stopTime.setAttribute(
"xsi:nil",
"true");
307 QString timeValue = stopTime.text();
308 if (!timeValue.contains(
"Z")) {
313 xmlPath <<
"Product_Observational"
314 <<
"Observation_Area"
317 <<
"geom:Geometry_Orbiter"
318 <<
"geom:geometry_reference_time_utc";
320 QDomElement baseElement =
m_domDoc->documentElement();
321 QDomElement geomRefTime =
getElement(xmlPath, baseElement);
322 if (geomRefTime.text() ==
"") {
323 geomRefTime.setAttribute(
"xsi:nil",
"true");
326 QString timeValue = geomRefTime.text();
330 xmlPath <<
"Product_Observational"
331 <<
"Observation_Area"
334 <<
"geom:Image_Display_Geometry"
335 <<
"geom:Object_Orientation_North_East"
336 <<
"geom:east_azimuth";
337 QDomElement eastAzimuth =
getElement(xmlPath, baseElement);
338 if (eastAzimuth.text() !=
"") {
343 QDomElement investigationAreaNode = obsAreaNode.firstChildElement(
"Investigation_Area");
344 obsAreaNode.insertAfter(investigationAreaNode, obsAreaNode.firstChildElement(
"Time_Coordinates"));
346 QDomElement obsSystemNode = obsAreaNode.firstChildElement(
"Observing_System");
347 obsAreaNode.insertAfter(obsSystemNode, obsAreaNode.firstChildElement(
"Investigation_Area"));
349 QDomElement targetIdNode = obsAreaNode.firstChildElement(
"Target_Identification");
350 obsAreaNode.insertAfter(targetIdNode, obsAreaNode.firstChildElement(
"Observing_System"));
352 QDomElement missionAreaNode = obsAreaNode.firstChildElement(
"Mission_Area");
353 obsAreaNode.insertAfter(missionAreaNode, obsAreaNode.firstChildElement(
"Target_Identification"));
355 QDomElement disciplineAreaNode = obsAreaNode.firstChildElement(
"Discipline_Area");
356 obsAreaNode.insertAfter(disciplineAreaNode, obsAreaNode.firstChildElement(
"Mission_Area"));
359 QDomElement identificationAreaNode =
m_domDoc->documentElement().firstChildElement(
"Identification_Area");
360 if ( !identificationAreaNode.isNull() ) {
361 QDomElement aliasListNode = identificationAreaNode.firstChildElement(
"Alias_List");
362 identificationAreaNode.insertAfter(aliasListNode, identificationAreaNode.firstChildElement(
"product_class"));
366 QDomElement referenceListNode =
m_domDoc->documentElement().firstChildElement(
"Reference_List");
367 if ( !referenceListNode.isNull() && !identificationAreaNode.isNull() ) {
368 m_domDoc->documentElement().insertAfter(referenceListNode, obsAreaNode);
371 QDomElement fileAreaObservationalNode =
m_domDoc->documentElement().firstChildElement(
"File_Area_Observational");
372 QDomElement array2DImageNode = fileAreaObservationalNode.firstChildElement(
"Array_2D_Image");
373 if ( !array2DImageNode.isNull() ) {
374 QDomElement descriptionNode = array2DImageNode.firstChildElement(
"description");
375 array2DImageNode.insertAfter(descriptionNode, array2DImageNode.firstChildElement(
"axis_index_order"));
408 m_lid = lid.toLower();
465 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportIdentificationArea.trn";
469 if (
m_lid.isEmpty()) {
470 m_lid =
"urn:nasa:pds:TBD:TBD:TBD";
473 QDomElement identificationElement;
475 identificationPath.append(
"Product_Observational");
476 identificationPath.append(
"Identification_Area");
478 identificationElement =
getElement(identificationPath);
479 if( identificationElement.isNull() ) {
484 QString msg =
"Could not find Identification_Area element "
485 "to add modification history under.";
489 QDomElement lidElement = identificationElement.firstChildElement(
"logical_identifier");
493 QDomElement versionElement = identificationElement.firstChildElement(
"version_id");
498 QDomElement titleElement = identificationElement.firstChildElement(
"title");
505 QRegularExpression versionRegex(
" \\| \\d{4}\\-\\d{2}\\-\\d{2}");
506 QString historyDescription =
"Created PDS4 output product from ISIS cube with the "
508 +
" application from ISIS version "
511 QRegularExpression dateRegex(
"T\\d{2}:\\d{2}:\\d{2}");
524 "PDS4_DISP_1B00.xsd",
526 "http://pds.nasa.gov/pds4/disp/v1");
530 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportDisplaySettings.trn";
542 if ( !inputLabel->findObject(
"IsisCube").hasGroup(
"BandBin") )
return;
545 "PDS4_IMG_1A10_1510.xsd",
547 "http://pds.nasa.gov/pds4/img/v1");
558 "http://pds.nasa.gov/pds4/sp/v1");
573 QString translationFile =
"$ISISROOT/appdata/translations/";
574 translationFile +=
"pds4ExportBandBinImage.trn";
575 FileName translationFileName(translationFile);
585 QString translationFile =
"$ISISROOT/appdata/translations/";
586 translationFile +=
"pds4ExportBandBinSpectrumUniform.trn";
587 FileName translationFileName(translationFile);
591 PvlGroup bandBinGroup = inputLabel.findObject(
"IsisCube").findGroup(
"BandBin");
594 xmlPath <<
"Product_Observational"
595 <<
"Observation_Area"
597 <<
"sp:Spectral_Characteristics";
598 QDomElement baseElement =
m_domDoc->documentElement();
599 QDomElement spectralCharElement =
getElement(xmlPath, baseElement);
606 if (bandBinGroup.hasKeyword(
"Center")) {
607 center = bandBinGroup[
"Center"];
609 else if (bandBinGroup.hasKeyword(
"FilterCenter")) {
610 center = bandBinGroup[
"FilterCenter"];
613 QString msg =
"Unable to translate BandBin info for BinSetSpectrum. "
614 "Translation for PDS4 required value [center_value] not found.";
618 if (bandBinGroup.hasKeyword(
"Width")) {
619 width = bandBinGroup[
"Width"];
621 else if (bandBinGroup.hasKeyword(
"FilterWidth")) {
622 width = bandBinGroup[
"FilterWidth"];
625 QString msg =
"Unable to translate BandBin info for BinSetSpectrum. "
626 "Translation for PDS4 required value [bin_width] not found.";
630 QString units = center.
unit();
632 if (!width.
unit().isEmpty() ) {
633 if (units.isEmpty()) {
634 units = width.
unit();
636 if (units.compare(width.
unit(), Qt::CaseInsensitive) != 0) {
637 QString msg =
"Unable to translate BandBin info for BinSetSpectrum. "
638 "Unknown or unmatching units for [center_value] and [bin_width].";
644 if (bandBinGroup.hasKeyword(
"OriginalBand")) {
645 originalBand = bandBinGroup[
"OriginalBand"];
648 if (bandBinGroup.hasKeyword(
"Name")) {
649 name = bandBinGroup[
"Name"];
651 else if (bandBinGroup.hasKeyword(
"FilterName")) {
652 name = bandBinGroup[
"FilterName"];
654 else if (bandBinGroup.hasKeyword(
"FilterId")) {
655 name = bandBinGroup[
"FilterId"];
658 if (bandBinGroup.hasKeyword(
"Number")) {
659 number = bandBinGroup[
"Number"];
661 else if (bandBinGroup.hasKeyword(
"FilterNumber")) {
662 number = bandBinGroup[
"FilterNumber"];
665 QDomElement axisBinSetElement = spectralCharElement.firstChildElement(
"sp:Axis_Bin_Set");
666 if (axisBinSetElement.isNull()) {
667 axisBinSetElement =
m_domDoc->createElement(
"sp:Axis_Bin_Set");
668 spectralCharElement.appendChild(axisBinSetElement);
670 int bands = (int)inputLabel.findObject(
"IsisCube")
672 .findGroup(
"Dimensions")
673 .findKeyword(
"Bands");
675 for (
int i = 0; i < bands; i++) {
677 QDomElement bin =
m_domDoc->createElement(
"sp:Bin");
678 axisBinSetElement.appendChild(bin);
680 QDomElement binSequenceNumber =
m_domDoc->createElement(
"sp:bin_sequence_number");
682 bin.appendChild(binSequenceNumber);
685 QDomElement centerValue =
m_domDoc->createElement(
"sp:center_value");
687 bin.appendChild(centerValue);
689 QDomElement binWidth =
m_domDoc->createElement(
"sp:bin_width");
690 if (width.
size() == bands) {
696 bin.appendChild(binWidth);
698 QDomElement originalBinNumber =
m_domDoc->createElement(
"sp:original_bin_number");
699 if (originalBand.size() > 0) {
701 bin.appendChild(originalBinNumber);
704 if (name.
size() > 0 || number.size() > 0) {
705 QDomElement filter =
m_domDoc->createElement(
"sp:Filter");
706 bin.appendChild(filter);
707 if (name.
size() > 0) {
708 QDomElement filterName =
m_domDoc->createElement(
"sp:filter_name");
710 filter.appendChild(filterName);
712 if (number.size() > 0) {
713 QDomElement filterNumber=
m_domDoc->createElement(
"sp:filter_number");
715 filter.appendChild(filterNumber);
727 QString translationFile =
"$ISISROOT/appdata/translations/";
728 translationFile +=
"pds4ExportBandBinSpectrumBinSet.trn";
729 FileName translationFileName(translationFile);
733 PvlGroup bandBinGroup = inputLabel.findObject(
"IsisCube").findGroup(
"BandBin");
736 xmlPath <<
"Product_Observational"
737 <<
"Observation_Area"
739 <<
"sp:Spectral_Characteristics";
740 QDomElement baseElement =
m_domDoc->documentElement();
741 QDomElement spectralCharElement =
getElement(xmlPath, baseElement);
762 if (bandBinGroup.hasKeyword(
"FilterCenter")) {
763 center = bandBinGroup[
"FilterCenter"];
765 else if (bandBinGroup.hasKeyword(
"Center")) {
766 center = bandBinGroup[
"Center"];
769 QString msg =
"Unable to translate BandBin info for UniformlySpacedSpectrum. "
770 "Translation for PDS4 required value [last_center_value] not found.";
773 QString lastCenter = center[center.
size() - 1];
775 QDomElement axisBinSetElement = spectralCharElement.firstChildElement(
"sp:Axis_Uniformly_Sampled");
776 if (axisBinSetElement.isNull()) {
777 axisBinSetElement =
m_domDoc->createElement(
"sp:Axis_Uniformly_Sampled");
778 spectralCharElement.appendChild(axisBinSetElement);
781 QDomElement lastCenterElement =
m_domDoc->createElement(
"sp:last_center_value");
783 spectralCharElement.appendChild(lastCenterElement);
804 QString imageObject =
"";
806 QString translationFile =
"$ISISROOT/appdata/translations/pds4Export";
808 int bands = (int)inputLabel->
findObject(
"IsisCube")
810 .findGroup(
"Dimensions")
811 .findKeyword(
"Bands");
813 imageObject =
"Array_3D_Image";
816 imageObject =
"Array_2D_Image";
818 translationFile += QString(imageObject).remove(
'_');
821 imageObject =
"Array_3D_Spectrum";
822 translationFile += QString(imageObject).remove(
'_');
824 translationFile +=
"Uniform";
827 translationFile +=
"BinSet";
830 translationFile +=
".trn";
831 FileName translationFileName(translationFile);
836 QDomElement rootElement =
m_domDoc->documentElement();
837 QDomElement fileAreaObservationalElement =
838 rootElement.firstChildElement(
"File_Area_Observational");
842 double multiplier = 1.0;
843 double outputMin, outputMax;
859 multiplier = (inputMax - inputMin) / (outputMax - outputMin);
860 base = inputMin - multiplier * outputMin;
863 if (!fileAreaObservationalElement.isNull()) {
864 QDomElement arrayImageElement =
865 fileAreaObservationalElement.firstChildElement(imageObject);
866 if (!arrayImageElement.isNull()) {
871 QDomElement axisArrayElement = arrayImageElement.firstChildElement(
"Axis_Array");
872 while( !axisArrayElement.isNull() ) {
873 QDomElement axisNameElement = axisArrayElement.firstChildElement(
"axis_name");
874 axisArrayElement.insertBefore(axisNameElement,
875 axisArrayElement.firstChildElement(
"elements"));
876 axisArrayElement = axisArrayElement.nextSiblingElement(
"Axis_Array");
879 QDomElement elementArrayElement =
m_domDoc->createElement(
"Element_Array");
880 arrayImageElement.insertBefore(elementArrayElement,
881 arrayImageElement.firstChildElement(
"Axis_Array"));
883 QDomElement dataTypeElement =
m_domDoc->createElement(
"data_type");
886 elementArrayElement.appendChild(dataTypeElement);
888 QDomElement scalingFactorElement =
m_domDoc->createElement(
"scaling_factor");
891 elementArrayElement.appendChild(scalingFactorElement);
893 QDomElement offsetElement =
m_domDoc->createElement(
"value_offset");
896 elementArrayElement.appendChild(offsetElement);
900 QDomElement specialConstantElement =
m_domDoc->createElement(
"Special_Constants");
901 arrayImageElement.insertAfter(specialConstantElement,
902 arrayImageElement.lastChildElement(
"Axis_Array"));
906 { QDomElement nullElement =
m_domDoc->createElement(
"missing_constant");
908 specialConstantElement.appendChild(nullElement);
910 QDomElement highInstrumentSatElement =
m_domDoc->createElement(
"high_instrument_saturation");
912 specialConstantElement.appendChild(highInstrumentSatElement);
914 QDomElement highRepresentationSatElement =
m_domDoc->createElement(
"high_representation_saturation");
916 specialConstantElement.appendChild(highRepresentationSatElement);
918 QDomElement lowInstrumentSatElement =
m_domDoc->createElement(
"low_instrument_saturation");
920 specialConstantElement.appendChild(lowInstrumentSatElement);
922 QDomElement lowRepresentationSatElement =
m_domDoc->createElement(
"low_representation_saturation");
924 specialConstantElement.appendChild(lowRepresentationSatElement);
928 { QDomElement nullElement =
m_domDoc->createElement(
"missing_constant");
930 specialConstantElement.appendChild(nullElement);
932 QDomElement highInstrumentSatElement =
m_domDoc->createElement(
"high_instrument_saturation");
934 specialConstantElement.appendChild(highInstrumentSatElement);
936 QDomElement highRepresentationSatElement =
m_domDoc->createElement(
"high_representation_saturation");
938 specialConstantElement.appendChild(highRepresentationSatElement);
940 QDomElement lowInstrumentSatElement =
m_domDoc->createElement(
"low_instrument_saturation");
942 specialConstantElement.appendChild(lowInstrumentSatElement);
944 QDomElement lowRepresentationSatElement =
m_domDoc->createElement(
"low_representation_saturation");
946 specialConstantElement.appendChild(lowRepresentationSatElement);
950 { QDomElement nullElement =
m_domDoc->createElement(
"missing_constant");
952 specialConstantElement.appendChild(nullElement);
954 QDomElement highInstrumentSatElement =
m_domDoc->createElement(
"high_instrument_saturation");
956 specialConstantElement.appendChild(highInstrumentSatElement);
958 QDomElement highRepresentationSatElement =
m_domDoc->createElement(
"high_representation_saturation");
960 specialConstantElement.appendChild(highRepresentationSatElement);
962 QDomElement lowInstrumentSatElement =
m_domDoc->createElement(
"low_instrument_saturation");
964 specialConstantElement.appendChild(lowInstrumentSatElement);
966 QDomElement lowRepresentationSatElement =
m_domDoc->createElement(
"low_representation_saturation");
968 specialConstantElement.appendChild(lowRepresentationSatElement);
972 { QDomElement nullElement =
m_domDoc->createElement(
"missing_constant");
974 specialConstantElement.appendChild(nullElement);
976 QDomElement highInstrumentSatElement =
m_domDoc->createElement(
"high_instrument_saturation");
978 specialConstantElement.appendChild(highInstrumentSatElement);
980 QDomElement highRepresentationSatElement =
m_domDoc->createElement(
"high_representation_saturation");
982 specialConstantElement.appendChild(highRepresentationSatElement);
984 QDomElement lowInstrumentSatElement =
m_domDoc->createElement(
"low_instrument_saturation");
986 specialConstantElement.appendChild(lowInstrumentSatElement);
988 QDomElement lowRepresentationSatElement =
m_domDoc->createElement(
"low_representation_saturation");
990 specialConstantElement.appendChild(lowRepresentationSatElement);
1003 QDomElement descriptionElement =
m_domDoc->createElement(
"description");
1006 arrayImageElement.insertAfter(descriptionElement, arrayImageElement.lastChildElement());
1022 QDomElement root =
m_domDoc->documentElement();
1023 root.setAttribute(xmlns, xmlnsURI);
1047 xmlModel +=
"href=\"";
1048 xmlModel += xmlnsURI;
1051 xmlModel +=
"\" schematypens=\"http://purl.oclc.org/dsdl/schematron\"";
1052 QDomProcessingInstruction header =
1053 m_domDoc->createProcessingInstruction(
"xml-model", xmlModel);
1067 os <<
m_domDoc->toString() << endl;
1090 if (
m_domDoc->documentElement().isNull()) {
1091 QDomElement root =
m_domDoc->createElement(
"Product_Observational");
1092 root.setAttribute(
"xmlns",
"http://pds.nasa.gov/pds4/pds/v1");
1093 root.setAttribute(
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
1094 root.setAttribute(
"xsi:schemaLocation",
1095 "http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1");
1115 QString path(outputFile.originalPath());
1116 QString name(outputFile.baseName());
1117 QString labelName = path +
"/" + name +
".xml";
1120 QString imageName = outputFile.expanded();
1124 if (QString::compare(outputFile.extension(),
"xml", Qt::CaseInsensitive) == 0) {
1125 imageName = path +
"/" + name +
".img";
1128 QDomElement rootElement =
m_domDoc->documentElement();
1129 QDomElement fileAreaObservationalElement =
1130 rootElement.firstChildElement(
"File_Area_Observational");
1132 QDomElement fileElement =
m_domDoc->createElement(
"File");
1133 fileAreaObservationalElement.insertBefore(fileElement,
1134 fileAreaObservationalElement.firstChildElement());
1136 QDomElement fileNameElement =
m_domDoc->createElement(
"file_name");
1138 fileElement.appendChild(fileNameElement);
1144 ofstream outputLabel(labelName.toLatin1().data());
1146 outputLabel.close();
1148 ofstream outputImageFile(imageName.toLatin1().data());
1150 outputImageFile.close();
1168 if(inputLabel->hasObject(
"IsisCube") &&
1169 !(inputLabel->findObject(
"IsisCube").hasGroup(
"Mapping")))
return;
1173 "PDS4_CART_1900.xsd",
1175 "http://pds.nasa.gov/pds4/cart/v1");
1179 QString projName = proj->Name();
1182 "$ISISROOT/appdata/translations/pds4Export" + projName +
".trn");
1186 QString msg =
"Unable to export projection [" + projName +
"] to PDS4 product. " +
1187 "This projection is not supported in ISIS3.";
1193 xmlPath <<
"Product_Observational"
1194 <<
"Observation_Area"
1195 <<
"Discipline_Area"
1196 <<
"cart:Cartography"
1197 <<
"cart:Map_Projection"
1198 <<
"cart:Spatial_Reference_Information"
1199 <<
"cart:Horizontal_Coordinate_System_Definition"
1200 <<
"cart:Geodetic_Model";
1202 QDomElement baseElement =
m_domDoc->documentElement();
1203 QDomElement geodeticModelElement =
getElement(xmlPath, baseElement);
1204 QDomElement semiMajorRadElement = geodeticModelElement.firstChildElement(
"cart:semi_major_radius");
1205 if (!semiMajorRadElement.isNull()) {
1207 QString units = semiMajorRadElement.attribute(
"unit");
1208 if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) {
1211 double dValue =
toDouble(semiMajorRadElement.text());
1217 QDomElement semiMinorRadElement = geodeticModelElement.firstChildElement(
"cart:semi_minor_radius");
1218 if (!semiMinorRadElement.isNull()) {
1220 QString units = semiMinorRadElement.attribute(
"unit");
1221 if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) {
1223 double dValue =
toDouble(semiMinorRadElement.text());
1229 QDomElement polarRadElement = geodeticModelElement.firstChildElement(
"cart:polar_radius");
1230 if (!polarRadElement.isNull()) {
1231 QString units = polarRadElement.attribute(
"unit");
1232 if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) {
1234 double dValue =
toDouble(polarRadElement.text());
1240 PvlKeyword &isisLonDir = inputMapping.findKeyword(
"LongitudeDirection");
1241 QString lonDir = isisLonDir[0];
1242 lonDir = lonDir.toUpper();
1245 double maxLon, minLon, maxLat, minLat;
1246 InputCubes[0]->latLonRange(minLat, maxLat, minLon, maxLon);
1249 xmlPath <<
"Product_Observational"
1250 <<
"Observation_Area"
1251 <<
"Discipline_Area"
1252 <<
"cart:Cartography"
1253 <<
"cart:Spatial_Domain"
1254 <<
"cart:Bounding_Coordinates";
1255 QDomElement boundingCoordElement =
getElement(xmlPath, baseElement);
1256 QDomElement eastElement = boundingCoordElement.firstChildElement(
"cart:east_bounding_coordinate");
1257 QDomElement westElement = boundingCoordElement.firstChildElement(
"cart:west_bounding_coordinate");
1258 QDomElement northElement = boundingCoordElement.firstChildElement(
"cart:north_bounding_coordinate");
1259 QDomElement southElement = boundingCoordElement.firstChildElement(
"cart:south_bounding_coordinate");
1263 if(QString::compare(lonDir,
"PositiveEast", Qt::CaseInsensitive) == 0) {
1278 xmlPath <<
"Product_Observational"
1279 <<
"Observation_Area"
1280 <<
"Discipline_Area"
1281 <<
"cart:Cartography"
1282 <<
"cart:Spatial_Reference_Information"
1283 <<
"cart:Horizontal_Coordinate_System_Definition"
1285 <<
"cart:Map_Projection";
1288 QDomElement projectionElement =
getElement(xmlPath, baseElement);
1289 QDomElement tempElement = projectionElement.firstChildElement();
1290 QDomElement nameElement = tempElement.nextSiblingElement();
1292 QDomElement longitudeElement = nameElement.firstChildElement(
"cart:longitude_of_central_meridian");
1293 QDomElement originElement = nameElement.firstChildElement(
"cart:latitude_of_projection_origin");
1295 double longitudeElementValue = longitudeElement.text().toDouble();
1296 double originElementValue = originElement.text().toDouble();
1299 if (!longitudeElement.text().contains(
'.')) {
1300 QString toset1 = QString::number(longitudeElementValue,
'f', 1);
1304 if (!originElement.text().contains(
'.')) {
1305 QString toset2 = QString::number(originElementValue,
'f', 1);
1328 QDomElement baseElement = parent;
1329 if (baseElement.isNull()) {
1330 baseElement =
m_domDoc->documentElement();
1332 if (baseElement.isNull()) {
1333 QString msg =
"Unable to get element from empty XML document.";
1336 QString parentName = xmlPath[0];
1337 if (parentName != baseElement.tagName()) {
1338 QString msg =
"The tag name of the parent element passed in "
1339 "must be the first value in the given XML path.";
1342 for (
int i = 1; i < xmlPath.size(); i++) {
1343 QString elementName = xmlPath[i];
1344 QDomElement nextElement = baseElement.firstChildElement(elementName);
1345 baseElement = nextElement;
1360 QString pds4Type(
"UNK");
1362 pds4Type =
"UnsignedByte";
1365 pds4Type =
"UnsignedMSB2";
1368 pds4Type =
"UnsignedLSB2";
1371 pds4Type =
"SignedMSB2";
1374 pds4Type =
"SignedLSB2";
1377 pds4Type =
"IEEE754MSBSingle";
1380 pds4Type =
"IEEE754LSBSingle";
1383 QString msg =
"Unsupported PDS pixel type or sample size";
1401 QDomElement identificationElement;
1403 identificationPath.append(
"Product_Observational");
1404 identificationPath.append(
"Identification_Area");
1406 identificationElement =
getElement(identificationPath);
1407 if( identificationElement.isNull() ) {
1412 QString msg =
"Could not find Identification_Area element "
1413 "to add modification history under.";
1419 QDomElement historyElement = identificationElement.firstChildElement(
"Modification_History");
1420 if ( historyElement.isNull() ) {
1421 historyElement =
m_domDoc->createElement(
"Modification_History");
1422 identificationElement.insertAfter( historyElement,
1423 identificationElement.lastChildElement() );
1428 QDomElement detailElement =
m_domDoc->createElement(
"Modification_Detail");
1430 QDomElement modDateElement =
m_domDoc->createElement(
"modification_date");
1432 detailElement.appendChild(modDateElement);
1434 QDomElement versionIdElement =
m_domDoc->createElement(
"version_id");
1436 detailElement.appendChild(versionIdElement);
1438 QDomElement descriptionElement =
m_domDoc->createElement(
"description");
1440 detailElement.appendChild(descriptionElement);
1442 historyElement.insertAfter( detailElement,
1443 historyElement.lastChildElement() );
1467 configPvl.
read(transMapFile);
1470 QString msg =
"Failed to read unit translation config file [" + transMapFile +
"].";
1474 QMap<QString, QString> transMap;
1479 QString msg =
"Failed to load unit translation config file [" + transMapFile +
"].";
1489 QString msg =
"Failed to translate units with config file [" + transMapFile +
"].";
1506 QMap<QString, QString> transMap;
1507 for (
int i = 0; i < configPvl.objects(); i++) {
1509 for (
int j = 0; j < unitObject.groups(); j++) {
1510 PvlGroup unitGroup = unitObject.group(j);
1511 if (!unitGroup.hasKeyword(
"PDS4_Unit")) {
1512 QString msg =
"No PDS4 standard specified for for [" + unitGroup.
name() +
"]";
1518 transMap.insert(pds4Key[0].toLower(), pds4Key[0]);
1521 if (unitGroup.hasKeyword(
"ISIS_Units")) {
1522 PvlKeyword isisKey = unitGroup[
"ISIS_Units"];
1523 for (
int k = 0; k < isisKey.size() ; k++) {
1524 transMap.insert(isisKey[k].toLower(), pds4Key[0]);
1546 QDomElement childElement = parent.firstChildElement();
1548 while( !childElement.isNull() ) {
1549 if ( childElement.hasAttribute(
"unit") ) {
1550 QString originalUnit = childElement.attribute(
"unit");
1551 if ( transMap.contains( originalUnit.toLower() ) ) {
1552 childElement.setAttribute(
"unit", transMap.value( originalUnit.toLower() ) );
1555 QString msg =
"Could not translate unit [" + originalUnit +
"] to PDS4 format.";
1560 childElement = childElement.nextSiblingElement();
static QString DateTime(time_t *curtime=0)
Returns the date and time as a QString.
static QString Version()
The Isis Version for this application.
static QString Name()
Returns the name of the application.
File name manipulation and expansion.
QString baseName() const
Returns the name of the file without the path and without extensions.
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
@ Io
A type of error that occurred when performing an actual I/O operation.
double p_outputMinimum
Desired minimum pixel value in the Buffer.
double p_outputMaximum
Desired maximum pixel value in the Buffer.
std::vector< double > p_inputMaximum
Maximum pixel value in the input cube to be mapped to the maximum value in the Buffer.
virtual void StartProcess(void funct(Isis::Buffer &in))
This method invokes the process operation over a single input cube.
PixelType p_pixelType
The bits per pixel of the output image.
ByteOrder p_endianType
The byte order of the output file.
std::vector< double > p_inputMinimum
Minimum pixel value in the input cube to be mapped to the minimum value in the Buffer.
void StartProcess(std::ofstream &fout)
This method fills the image data of the PDS4 file using the parent class ProcessExport::StartProcess.
void setVersionId(QString versionId)
Allows mission specific programs to set version_id required for PDS4 labels.
void setImageType(ImageType imageType)
Create a standard PDS4 image label from the input cube.
void setLogicalId(QString lid)
Allows mission specific programs to set logical_identifier required for PDS4 labels.
QDomDocument * m_domDoc
XML label.
QString m_versionId
QString with specified version id.
void identificationArea()
This method writes the identification information to the PDS4 labels.
void translateBandBinSpectrumUniform(Pvl &inputLabel)
Export BandBin group for uniformly spaced 3D Spectral data format.
ProcessExportPds4()
Default Constructor - Set to default the data members.
QDomDocument & GetLabel()
Return the internalized PDS4 label.
void translateBandBinSpectrumBinSet(Pvl &inputLabel)
Export BandBin group for non-uniformly spaced 3D Spectral data format.
static void translateChildUnits(QDomElement parent, QMap< QString, QString > transMap)
Recursive method that will translate the "unit" attribute of any child elements of a given element.
void addHistory(QString description, QString date="tbd", QString version="1.0")
Add a modification history instance by adding a Modification_Detail entry to the Modification_History...
QDomElement getElement(QStringList xmlPath, QDomElement parent=QDomElement())
Convenience method to get an element given a path and its parent.
QString m_schemaLocation
QString with all schema locations required.
void setTitle(QString title)
Allows mission specific programs to set the title required for PDS4 labels.
~ProcessExportPds4()
Destructor.
void reorder()
This method reorders the existing m_domDoc to follow PDS4 standards and fixes time formatting if need...
void setSchemaLocation(QString schema)
Allows mission specific programs to use specified versions of dictionaries.
QString m_lid
QString with specified logical identifier.
static void translateUnits(QDomDocument &label, QString transMapFile="$ISISROOT/appdata/translations/pds4ExportUnits.pvl")
This function will go through an XML document and attempt to convert all "units" attributes to the ap...
ImageType m_imageType
Type of image data to be written.
void standardBandBin()
Export bandbin group to sp:Spectral Characteristics.
void addSchema(QString sch, QString xsd, QString xmlns, QString xmlnsURI)
Adds necessary information to the xml header for a pds4 class.
void translateBandBinImage(Pvl &inputLabel)
Export BandBin group for 2D or 3D Image format.
void fileAreaObservational()
Create and internalize an image output label from the input image.
QString m_title
QString with specified title.
void StandardAllMapping()
Create the standard keywords for the IMAGE_MAP_PROJECTION group in a PDS label.
void standardInstrument()
This method translates the information from the ISIS Instrument group to the PDS4 labels.
void setPixelDescription(QString description)
Sets the description string which describes the pixel vales in File_Area_Observational.
QString PDS4PixelType(PixelType pixelType, ByteOrder endianType)
Helper function for converting ISIS pixel type and byte order to a PDS4 data_type value.
QDomDocument & StandardPds4Label()
Create a standard PDS4 image label from the input cube.
QString m_pixelDescription
Description of pixel values.
void CreateImageLabel()
Creates a PDS4 label.
void displaySettings()
This method writes the display direction information to the PDS4 labels.
static QMap< QString, QString > createUnitMap(Pvl configPvl)
Helper function for creating the unit translation map from a PVL object.
void OutputLabel(std::ofstream &os)
Write the XML label to the supplied stream.
void WritePds4(QString outFile)
This method write out the labels and image data to the specified output file.
virtual void EndProcess()
End the processing sequence and cleans up by closing cubes, freeing memory, etc.
std::vector< Isis::Cube * > InputCubes
A vector of pointers to opened Cube objects.
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
Base class for Map Projections.
QString name() const
Returns the container name.
Contains multiple PvlContainers.
Container for cube-like labels.
void read(const QString &file)
Loads PVL information from a stream.
A single keyword-value pair.
int size() const
Returns the number of values stored in this keyword.
QString unit(const int index=0) const
Returns the units of measurement of the element of the array of values for the object at the specifie...
void clear()
Clears all values and units for this PvlKeyword object.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
PvlObject & object(const int index)
Return the object at the specified index.
@ Traverse
Search child objects.
Allows applications to translate simple text files.
static void resetElementValue(QDomElement &element, QString value, QString units="")
Reset the QDomElement's value, and units, if units != "".
static void setElementValue(QDomElement &element, QString value, QString units="")
Set the QDomElement's value, and units, if units != "".
ByteOrder
Tests the current architecture for byte order.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
double toDouble(const QString &string)
Global function to convert from a string to a double.
PixelType
Enumerations for Isis Pixel Types.
Namespace for the standard library.