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"
35 ProcessExportPds4::ProcessExportPds4() {
41 m_imageType = StandardImage;
43 qSetGlobalQHashSeed(1031);
45 m_domDoc =
new QDomDocument(
"");
49 QString xmlVersion =
"version=\"1.0\" encoding=\"utf-8\"";
50 QDomProcessingInstruction xmlHeader =
51 m_domDoc->createProcessingInstruction(
"xml", xmlVersion);
52 m_domDoc->appendChild(xmlHeader);
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);
62 m_domDoc->appendChild(header);
71 ProcessExportPds4::~ProcessExportPds4() {
82 QDomDocument &ProcessExportPds4::StandardPds4Label() {
84 translateUnits(*m_domDoc);
94 void ProcessExportPds4::setImageType(ImageType imageType) {
95 m_imageType = imageType;
108 void ProcessExportPds4::CreateImageLabel() {
109 if (InputCubes.size() == 0) {
110 QString msg(
"Must set an input cube before creating a PDS4 label.");
111 throw IException(IException::Programmer, msg, _FILEINFO_);
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");
119 m_domDoc->appendChild(root);
125 identificationArea();
128 QString msg =
"Unable to translate and export identification information.";
129 throw IException(e, IException::Programmer, msg, _FILEINFO_);
134 standardInstrument();
137 QString msg =
"Unable to translate and export instrument information.";
138 throw IException(e, IException::Programmer, msg, _FILEINFO_);
148 QString msg =
"Unable to translate and export display settings.";
149 throw IException(e, IException::Programmer, msg, _FILEINFO_);
160 QString msg =
"Unable to translate and export spectral information.";
161 throw IException(e, IException::Programmer, msg, _FILEINFO_);
169 StandardAllMapping();
172 QString msg =
"Unable to translate and export mapping group.";
173 throw IException(e, IException::Programmer, msg, _FILEINFO_);
178 fileAreaObservational();
181 QString msg =
"Unable to translate and export standard image information.";
182 throw IException(e, IException::Programmer, msg, _FILEINFO_);
191 void ProcessExportPds4::standardInstrument() {
192 Pvl *inputLabel = InputCubes[0]->label();
195 if (inputLabel->
findObject(
"IsisCube").hasGroup(
"Instrument")) {
198 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportInstrument.trn";
200 instXlator.
Auto(*m_domDoc);
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();
216 PvlToXmlTranslationManager::resetElementValue(startTime, timeValue +
"Z");
218 QDomElement stopTime = timeNode.firstChildElement(
"stop_date_time");
219 if (stopTime.text() ==
"") {
220 stopTime.setAttribute(
"xsi:nil",
"true");
223 QString timeValue = stopTime.text();
224 PvlToXmlTranslationManager::resetElementValue(stopTime, timeValue +
"Z");
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";
262 targXlator.
Auto(*m_domDoc);
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";
272 targXlator.
Auto(*m_domDoc);
275 throw IException(IException::Unknown,
"Unable to find a target in input cube.", _FILEINFO_);
284 void ProcessExportPds4::reorder() {
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")) {
298 PvlToXmlTranslationManager::resetElementValue(startTime, timeValue +
"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")) {
309 PvlToXmlTranslationManager::resetElementValue(stopTime, timeValue +
"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();
327 PvlToXmlTranslationManager::resetElementValue(geomRefTime, timeValue +
"Z");
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() !=
"") {
339 PvlToXmlTranslationManager::resetElementValue(eastAzimuth, eastAzimuth.text(),
"deg");
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"));
407 void ProcessExportPds4::setLogicalId(QString lid) {
408 m_lid = lid.toLower();
425 void ProcessExportPds4::setVersionId(QString versionId) {
426 m_versionId = versionId;
440 void ProcessExportPds4::setTitle(QString title) {
453 void ProcessExportPds4::setSchemaLocation(QString schema) {
454 m_schemaLocation = schema;
462 void ProcessExportPds4::identificationArea() {
463 Pvl *inputLabel = InputCubes[0]->label();
465 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportIdentificationArea.trn";
467 xlator.
Auto(*m_domDoc);
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() ) {
480 throw IException(IException::Unknown,
"", _FILEINFO_);
484 QString msg =
"Could not find Identification_Area element "
485 "to add modification history under.";
486 throw IException(IException::Programmer, msg, _FILEINFO_);
489 QDomElement lidElement = identificationElement.firstChildElement(
"logical_identifier");
490 PvlToXmlTranslationManager::resetElementValue(lidElement, m_lid);
492 if (m_versionId !=
"") {
493 QDomElement versionElement = identificationElement.firstChildElement(
"version_id");
494 PvlToXmlTranslationManager::resetElementValue(versionElement, m_versionId);
498 QDomElement titleElement = identificationElement.firstChildElement(
"title");
499 PvlToXmlTranslationManager::resetElementValue(titleElement, m_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 "
509 + Application::Version().remove(versionRegex) +
".";
511 QRegularExpression dateRegex(
"T\\d{2}:\\d{2}:\\d{2}");
512 QString historyDate = Application::DateTime().remove(dateRegex);
513 addHistory(historyDescription, historyDate);
521 void ProcessExportPds4::displaySettings() {
523 addSchema(
"PDS4_DISP_1B00.sch",
524 "PDS4_DISP_1B00.xsd",
526 "http://pds.nasa.gov/pds4/disp/v1");
528 Pvl *inputLabel = InputCubes[0]->label();
530 translationFileName =
"$ISISROOT/appdata/translations/pds4ExportDisplaySettings.trn";
532 xlator.
Auto(*m_domDoc);
540 void ProcessExportPds4::standardBandBin() {
541 Pvl *inputLabel = InputCubes[0]->label();
542 if ( !inputLabel->
findObject(
"IsisCube").hasGroup(
"BandBin") )
return;
544 addSchema(
"PDS4_IMG_1A10_1510.sch",
545 "PDS4_IMG_1A10_1510.xsd",
547 "http://pds.nasa.gov/pds4/img/v1");
550 if (m_imageType == StandardImage) {
551 translateBandBinImage(*inputLabel);
555 addSchema(
"PDS4_SP_1100.sch",
558 "http://pds.nasa.gov/pds4/sp/v1");
559 if (m_imageType == UniformlySampledSpectrum) {
560 translateBandBinSpectrumUniform(*inputLabel);
562 else if (m_imageType == BinSetSpectrum) {
563 translateBandBinSpectrumBinSet(*inputLabel);
572 void ProcessExportPds4::translateBandBinImage(
Pvl &inputLabel) {
573 QString translationFile =
"$ISISROOT/appdata/translations/";
574 translationFile +=
"pds4ExportBandBinImage.trn";
575 FileName translationFileName(translationFile);
577 xlator.
Auto(*m_domDoc);
584 void ProcessExportPds4::translateBandBinSpectrumUniform(
Pvl &inputLabel) {
585 QString translationFile =
"$ISISROOT/appdata/translations/";
586 translationFile +=
"pds4ExportBandBinSpectrumUniform.trn";
587 FileName translationFileName(translationFile);
589 xlator.
Auto(*m_domDoc);
594 xmlPath <<
"Product_Observational"
595 <<
"Observation_Area"
597 <<
"sp:Spectral_Characteristics";
598 QDomElement baseElement = m_domDoc->documentElement();
599 QDomElement spectralCharElement = getElement(xmlPath, baseElement);
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.";
615 throw IException(IException::Programmer, msg, _FILEINFO_);
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.";
627 throw IException(IException::Programmer, msg, _FILEINFO_);
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].";
639 throw IException(IException::Programmer, msg, _FILEINFO_);
644 if (bandBinGroup.
hasKeyword(
"OriginalBand")) {
645 originalBand = bandBinGroup[
"OriginalBand"];
649 name = bandBinGroup[
"Name"];
651 else if (bandBinGroup.
hasKeyword(
"FilterName")) {
652 name = bandBinGroup[
"FilterName"];
654 else if (bandBinGroup.
hasKeyword(
"FilterId")) {
655 name = bandBinGroup[
"FilterId"];
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");
681 PvlToXmlTranslationManager::setElementValue(binSequenceNumber,
toString(i+1));
682 bin.appendChild(binSequenceNumber);
685 QDomElement centerValue = m_domDoc->createElement(
"sp:center_value");
686 PvlToXmlTranslationManager::setElementValue(centerValue, center[i], units);
687 bin.appendChild(centerValue);
689 QDomElement binWidth = m_domDoc->createElement(
"sp:bin_width");
690 if (width.
size() == bands) {
691 PvlToXmlTranslationManager::setElementValue(binWidth, width[i] , units);
694 PvlToXmlTranslationManager::setElementValue(binWidth, width[0] , units);
696 bin.appendChild(binWidth);
698 QDomElement originalBinNumber = m_domDoc->createElement(
"sp:original_bin_number");
699 if (originalBand.
size() > 0) {
700 PvlToXmlTranslationManager::setElementValue(originalBinNumber, originalBand[i]);
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");
709 PvlToXmlTranslationManager::setElementValue(filterName, name[i]);
710 filter.appendChild(filterName);
712 if (number.
size() > 0) {
713 QDomElement filterNumber= m_domDoc->createElement(
"sp:filter_number");
714 PvlToXmlTranslationManager::setElementValue(filterNumber, number[i]);
715 filter.appendChild(filterNumber);
726 void ProcessExportPds4::translateBandBinSpectrumBinSet(
Pvl &inputLabel) {
727 QString translationFile =
"$ISISROOT/appdata/translations/";
728 translationFile +=
"pds4ExportBandBinSpectrumBinSet.trn";
729 FileName translationFileName(translationFile);
731 xlator.
Auto(*m_domDoc);
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"];
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.";
771 throw IException(IException::Programmer, msg, _FILEINFO_);
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");
782 PvlToXmlTranslationManager::setElementValue(lastCenterElement, lastCenter);
783 spectralCharElement.appendChild(lastCenterElement);
793 void ProcessExportPds4::setPixelDescription(QString description) {
794 m_pixelDescription = description;
802 void ProcessExportPds4::fileAreaObservational() {
803 Pvl *inputLabel = InputCubes[0]->label();
804 QString imageObject =
"";
806 QString translationFile =
"$ISISROOT/appdata/translations/pds4Export";
807 if (m_imageType == StandardImage) {
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(
'_');
823 if (m_imageType == UniformlySampledSpectrum) {
824 translationFile +=
"Uniform";
826 else if (m_imageType == BinSetSpectrum) {
827 translationFile +=
"BinSet";
830 translationFile +=
".trn";
831 FileName translationFileName(translationFile);
834 xlator.
Auto(*m_domDoc);
836 QDomElement rootElement = m_domDoc->documentElement();
837 QDomElement fileAreaObservationalElement =
838 rootElement.firstChildElement(
"File_Area_Observational");
842 double multiplier = 1.0;
843 double outputMin, outputMax;
845 double inputMin = (p_inputMinimum.size()) ? p_inputMinimum[0] : 0.0;
846 double inputMax = (p_inputMaximum.size()) ? p_inputMaximum[0] : 0.0;
848 for(
unsigned int i = 0; i < p_inputMinimum.size(); i ++) {
849 inputMin = std::min(inputMin, p_inputMinimum[i]);
850 inputMax = std::max(inputMax, p_inputMaximum[i]);
853 outputMin = p_outputMinimum;
854 outputMax = p_outputMaximum;
856 if(p_inputMinimum.size() && ( p_pixelType == Isis::UnsignedByte ||
857 p_pixelType == Isis::SignedWord ||
858 p_pixelType == Isis::UnsignedWord ) ) {
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");
884 PvlToXmlTranslationManager::setElementValue(dataTypeElement,
885 PDS4PixelType(p_pixelType, p_endianType));
886 elementArrayElement.appendChild(dataTypeElement);
888 QDomElement scalingFactorElement = m_domDoc->createElement(
"scaling_factor");
889 PvlToXmlTranslationManager::setElementValue(scalingFactorElement,
891 elementArrayElement.appendChild(scalingFactorElement);
893 QDomElement offsetElement = m_domDoc->createElement(
"value_offset");
894 PvlToXmlTranslationManager::setElementValue(offsetElement,
896 elementArrayElement.appendChild(offsetElement);
900 QDomElement specialConstantElement = m_domDoc->createElement(
"Special_Constants");
901 arrayImageElement.insertAfter(specialConstantElement,
902 arrayImageElement.lastChildElement(
"Axis_Array"));
904 switch (p_pixelType) {
906 { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
907 PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL4,
'g', 18));
908 specialConstantElement.appendChild(nullElement);
910 QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
911 PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT4,
'g', 18));
912 specialConstantElement.appendChild(highInstrumentSatElement);
914 QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
915 PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT4,
'g', 18));
916 specialConstantElement.appendChild(highRepresentationSatElement);
918 QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
919 PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT4,
'g', 18));
920 specialConstantElement.appendChild(lowInstrumentSatElement);
922 QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
923 PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT4,
'g', 18));
924 specialConstantElement.appendChild(lowRepresentationSatElement);
928 { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
929 PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL1,
'g', 18));
930 specialConstantElement.appendChild(nullElement);
932 QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
933 PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT1,
'g', 18));
934 specialConstantElement.appendChild(highInstrumentSatElement);
936 QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
937 PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT1,
'g', 18));
938 specialConstantElement.appendChild(highRepresentationSatElement);
940 QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
941 PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT1,
'g', 18));
942 specialConstantElement.appendChild(lowInstrumentSatElement);
944 QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
945 PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT1,
'g', 18));
946 specialConstantElement.appendChild(lowRepresentationSatElement);
950 { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
951 PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL2,
'g', 18));
952 specialConstantElement.appendChild(nullElement);
954 QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
955 PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT2,
'g', 18));
956 specialConstantElement.appendChild(highInstrumentSatElement);
958 QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
959 PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT2,
'g', 18));
960 specialConstantElement.appendChild(highRepresentationSatElement);
962 QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
963 PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT2,
'g', 18));
964 specialConstantElement.appendChild(lowInstrumentSatElement);
966 QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
967 PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT2,
'g', 18));
968 specialConstantElement.appendChild(lowRepresentationSatElement);
972 { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
973 PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULLU2,
'g', 18));
974 specialConstantElement.appendChild(nullElement);
976 QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
977 PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SATU2,
'g', 18));
978 specialConstantElement.appendChild(highInstrumentSatElement);
980 QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
981 PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SATU2,
'g', 18));
982 specialConstantElement.appendChild(highRepresentationSatElement);
984 QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
985 PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SATU2,
'g', 18));
986 specialConstantElement.appendChild(lowInstrumentSatElement);
988 QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
989 PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SATU2,
'g', 18));
990 specialConstantElement.appendChild(lowRepresentationSatElement);
1002 if (!m_pixelDescription.isEmpty()) {
1003 QDomElement descriptionElement = m_domDoc->createElement(
"description");
1004 PvlToXmlTranslationManager::setElementValue(descriptionElement,
1005 m_pixelDescription);
1006 arrayImageElement.insertAfter(descriptionElement, arrayImageElement.lastChildElement());
1020 void ProcessExportPds4::addSchema(QString xsd, QString xmlns, QString xmlnsURI) {
1022 QDomElement root = m_domDoc->documentElement();
1023 root.setAttribute(xmlns, xmlnsURI);
1026 m_schemaLocation +=
" ";
1027 m_schemaLocation += xmlnsURI;
1028 m_schemaLocation +=
" ";
1029 m_schemaLocation += xmlnsURI;
1030 m_schemaLocation +=
"/";
1031 m_schemaLocation += xsd;
1032 root.setAttribute(
"xsi:schemaLocation", m_schemaLocation);
1044 void ProcessExportPds4::addSchema(QString sch, QString xsd, QString xmlns, QString 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);
1054 m_domDoc->insertAfter(header, m_domDoc->firstChild());
1057 addSchema(xsd, xmlns, xmlnsURI);
1066 void ProcessExportPds4::OutputLabel(std::ofstream &os) {
1067 os << m_domDoc->toString() << endl;
1078 void ProcessExportPds4::StartProcess(std::ofstream &fout) {
1079 ProcessExport::StartProcess(fout);
1089 QDomDocument &ProcessExportPds4::GetLabel() {
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");
1096 m_domDoc->appendChild(root);
1110 void ProcessExportPds4::WritePds4(QString outFile) {
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");
1137 PvlToXmlTranslationManager::setElementValue(fileNameElement, outputFile.
name());
1138 fileElement.appendChild(fileNameElement);
1144 ofstream outputLabel(labelName.toLatin1().data());
1145 OutputLabel(outputLabel);
1146 outputLabel.close();
1148 ofstream outputImageFile(imageName.toLatin1().data());
1149 StartProcess(outputImageFile);
1150 outputImageFile.close();
1164 void ProcessExportPds4::StandardAllMapping() {
1167 Pvl *inputLabel = InputCubes[0]->label();
1169 !(inputLabel->
findObject(
"IsisCube").hasGroup(
"Mapping")))
return;
1172 addSchema(
"PDS4_CART_1900.sch",
1173 "PDS4_CART_1900.xsd",
1175 "http://pds.nasa.gov/pds4/cart/v1");
1178 Projection *proj = ProjectionFactory::Create(*inputLabel);
1179 QString projName = proj->
Name();
1182 "$ISISROOT/appdata/translations/pds4Export" + projName +
".trn");
1183 xlatorSpecProj.
Auto(*m_domDoc);
1186 QString msg =
"Unable to export projection [" + projName +
"] to PDS4 product. " +
1187 "This projection is not supported in ISIS3.";
1188 throw IException(e, IException::User, msg, _FILEINFO_);
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());
1213 PvlToXmlTranslationManager::resetElementValue(semiMajorRadElement,
toString(dValue),
"km");
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());
1225 PvlToXmlTranslationManager::resetElementValue(semiMinorRadElement,
toString(dValue),
"km");
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());
1236 PvlToXmlTranslationManager::resetElementValue(polarRadElement,
toString(dValue),
"km");
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) {
1265 PvlToXmlTranslationManager::resetElementValue(eastElement,
toString(maxLon),
"deg");
1266 PvlToXmlTranslationManager::resetElementValue(westElement,
toString(minLon),
"deg");
1269 PvlToXmlTranslationManager::resetElementValue(eastElement,
toString(minLon),
"deg");
1270 PvlToXmlTranslationManager::resetElementValue(westElement,
toString(maxLon),
"deg");
1273 PvlToXmlTranslationManager::resetElementValue(northElement,
toString(maxLat),
"deg");
1274 PvlToXmlTranslationManager::resetElementValue(southElement,
toString(minLat),
"deg");
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);
1301 PvlToXmlTranslationManager::resetElementValue(longitudeElement, toset1,
"deg");
1304 if (!originElement.text().contains(
'.')) {
1305 QString toset2 = QString::number(originElementValue,
'f', 1);
1306 PvlToXmlTranslationManager::resetElementValue(originElement, toset2,
"deg");
1327 QDomElement ProcessExportPds4::getElement(
QStringList xmlPath, QDomElement parent) {
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.";
1334 throw IException(IException::Programmer, msg, _FILEINFO_);
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.";
1340 throw IException(IException::Programmer, msg, _FILEINFO_);
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");
1361 if(p_pixelType == Isis::UnsignedByte) {
1362 pds4Type =
"UnsignedByte";
1364 else if((p_pixelType == Isis::UnsignedWord) && (p_endianType == Isis::Msb)) {
1365 pds4Type =
"UnsignedMSB2";
1367 else if((p_pixelType == Isis::UnsignedWord) && (p_endianType == Isis::Lsb)) {
1368 pds4Type =
"UnsignedLSB2";
1370 else if((p_pixelType == Isis::SignedWord) && (p_endianType == Isis::Msb)) {
1371 pds4Type =
"SignedMSB2";
1373 else if((p_pixelType == Isis::SignedWord) && (p_endianType == Isis::Lsb)) {
1374 pds4Type =
"SignedLSB2";
1376 else if((p_pixelType == Isis::Real) && (p_endianType == Isis::Msb)) {
1377 pds4Type =
"IEEE754MSBSingle";
1379 else if((p_pixelType == Isis::Real) && (p_endianType == Isis::Lsb)) {
1380 pds4Type =
"IEEE754LSBSingle";
1383 QString msg =
"Unsupported PDS pixel type or sample size";
1384 throw IException(IException::User, msg, _FILEINFO_);
1399 void ProcessExportPds4::addHistory(QString description, QString date, QString version) {
1401 QDomElement identificationElement;
1403 identificationPath.append(
"Product_Observational");
1404 identificationPath.append(
"Identification_Area");
1406 identificationElement = getElement(identificationPath);
1407 if( identificationElement.isNull() ) {
1408 throw IException(IException::Unknown,
"", _FILEINFO_);
1412 QString msg =
"Could not find Identification_Area element "
1413 "to add modification history under.";
1414 throw IException(IException::Programmer, msg, _FILEINFO_);
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");
1431 PvlToXmlTranslationManager::setElementValue(modDateElement, date);
1432 detailElement.appendChild(modDateElement);
1434 QDomElement versionIdElement = m_domDoc->createElement(
"version_id");
1435 PvlToXmlTranslationManager::setElementValue(versionIdElement, version);
1436 detailElement.appendChild(versionIdElement);
1438 QDomElement descriptionElement = m_domDoc->createElement(
"description");
1439 PvlToXmlTranslationManager::setElementValue(descriptionElement, description);
1440 detailElement.appendChild(descriptionElement);
1442 historyElement.insertAfter( detailElement,
1443 historyElement.lastChildElement() );
1464 void ProcessExportPds4::translateUnits(QDomDocument &label, QString transMapFile) {
1467 configPvl.
read(transMapFile);
1470 QString msg =
"Failed to read unit translation config file [" + transMapFile +
"].";
1471 throw IException(e, IException::Io, msg, _FILEINFO_);
1476 transMap = createUnitMap(configPvl);
1479 QString msg =
"Failed to load unit translation config file [" + transMapFile +
"].";
1480 throw IException(e, IException::Unknown, msg, _FILEINFO_);
1486 translateChildUnits( label.documentElement(), transMap );
1489 QString msg =
"Failed to translate units with config file [" + transMapFile +
"].";
1490 throw IException(e, IException::Unknown, msg, _FILEINFO_);
1507 for (
int i = 0; i < configPvl.
objects(); i++) {
1509 for (
int j = 0; j < unitObject.
groups(); j++) {
1512 QString msg =
"No PDS4 standard specified for for [" + unitGroup.
name() +
"]";
1513 throw IException(IException::Programmer, msg, _FILEINFO_);
1518 transMap.insert(pds4Key[0].toLower(), pds4Key[0]);
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.";
1556 throw IException(IException::Unknown, msg, _FILEINFO_);
1559 translateChildUnits(childElement, transMap);
1560 childElement = childElement.nextSiblingElement();