|
Isis 3.0 Application Source Code Reference |
Home |
00001 #include "Isis.h" 00002 00003 #include <cstdio> 00004 #include <QString> 00005 00006 #include "ProcessImportPds.h" 00007 #include "ProcessByLine.h" 00008 00009 #include "UserInterface.h" 00010 #include "FileName.h" 00011 #include "IException.h" 00012 #include "iTime.h" 00013 #include "Preference.h" 00014 #include "Buffer.h" 00015 #include "PvlGroup.h" 00016 #include "PvlKeyword.h" 00017 #include "PvlSequence.h" 00018 #include "Stretch.h" 00019 00020 using namespace std; 00021 using namespace Isis; 00022 00023 // Global variables for processing functions 00024 Stretch stretch; 00025 00026 // The input raw EDR contains 6 sections. The following counts keep track 00027 // of the types of pixels found in each section. The order of sections 00028 // is the order they arae encountered within the raw EDR. (i.e., calibration 00029 // buffer, calibration image, calibration dark/reference, image buffer, 00030 // image, image dark/reference) 00031 int gapCount[6]; 00032 int suspectGapCount[6]; 00033 int invalidCount[6]; 00034 int lisCount[6]; 00035 int hisCount[6]; 00036 int validCount[6]; 00037 int section; 00038 00039 bool lsbGap; 00040 00041 00042 void IsisMain() { 00043 stretch.ClearPairs(); 00044 00045 for(int i = 0; i < 6; i++) { 00046 gapCount[i] = 0; 00047 suspectGapCount[i] = 0; 00048 invalidCount[i] = 0; 00049 lisCount[i] = 0; 00050 hisCount[i] = 0; 00051 validCount[i] = 0; 00052 } 00053 00054 void TranslateHiriseEdrLabels(FileName & labelFile, Cube *); 00055 void SaveHiriseCalibrationData(ProcessImportPds & process, Cube *, 00056 Pvl & pdsLabel); 00057 void SaveHiriseAncillaryData(ProcessImportPds & process, Cube *); 00058 void FixDns8(Buffer & buf); 00059 void FixDns16(Buffer & buf); 00060 00061 ProcessImportPds p; 00062 Pvl pdsLabel; 00063 UserInterface &ui = Application::GetUserInterface(); 00064 00065 // Get the input filename and make sure it is a HiRISE EDR 00066 FileName inFile = ui.GetFileName("FROM"); 00067 QString id; 00068 bool projected; 00069 try { 00070 Pvl lab(inFile.expanded()); 00071 id = (QString) lab.FindKeyword("DATA_SET_ID"); 00072 projected = lab.HasObject("IMAGE_MAP_PROJECTION"); 00073 } 00074 catch(IException &e) { 00075 QString msg = "Unable to read [DATA_SET_ID] from input file [" + 00076 inFile.expanded() + "]"; 00077 throw IException(e, IException::Io, msg, _FILEINFO_); 00078 } 00079 00080 //Checks if in file is rdr 00081 if(projected) { 00082 QString msg = "[" + inFile.name() + "] appears to be an rdr file."; 00083 msg += " Use pds2isis."; 00084 throw IException(IException::User, msg, _FILEINFO_); 00085 } 00086 00087 id = id.simplified().trimmed(); 00088 if(id != "MRO-M-HIRISE-2-EDR-V1.0") { 00089 QString msg = "Input file [" + inFile.expanded() + "] does not appear to be " + 00090 "in HiRISE EDR format. DATA_SET_ID is [" + id + "]"; 00091 throw IException(IException::Io, msg, _FILEINFO_); 00092 } 00093 00094 p.SetPdsFile(inFile.expanded(), "", pdsLabel); 00095 00096 // Make sure the data we need for the BLOBs is saved by the Process 00097 p.SaveFileHeader(); 00098 p.SaveDataPrefix(); 00099 p.SaveDataSuffix(); 00100 00101 // Let the Process create the output file but override any commandline 00102 // output bit type and min/max. It has to be 16bit for the rest of hi2isis 00103 // to run. 00104 // Setting the min/max to the 16 bit min/max keeps all the dns (including 00105 // the 8 bit special pixels from changing their value when they are mapped 00106 // to the 16 bit output. 00107 CubeAttributeOutput &outAtt = ui.GetOutputAttribute("TO"); 00108 outAtt.setPixelType(Isis::SignedWord); 00109 outAtt.setMinimum((double)VALID_MIN2); 00110 outAtt.setMaximum((double)VALID_MAX2); 00111 Cube *ocube = p.SetOutputCube(ui.GetFileName("TO"), outAtt); 00112 p.StartProcess(); 00113 TranslateHiriseEdrLabels(inFile, ocube); 00114 00115 // Pull out the lookup table so we can apply it in the second pass 00116 // and remove it from the labels. 00117 // Add the UNLUTTED keyword to the instrument group so we know 00118 // if the lut has been used to convert back to 14 bit data 00119 PvlGroup &instgrp = ocube->group("Instrument"); 00120 PvlKeyword lutKey = instgrp["LookupTable"]; 00121 PvlSequence lutSeq; 00122 lutSeq = lutKey; 00123 00124 // Set up the Stretch object with the info from the lookup table 00125 // If the first entry is (0,0) then no lut was applied. 00126 if((lutKey.IsNull()) || 00127 (lutSeq.Size() == 1 && lutSeq[0][0] == "0" && lutSeq[0][1] == "0")) { 00128 stretch.AddPair(0.0, 0.0); 00129 stretch.AddPair(65536.0, 65536.0); 00130 instgrp.AddKeyword(PvlKeyword("Unlutted", "TRUE")); 00131 instgrp.DeleteKeyword("LookupTable"); 00132 } 00133 // The user wants it unlutted 00134 else if(ui.GetBoolean("UNLUT")) { 00135 for(int i = 0; i < lutSeq.Size(); i++) { 00136 stretch.AddPair(i, ((toDouble(lutSeq[i][0]) + toDouble(lutSeq[i][1])) / 2.0)); 00137 } 00138 instgrp.AddKeyword(PvlKeyword("Unlutted", "TRUE")); 00139 instgrp.DeleteKeyword("LookupTable"); 00140 } 00141 // The user does not want the data unlutted 00142 else { 00143 stretch.AddPair(0.0, 0.0); 00144 stretch.AddPair(65536.0, 65536.0); 00145 instgrp.AddKeyword(PvlKeyword("Unlutted", "FALSE")); 00146 } 00147 00148 // Save the calibration and ancillary data as BLOBs. Both get run thru the 00149 // lookup table just like the image data. 00150 SaveHiriseCalibrationData(p, ocube, pdsLabel); 00151 SaveHiriseAncillaryData(p, ocube); 00152 00153 // Save off the input bit type so we know how to process it on the 00154 // second pass below. 00155 Isis::PixelType inType = p.PixelType(); 00156 00157 // All finished with the ImportPds object 00158 p.EndProcess(); 00159 00160 00161 // Make another pass thru the data using the output file in read/write mode 00162 // This allows us to correct gaps, remap special pixels and accumulate some 00163 // counts 00164 lsbGap = ui.GetBoolean("LSBGAP"); 00165 ProcessByLine p2; 00166 QString ioFile = ui.GetFileName("TO"); 00167 CubeAttributeInput att; 00168 p2.SetInputCube(ioFile, att, ReadWrite); 00169 p2.Progress()->SetText("Converting special pixels"); 00170 section = 4; 00171 p2.StartProcess((inType == Isis::UnsignedByte) ? FixDns8 : FixDns16); 00172 p2.EndProcess(); 00173 00174 00175 // Log the results of the image conversion 00176 PvlGroup results("Results"); 00177 results += PvlKeyword("From", inFile.expanded()); 00178 00179 results += PvlKeyword("CalibrationBufferGaps", toString(gapCount[0])); 00180 results += PvlKeyword("CalibrationBufferLIS", toString(lisCount[0])); 00181 results += PvlKeyword("CalibrationBufferHIS", toString(hisCount[0])); 00182 results += PvlKeyword("CalibrationBufferPossibleGaps", toString(suspectGapCount[0])); 00183 results += PvlKeyword("CalibrationBufferInvalid", toString(invalidCount[0])); 00184 results += PvlKeyword("CalibrationBufferValid", toString(validCount[0])); 00185 00186 results += PvlKeyword("CalibrationImageGaps", toString(gapCount[1])); 00187 results += PvlKeyword("CalibrationImageLIS", toString(lisCount[1])); 00188 results += PvlKeyword("CalibrationImageHIS", toString(hisCount[1])); 00189 results += PvlKeyword("CalibrationImagePossibleGaps", toString(suspectGapCount[1])); 00190 results += PvlKeyword("CalibrationImageInvalid", toString(invalidCount[1])); 00191 results += PvlKeyword("CalibrationImageValid", toString(validCount[1])); 00192 00193 results += PvlKeyword("CalibrationDarkGaps", toString(gapCount[2])); 00194 results += PvlKeyword("CalibrationDarkLIS", toString(lisCount[2])); 00195 results += PvlKeyword("CalibrationDarkHIS", toString(hisCount[2])); 00196 results += PvlKeyword("CalibrationDarkPossibleGaps", toString(suspectGapCount[2])); 00197 results += PvlKeyword("CalibrationDarkInvalid", toString(invalidCount[2])); 00198 results += PvlKeyword("CalibrationDarkValid", toString(validCount[2])); 00199 00200 results += PvlKeyword("ObservationBufferGaps", toString(gapCount[3])); 00201 results += PvlKeyword("ObservationBufferLIS", toString(lisCount[3])); 00202 results += PvlKeyword("ObservationBufferHIS", toString(hisCount[3])); 00203 results += PvlKeyword("ObservationBufferPossibleGaps", toString(suspectGapCount[3])); 00204 results += PvlKeyword("ObservationBufferInvalid", toString(invalidCount[3])); 00205 results += PvlKeyword("ObservationBufferValid", toString(validCount[3])); 00206 00207 results += PvlKeyword("ObservationImageGaps", toString(gapCount[4])); 00208 results += PvlKeyword("ObservationImageLIS", toString(lisCount[4])); 00209 results += PvlKeyword("ObservationImageHIS", toString(hisCount[4])); 00210 results += PvlKeyword("ObservationImagePossibleGaps", toString(suspectGapCount[4])); 00211 results += PvlKeyword("ObservationImageInvalid", toString(invalidCount[4])); 00212 results += PvlKeyword("ObservationImageValid", toString(validCount[4])); 00213 00214 results += PvlKeyword("ObservationDarkGaps", toString(gapCount[5])); 00215 results += PvlKeyword("ObservationDarkLIS", toString(lisCount[5])); 00216 results += PvlKeyword("ObservationDarkHIS", toString(hisCount[5])); 00217 results += PvlKeyword("ObservationDarkPossibleGaps", toString(suspectGapCount[5])); 00218 results += PvlKeyword("ObservationDarkInvalid", toString(invalidCount[5])); 00219 results += PvlKeyword("ObservationDarkValid", toString(validCount[5])); 00220 00221 // Write the results to the log 00222 Application::Log(results); 00223 00224 return; 00225 } 00226 00227 00228 void TranslateHiriseEdrLabels(FileName &labelFile, Cube *ocube) { 00229 00230 //Create a PVL to store the translated labels 00231 Pvl outLabel; 00232 00233 // Get the directory where the MRO HiRISE translation tables are. 00234 PvlGroup dataDir(Preference::Preferences().FindGroup("DataDirectory")); 00235 QString transDir = (QString) dataDir["Mro"] + "/translations/"; 00236 00237 // Get a filename for the HiRISE EDR label 00238 Pvl labelPvl(labelFile.expanded()); 00239 00240 // Translate the Instrument group 00241 FileName transFile(transDir + "hiriseInstrument.trn"); 00242 PvlTranslationManager instrumentXlater(labelPvl, transFile.expanded()); 00243 instrumentXlater.Auto(outLabel); 00244 00245 // Translate the BandBin group 00246 transFile = transDir + "hiriseBandBin.trn"; 00247 PvlTranslationManager bandBinXlater(labelPvl, transFile.expanded()); 00248 bandBinXlater.Auto(outLabel); 00249 00250 // Translate the Archive group 00251 transFile = transDir + "hiriseArchive.trn"; 00252 PvlTranslationManager archiveXlater(labelPvl, transFile.expanded()); 00253 archiveXlater.Auto(outLabel); 00254 00255 // Create the Instrument group keyword CcdId from the ProductId 00256 // SCS 28-03-06 Do it in the instrument translation table instead of here 00257 // PvlGroup &archiveGroup(outLabel.FindGroup("Archive", Pvl::Traverse)); 00258 // QString productId = (QString)archiveGroup.FindKeyword("ProductId"); 00259 // productId.Token("_"); 00260 // productId.Token("_"); 00261 // productId = productId.Token("_"); 00262 // outLabel.FindGroup("Instrument", Pvl::Traverse) += 00263 // PvlKeyword ("CcdId", productId); 00264 00265 // Create the Kernel Group 00266 PvlGroup kerns("Kernels"); 00267 kerns += PvlKeyword("NaifIkCode", "-74699"); 00268 00269 // Write the Instrument, BandBin, Archive, and Kernels groups to the output 00270 // cube label 00271 ocube->putGroup(outLabel.FindGroup("Instrument", Pvl::Traverse)); 00272 ocube->putGroup(outLabel.FindGroup("BandBin", Pvl::Traverse)); 00273 ocube->putGroup(outLabel.FindGroup("Archive", Pvl::Traverse)); 00274 ocube->putGroup(kerns); 00275 } 00276 00277 00278 // The input buffer has a raw 16 bit buffer but the values are still 0 to 255 00279 void FixDns8(Buffer &buf) { 00280 00281 // Convert all 8bit image values of =255 (xFF) to 16bit NULL, count as gap 00282 // Convert all 8bit image values of =254 (xFE) to 16bit HIS, count as HIS 00283 // Convert all 8bit image values of =0 (x00) to 16bit LIS, count as NULL 00284 // Convert 8bit image data to 16bit by applying the LUT 00285 00286 short int *raw = (short int *)(buf.RawBuffer()); 00287 00288 for(int i = 0; i < buf.size(); i++) { 00289 00290 if(raw[i] == (short int)255) { 00291 buf[i] = Isis::NULL8; 00292 gapCount[section]++; 00293 } 00294 else if(raw[i] == (short int)254) { 00295 buf[i] = Isis::HIGH_INSTR_SAT8; 00296 hisCount[section]++; 00297 } 00298 else if(raw[i] == (short int)0) { 00299 buf[i] = Isis::LOW_INSTR_SAT8; 00300 lisCount[section]++; 00301 } 00302 else { // It's valid so just run it thru the lookup table to get a 16 bit dn 00303 buf[i] = stretch.Map(buf[i]); 00304 validCount[section]++; 00305 } 00306 } 00307 } 00308 00309 00310 void FixDns16(Buffer &buf) { 00311 00312 // Convert 16-bit image values of =65535 (xFFFF) to NULL, count as gap 00313 // Convert 16-bit image values of >16383 (x3FFF) to NULL, count as gap 00314 // Convert 16-bit image values of =16383 (x3FFF) to HIS, count as HIS 00315 // Convert 16-bit image values of =0 (x00) to LIS, count as LIS 00316 00317 short int *raw = (short int *)(buf.RawBuffer()); 00318 00319 for(int i = 0; i < buf.size(); i++) { 00320 00321 // This pixel is a gap 00322 if(raw[i] == (short int)0xffff) { // 0xffff = -1 = 65535 = gap 00323 buf[i] = Isis::NULL8; 00324 gapCount[section]++; 00325 } 00326 // The low order byte of this pixel is the beginning of a gap 00327 else if((i + 1 < buf.size()) && // is there at least on more pixel to look at 00328 (raw[i+1] == (short int)0xffff) && // Is the next pixel a gap 00329 ((short int)(raw[i] & 0x00ff) == (short int)0x00ff)) { // Is the low byte 0xff 00330 suspectGapCount[section]++; 00331 if(lsbGap) { 00332 buf[i] = Isis::NULL8; 00333 } 00334 } 00335 // This pixel is not within the legal 14 bit range (0) to (16383=0x3fff) 00336 // It might be the end of a gap (0xff??) but it's still illegal 00337 else if((raw[i] > 16383) || (raw[i] < 0)) { 00338 buf[i] = Isis::NULL8; 00339 invalidCount[section]++; 00340 } 00341 // This pixel is saturated on the bright end 00342 else if(raw[i] == 16383) { // Max value for instrument 00343 buf[i] = Isis::HIGH_INSTR_SAT8; 00344 hisCount[section]++; 00345 } 00346 // This pixel is saturated on the dark end 00347 // Shouldn't happen because dark currents are above zero (0) 00348 else if(raw[i] == 0) { 00349 buf[i] = Isis::LOW_INSTR_SAT8; 00350 lisCount[section]++; 00351 } 00352 // Pixel value is ok, so just leave it alone 00353 else { 00354 validCount[section]++; 00355 } 00356 } 00357 } 00358