19 #include "ProcessExportPds4.h"    25 #include <QDomDocument>    27 #include <QRegularExpression>    47   ProcessExportPds4::ProcessExportPds4() {
    53     m_imageType = StandardImage;
    55     qSetGlobalQHashSeed(1031); 
    57     m_domDoc = 
new QDomDocument(
"");
    61     QString xmlVersion = 
"version=\"1.0\" encoding=\"utf-8\"";
    62     QDomProcessingInstruction xmlHeader =
    63         m_domDoc->createProcessingInstruction(
"xml", xmlVersion);
    64     m_domDoc->appendChild(xmlHeader);
    67     m_schemaLocation = 
"http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1B00.xsd"; 
    70     xmlModel += 
"href=\"http://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1B00.sch\" ";
    71     xmlModel += 
"schematypens=\"http://purl.oclc.org/dsdl/schematron\"";
    72     QDomProcessingInstruction header =
    73         m_domDoc->createProcessingInstruction(
"xml-model", xmlModel);
    74     m_domDoc->appendChild(header);
    83   ProcessExportPds4::~ProcessExportPds4() {
    94   QDomDocument &ProcessExportPds4::StandardPds4Label() {
    96     translateUnits(*m_domDoc);
   106   void ProcessExportPds4::setImageType(ImageType imageType) {
   107     m_imageType = imageType;
   120   void ProcessExportPds4::CreateImageLabel() {
   121     if (InputCubes.size() == 0) {
   122       QString msg(
"Must set an input cube before creating a PDS4 label.");
   125     if (m_domDoc->documentElement().isNull()) {
   126       QDomElement root = m_domDoc->createElement(
"Product_Observational");
   127       root.setAttribute(
"xmlns", 
"http://pds.nasa.gov/pds4/pds/v1");
   128       root.setAttribute(
"xmlns:xsi", 
"http://www.w3.org/2001/XMLSchema-instance");
   129       root.setAttribute(
"xsi:schemaLocation",
   130                         "http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1");
   131       m_domDoc->appendChild(root);
   137       identificationArea();
   140       QString msg = 
"Unable to translate and export identification information.";
   146       standardInstrument();
   149       QString msg = 
"Unable to translate and export instrument information.";
   160       QString msg = 
"Unable to translate and export display settings.";
   172       QString msg = 
"Unable to translate and export spectral information.";
   181       StandardAllMapping();
   184       QString msg = 
"Unable to translate and export mapping group.";
   190       fileAreaObservational();
   193       QString msg = 
"Unable to translate and export standard image information.";
   203   void ProcessExportPds4::standardInstrument() {
   204     Pvl *inputLabel = InputCubes[0]->label();
   207     if (inputLabel->
findObject(
"IsisCube").hasGroup(
"Instrument")) {
   210       translationFileName = 
"$base/translations/pds4ExportInstrument.trn";
   212       instXlator.
Auto(*m_domDoc);
   215       QDomElement obsAreaNode = m_domDoc->documentElement().firstChildElement(
"Observation_Area");
   217       if ( !obsAreaNode.isNull() ) {
   220         QDomElement timeNode = obsAreaNode.firstChildElement(
"Time_Coordinates");
   221         if (!timeNode.isNull()) {
   222           QDomElement startTime = timeNode.firstChildElement(
"start_date_time");
   223           if (startTime.text() == 
"") {
   224             startTime.setAttribute(
"xsi:nil", 
"true");
   227             QString timeValue = startTime.text();
   228             PvlToXmlTranslationManager::resetElementValue(startTime, timeValue + 
"Z"); 
   230           QDomElement stopTime  = timeNode.firstChildElement(
"stop_date_time"); 
   231           if (stopTime.text() == 
"") {
   232             stopTime.setAttribute(
"xsi:nil", 
"true");
   235             QString timeValue = stopTime.text();
   236             PvlToXmlTranslationManager::resetElementValue(stopTime, timeValue + 
"Z");
   240         QDomElement obsSysNode = obsAreaNode.firstChildElement(
"Observing_System");
   241         if ( !obsSysNode.isNull() ) {
   242           QString instrumentName;
   243           QString spacecraftName;
   244           QDomElement obsSysCompNode = obsSysNode.firstChildElement(
"Observing_System_Component");
   245           while ( !obsSysCompNode.isNull()) {
   246             QDomElement compTypeNode = obsSysCompNode.firstChildElement(
"type");
   247             if ( compTypeNode.text().compare(
"Spacecraft") == 0 ) {
   248               QString componentName = obsSysCompNode.firstChildElement(
"name").text();
   249               if (QString::compare(componentName, 
"TBD", Qt::CaseInsensitive) != 0) {
   250                 spacecraftName = componentName; 
   253             else if ( compTypeNode.text().compare(
"Instrument") == 0 ) {
   254               QString componentName = obsSysCompNode.firstChildElement(
"name").text();
   255               if (QString::compare(componentName, 
"TBD", Qt::CaseInsensitive) != 0) {
   256                 instrumentName = componentName;
   259             obsSysCompNode = obsSysCompNode.nextSiblingElement(
"Observing_System_Component");
   261           QDomElement combinedNode = m_domDoc->createElement(
"name");
   262           QString combinedValue = 
"TBD";
   263           if ( !instrumentName.isEmpty() && !spacecraftName.isEmpty() ) {
   264             combinedValue = spacecraftName + 
" " + instrumentName;
   266           combinedNode.appendChild( m_domDoc->createTextNode(combinedValue) );
   267           obsSysNode.insertBefore( combinedNode, obsSysNode.firstChild() );
   272       translationFileName = 
"$base/translations/pds4ExportTargetFromInstrument.trn"; 
   274       targXlator.
Auto(*m_domDoc);
   277       QDomElement targetIdNode = obsAreaNode.firstChildElement(
"Target_Identification");
   278       obsAreaNode.insertAfter(targetIdNode, obsAreaNode.firstChildElement(
"Observing_System"));
   280     else if (inputLabel->
findObject(
"IsisCube").hasGroup(
"Mapping")) {
   282       translationFileName = 
"$base/translations/pds4ExportTargetFromMapping.trn"; 
   284       targXlator.
Auto(*m_domDoc);
   296   void ProcessExportPds4::reorder() {
   297       QDomElement obsAreaNode = m_domDoc->documentElement().firstChildElement(
"Observation_Area");
   298       if ( !obsAreaNode.isNull() ) {
   301         QDomElement timeNode = obsAreaNode.firstChildElement(
"Time_Coordinates");
   302         if (!timeNode.isNull()) {
   303           QDomElement startTime = timeNode.firstChildElement(
"start_date_time");
   304           if (startTime.text() == 
"") {
   305             startTime.setAttribute(
"xsi:nil", 
"true");
   308             QString timeValue = startTime.text();
   309             if (!timeValue.contains(
"Z")) {
   310               PvlToXmlTranslationManager::resetElementValue(startTime, timeValue + 
"Z"); 
   314           QDomElement stopTime  = timeNode.firstChildElement(
"stop_date_time"); 
   315           if (stopTime.text() == 
"") {
   316             stopTime.setAttribute(
"xsi:nil", 
"true");
   319             QString timeValue = stopTime.text();
   320             if (!timeValue.contains(
"Z")) {
   321               PvlToXmlTranslationManager::resetElementValue(stopTime, timeValue + 
"Z"); 
   325           xmlPath << 
"Product_Observational"   326             << 
"Observation_Area"   329             << 
"geom:Geometry_Orbiter"   330             << 
"geom:geometry_reference_time_utc";
   332           QDomElement baseElement = m_domDoc->documentElement();
   333           QDomElement geomRefTime = getElement(xmlPath, baseElement);
   334           if (geomRefTime.text() == 
"") {
   335             geomRefTime.setAttribute(
"xsi:nil", 
"true");
   338             QString timeValue = geomRefTime.text();
   339             PvlToXmlTranslationManager::resetElementValue(geomRefTime, timeValue + 
"Z");
   342           xmlPath << 
"Product_Observational"   343             << 
"Observation_Area"   346             << 
"geom:Image_Display_Geometry"   347             << 
"geom:Object_Orientation_North_East"   348             << 
"geom:east_azimuth";
   349           QDomElement eastAzimuth = getElement(xmlPath, baseElement);
   350           if (eastAzimuth.text() != 
"") {
   351             PvlToXmlTranslationManager::resetElementValue(eastAzimuth, eastAzimuth.text(), 
"deg");
   355         QDomElement investigationAreaNode = obsAreaNode.firstChildElement(
"Investigation_Area");
   356         obsAreaNode.insertAfter(investigationAreaNode, obsAreaNode.firstChildElement(
"Time_Coordinates"));
   358         QDomElement obsSystemNode = obsAreaNode.firstChildElement(
"Observing_System");
   359         obsAreaNode.insertAfter(obsSystemNode, obsAreaNode.firstChildElement(
"Investigation_Area"));
   361         QDomElement targetIdNode = obsAreaNode.firstChildElement(
"Target_Identification");
   362         obsAreaNode.insertAfter(targetIdNode, obsAreaNode.firstChildElement(
"Observing_System"));
   364         QDomElement missionAreaNode = obsAreaNode.firstChildElement(
"Mission_Area");
   365         obsAreaNode.insertAfter(missionAreaNode, obsAreaNode.firstChildElement(
"Target_Identification"));
   367         QDomElement disciplineAreaNode = obsAreaNode.firstChildElement(
"Discipline_Area");
   368         obsAreaNode.insertAfter(disciplineAreaNode, obsAreaNode.firstChildElement(
"Mission_Area"));
   371       QDomElement identificationAreaNode = m_domDoc->documentElement().firstChildElement(
"Identification_Area");
   372       if ( !identificationAreaNode.isNull() ) {
   373         QDomElement aliasListNode = identificationAreaNode.firstChildElement(
"Alias_List");
   374         identificationAreaNode.insertAfter(aliasListNode, identificationAreaNode.firstChildElement(
"product_class"));
   377       QDomElement fileAreaObservationalNode = m_domDoc->documentElement().firstChildElement(
"File_Area_Observational");
   378       QDomElement array2DImageNode = fileAreaObservationalNode.firstChildElement(
"Array_2D_Image");
   379       if ( !array2DImageNode.isNull() ) {
   380         QDomElement descriptionNode = array2DImageNode.firstChildElement(
"description");
   381         array2DImageNode.insertAfter(descriptionNode, array2DImageNode.firstChildElement(
"axis_index_order"));
   413   void ProcessExportPds4::setLogicalId(QString lid) {
   414     m_lid = lid.toLower();
   431    void ProcessExportPds4::setVersionId(QString versionId) {
   432     m_versionId = versionId;
   446    void ProcessExportPds4::setTitle(QString title) {
   459   void ProcessExportPds4::setSchemaLocation(QString schema) {
   460     m_schemaLocation = schema;
   468   void ProcessExportPds4::identificationArea() {
   469     Pvl *inputLabel = InputCubes[0]->label(); 
   471     translationFileName = 
"$base/translations/pds4ExportIdentificationArea.trn";
   473     xlator.
Auto(*m_domDoc);
   475     if (m_lid.isEmpty()) {
   476       m_lid = 
"urn:nasa:pds:TBD:TBD:TBD";
   479     QDomElement identificationElement;
   481     identificationPath.append(
"Product_Observational");
   482     identificationPath.append(
"Identification_Area");
   484       identificationElement = getElement(identificationPath);
   485       if( identificationElement.isNull() ) {
   490       QString msg = 
"Could not find Identification_Area element "   491                     "to add modification history under.";
   495     QDomElement lidElement = identificationElement.firstChildElement(
"logical_identifier");
   496     PvlToXmlTranslationManager::resetElementValue(lidElement, m_lid);
   498     if (m_versionId != 
"") {
   499       QDomElement versionElement = identificationElement.firstChildElement(
"version_id"); 
   500       PvlToXmlTranslationManager::resetElementValue(versionElement, m_versionId);
   504       QDomElement titleElement = identificationElement.firstChildElement(
"title"); 
   505       PvlToXmlTranslationManager::resetElementValue(titleElement, m_title);
   511     QRegularExpression versionRegex(
" \\| \\d{4}\\-\\d{2}\\-\\d{2}");
   512     QString historyDescription = 
"Created PDS4 output product from ISIS cube with the "   514                                  + 
" application from ISIS version "   515                                  + Application::Version().remove(versionRegex) + 
".";
   517     QRegularExpression dateRegex(
"T\\d{2}:\\d{2}:\\d{2}");
   518     QString historyDate = Application::DateTime().remove(dateRegex);
   519     addHistory(historyDescription, historyDate);
   527   void ProcessExportPds4::displaySettings() {
   529     addSchema(
"PDS4_DISP_1B00.sch", 
   530               "PDS4_DISP_1B00.xsd",
   532               "http://pds.nasa.gov/pds4/disp/v1"); 
   534     Pvl *inputLabel = InputCubes[0]->label(); 
   536     translationFileName = 
"$base/translations/pds4ExportDisplaySettings.trn";
   538     xlator.
Auto(*m_domDoc);
   546   void ProcessExportPds4::standardBandBin() {
   547     Pvl *inputLabel = InputCubes[0]->label(); 
   548     if ( !inputLabel->
findObject(
"IsisCube").hasGroup(
"BandBin") ) 
return;
   550     addSchema(
"PDS4_IMG_1A10_1510.sch", 
   551               "PDS4_IMG_1A10_1510.xsd",
   553               "http://pds.nasa.gov/pds4/img/v1"); 
   556     if (m_imageType == StandardImage) {
   557       translateBandBinImage(*inputLabel);
   561       addSchema(
"PDS4_SP_1100.sch", 
   564                 "http://pds.nasa.gov/pds4/sp/v1");
   565       if (m_imageType == UniformlySampledSpectrum) {
   566         translateBandBinSpectrumUniform(*inputLabel);
   568       else if (m_imageType == BinSetSpectrum) {
   569         translateBandBinSpectrumBinSet(*inputLabel);
   578   void ProcessExportPds4::translateBandBinImage(
Pvl &inputLabel) {
   579     QString translationFile = 
"$base/translations/";
   580     translationFile += 
"pds4ExportBandBinImage.trn";
   581     FileName translationFileName(translationFile);
   583     xlator.
Auto(*m_domDoc);
   590   void ProcessExportPds4::translateBandBinSpectrumUniform(
Pvl &inputLabel) {
   591     QString translationFile = 
"$base/translations/";
   592     translationFile += 
"pds4ExportBandBinSpectrumUniform.trn";
   593     FileName translationFileName(translationFile);
   595     xlator.
Auto(*m_domDoc);
   600     xmlPath << 
"Product_Observational"   601             << 
"Observation_Area"   603             << 
"sp:Spectral_Characteristics";
   604     QDomElement baseElement = m_domDoc->documentElement();
   605     QDomElement spectralCharElement = getElement(xmlPath, baseElement);
   613       center = bandBinGroup[
"Center"];
   615     else if (bandBinGroup.
hasKeyword(
"FilterCenter")) {
   616       center = bandBinGroup[
"FilterCenter"];
   619       QString msg = 
"Unable to translate BandBin info for BinSetSpectrum. "   620                     "Translation for PDS4 required value [center_value] not found.";
   625       width = bandBinGroup[
"Width"];
   627     else if (bandBinGroup.
hasKeyword(
"FilterWidth")) {
   628       width = bandBinGroup[
"FilterWidth"];
   631       QString msg = 
"Unable to translate BandBin info for BinSetSpectrum. "   632                     "Translation for PDS4 required value [bin_width] not found.";
   636     QString units = center.
unit();
   638     if (!width.
unit().isEmpty() ) {
   639       if (units.isEmpty()) {
   640         units = width.
unit();
   642       if (units.compare(width.
unit(), Qt::CaseInsensitive) != 0) {
   643         QString msg = 
"Unable to translate BandBin info for BinSetSpectrum. "   644                       "Unknown or unmatching units for [center_value] and [bin_width].";
   650     if (bandBinGroup.
hasKeyword(
"OriginalBand")) {
   651       originalBand = bandBinGroup[
"OriginalBand"];
   655       name = bandBinGroup[
"Name"];
   657     else if (bandBinGroup.
hasKeyword(
"FilterName")) {
   658       name = bandBinGroup[
"FilterName"];
   660     else if (bandBinGroup.
hasKeyword(
"FilterId")) {
   661       name = bandBinGroup[
"FilterId"];
   665       number = bandBinGroup[
"Number"];
   667     else if (bandBinGroup.
hasKeyword(
"FilterNumber")) {
   668       number = bandBinGroup[
"FilterNumber"];
   671     QDomElement axisBinSetElement = spectralCharElement.firstChildElement(
"sp:Axis_Bin_Set");
   672     if (axisBinSetElement.isNull()) {
   673       axisBinSetElement = m_domDoc->createElement(
"sp:Axis_Bin_Set");
   674       spectralCharElement.appendChild(axisBinSetElement);
   676     int bands = (int)inputLabel.
findObject(
"IsisCube")
   678                                 .findGroup(
"Dimensions")
   679                                 .findKeyword(
"Bands");
   681     for (
int i = 0; i < bands; i++) {
   683       QDomElement bin = m_domDoc->createElement(
"sp:Bin");
   684       axisBinSetElement.appendChild(bin);
   686       QDomElement binSequenceNumber = m_domDoc->createElement(
"sp:bin_sequence_number");
   687       PvlToXmlTranslationManager::setElementValue(binSequenceNumber, 
toString(i+1));
   688       bin.appendChild(binSequenceNumber);
   691       QDomElement centerValue = m_domDoc->createElement(
"sp:center_value");
   692       PvlToXmlTranslationManager::setElementValue(centerValue, center[i], units);
   693       bin.appendChild(centerValue);
   695       QDomElement binWidth = m_domDoc->createElement(
"sp:bin_width");
   696       if (width.
size() == bands) {
   697         PvlToXmlTranslationManager::setElementValue(binWidth, width[i] , units);
   700         PvlToXmlTranslationManager::setElementValue(binWidth, width[0] , units);
   702       bin.appendChild(binWidth);
   704       QDomElement originalBinNumber = m_domDoc->createElement(
"sp:original_bin_number");
   705       if (originalBand.
size() > 0) {
   706         PvlToXmlTranslationManager::setElementValue(originalBinNumber, originalBand[i]);
   707         bin.appendChild(originalBinNumber);
   710       if (name.
size() > 0 || number.
size() > 0) {
   711         QDomElement filter = m_domDoc->createElement(
"sp:Filter");
   712         bin.appendChild(filter);
   713         if (name.
size() > 0) {
   714           QDomElement filterName = m_domDoc->createElement(
"sp:filter_name");
   715           PvlToXmlTranslationManager::setElementValue(filterName, name[i]);
   716           filter.appendChild(filterName);
   718         if (number.
size() > 0) {
   719           QDomElement filterNumber= m_domDoc->createElement(
"sp:filter_number");
   720           PvlToXmlTranslationManager::setElementValue(filterNumber, number[i]);
   721           filter.appendChild(filterNumber);
   732   void ProcessExportPds4::translateBandBinSpectrumBinSet(
Pvl &inputLabel) {
   733     QString translationFile = 
"$base/translations/";
   734     translationFile += 
"pds4ExportBandBinSpectrumBinSet.trn";
   735     FileName translationFileName(translationFile);
   737     xlator.
Auto(*m_domDoc);
   742     xmlPath << 
"Product_Observational"   743             << 
"Observation_Area"   745             << 
"sp:Spectral_Characteristics";
   746     QDomElement baseElement = m_domDoc->documentElement();
   747     QDomElement spectralCharElement = getElement(xmlPath, baseElement);
   768     if (bandBinGroup.
hasKeyword(
"FilterCenter")) {
   769       center = bandBinGroup[
"FilterCenter"];
   772       center = bandBinGroup[
"Center"];
   775       QString msg = 
"Unable to translate BandBin info for UniformlySpacedSpectrum. "   776                     "Translation for PDS4 required value [last_center_value] not found.";
   779     QString lastCenter = center[center.
size() - 1];
   781     QDomElement axisBinSetElement = spectralCharElement.firstChildElement(
"sp:Axis_Uniformly_Sampled");
   782     if (axisBinSetElement.isNull()) {
   783       axisBinSetElement = m_domDoc->createElement(
"sp:Axis_Uniformly_Sampled");
   784       spectralCharElement.appendChild(axisBinSetElement);
   787     QDomElement lastCenterElement = m_domDoc->createElement(
"sp:last_center_value");
   788     PvlToXmlTranslationManager::setElementValue(lastCenterElement, lastCenter);
   789     spectralCharElement.appendChild(lastCenterElement);
   799   void ProcessExportPds4::setPixelDescription(QString description) {
   800     m_pixelDescription = description;
   808   void ProcessExportPds4::fileAreaObservational() {
   809     Pvl *inputLabel = InputCubes[0]->label(); 
   810     QString imageObject = 
"";
   812     QString translationFile = 
"$base/translations/pds4Export";
   813     if (m_imageType == StandardImage) {
   814       int bands = (int)inputLabel->
findObject(
"IsisCube")
   816                                   .findGroup(
"Dimensions")
   817                                   .findKeyword(
"Bands");
   819         imageObject = 
"Array_3D_Image";
   822         imageObject = 
"Array_2D_Image";
   824       translationFile += QString(imageObject).remove(
'_');
   827       imageObject = 
"Array_3D_Spectrum";
   828       translationFile += QString(imageObject).remove(
'_');
   829       if (m_imageType == UniformlySampledSpectrum) {
   830         translationFile += 
"Uniform";
   832       else if (m_imageType == BinSetSpectrum) {
   833         translationFile += 
"BinSet";
   836     translationFile += 
".trn";
   837     FileName translationFileName(translationFile);
   840     xlator.
Auto(*m_domDoc);
   842     QDomElement rootElement = m_domDoc->documentElement();
   843     QDomElement fileAreaObservationalElement =
   844                     rootElement.firstChildElement(
"File_Area_Observational");
   848     double multiplier = 1.0;
   849     double outputMin, outputMax;
   851     double inputMin = (p_inputMinimum.size()) ? p_inputMinimum[0] : 0.0;
   852     double inputMax = (p_inputMaximum.size()) ? p_inputMaximum[0] : 0.0;
   854     for(
unsigned int i = 0; i < p_inputMinimum.size(); i ++) {
   855       inputMin = std::min(inputMin, p_inputMinimum[i]);
   856       inputMax = std::max(inputMax, p_inputMaximum[i]);
   859     outputMin = p_outputMinimum;
   860     outputMax = p_outputMaximum;
   862     if(p_inputMinimum.size() && ( p_pixelType == Isis::UnsignedByte ||
   863                                   p_pixelType == Isis::SignedWord   ||
   864                                   p_pixelType == Isis::UnsignedWord ) ) {
   865       multiplier = (inputMax - inputMin) / (outputMax - outputMin);
   866       base = inputMin - multiplier * outputMin;
   869     if (!fileAreaObservationalElement.isNull()) {
   870       QDomElement arrayImageElement =
   871                       fileAreaObservationalElement.firstChildElement(imageObject);
   872       if (!arrayImageElement.isNull()) {
   877         QDomElement axisArrayElement = arrayImageElement.firstChildElement(
"Axis_Array");
   878         while( !axisArrayElement.isNull() ) {
   879           QDomElement axisNameElement = axisArrayElement.firstChildElement(
"axis_name");
   880           axisArrayElement.insertBefore(axisNameElement, 
   881                                         axisArrayElement.firstChildElement(
"elements"));
   882           axisArrayElement = axisArrayElement.nextSiblingElement(
"Axis_Array");
   885         QDomElement elementArrayElement = m_domDoc->createElement(
"Element_Array");
   886         arrayImageElement.insertBefore(elementArrayElement,
   887                                          arrayImageElement.firstChildElement(
"Axis_Array"));
   889         QDomElement dataTypeElement = m_domDoc->createElement(
"data_type");
   890         PvlToXmlTranslationManager::setElementValue(dataTypeElement,
   891                                                     PDS4PixelType(p_pixelType, p_endianType));
   892         elementArrayElement.appendChild(dataTypeElement);
   894         QDomElement scalingFactorElement = m_domDoc->createElement(
"scaling_factor");
   895         PvlToXmlTranslationManager::setElementValue(scalingFactorElement,
   897         elementArrayElement.appendChild(scalingFactorElement);
   899         QDomElement offsetElement = m_domDoc->createElement(
"value_offset");
   900         PvlToXmlTranslationManager::setElementValue(offsetElement,
   902         elementArrayElement.appendChild(offsetElement);
   906       QDomElement specialConstantElement = m_domDoc->createElement(
"Special_Constants"); 
   907       arrayImageElement.insertAfter(specialConstantElement,
   908                                     arrayImageElement.lastChildElement(
"Axis_Array"));
   910       switch (p_pixelType) {
   912           { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
   913           PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL4, 
'g', 18));
   914           specialConstantElement.appendChild(nullElement);
   916           QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
   917           PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT4, 
'g', 18));
   918           specialConstantElement.appendChild(highInstrumentSatElement);
   920           QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
   921           PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT4, 
'g', 18));
   922           specialConstantElement.appendChild(highRepresentationSatElement);
   924           QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
   925           PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT4, 
'g', 18));
   926           specialConstantElement.appendChild(lowInstrumentSatElement);
   928           QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
   929           PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT4, 
'g', 18));
   930           specialConstantElement.appendChild(lowRepresentationSatElement); 
   934           { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
   935           PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL1, 
'g', 18));
   936           specialConstantElement.appendChild(nullElement);
   938           QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
   939           PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT1, 
'g', 18));
   940           specialConstantElement.appendChild(highInstrumentSatElement);
   942           QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
   943           PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT1, 
'g', 18));
   944           specialConstantElement.appendChild(highRepresentationSatElement);
   946           QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
   947           PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT1, 
'g', 18));
   948           specialConstantElement.appendChild(lowInstrumentSatElement);
   950           QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
   951           PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT1, 
'g', 18));
   952           specialConstantElement.appendChild(lowRepresentationSatElement);
   956           { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
   957           PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULL2, 
'g', 18));
   958           specialConstantElement.appendChild(nullElement);
   960           QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
   961           PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SAT2, 
'g', 18));
   962           specialConstantElement.appendChild(highInstrumentSatElement);
   964           QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
   965           PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SAT2, 
'g', 18));
   966           specialConstantElement.appendChild(highRepresentationSatElement);
   968           QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
   969           PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SAT2, 
'g', 18));
   970           specialConstantElement.appendChild(lowInstrumentSatElement);
   972           QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
   973           PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SAT2, 
'g', 18));
   974           specialConstantElement.appendChild(lowRepresentationSatElement); 
   978           { QDomElement nullElement = m_domDoc->createElement(
"missing_constant");
   979           PvlToXmlTranslationManager::setElementValue(nullElement, QString::number(NULLU2, 
'g', 18));
   980           specialConstantElement.appendChild(nullElement);
   982           QDomElement highInstrumentSatElement = m_domDoc->createElement(
"high_instrument_saturation");
   983           PvlToXmlTranslationManager::setElementValue(highInstrumentSatElement, QString::number(HIGH_INSTR_SATU2, 
'g', 18));
   984           specialConstantElement.appendChild(highInstrumentSatElement);
   986           QDomElement highRepresentationSatElement = m_domDoc->createElement(
"high_representation_saturation");
   987           PvlToXmlTranslationManager::setElementValue(highRepresentationSatElement, QString::number(HIGH_REPR_SATU2, 
'g', 18));
   988           specialConstantElement.appendChild(highRepresentationSatElement);
   990           QDomElement lowInstrumentSatElement = m_domDoc->createElement(
"low_instrument_saturation");
   991           PvlToXmlTranslationManager::setElementValue(lowInstrumentSatElement, QString::number(LOW_INSTR_SATU2, 
'g', 18));
   992           specialConstantElement.appendChild(lowInstrumentSatElement);
   994           QDomElement lowRepresentationSatElement = m_domDoc->createElement(
"low_representation_saturation");
   995           PvlToXmlTranslationManager::setElementValue(lowRepresentationSatElement, QString::number(LOW_REPR_SATU2, 
'g', 18));
   996           specialConstantElement.appendChild(lowRepresentationSatElement); 
  1008       if (!m_pixelDescription.isEmpty()) {
  1009         QDomElement descriptionElement = m_domDoc->createElement(
"description"); 
  1010         PvlToXmlTranslationManager::setElementValue(descriptionElement,
  1011                                                     m_pixelDescription);
  1012         arrayImageElement.insertAfter(descriptionElement, arrayImageElement.lastChildElement());
  1026   void ProcessExportPds4::addSchema(QString xsd, QString xmlns, QString xmlnsURI) {
  1028     QDomElement root = m_domDoc->documentElement();
  1029     root.setAttribute(xmlns, xmlnsURI);
  1032     m_schemaLocation += 
" "; 
  1033     m_schemaLocation += xmlnsURI;
  1034     m_schemaLocation += 
" ";
  1035     m_schemaLocation += xmlnsURI;
  1036     m_schemaLocation += 
"/";
  1037     m_schemaLocation += xsd;
  1038     root.setAttribute(
"xsi:schemaLocation", m_schemaLocation);
  1050   void ProcessExportPds4::addSchema(QString sch, QString xsd, QString xmlns, QString xmlnsURI) {
  1053     xmlModel += 
"href=\"";
  1054     xmlModel +=  xmlnsURI;
  1057     xmlModel += 
"\" schematypens=\"http://purl.oclc.org/dsdl/schematron\"";
  1058     QDomProcessingInstruction header =
  1059         m_domDoc->createProcessingInstruction(
"xml-model", xmlModel);
  1060     m_domDoc->insertAfter(header, m_domDoc->firstChild());
  1063     addSchema(xsd, xmlns, xmlnsURI);
  1072   void ProcessExportPds4::OutputLabel(std::ofstream &os) {
  1073     os << m_domDoc->toString() << endl;
  1084   void ProcessExportPds4::StartProcess(std::ofstream &fout) {
  1085     ProcessExport::StartProcess(fout);
  1095   QDomDocument &ProcessExportPds4::GetLabel() {
  1096     if (m_domDoc->documentElement().isNull()) {
  1097       QDomElement root = m_domDoc->createElement(
"Product_Observational");
  1098       root.setAttribute(
"xmlns", 
"http://pds.nasa.gov/pds4/pds/v1");
  1099       root.setAttribute(
"xmlns:xsi", 
"http://www.w3.org/2001/XMLSchema-instance");
  1100       root.setAttribute(
"xsi:schemaLocation",
  1101                         "http://pds.nasa.gov/pds4/pds/v1 http://pds.nasa.gov/pds4/pds/v1");
  1102       m_domDoc->appendChild(root);
  1116   void ProcessExportPds4::WritePds4(QString outFile) {
  1122     QString name(outputFile.
baseName());
  1123     QString labelName = path + 
"/" + name + 
".xml";
  1126     QString imageName = outputFile.
expanded();
  1130     if (QString::compare(outputFile.
extension(), 
"xml", Qt::CaseInsensitive) == 0) {
  1131       imageName = path + 
"/" + name + 
".img";
  1134     QDomElement rootElement = m_domDoc->documentElement();
  1135     QDomElement fileAreaObservationalElement =
  1136                     rootElement.firstChildElement(
"File_Area_Observational");
  1138     QDomElement fileElement = m_domDoc->createElement(
"File");
  1139     fileAreaObservationalElement.insertBefore(fileElement, 
  1140                                               fileAreaObservationalElement.firstChildElement());
  1142     QDomElement fileNameElement = m_domDoc->createElement(
"file_name");
  1143     PvlToXmlTranslationManager::setElementValue(fileNameElement, outputFile.
name());
  1144     fileElement.appendChild(fileNameElement);
  1150     ofstream outputLabel(labelName.toLatin1().data());
  1151     OutputLabel(outputLabel);
  1152     outputLabel.close();
  1154     ofstream outputImageFile(imageName.toLatin1().data());
  1155     StartProcess(outputImageFile);
  1156     outputImageFile.close();
  1170   void ProcessExportPds4::StandardAllMapping() {
  1173     Pvl *inputLabel = InputCubes[0]->label();
  1175         !(inputLabel->
findObject(
"IsisCube").hasGroup(
"Mapping"))) 
return;
  1178     addSchema(
"PDS4_CART_1900.sch", 
  1179               "PDS4_CART_1900.xsd",
  1181               "http://pds.nasa.gov/pds4/cart/v1"); 
  1184     Projection *proj = ProjectionFactory::Create(*inputLabel); 
  1185     QString projName = proj->
Name();
  1188                                                 "$base/translations/pds4Export" + projName + 
".trn");
  1189       xlatorSpecProj.
Auto(*m_domDoc);
  1192       QString msg = 
"Unable to export projection [" + projName + 
"] to PDS4 product. " + 
  1193                      "This projection is not supported in ISIS3.";
  1199     xmlPath << 
"Product_Observational"   1200             << 
"Observation_Area"   1201             << 
"Discipline_Area"   1202             << 
"cart:Cartography"   1203             << 
"cart:Map_Projection"   1204             << 
"cart:Spatial_Reference_Information"   1205             << 
"cart:Horizontal_Coordinate_System_Definition"  1206             << 
"cart:Geodetic_Model";
  1208     QDomElement baseElement = m_domDoc->documentElement();
  1209     QDomElement geodeticModelElement = getElement(xmlPath, baseElement);
  1210     QDomElement semiMajorRadElement = geodeticModelElement.firstChildElement(
"cart:semi_major_radius");
  1211     if (!semiMajorRadElement.isNull()) {
  1213       QString units = semiMajorRadElement.attribute(
"unit");
  1214       if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) { 
  1217         double dValue = 
toDouble(semiMajorRadElement.text());
  1219         PvlToXmlTranslationManager::resetElementValue(semiMajorRadElement, 
toString(dValue), 
"km");
  1223     QDomElement semiMinorRadElement = geodeticModelElement.firstChildElement(
"cart:semi_minor_radius");
  1224     if (!semiMinorRadElement.isNull()) {
  1226       QString units = semiMinorRadElement.attribute(
"unit");
  1227       if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) { 
  1229         double dValue = 
toDouble(semiMinorRadElement.text());
  1231         PvlToXmlTranslationManager::resetElementValue(semiMinorRadElement, 
toString(dValue), 
"km");
  1235     QDomElement polarRadElement = geodeticModelElement.firstChildElement(
"cart:polar_radius");
  1236     if (!polarRadElement.isNull()) {
  1237       QString units = polarRadElement.attribute(
"unit");
  1238       if( units.compare(
"km", Qt::CaseInsensitive) != 0 && units.compare(
"kilometers", Qt::CaseInsensitive) != 0) { 
  1240         double dValue = 
toDouble(polarRadElement.text());
  1242         PvlToXmlTranslationManager::resetElementValue(polarRadElement, 
toString(dValue), 
"km");
  1247     QString lonDir = isisLonDir[0];
  1248     lonDir = lonDir.toUpper();
  1251     double maxLon, minLon, maxLat, minLat; 
  1252     InputCubes[0]->latLonRange(minLat, maxLat, minLon, maxLon); 
  1255     xmlPath << 
"Product_Observational"  1256             << 
"Observation_Area"   1257             << 
"Discipline_Area"  1258             << 
"cart:Cartography"   1259             << 
"cart:Spatial_Domain"  1260             << 
"cart:Bounding_Coordinates";
  1261     QDomElement boundingCoordElement = getElement(xmlPath, baseElement);
  1262     QDomElement eastElement = boundingCoordElement.firstChildElement(
"cart:east_bounding_coordinate");
  1263     QDomElement westElement = boundingCoordElement.firstChildElement(
"cart:west_bounding_coordinate");
  1264     QDomElement northElement = boundingCoordElement.firstChildElement(
"cart:north_bounding_coordinate");
  1265     QDomElement southElement = boundingCoordElement.firstChildElement(
"cart:south_bounding_coordinate");
  1269     if(QString::compare(lonDir, 
"PositiveEast", Qt::CaseInsensitive) == 0) {
  1271       PvlToXmlTranslationManager::resetElementValue(eastElement, 
toString(maxLon), 
"deg");
  1272       PvlToXmlTranslationManager::resetElementValue(westElement, 
toString(minLon), 
"deg");
  1275       PvlToXmlTranslationManager::resetElementValue(eastElement, 
toString(minLon), 
"deg");
  1276       PvlToXmlTranslationManager::resetElementValue(westElement, 
toString(maxLon), 
"deg");
  1279     PvlToXmlTranslationManager::resetElementValue(northElement, 
toString(maxLat), 
"deg");
  1280     PvlToXmlTranslationManager::resetElementValue(southElement, 
toString(minLat), 
"deg");
  1284     xmlPath << 
"Product_Observational"  1285             << 
"Observation_Area"   1286             << 
"Discipline_Area"  1287             << 
"cart:Cartography"   1288             << 
"cart:Spatial_Reference_Information"  1289             << 
"cart:Horizontal_Coordinate_System_Definition"  1291             << 
"cart:Map_Projection";
  1294     QDomElement projectionElement = getElement(xmlPath, baseElement);
  1295     QDomElement tempElement = projectionElement.firstChildElement();
  1296     QDomElement nameElement = tempElement.nextSiblingElement();
  1298     QDomElement longitudeElement = nameElement.firstChildElement(
"cart:longitude_of_central_meridian"); 
  1299     QDomElement originElement = nameElement.firstChildElement(
"cart:latitude_of_projection_origin");
  1301     double longitudeElementValue = longitudeElement.text().toDouble(); 
  1302     double originElementValue = originElement.text().toDouble(); 
  1305     if (!longitudeElement.text().contains(
'.')) {
  1306       QString toset1 = QString::number(longitudeElementValue, 
'f', 1); 
  1307       PvlToXmlTranslationManager::resetElementValue(longitudeElement, toset1, 
"deg"); 
  1310     if (!originElement.text().contains(
'.')) {
  1311       QString toset2 = QString::number(originElementValue, 
'f', 1); 
  1312       PvlToXmlTranslationManager::resetElementValue(originElement, toset2, 
"deg");
  1333   QDomElement ProcessExportPds4::getElement(
QStringList xmlPath, QDomElement parent) {
  1334     QDomElement baseElement = parent;
  1335     if (baseElement.isNull()) {
  1336       baseElement = m_domDoc->documentElement();
  1338     if (baseElement.isNull()) { 
  1339       QString msg = 
"Unable to get element from empty XML document."; 
  1342     QString parentName = xmlPath[0];
  1343     if (parentName != baseElement.tagName()) {
  1344       QString msg = 
"The tag name of the parent element passed in "  1345                     "must be the first value in the given XML path."; 
  1348     for (
int i = 1; i < xmlPath.size(); i++) {
  1349       QString elementName = xmlPath[i];
  1350       QDomElement nextElement = baseElement.firstChildElement(elementName);
  1351       baseElement = nextElement;
  1366     QString pds4Type(
"UNK");
  1367     if(p_pixelType == Isis::UnsignedByte) {
  1368       pds4Type = 
"UnsignedByte";
  1370     else if((p_pixelType == Isis::UnsignedWord) && (p_endianType == Isis::Msb)) {
  1371       pds4Type = 
"UnsignedMSB2";
  1373     else if((p_pixelType == Isis::UnsignedWord) && (p_endianType == Isis::Lsb)) {
  1374       pds4Type = 
"UnsignedLSB2";
  1376     else if((p_pixelType == Isis::SignedWord) && (p_endianType == Isis::Msb)) {
  1377       pds4Type = 
"SignedMSB2";
  1379     else if((p_pixelType == Isis::SignedWord) && (p_endianType == Isis::Lsb)) {
  1380       pds4Type = 
"SignedLSB2";
  1382     else if((p_pixelType == Isis::Real) && (p_endianType == Isis::Msb)) {
  1383       pds4Type = 
"IEEE754MSBSingle";
  1385     else if((p_pixelType == Isis::Real) && (p_endianType == Isis::Lsb)) {
  1386       pds4Type = 
"IEEE754LSBSingle";
  1389       QString msg = 
"Unsupported PDS pixel type or sample size";
  1405   void ProcessExportPds4::addHistory(QString description, QString date, QString version) {
  1407     QDomElement identificationElement;
  1409     identificationPath.append(
"Product_Observational");
  1410     identificationPath.append(
"Identification_Area");
  1412       identificationElement = getElement(identificationPath);
  1413       if( identificationElement.isNull() ) {
  1418       QString msg = 
"Could not find Identification_Area element "  1419                     "to add modification history under.";
  1425     QDomElement historyElement = identificationElement.firstChildElement(
"Modification_History");
  1426     if ( historyElement.isNull() ) {
  1427       historyElement = m_domDoc->createElement(
"Modification_History");
  1428       identificationElement.insertAfter( historyElement,
  1429                                          identificationElement.lastChildElement() );
  1434     QDomElement detailElement = m_domDoc->createElement(
"Modification_Detail");
  1436     QDomElement modDateElement = m_domDoc->createElement(
"modification_date");
  1437     PvlToXmlTranslationManager::setElementValue(modDateElement, date);
  1438     detailElement.appendChild(modDateElement);
  1440     QDomElement versionIdElement = m_domDoc->createElement(
"version_id");
  1441     PvlToXmlTranslationManager::setElementValue(versionIdElement, version);
  1442     detailElement.appendChild(versionIdElement);
  1444     QDomElement descriptionElement = m_domDoc->createElement(
"description");
  1445     PvlToXmlTranslationManager::setElementValue(descriptionElement, description);
  1446     detailElement.appendChild(descriptionElement);
  1448     historyElement.insertAfter( detailElement,
  1449                                 historyElement.lastChildElement() );
  1470   void ProcessExportPds4::translateUnits(QDomDocument &label, QString transMapFile) {
  1473       configPvl.
read(transMapFile);
  1476       QString msg = 
"Failed to read unit translation config file [" + transMapFile + 
"].";
  1482       transMap = createUnitMap(configPvl);
  1485       QString msg = 
"Failed to load unit translation config file [" + transMapFile + 
"].";
  1492       translateChildUnits( label.documentElement(), transMap );
  1495       QString msg = 
"Failed to translate units with config file [" + transMapFile + 
"].";
  1513     for (
int i = 0; i < configPvl.
objects(); i++) {
  1515       for (
int j = 0; j < unitObject.
groups(); j++) {
  1518           QString msg = 
"No PDS4 standard specified for for [" + unitGroup.
name() + 
"]";
  1524         transMap.insert(pds4Key[0].toLower(), pds4Key[0]);
  1528           PvlKeyword isisKey = unitGroup[
"ISIS_Units"];
  1529           for (
int k = 0; k < isisKey.
size() ; k++) {
  1530             transMap.insert(isisKey[k].toLower(), pds4Key[0]);
  1552     QDomElement childElement = parent.firstChildElement();
  1554     while( !childElement.isNull() ) {
  1555       if ( childElement.hasAttribute(
"unit") ) {
  1556         QString originalUnit = childElement.attribute(
"unit");
  1557         if ( transMap.contains( originalUnit.toLower() ) ) {
  1558           childElement.setAttribute(
"unit", transMap.value( originalUnit.toLower() ) );
  1561           QString msg = 
"Could not translate unit [" + originalUnit + 
"] to PDS4 format.";
  1565       translateChildUnits(childElement, transMap);
  1566       childElement = childElement.nextSiblingElement();
 PvlObject & object(const int index)
Return the object at the specified index. 
 
bool hasKeyword(const QString &name) const
Check to see if a keyword exists. 
 
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...
 
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes. 
 
File name manipulation and expansion. 
 
int objects() const
Returns the number of objects. 
 
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes. 
 
Namespace for the standard library. 
 
ByteOrder
Tests the current architecture for byte order. 
 
QString name() const
Returns the name of the file excluding the path and the attributes in the file name. 
 
QString toString(bool boolToConvert)
Global function to convert a boolean to a string. 
 
QString originalPath() const
Returns the path of the original file name. 
 
double toDouble(const QString &string)
Global function to convert from a string to a double. 
 
PixelType
Enumerations for Isis Pixel Types. 
 
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
 
QString name() const
Returns the container name. 
 
Base class for Map Projections. 
 
int size() const
Returns the number of values stored in this keyword. 
 
Contains multiple PvlContainers. 
 
#define _FILEINFO_
Macro for the filename and line number. 
 
A single keyword-value pair. 
 
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes. 
 
Container for cube-like labels. 
 
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name. 
 
QString baseName() const
Returns the name of the file without the path and without extensions. 
 
PvlGroup & group(const int index)
Return the group at the specified index. 
 
Allows applications to translate simple text files. 
 
void Auto(QDomDocument &outputLabel)
Automatically translate all the output names found in the translation table. 
 
Namespace for ISIS/Bullet specific routines. 
 
QString extension() const
Returns the last extension of the file name. 
 
int groups() const
Returns the number of groups contained. 
 
Contains Pvl Groups and Pvl Objects. 
 
void read(const QString &file)
Loads PVL information from a stream. 
 
virtual QString Name() const =0
This method returns the name of the map projection.