USGS

Isis 3.0 Application Source Code Reference

Home

voy2isis.cpp

Go to the documentation of this file.
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