USGS

Isis 3.0 Object Programmers' Reference

Home

ProcessImportPds.cpp

Go to the documentation of this file.
00001 
00022 #include "ProcessImportPds.h"
00023 
00024 #include <QString>
00025 
00026 #include <iostream>
00027 #include <QString>
00028 #include <sstream>
00029 
00030 #include "IException.h"
00031 #include "ImportPdsTable.h"
00032 #include "IString.h"
00033 #include "LineManager.h"
00034 #include "OriginalLabel.h"
00035 #include "PixelType.h"
00036 #include "Preference.h"
00037 #include "Projection.h"
00038 #include "Pvl.h"
00039 #include "PvlObject.h"
00040 #include "PvlTokenizer.h"
00041 #include "PvlTranslationManager.h"
00042 #include "SpecialPixel.h"
00043 #include "Table.h"
00044 #include "UserInterface.h"
00045 
00046 using namespace std;
00047 namespace Isis {
00048 
00052   ProcessImportPds::ProcessImportPds() {
00053     p_keepOriginalLabel = true;
00054     p_encodingType = NONE;
00055     p_jp2File.clear();
00056 
00057     // Set up a translater for PDS file of type IMAGE
00058     Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
00059     p_transDir = (QString) dataDir["Base"];
00060   }
00061 
00062 
00063   ProcessImportPds::~ProcessImportPds() {
00064   }
00065 
00066 
00084   void ProcessImportPds::SetPdsFile(const QString &pdsLabelFile,
00085                                     const QString &pdsDataFile,
00086                                     Isis::Pvl &pdsLabel) {
00087 
00088     // Internalize the PDS label in the PVL that was passed in
00089     try {
00090       pdsLabel.Read(pdsLabelFile);
00091     }
00092     catch (IException &e) {
00093       throw IException(e, IException::User,
00094                        QObject::tr("This image does not contain a pds label.  You will need an "
00095                                    "image with a PDS label or a detached PDS label for this "
00096                                    "image."), _FILEINFO_);
00097     }
00098 
00099     // Save the label and file for future use
00100     p_pdsLabel = pdsLabel;
00101     p_labelFile = pdsLabelFile;
00102 
00103     // Create a temporary Isis::PvlTranslationManager so we can find out what
00104     // type of PDS file this is (i.e., Qube or Image or SpectralQube)
00105     stringstream trnsStrm;
00106     trnsStrm << "Group = PdsTypeImage" << endl;
00107     trnsStrm << "  InputPosition = ROOT" << endl;
00108     trnsStrm << "  InputPosition = FILE" << endl;
00109     trnsStrm << "  InputPosition = UNCOMPRESSED_FILE" << endl;
00110     trnsStrm << "  InputKey = ^IMAGE" << endl;
00111     trnsStrm << "EndGroup" << endl;
00112     trnsStrm << "Group = PdsTypeQube" << endl;
00113     trnsStrm << "  InputKey = ^QUBE" << endl;
00114     trnsStrm << "EndGroup" << endl;
00115     trnsStrm << "Group = PdsTypeSpectralQube" << endl;
00116     trnsStrm << "  InputKey = ^SPECTRAL_QUBE" << endl;
00117     trnsStrm << "EndGroup" << endl;
00118     trnsStrm << "Group = PdsEncodingType" << endl;
00119     trnsStrm << "  InputPosition = COMPRESSED_FILE" << endl;
00120     trnsStrm << "  InputKey = ENCODING_TYPE" << endl;
00121     trnsStrm << "  Translation = (*,*)" << endl;
00122     trnsStrm << "EndGroup" << endl;
00123     trnsStrm << "Group = PdsCompressedFile" << endl;
00124     trnsStrm << "  InputPosition = COMPRESSED_FILE" << endl;
00125     trnsStrm << "  InputKey = FILE_NAME" << endl;
00126     trnsStrm << "  Translation = (*,*)" << endl;
00127     trnsStrm << "EndGroup" << endl;
00128     trnsStrm << "END";
00129 
00130     Isis::PvlTranslationManager pdsXlater(p_pdsLabel, trnsStrm);
00131 
00132     // Check to see if we are dealing with a JPEG2000 file
00133     QString str;
00134     if(pdsXlater.InputHasKeyword("PdsEncodingType")) {
00135       str = pdsXlater.Translate("PdsEncodingType");
00136       if(str == "JP2") {
00137         p_encodingType = JP2;
00138         str = pdsXlater.Translate("PdsCompressedFile");
00139         if(pdsDataFile.isEmpty()) {
00140           Isis::FileName lfile(p_labelFile);
00141           Isis::FileName ifile(lfile.path() + "/" + str);
00142           if(ifile.fileExists()) {
00143             p_jp2File = ifile.expanded();
00144           }
00145           else {
00146             QString tmp = ifile.expanded();
00147             str = str.toLower();
00148             ifile = lfile.path() + "/" + str;
00149             if(ifile.fileExists()) {
00150               p_jp2File = ifile.expanded();
00151             }
00152             else {
00153               QString msg = "Unable to find input file [" + tmp + "] or [" +
00154                            ifile.expanded() + "]";
00155               throw IException(IException::Io, msg, _FILEINFO_);
00156             }
00157           }
00158         }
00159       }
00160       else {
00161         QString msg = "Unsupported encoding type in [" + p_labelFile + "]";
00162         throw IException(IException::Io, msg, _FILEINFO_);
00163       }
00164     }
00165 
00166     // Call the correct label processing
00167     if(pdsXlater.InputHasKeyword("PdsTypeImage")) {
00168       ProcessPdsImageLabel(pdsDataFile);
00169     }
00170     else if(pdsXlater.InputHasKeyword("PdsTypeQube")) {
00171       ProcessPdsQubeLabel(pdsDataFile, "pdsQube.trn");
00172     }
00173     else if(pdsXlater.InputHasKeyword("PdsTypeSpectralQube")) {
00174       ProcessPdsQubeLabel(pdsDataFile, "pdsSpectralQube.trn");
00175     }
00176     else {
00177       QString msg = "Unknown label type in [" + p_labelFile + "]";
00178       throw IException(IException::Io, msg, _FILEINFO_);
00179     }
00180 
00181     // Find out if this is a PDS file or an ISIS2 file
00182     IdentifySource(p_pdsLabel);
00183 
00184     return;
00185   }
00186 
00193   void ProcessImportPds::ProcessDataFilePointer(Isis::PvlTranslationManager & pdsXlater, const bool & calcOffsetOnly) {
00194     const PvlKeyword & dataFilePointer = pdsXlater.InputKeyword("DataFilePointer");
00195 
00196     QString dataFileName;
00197     QString units;
00198     QString str;
00199     int offset = -1;
00200 
00201     // If only size 1, we either have a file name or an offset
00202     // Either way, when we're done with these two ifs, variables offset and
00203     // dataFileName will be set.
00204     if (dataFilePointer.Size() == 1) {
00205       try {
00206         str = pdsXlater.Translate("DataFilePointer");
00207         offset = toInt(str);
00208         units = dataFilePointer.Unit();
00209         // Successful? we have an offset, means current, p_labelFile
00210         // is the location of the data as well
00211         dataFileName = FileName(p_labelFile).name();
00212       }
00213       catch(IException &e) {
00214         // Failed to parse to an int, means we have a file name
00215         // No offset given, so we use 1, offsets are 1 based
00216         offset = 1;
00217         units = "BYTES";
00218         dataFileName = str;
00219       }
00220     }
00221     // We must have a filename and an offset, in that order
00222     // Expection ("filname", <offset>)
00223     else if (dataFilePointer.Size() == 2) {
00224       dataFileName = pdsXlater.Translate("DataFilePointer", 0);
00225       offset = IString(pdsXlater.Translate("DataFilePointer", 1)).ToInteger();
00226       units = dataFilePointer.Unit(1);
00227     }
00228     // Error, no value
00229     else if (dataFilePointer.Size() == 0) {
00230       QString msg = "Data file pointer ^IMAGE or ^QUBE has no value, must"
00231                    "have either file name or offset or both, in [" +
00232                    p_labelFile + "]";
00233       throw IException(IException::Unknown, msg, _FILEINFO_);
00234     }
00235     // Error, more than two values
00236     else {
00237       QString msg = "Improperly formatted data file pointer keyword ^IMAGE or "
00238                    "^QUBE, in [" + p_labelFile + "], must contain filename "
00239                    " or offset or both";
00240       throw IException(IException::Unknown, msg, _FILEINFO_);
00241     }
00242 
00243     // Now, to handle the values we found
00244     // the filename first, only do so if calcOffsetOnly is false
00245     if (!calcOffsetOnly) {
00246       Isis::FileName labelFile(p_labelFile);
00247 
00248       // If dataFileName isn't empty, and does start at the root, use it
00249       Isis::FileName dataFile;
00250       if (dataFileName.size() != 0 && dataFileName.at(0) == '/')
00251         dataFile = FileName(dataFileName);
00252       // Otherwise, use the path to it and its name
00253       else
00254         dataFile = FileName(labelFile.path() + "/" + dataFileName);
00255 
00256       // If it exists, use it
00257       if (dataFile.fileExists()) {
00258         SetInputFile(dataFile.expanded());
00259       }
00260       // Retry with downcased name, if still no luck, fail
00261       else {
00262         QString tmp = dataFile.expanded();
00263         dataFileName = dataFileName.toLower();
00264         dataFile = FileName(labelFile.path() + "/" + dataFileName);
00265         if (dataFile.fileExists()) {
00266           SetInputFile(dataFile.expanded());
00267         }
00268         else {
00269           QString msg = "Unable to find input file [" + tmp + "] or [" +
00270                        dataFile.expanded() + "]";
00271           throw IException(IException::Io, msg, _FILEINFO_);
00272         }
00273       }
00274     }
00275 
00276     // Now, to handle the offset
00277     units = units.trimmed();
00278     if (units == "BYTES" || units == "B") {
00279       SetFileHeaderBytes(offset - 1);
00280     }
00281     else {
00282       QString recSize = pdsXlater.Translate("DataFileRecordBytes");
00283       SetFileHeaderBytes((offset - 1) * toInt(recSize));
00284     }
00285   }
00286 
00291   void ProcessImportPds::ProcessPixelBitandType(Isis::PvlTranslationManager & pdsXlater) {
00292     QString str;
00293     str = pdsXlater.Translate("CoreBitsPerPixel");
00294     int bitsPerPixel = toInt(str);
00295     str = pdsXlater.Translate("CorePixelType");
00296     if((str == "Real") && (bitsPerPixel == 32)) {
00297       SetPixelType(Isis::Real);
00298     }
00299     else if((str == "Integer") && (bitsPerPixel == 8)) {
00300       SetPixelType(Isis::UnsignedByte);
00301     }
00302     else if((str == "Integer") && (bitsPerPixel == 16)) {
00303       SetPixelType(Isis::SignedWord);
00304     }
00305     else if((str == "Integer") && (bitsPerPixel == 32)) {
00306       SetPixelType(Isis::SignedInteger);
00307     }
00308     else if((str == "Natural") && (bitsPerPixel == 8)) {
00309       SetPixelType(Isis::UnsignedByte);
00310     }
00311     else if((str == "Natural") && (bitsPerPixel == 16)) {
00312       SetPixelType(Isis::UnsignedWord);
00313     }
00314     else if((str == "Natural") && (bitsPerPixel == 16)) {
00315       SetPixelType(Isis::SignedWord);
00316     }
00317     else if((str == "Natural") && (bitsPerPixel == 32)) {
00318       SetPixelType(Isis::UnsignedInteger);
00319     }
00320     else {
00321       QString msg = "Invalid PixelType and BitsPerPixel combination [" + str +
00322                    ", " + toString(bitsPerPixel) + "]";
00323       throw IException(IException::Io, msg, _FILEINFO_);
00324     }
00325   }
00326 
00330   void ProcessImportPds::ProcessSpecialPixels(Isis::PvlTranslationManager & pdsXlater, const bool & isQube) {
00331     QString str;
00332     // Set any special pixel values
00333     double pdsNull = Isis::NULL8;
00334     if(pdsXlater.InputHasKeyword("CoreNull")) {
00335       str = pdsXlater.Translate("CoreNull");
00336       if(str != "NULL") {
00337         pdsNull = toDouble(str);
00338       }
00339     }
00340     else if(!isQube && pdsXlater.InputHasKeyword("CoreNull2")) {
00341       str = pdsXlater.Translate("CoreNull2");
00342       if(str != "NULL") {
00343         pdsNull = toDouble(str);
00344       }
00345     }
00346 
00347     double pdsLrs = Isis::Lrs;
00348     if(pdsXlater.InputHasKeyword("CoreLrs")) {
00349       str = pdsXlater.Translate("CoreLrs");
00350       if(str != "NULL") {
00351         pdsLrs = toDouble(str);
00352       }
00353     }
00354     else if(!isQube && pdsXlater.InputHasKeyword("CoreLrs2")) {
00355       str = pdsXlater.Translate("CoreLrs2");
00356       if(str != "NULL") {
00357         pdsLrs = toDouble(str);
00358       }
00359     }
00360 
00361     double pdsLis = Isis::Lis;
00362     if(pdsXlater.InputHasKeyword("CoreLis")) {
00363       str = pdsXlater.Translate("CoreLis");
00364       if(str != "NULL") {
00365         pdsLis = toDouble(str);
00366       }
00367     }
00368     else if(!isQube && pdsXlater.InputHasKeyword("CoreLis2")) {
00369       str = pdsXlater.Translate("CoreLis2");
00370       if(str != "NULL") {
00371         pdsLis = toDouble(str);
00372       }
00373     }
00374 
00375     double pdsHrs = Isis::Hrs;
00376     if(pdsXlater.InputHasKeyword("CoreHrs")) {
00377       str = pdsXlater.Translate("CoreHrs");
00378       if(str != "NULL") {
00379         pdsHrs = toDouble(str);
00380       }
00381     }
00382     else if(!isQube && pdsXlater.InputHasKeyword("CoreHrs2")) {
00383       str = pdsXlater.Translate("CoreHrs2");
00384       if(str != "NULL") {
00385         pdsHrs = toDouble(str);
00386       }
00387     }
00388 
00389     double pdsHis = Isis::His;
00390     if(pdsXlater.InputHasKeyword("CoreHis")) {
00391       str = pdsXlater.Translate("CoreHis");
00392       if(str != "NULL") {
00393         pdsHis = toDouble(str);
00394       }
00395     }
00396     else if(!isQube && pdsXlater.InputHasKeyword("CoreHis2")) {
00397       str = pdsXlater.Translate("CoreHis2");
00398       if(str != "NULL") {
00399         pdsHis = toDouble(str);
00400       }
00401     }
00402 
00403     SetSpecialValues(pdsNull, pdsLrs, pdsLis, pdsHrs, pdsHis);
00404   }
00405 
00417   void ProcessImportPds::ProcessPdsImageLabel(const QString &pdsDataFile) {
00418     Isis::FileName transFile(p_transDir + "/translations/pdsImage.trn");
00419     Isis::PvlTranslationManager pdsXlater(p_pdsLabel, transFile.expanded());
00420 
00421     QString str;
00422 
00423     str = pdsXlater.Translate("CoreLinePrefixBytes");
00424     SetDataPrefixBytes(toInt(str));
00425 
00426     str = pdsXlater.Translate("CoreLineSuffixBytes");
00427     SetDataSuffixBytes(toInt(str));
00428 
00429     ProcessPixelBitandType(pdsXlater);
00430 
00431     str = pdsXlater.Translate("CoreByteOrder");
00432     SetByteOrder(Isis::ByteOrderEnumeration(str));
00433 
00434     str = pdsXlater.Translate("CoreSamples");
00435     int ns = toInt(str);
00436     str = pdsXlater.Translate("CoreLines");
00437     int nl = toInt(str);
00438     str = pdsXlater.Translate("CoreBands");
00439     int nb = toInt(str);
00440     SetDimensions(ns, nl, nb);
00441 
00442     // Set any special pixel values, not qube, so use false
00443     ProcessSpecialPixels(pdsXlater, false);
00444 
00445     //-----------------------------------------------------------------
00446     // Find the data filename it may be the same as the label file
00447     // OR the label file may contain a pointer to the data
00448     //-----------------------------------------------------------------
00449 
00450     // Use the name supplied by the application if it is there
00451     if(pdsDataFile.length() > 0) {
00452       SetInputFile(pdsDataFile);
00453       ProcessDataFilePointer(pdsXlater, true);
00454     }
00455     // If the data is in JPEG 2000 format, then use the name of the file
00456     // from the label
00457     else if(p_jp2File.length() > 0) {
00458       SetInputFile(p_jp2File);
00459       ProcessDataFilePointer(pdsXlater, true);
00460     }
00461     // Use the "^IMAGE or ^QUBE" label to get the filename for the image data
00462     // Get the path portion from user entered label file spec
00463     else {
00464       // Handle filename and offset
00465       ProcessDataFilePointer(pdsXlater, false);
00466     }
00467 
00468     //------------------------------------------------------------
00469     // Find the image data base and multiplier
00470     //------------------------------------------------------------
00471     str = pdsXlater.Translate("CoreBase");
00472     SetBase(toDouble(str));
00473     str = pdsXlater.Translate("CoreMultiplier");
00474     SetMultiplier(toDouble(str));
00475 
00476     // Find the organization of the image data
00477     str = pdsXlater.Translate("CoreOrganization");
00478 
00479     if(p_encodingType == JP2) {
00480       SetOrganization(ProcessImport::JP2);
00481     }
00482     else if(str == "BSQ") {
00483       SetOrganization(ProcessImport::BSQ);
00484     }
00485     else if(str == "BIP") {
00486       SetOrganization(ProcessImport::BIP);
00487     }
00488     else if(str == "BIL") {
00489       SetOrganization(ProcessImport::BIL);
00490     }
00491     else {
00492       QString msg = "Unsupported axis order [" + str + "]";
00493       throw IException(IException::Programmer, msg, _FILEINFO_);
00494     }
00495   }
00496 
00497 
00514   void ProcessImportPds::ProcessPdsQubeLabel(const QString &pdsDataFile,
00515       const QString &transFile) {
00516 
00517     Isis::FileName tFile(p_transDir + "/translations/" + transFile);
00518 
00519     Isis::PvlTranslationManager pdsXlater(p_pdsLabel, tFile.expanded());
00520 
00521     QString str;
00522 
00523     // Find the organization of the image data
00524     // Save off which axis the samples, lines and bands are on
00525     int linePos = 0;
00526     int samplePos = 0;
00527     int bandPos = 0;
00528     int val = pdsXlater.InputKeyword("CoreOrganization").Size();
00529     QString tmp = "";
00530     for(int i = 0; i < val; i++) {
00531       str = pdsXlater.Translate("CoreOrganization", i);
00532       tmp += str;
00533       if(str == "SAMPLE") {
00534         samplePos = i;
00535       }
00536       else if(str == "LINE") {
00537         linePos = i;
00538       }
00539       else if(str == "BAND") {
00540         bandPos = i;
00541       }
00542       else {
00543         QString message = "Unknown file axis name [" + str + "]";
00544         throw IException(IException::User, message, _FILEINFO_);
00545       }
00546     }
00547 
00548     if(p_encodingType == JP2) {
00549       SetOrganization(ProcessImport::JP2);
00550     }
00551     else if(tmp == "SAMPLELINEBAND") {
00552       SetOrganization(ProcessImport::BSQ);
00553     }
00554     else if(tmp == "BANDSAMPLELINE") {
00555       SetOrganization(ProcessImport::BIP);
00556     }
00557     else if(tmp == "SAMPLEBANDLINE") {
00558       SetOrganization(ProcessImport::BIL);
00559     }
00560     else {
00561       PvlKeyword pdsCoreOrg = p_pdsLabel.FindKeyword(pdsXlater.
00562           InputKeywordName("CoreOrganization"), Pvl::Traverse);
00563 
00564       stringstream pdsCoreOrgStream;
00565       pdsCoreOrgStream << pdsCoreOrg;
00566 
00567       QString msg = "Unsupported axis order [" + QString(pdsCoreOrgStream.str().c_str()) + "]";
00568       throw IException(IException::Programmer, msg, _FILEINFO_);
00569     }
00570 
00571 
00572     // Set the number of byte preceding the second dimension (left side plane)
00573     // There are no capabilities in a PDS QUBE for this
00574     SetDataPrefixBytes(0);
00575 
00576     // Set the number of bytes following the second dimension (right side plane)
00577     str = pdsXlater.Translate("SuffixItemSize");
00578     int suffix = toInt(str);
00579     str = pdsXlater.Translate("AxisSuffixCount", 0);
00580     suffix *= toInt(str);
00581     SetDataSuffixBytes(suffix);
00582 
00583     str = pdsXlater.Translate("SuffixItemSize");
00584     int trailer = toInt(str);
00585     str = pdsXlater.Translate("AxisSuffixCount", 1);
00586     trailer *= toInt(str);
00587     str = pdsXlater.Translate("CoreSamples", samplePos);
00588     trailer *= toInt(str);
00589     trailer += suffix;
00590     SetDataTrailerBytes(trailer);
00591 
00592     ProcessPixelBitandType(pdsXlater);
00593 
00594     // Set the byte order
00595     str = pdsXlater.Translate("CoreByteOrder");
00596     SetByteOrder(Isis::ByteOrderEnumeration(str));
00597 
00598     // Set the number of samples, lines and bands
00599     str = pdsXlater.Translate("CoreSamples", samplePos);
00600     int ns = toInt(str);
00601     str = pdsXlater.Translate("CoreLines", linePos);
00602     int nl = toInt(str);
00603     str = pdsXlater.Translate("CoreBands", bandPos);
00604     int nb = toInt(str);
00605     SetDimensions(ns, nl, nb);
00606 
00607     // Set any special pixels values, qube, so use true
00608     ProcessSpecialPixels(pdsXlater, true);
00609 
00610     //---------------------------------------------------------------
00611     // Find the data filename, it may be the same as the label file
00612     // Or the label file may contain a pointer to the data
00613     //---------------------------------------------------------------
00614 
00615     // Use the name supplied by the application if it is there
00616     if(pdsDataFile.length() > 0) {
00617       SetInputFile(pdsDataFile);
00618       ProcessDataFilePointer(pdsXlater, true);
00619     }
00620     // If the data is in JPEG 2000 format, then use the name of the file
00621     // from the label
00622     else if(p_jp2File.length() > 0) {
00623       SetInputFile(p_jp2File);
00624       ProcessDataFilePointer(pdsXlater, true);
00625     }
00626     else {
00627       // Handle filename and offset
00628       ProcessDataFilePointer(pdsXlater, false);
00629     }
00630 
00631 
00632     //------------------------------------------------------------
00633     // Find the image data base and multiplier
00634     //------------------------------------------------------------
00635     // First see if there are base and multiplier in the band bin group
00636     if((pdsXlater.InputHasKeyword("BandBase")) &&
00637         (pdsXlater.InputHasKeyword("BandMultiplier"))) {
00638       vector<double> bases;
00639       vector<double> mults;
00640       for(int i = 0; i < pdsXlater.InputKeyword("BandBase").Size(); i++) {
00641         str = pdsXlater.Translate("BandBase", i);
00642         bases.push_back(toDouble(str));
00643         str = pdsXlater.Translate("BandMultiplier", i);
00644         mults.push_back(toDouble(str));
00645       }
00646       SetBase(bases);
00647       SetMultiplier(mults);
00648     }
00649     else {
00650       str = pdsXlater.Translate("CoreBase");
00651       SetBase(toDouble(str));
00652       str = pdsXlater.Translate("CoreMultiplier");
00653       SetMultiplier(toDouble(str));
00654     }
00655   }
00656 
00668   void ProcessImportPds::TranslatePdsProjection(Isis::Pvl &lab) {
00669 
00670     // Create a temporary Isis::PvlTranslationManager so we can find out what
00671     // type of projection labels exist
00672     stringstream trnsStrm;
00673     trnsStrm << "Group = PdsProjectionTypeImage" << endl;
00674     trnsStrm << "  InputPosition = IMAGE_MAP_PROJECTION" << endl;
00675     trnsStrm << "  InputPosition = IMAGE_MAP_PROJECTION_CATALOG" << endl;
00676     trnsStrm << "  InputKey = MAP_PROJECTION_TYPE" << endl;
00677     trnsStrm << "EndGroup" << endl;
00678     trnsStrm << "Group = PdsProjectionTypeQube" << endl;
00679     trnsStrm << "  InputPosition = (QUBE,IMAGE_MAP_PROJECTION)" << endl;
00680     trnsStrm << "  InputKey = MAP_PROJECTION_TYPE" << endl;
00681     trnsStrm << "EndGroup" << endl;
00682     trnsStrm << "Group = PdsProjectionTypeSpectralQube" << endl;
00683     trnsStrm << "  InputPosition = (SPECTRAL_QUBE,IMAGE_MAP_PROJECTION)" << endl;
00684     trnsStrm << "  InputKey = MAP_PROJECTION_TYPE" << endl;
00685     trnsStrm << "EndGroup" << endl;
00686     trnsStrm << "END";
00687 
00688     Isis::PvlTranslationManager projType(p_pdsLabel, trnsStrm);
00689 
00690     // Set up the correct projection translation table for this label
00691     Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
00692     QString transDir = (QString) dataDir["Base"];
00693 
00694     Isis::FileName transFile;
00695     if(projType.InputHasKeyword("PdsProjectionTypeImage")) {
00696       transFile = transDir + "/" + "translations/pdsImageProjection.trn";
00697     }
00698     else if(projType.InputHasKeyword("PdsProjectionTypeQube")) {
00699       transFile = transDir + "/" + "translations/pdsQubeProjection.trn";
00700     }
00701     else if(projType.InputHasKeyword("PdsProjectionTypeSpectralQube")) {
00702       transFile = transDir + "/" + "translations/pdsSpectralQubeProjection.trn";
00703     }
00704     else {
00705       return;
00706     }
00707 
00708     Isis::PvlTranslationManager pdsXlater(p_pdsLabel, transFile.expanded());
00709 
00710     ExtractPdsProjection(pdsXlater);
00711 
00712     Isis::PvlGroup mapGroup("Mapping");
00713     mapGroup += Isis::PvlKeyword("ProjectionName", p_projection);
00714     mapGroup += Isis::PvlKeyword("TargetName", p_targetName);
00715     mapGroup += Isis::PvlKeyword("EquatorialRadius", toString(p_equatorialRadius), "meters");
00716     mapGroup += Isis::PvlKeyword("PolarRadius", toString(p_polarRadius), "meters");
00717     mapGroup += Isis::PvlKeyword("LongitudeDirection", p_longitudeDirection);
00718     mapGroup += Isis::PvlKeyword("LongitudeDomain", toString(p_longitudeDomain));
00719     mapGroup += Isis::PvlKeyword("LatitudeType", p_latitudeType);
00720     if(p_minimumLatitude != Isis::NULL8) {
00721       mapGroup += Isis::PvlKeyword("MinimumLatitude", toString(p_minimumLatitude));
00722     }
00723     if(p_maximumLatitude != Isis::NULL8) {
00724       mapGroup += Isis::PvlKeyword("MaximumLatitude", toString(p_maximumLatitude));
00725     }
00726     if(p_minimumLongitude != Isis::NULL8) {
00727       mapGroup += Isis::PvlKeyword("MinimumLongitude", toString(p_minimumLongitude));
00728     }
00729     if(p_maximumLongitude != Isis::NULL8) {
00730       mapGroup += Isis::PvlKeyword("MaximumLongitude", toString(p_maximumLongitude));
00731     }
00732 
00733     // if both longitudes exist, verify they are ordered correctly
00734     if(p_minimumLongitude != Isis::NULL8 && p_maximumLongitude != Isis::NULL8) {
00735       if(p_maximumLongitude <= p_minimumLongitude) {
00736         if(p_longitudeDomain == 180) {
00737           mapGroup["MinimumLongitude"] = toString(-180);
00738           mapGroup["MaximumLongitude"] = toString(180);
00739         }
00740         else {
00741           mapGroup["MinimumLongitude"] = toString(0);
00742           mapGroup["MaximumLongitude"] = toString(360);
00743         }
00744       }
00745     }
00746 
00747     mapGroup += Isis::PvlKeyword("PixelResolution", toString(p_pixelResolution), "meters/pixel");
00748     mapGroup += Isis::PvlKeyword("Scale", toString(p_scaleFactor), "pixels/degree");
00749     mapGroup += Isis::PvlKeyword("UpperLeftCornerX", toString(p_upperLeftX), "meters");
00750     mapGroup += Isis::PvlKeyword("UpperLeftCornerY", toString(p_upperLeftY), "meters");
00751     if(p_rotation != 0.0) {
00752       mapGroup += Isis::PvlKeyword("Rotation", toString(p_rotation));
00753     }
00754 
00755     // To handle new projections without the need to modify source code
00756     // we will construct a filename from the projection.  The filename will
00757     // contain the projection specific translations from PDS to ISIS for each
00758     // projection
00759 
00760     QString projSpecificFileName = "$base/translations/pdsImport";
00761     projSpecificFileName += p_projection + ".trn";
00762     Isis::PvlTranslationManager specificXlater(p_pdsLabel, projSpecificFileName);
00763 
00764     lab.AddGroup(mapGroup);
00765     specificXlater.Auto(lab);
00766 
00767     if(lab.FindGroup("Mapping").HasKeyword("CenterLongitude")) {
00768       PvlKeyword &centerLon = lab.FindGroup("Mapping")["CenterLongitude"];
00769       if(p_longitudeDomain == 180)
00770         centerLon = toString(Projection::To180Domain((double)centerLon));
00771       else
00772         centerLon = toString(Projection::To360Domain((double)centerLon));
00773     }
00774 
00775     if(lab.FindGroup("Mapping").HasKeyword("PoleLongitude")) {
00776       PvlKeyword &poleLon = lab.FindGroup("Mapping")["PoleLongitude"];
00777       if(p_longitudeDomain == 180)
00778         poleLon = toString(Projection::To180Domain((double)poleLon));
00779       else
00780         poleLon = toString(Projection::To360Domain((double)poleLon));
00781     }
00782 
00783     OutputCubes[0]->putGroup(lab.FindGroup("Mapping"));
00784   }
00785 
00810   void ProcessImportPds::ExtractPdsProjection(Isis::PvlTranslationManager &pdsXlater) {
00811 
00812     QString str;
00813 
00814     if(pdsXlater.InputHasKeyword("ProjectionName")) {
00815       p_projection = pdsXlater.Translate("ProjectionName");
00816     }
00817     else {
00818       QString message = "No projection name in labels";
00819       throw IException(IException::Unknown, message, _FILEINFO_);
00820     }
00821 
00822     if(pdsXlater.InputHasKeyword("TargetName")) {
00823       p_targetName = pdsXlater.Translate("TargetName");
00824     }
00825     else {
00826       QString message = "No target name in labels";
00827       throw IException(IException::Unknown, message, _FILEINFO_);
00828     }
00829 
00830     if(pdsXlater.InputHasKeyword("EquatorialRadius")) {
00831       str = pdsXlater.Translate("EquatorialRadius");
00832       p_equatorialRadius = toDouble(str) * 1000.0;
00833     }
00834     else {
00835       QString message = "No equatorial radius name in labels";
00836       throw IException(IException::User, message, _FILEINFO_);
00837     }
00838 
00839     if(pdsXlater.InputHasKeyword("PolarRadius")) {
00840       str = pdsXlater.Translate("PolarRadius");
00841       p_polarRadius = toDouble(str) * 1000.0;
00842     }
00843     else {
00844       QString message = "No polar radius in labels";
00845       throw IException(IException::User, message, _FILEINFO_);
00846     }
00847 
00848     if(pdsXlater.InputHasKeyword("LongitudeDirection")) {
00849       p_longitudeDirection = pdsXlater.Translate("LongitudeDirection");
00850     }
00851     else {
00852       p_longitudeDirection = pdsXlater.Translate("LongitudeDirection2");
00853     }
00854 
00855     if(p_polarRadius == p_equatorialRadius) {
00856       p_latitudeType = "Planetocentric";
00857     }
00858     else if(pdsXlater.InputHasKeyword("LatitudeType2")) {
00859       p_latitudeType = pdsXlater.Translate("LatitudeType2");
00860     }
00861     else {
00862       p_latitudeType = pdsXlater.Translate("LatitudeType");
00863     }
00864 
00865     if(pdsXlater.InputHasKeyword("MinimumLatitude")) {
00866       str = pdsXlater.Translate("MinimumLatitude");
00867       try {
00868         p_minimumLatitude = toDouble(str);
00869       }
00870       catch(IException &e) {
00871         p_minimumLatitude = Isis::NULL8;
00872       }
00873     }
00874     else {
00875       p_minimumLatitude = Isis::NULL8;
00876     }
00877 
00878     if(pdsXlater.InputHasKeyword("MaximumLatitude")) {
00879       str = pdsXlater.Translate("MaximumLatitude");
00880       try {
00881         p_maximumLatitude = toDouble(str);
00882       }
00883       catch(IException &e) {
00884         p_maximumLatitude = Isis::NULL8;
00885       }
00886     }
00887     else {
00888       p_maximumLatitude = Isis::NULL8;
00889     }
00890 
00891     // This variable represents if the longitudes were read in as
00892     //   positive west
00893     bool positiveWest = false;
00894     if(pdsXlater.InputHasKeyword("MinimumLongitude")) {
00895       str = pdsXlater.Translate("MinimumLongitude");
00896       try {
00897         positiveWest = true;
00898         p_minimumLongitude = toDouble(str);
00899       }
00900       catch(IException &e) {
00901         p_minimumLongitude = Isis::NULL8;
00902       }
00903     }
00904     else if(pdsXlater.InputHasKeyword("MinimumLongitude2")) {
00905       str = pdsXlater.Translate("MinimumLongitude2");
00906       try {
00907         p_minimumLongitude = toDouble(str);
00908       }
00909       catch(IException &e) {
00910         p_minimumLongitude = Isis::NULL8;
00911       }
00912     }
00913     else {
00914       p_minimumLongitude = Isis::NULL8;
00915     }
00916 
00917     if(pdsXlater.InputHasKeyword("MaximumLongitude")) {
00918       str = pdsXlater.Translate("MaximumLongitude");
00919       try {
00920         positiveWest = true;
00921         p_maximumLongitude = toDouble(str);
00922       }
00923       catch(IException &e) {
00924         p_maximumLongitude = Isis::NULL8;
00925       }
00926     }
00927     else if(pdsXlater.InputHasKeyword("MaximumLongitude2")) {
00928       str = pdsXlater.Translate("MaximumLongitude2");
00929       try {
00930         p_maximumLongitude = toDouble(str);
00931       }
00932       catch(IException &e) {
00933         p_maximumLongitude = Isis::NULL8;
00934       }
00935     }
00936     else {
00937       p_maximumLongitude = Isis::NULL8;
00938     }
00939 
00940     str = pdsXlater.Translate("LongitudeDomain");
00941     p_longitudeDomain = toInt(str);
00942 
00961     if(positiveWest && (p_longitudeDirection.compare("PositiveEast") == 0)) {
00962       double tmp = p_minimumLongitude;
00963       p_minimumLongitude = p_maximumLongitude;
00964       p_maximumLongitude = tmp;
00965     }
00966 
00967     if(p_minimumLongitude > p_maximumLongitude) {
00968       // Force the change to 180
00969       p_longitudeDomain = 180;
00970       p_minimumLongitude = Isis::Projection::To180Domain(p_minimumLongitude);
00971     }
00972 
00973     //  If either the minimumLongitude or maximumLongitude are < 0, change
00974     //  longitude Domain to 180.
00975     if(p_minimumLongitude < 0 || p_maximumLongitude < 0) {
00976       p_longitudeDomain = 180;
00977     }
00978 
00979     str = pdsXlater.Translate("PixelResolution");
00980     p_pixelResolution = toDouble(str);
00981     str = pdsXlater.InputKeyword("PixelResolution").Unit().toUpper();
00982     // Assume KM/PIXEL if the unit doesn't exist or is not METERS/PIXEL
00983     if((str != "METERS/PIXEL") && (str != "M/PIXEL") && (str != "M/PIX")) {
00984       p_pixelResolution *= 1000.0;
00985     }
00986 
00987     str = pdsXlater.Translate("Scale");
00988     p_scaleFactor = toDouble(str);
00989 
00990     try {
00991       str = pdsXlater.Translate("Rotation");
00992       p_rotation = toDouble(str);
00993     }
00994     catch(IException &) {
00995       // assume no rotation if the value isn't a number
00996       p_rotation = 0.0;
00997     }
00998 
00999     //  Look for projection offsets/mults to convert between line/samp and x/y
01000     double xoff, yoff, xmult, ymult;
01001     GetProjectionOffsetMults(xoff, yoff, xmult, ymult);
01002 
01003     if(pdsXlater.InputHasKeyword("LineProjectionOffset")) {
01004       str = pdsXlater.Translate("LineProjectionOffset");
01005     }
01006     else {
01007       str = pdsXlater.Translate("LineProjectionOffset2");
01008     }
01009     p_lineProjectionOffset = toDouble(str);
01010     p_upperLeftY = ymult * (p_lineProjectionOffset + yoff) * p_pixelResolution;
01011 
01012     if(pdsXlater.InputHasKeyword("SampleProjectionOffset")) {
01013       str = pdsXlater.Translate("SampleProjectionOffset");
01014     }
01015     else {
01016       str = pdsXlater.Translate("SampleProjectionOffset2");
01017     }
01018     p_sampleProjectionOffset = toDouble(str);
01019     p_upperLeftX = xmult * (p_sampleProjectionOffset + xoff) * p_pixelResolution;
01020 
01021 
01022   }
01023 
01029   void ProcessImportPds::EndProcess() {
01030     if(p_keepOriginalLabel) {
01031       OriginalLabel ol(p_pdsLabel);
01032       for(unsigned int i = 0; i < OutputCubes.size(); i++) {
01033         OutputCubes[i]->write(ol);
01034       }
01035     }
01036     Process::EndProcess();
01037   }
01038 
01043   void ProcessImportPds::OmitOriginalLabel() {
01044     p_keepOriginalLabel = false;
01045   }
01046 
01047 
01054   void ProcessImportPds::IdentifySource(Isis::Pvl &inputLabel) {
01055 
01056     // Create a temporary Isis::PvlTranslationManager so we can find out what
01057     // type of input file we have
01058     stringstream trnsStrm;
01059     trnsStrm << "Group = PdsFile" << endl;
01060     trnsStrm << "  InputPosition = ROOT" << endl;
01061     trnsStrm << "  InputKey = PDS_VERSION_ID" << endl;
01062     trnsStrm << "EndGroup" << endl;
01063     trnsStrm << "Group = Isis2File" << endl;
01064     trnsStrm << "  InputPosition = ROOT" << endl;
01065     trnsStrm << "  InputKey = CCSD3ZF0000100000001NJPL3IF0PDS200000001" << endl;
01066     trnsStrm << "EndGroup" << endl;
01067     trnsStrm << "END";
01068 
01069     Isis::PvlTranslationManager sourceXlater(inputLabel, trnsStrm);
01070 
01071     if(sourceXlater.InputHasKeyword("PdsFile")) {
01072       p_source = PDS;
01073     }
01074     else if(sourceXlater.InputHasKeyword("Isis2File")) {
01075       p_source = ISIS2;
01076     }
01077     else {
01078       p_source = NOSOURCE;
01079     }
01080 
01081   }
01082 
01091   bool ProcessImportPds::IsIsis2() {
01092 
01093     if(p_source == ISIS2) {
01094       return true;
01095     }
01096     else {
01097       return false;
01098     }
01099   }
01100 
01101 
01102 
01110   void ProcessImportPds::TranslateIsis2Labels(Isis::Pvl &lab) {
01111     TranslateIsis2BandBin(lab);
01112     TranslateIsis2Instrument(lab);
01113   }
01114 
01115 
01116 
01124   void ProcessImportPds::TranslatePdsLabels(Isis::Pvl &lab) {
01125     TranslatePdsBandBin(lab);
01126     TranslatePdsArchive(lab);
01127   }
01128 
01135   void ProcessImportPds::TranslateIsis2BandBin(Isis::Pvl &lab) {
01136     // Set up a translater for Isis2 labels
01137     Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
01138     QString transDir = (QString) dataDir["Base"];
01139 
01140     Isis::FileName transFile(transDir + "/" + "translations/isis2bandbin.trn");
01141     Isis::PvlTranslationManager isis2Xlater(p_pdsLabel, transFile.expanded());
01142 
01143     // Add all the Isis2 keywords that can be translated to the requested label
01144     isis2Xlater.Auto(lab);
01145   }
01146 
01153   void ProcessImportPds::TranslateIsis2Instrument(Isis::Pvl &lab) {
01154     // Set up a translater for Isis2 labels
01155     Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
01156     QString transDir = (QString) dataDir["Base"];
01157     Isis::FileName transFile(transDir + "/" + "translations/isis2instrument.trn");
01158     Isis::PvlTranslationManager isis2Xlater(p_pdsLabel, transFile.expanded());
01159 
01160     // Add all the Isis2 keywords that can be translated to the requested label
01161     isis2Xlater.Auto(lab);
01162 
01163     //Check StartTime for appended 'z' (Zulu time) and remove
01164     Isis::PvlGroup &inst = lab.FindGroup("Instrument");
01165 
01166     if(inst.HasKeyword("StartTime")) {
01167       Isis::PvlKeyword &stkey = inst["StartTime"];
01168       QString stime = stkey[0];
01169       stime = stime.remove(QRegExp("[Zz]$"));
01170       stkey = stime;
01171     }
01172   }
01173 
01180   void ProcessImportPds::TranslatePdsBandBin(Isis::Pvl &lab) {
01181     // Set up a translater for PDS labels
01182     Isis::FileName transFile(p_transDir + "/" + "translations/pdsImageBandBin.trn");
01183     Isis::PvlTranslationManager isis2Xlater(p_pdsLabel, transFile.expanded());
01184 
01185     // Add all the Isis2 keywords that can be translated to the requested label
01186     isis2Xlater.Auto(lab);
01187   }
01188 
01195   void ProcessImportPds::TranslatePdsArchive(Isis::Pvl &lab) {
01196     // Set up a translater for PDS labels
01197     Isis::FileName transFile(p_transDir + "/" + "translations/pdsImageArchive.trn");
01198     Isis::PvlTranslationManager isis2Xlater(p_pdsLabel, transFile.expanded());
01199 
01200     // Add all the Isis2 keywords that can be translated to the requested label
01201     isis2Xlater.Auto(lab);
01202   }
01203 
01216   void ProcessImportPds::GetProjectionOffsetMults(double &xoff, double &yoff,
01217       double &xmult, double &ymult) {
01218 
01219     xmult = -1.0;
01220     ymult = 1.0;
01221     xoff = -0.5;
01222     yoff = -0.5;
01223 
01224     //  Open projectionOffsetMults file
01225     Isis::Pvl p(p_transDir + "/" + "translations/pdsProjectionLineSampToXY.def");
01226 
01227     Isis::PvlObject &projDef = p.FindObject("ProjectionOffsetMults",
01228                                             Pvl::Traverse);
01229 
01230     for(int g = 0; g < projDef.Groups(); g++) {
01231       QString key = projDef.Group(g)["Keyword"];
01232       if(p_pdsLabel.HasKeyword(key)) {
01233         QString value = p_pdsLabel[key];
01234         QString pattern = projDef.Group(g)["Pattern"];
01235         //  If value contains pattern, then set the mults to what is in translation file
01236         if(value.contains(pattern)) {
01237           xmult = projDef.Group(g)["xMult"];
01238           ymult = projDef.Group(g)["yMult"];
01239           xoff = projDef.Group(g)["xOff"];
01240           yoff = projDef.Group(g)["yOff"];
01241           return;
01242         }
01243       }
01244     }
01245   }
01246 
01254   void ProcessImportPds::ImportTable(QString pdsTableName) {
01255     // No table file given, let ImportPdsTable find it.
01256     ImportPdsTable pdsTable(p_labelFile, "", pdsTableName);
01257     // reformat the table name. If the name ends with the word "Table", remove
01258     // it. (So, for example, INSTRUMENT_POINTING_TABLE gets formatted to
01259     // InstrumentPointingTable and then to InstrumentPointing)
01260     QString isisTableName = pdsTable.getFormattedName(pdsTableName);
01261     int found = isisTableName.lastIndexOf("Table");
01262     if (found == isisTableName.length() - 5) {
01263       isisTableName.remove(found, 5);
01264     }
01265 
01266     Table isisTable = pdsTable.importTable(isisTableName);
01267     p_tables.push_back(isisTable);
01268   }
01269 
01273   void ProcessImportPds::StartProcess() {
01274     ProcessImport::StartProcess();
01275     for (unsigned int i = 0; i < p_tables.size(); i++) {
01276       OutputCubes[0]->write(p_tables[i]);
01277     }
01278     return;
01279   }
01280 }