Isis 3.0 Application Source Code Reference |
Home |
00001 #include "Isis.h" 00002 00003 #include <cstdio> 00004 #include <fstream> 00005 #include <string> 00006 00007 #include "Filename.h" 00008 #include "iException.h" 00009 #include "iString.h" 00010 #include "NaifStatus.h" 00011 #include "ProcessImportPds.h" 00012 #include "ProgramLauncher.h" 00013 #include "Pvl.h" 00014 #include "PvlGroup.h" 00015 #include "PvlTranslationManager.h" 00016 #include "UserInterface.h" 00017 00018 #include "naif/SpiceUsr.h" 00019 00020 #include <iostream> 00021 #include <iomanip> 00022 00023 using namespace std; 00024 using namespace Isis; 00025 00026 void TranslateVoyagerLabels(Pvl &inputLabel, Cube *ocube); 00027 void ConvertComments(Filename file); 00028 00029 void IsisMain() { 00030 // We should be processing a PDS file 00031 ProcessImportPds p; 00032 UserInterface &ui = Application::GetUserInterface(); 00033 Filename in = ui.GetFilename("FROM"); 00034 00035 string tempName = "$TEMPORARY/" + in.Basename() + ".img"; 00036 Filename temp(tempName); 00037 00038 bool tempFile = false; 00039 00040 // input files are compressed, use vdcomp to decompress 00041 iString ext = iString(in.Extension()).UpCase(); 00042 if(ext == "IMQ") { 00043 try { 00044 string command = "$ISISROOT/bin/vdcomp " + in.Expanded() + " " + temp.Expanded(); 00045 // don't pretend vdcomp is a standard Isis program, just run it 00046 ProgramLauncher::RunSystemCommand(command); 00047 in = temp.Expanded(); 00048 ConvertComments(in); 00049 tempFile = true; 00050 } 00051 catch(iException &e) { 00052 throw iException::Message(iException::Io, 00053 "Unable to decompress input file [" 00054 + in.Name() + "].", _FILEINFO_); 00055 } 00056 } 00057 else if (ext == "IMG") { 00058 // Do nothing 00059 } 00060 else { 00061 string msg = "Input file [" + in.Name() + 00062 "] does not appear to be a Voyager EDR"; 00063 throw iException::Message(iException::User, msg, _FILEINFO_); 00064 } 00065 // Convert the pds file to a cube 00066 Pvl pdsLabel; 00067 try { 00068 p.SetPdsFile(in.Expanded(), "", pdsLabel); 00069 } 00070 catch(iException &e) { 00071 string msg = "Unable to set PDS file. Decompressed input file [" 00072 + in.Name() + "] does not appear to be a PDS product"; 00073 throw iException::Message(iException::User, msg, _FILEINFO_); 00074 } 00075 00076 Cube *ocube = p.SetOutputCube("TO"); 00077 p.StartProcess(); 00078 TranslateVoyagerLabels(pdsLabel, ocube); 00079 p.EndProcess(); 00080 00081 if(tempFile) remove(temp.Expanded().c_str()); 00082 } 00083 00084 /** 00085 * Converts / * Some comment 00086 * to # Some comment 00087 * without the extra space. 00088 */ 00089 void ConvertComments(Filename file) { 00090 char tmp[10240]; 00091 00092 for(unsigned int i = 0; i < sizeof(tmp) / sizeof(char); i++) 00093 tmp[i] = '\0'; 00094 00095 unsigned int lineStartPos = 0; 00096 fstream stream; 00097 iString filename = file.Expanded(); 00098 stream.open(filename.c_str(), fstream::in | fstream::out | fstream::binary); 00099 00100 lineStartPos = stream.tellg(); 00101 stream.getline(tmp, sizeof(tmp) / sizeof(char)); 00102 while(iString(tmp).find("END") != 0 && stream.good()) { 00103 iString lineOfData(tmp); 00104 00105 if(lineOfData.find("/*") != string::npos && 00106 lineOfData.find("*/") == string::npos) { 00107 lineOfData = lineOfData.substr(0, lineOfData.find("/*")) + "# " + 00108 lineOfData.substr(lineOfData.find("/*") + 2); 00109 stream.seekp(lineStartPos); 00110 stream.write(lineOfData.c_str(), lineOfData.length()); 00111 } 00112 00113 lineStartPos = stream.tellg(); 00114 stream.getline(tmp, sizeof(tmp) / sizeof(char)); 00115 } 00116 00117 stream.close(); 00118 } 00119 00120 00121 /** 00122 * @brief Translate labels into Isis3 00123 * 00124 * @param inputLabel Reference to pvl label from the input image 00125 * @param ocube Pointer to output cube 00126 * @internal 00127 * @history 2009-03-11 Jeannie Walldren - Original Version 00128 */ 00129 void TranslateVoyagerLabels(Pvl &inputLabel, Cube *ocube) { 00130 // Get the directory where the Voyager translation tables are 00131 PvlGroup &dataDir = Preference::Preferences().FindGroup("DataDirectory"); 00132 iString missionDir = (string) dataDir[(string)inputLabel["SpacecraftName"]]; 00133 Filename transFile(missionDir + "/translations/voyager.trn"); 00134 00135 // Get the translation manager ready 00136 PvlTranslationManager labelXlater(inputLabel, transFile.Expanded()); 00137 00138 // Pvl output label 00139 Pvl *outputLabel = ocube->getLabel(); 00140 labelXlater.Auto(*(outputLabel)); 00141 00142 // Add needed keywords that are not in the translation table 00143 PvlGroup &inst = outputLabel->FindGroup("Instrument", Pvl::Traverse); 00144 00145 // Add Camera_State_1 and Camera_State_2 00146 // Camera_State_1 is the first number in ScanModeId 00147 // Camera_State_2 is from ShutterModeId and is 1 or 0, it is only 1 if 00148 // it is WA and BSIMAN or BOTSIM 00149 PvlKeyword sModeId = inst["ScanModeId"]; 00150 string cs1 = sModeId[0].Token(":"); 00151 inst.AddKeyword(PvlKeyword("CameraState1",cs1)); 00152 00153 string shutterMode = inst["ShutterModeId"]; 00154 string cam = inst["InstrumentId"]; 00155 if (cam == "WIDE_ANGLE_CAMERA" && (shutterMode == "BOTSIM" || shutterMode == "BSIMAN")) { 00156 inst.AddKeyword(PvlKeyword("CameraState2","1")); 00157 } 00158 else { 00159 inst.AddKeyword(PvlKeyword("CameraState2","0")); 00160 } 00161 00162 // Add units of measurement to keywords from translation table 00163 double exposureDuration = inst.FindKeyword("ExposureDuration"); 00164 inst.FindKeyword("ExposureDuration").SetValue(exposureDuration, "seconds"); 00165 00166 // Setup the kernel group 00167 PvlGroup kern("Kernels"); 00168 iString spacecraftNumber; 00169 int spacecraftCode = 0; 00170 iString instId = (string) inst.FindKeyword("InstrumentId"); 00171 if((string) inst.FindKeyword("SpacecraftName") == "VOYAGER_1") { 00172 spacecraftNumber = "1"; 00173 if(instId == "NARROW_ANGLE_CAMERA") { 00174 spacecraftCode = -31101; 00175 kern += PvlKeyword("NaifFrameCode", spacecraftCode); 00176 instId = "issna"; 00177 } 00178 else if (instId == "WIDE_ANGLE_CAMERA") { 00179 spacecraftCode = -31102; 00180 kern += PvlKeyword("NaifFrameCode", spacecraftCode); 00181 instId = "isswa"; 00182 } 00183 else { 00184 string msg = "Instrument ID [" + instId + "] does not match Narrow or" + 00185 "Wide angle camera"; 00186 iException::Message(iException::User, msg, _FILEINFO_); 00187 } 00188 } 00189 else if((string) inst.FindKeyword("SpacecraftName") == "VOYAGER_2") { 00190 spacecraftNumber = "2"; 00191 if(instId == "NARROW_ANGLE_CAMERA") { 00192 spacecraftCode = -32101; 00193 kern += PvlKeyword("NaifFrameCode", spacecraftCode); 00194 instId = "issna"; 00195 } 00196 else if (instId == "WIDE_ANGLE_CAMERA") { 00197 spacecraftCode = -32102; 00198 kern += PvlKeyword("NaifFrameCode", spacecraftCode); 00199 instId = "isswa"; 00200 } 00201 else { 00202 string msg = "Instrument ID [" + instId + "] does not match Narrow or" + 00203 "Wide angle camera"; 00204 iException::Message(iException::User, msg, _FILEINFO_); 00205 } 00206 } 00207 else { 00208 string msg = "Spacecraft name [" + (string)inst.FindKeyword("SpacecraftName") + 00209 "] does not match Voyager1 or Voyager2 spacecraft"; 00210 iException::Message(iException::User, msg, _FILEINFO_); 00211 } 00212 ocube->putGroup(kern); 00213 00214 // Modify time to remove Z from end 00215 iString time = inst.FindKeyword("StartTime")[0]; 00216 time.Remove("Z"); 00217 inst.FindKeyword("StartTime").SetValue(time); 00218 00219 // Fix image number - remove the period, if Wide angle camera and one of two 00220 // shutter modes, we must fix the wide angle image number for use below. 00221 // Before #####.## After ####### 00222 iString imgNumber = inst["SpacecraftClockCount"][0]; 00223 imgNumber.Replace(".", ""); 00224 // Save this change 00225 inst["SpacecraftClockCount"] = imgNumber; 00226 00227 // From vgrfixlabel documentation in Isis2. 00228 // Wide Angle (WA) images off of CD's will have a fake image 00229 // number (NA image_number + scan_mode_id) written over the 00230 // image_number label, which would have gotten the FSC count 00231 // rather than the FSD count if a Narrow Angle was shuttered 00232 // simultaneously. What I want is to figure out the NA image- 00233 // number, which will allow me to find the shutter time (same 00234 // for both NA & WA). So run backward, WA image_number - scan_ 00235 // mode_id. 00236 // If BSIMAN or BOTSIM and WA, go ahead. 00237 if((inst["ShutterModeId"][0] == "BSIMAN" || 00238 inst["ShutterModeId"][0] == "BOTSIM") && 00239 inst["InstrumentId"][0] == "WIDE_ANGLE_CAMERA") { 00240 iString scanId = inst["ScanModeId"][0]; 00241 int scanNum = iString(scanId.substr(0, 1)).ToInteger(); 00242 int imgNum = imgNumber.ToInteger(); 00243 00244 // We'll use this later, however, we do not write it to the labels. 00245 // if we didn't get in here, we'll be using the original image number, 00246 // otherwise, we'll use this modified image number. 00247 imgNumber = iString((imgNum - scanNum)); 00248 } 00249 00250 // This next section handles modifying the starttime slightly and requires 00251 // the leapsecond kernel, the spacecraft clock kernel, and a correct 00252 // spacecraft clock. 00253 // This functionality was copied from Isis2 by Mackenzie Boyd, the 00254 // documentation from Isis2 is here: (from vgrfixlabel.c) 00255 /******************************************************************* 00256 Get spacecraftClock from image FSC. 00257 00258 Calculate the START_TIME keyword value from FSC to get fractional 00259 seconds (PDS START_TIME provided is only to the nearest whole 00260 second). The algorithm below was extracted from the NAIF 00261 document Viking Orbiter Time Tag Analysis and Restoration by 00262 Boris Semenov and Chuck Acton and was modified for Voyager by 00263 Debbie Cook and K Teal Thompson. 00264 00265 1. Determine instCode, spacecraftCode. 00266 Get FSC (FDS_COUNT) from IMAGE_NUMBER to use as 00267 spacecraftClock. This was already done above when the 00268 IMAGE_NUMBER was read into imagenum. 00269 //Already accomplished above 00270 00271 2. Need to calc the image number for wide Angle images when 00272 SHUTTER_MODE_ID = BOTSIM or BSIMAN because the IMAGE_NUMBER 00273 on the labels is set to the readout count instead of the FDS 00274 (FLIGHT DATA SUBSYSTEM) count. In the old code, SCAN_MODE_ID 00275 is used to add to the image_number to get a new image_number 00276 for WA. In this code, take WA image number and subtract 00277 scan_mode id to get the narrow angle image_number. 00278 // This is also accomplished above 00279 00280 3. Load a leap second kernel and the appropriate FSC spacecraft 00281 clock kernel based on the spacecraft (Voyager 1 or Voyager 00282 2). Then convert image_number/spacecraftClock to et. 00283 00284 00285 4. Convert et to UTC calendar format and write to labels as 00286 START_TIME 00287 00288 00289 ********************************************************************/ 00290 00291 // We've already handled a couple of the steps mentioned above. 00292 NaifStatus::CheckErrors(); 00293 //* 3 *// 00294 // Leapsecond kernel 00295 string lsk = "$ISIS3DATA/base/kernels/lsk/naif????.tls"; 00296 Filename lskName(lsk); 00297 lskName.HighestVersion(); 00298 furnsh_c(lskName.Expanded().c_str()); 00299 00300 // Spacecraft clock kernel 00301 string sclk = "$ISIS3DATA/voyager"; 00302 sclk.append(spacecraftNumber); 00303 sclk.append("/kernels/sclk/vg"); 00304 sclk.append(spacecraftNumber); 00305 sclk.append("?????.tsc"); 00306 Filename sclkName(sclk); 00307 sclkName.HighestVersion(); 00308 furnsh_c(sclkName.Expanded().c_str()); 00309 00310 // The purpose of the next two steps, getting the spacecraft clock count, 00311 // are simply to get get the partition, the very first number 1/... 00312 double approxEphemeris = 0.0; 00313 utc2et_c(inst["StartTime"][0].c_str(), &approxEphemeris); 00314 char approxSpacecraftClock[80]; 00315 00316 // sce2s_c requires the spacecraft number, not the instrument number as 00317 // we've found elsewhere, either -31 or -32 in this case. 00318 int spacecraftClockNumber = -30; 00319 spacecraftClockNumber -= spacecraftNumber.ToInteger(); 00320 sce2s_c(spacecraftClockNumber, approxEphemeris, 80, approxSpacecraftClock); 00321 00322 /* 00323 * For our next trick, we will substitute the image number we got earlier 00324 * into this image number. The image number is in the format #######, 00325 * 7 digits, our freshly gotten image number is in the form #/#####:##:## 00326 * We want to save the first digit, before the /, and then substitute 00327 * the previously found image number into the next 7 digits, keeping the colon, 00328 * and then removing the last :## colon and two digits. Here goes. 00329 * BTW, our imageNumber from above and this number may be identical, 00330 * in which case this won't change anything in it. However, since the 00331 * conversion from ET to spacecraftClock is a range of ETs all mapping to one 00332 * clock count, even if we don't modifiy the spacecraft clock count, we'll 00333 * come out with a slightly different starttime which is, in theory, more accurate. 00334 * To rephrase, ETs are continuous, Spacecraft clock is discrete. For later 00335 * we will use the Starttime, the ET, so we want it to match the spacecraft clock 00336 * exactly. But, the original starttime holds valuable information... enough. 00337 */ 00338 00339 // Get first digit and the / 00340 iString newClockCount = string(approxSpacecraftClock).substr(0, 2); 00341 // Get first five digits of imgNumber and append 00342 newClockCount.append(imgNumber.substr(0, 5)); 00343 // I'll stop commenting now, you can read code as well as me 00344 newClockCount.append(":"); 00345 // I lied ;) get the last two digits. 00346 newClockCount.append(imgNumber.substr(5, 2)); 00347 00348 scs2e_c(spacecraftClockNumber, newClockCount.c_str(), &approxEphemeris); 00349 00350 //* 4 *// 00351 char utcOut[25]; 00352 et2utc_c(approxEphemeris, "ISOC", 3, 26, utcOut); 00353 NaifStatus::CheckErrors(); 00354 inst["StartTime"].SetValue(iString(utcOut)); 00355 00356 // Set up the nominal reseaus group 00357 PvlGroup res("Reseaus"); 00358 Pvl nomRes("$voyager" + spacecraftNumber + "/reseaus/nominal.pvl"); 00359 PvlKeyword samps, lines, type, valid; 00360 lines = PvlKeyword("Line"); 00361 samps = PvlKeyword("Sample"); 00362 type = PvlKeyword("Type"); 00363 valid = PvlKeyword("Valid"); 00364 00365 PvlKeyword key = nomRes.FindKeyword("VG" + spacecraftNumber + "_" 00366 + instId.UpCase() + "_RESEAUS"); 00367 int numRes = nomRes["VG" + spacecraftNumber + "_" + instId.UpCase() 00368 + "_NUMBER_RESEAUS"]; 00369 for(int i = 0; i < numRes * 3; i += 3) { 00370 lines += key[i]; 00371 samps += key[i+1]; 00372 type += key[i+2]; 00373 valid += 0; 00374 } 00375 res += lines; 00376 res += samps; 00377 res += type; 00378 res += valid; 00379 res += PvlKeyword("Template", "$voyager" + spacecraftNumber + "/reseaus/vg" 00380 + spacecraftNumber + "." + instId.DownCase() 00381 + ".template.cub"); 00382 res += PvlKeyword("Status", "Nominal"); 00383 ocube->putGroup(res); 00384 } 00385