USGS

Isis 3.0 Application Source Code Reference

Home

SpiceSegment.cpp

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * $Revision: 4943 $
00004  * $Date: 2013-01-04 11:02:32 -0700 (Fri, 04 Jan 2013) $
00005  * $Id: SpiceSegment.cpp 4943 2013-01-04 18:02:32Z janderson $
00006  *
00007  *   Unless noted otherwise, the portions of Isis written by the USGS are
00008  *   public domain. See individual third-party library and package descriptions
00009  *   for intellectual property information, user agreements, and related
00010  *   information.
00011  *
00012  *   Although Isis has been used by the USGS, no warranty, expressed or
00013  *   implied, is made by the USGS as to the accuracy and functioning of such
00014  *   software and related material nor shall the fact of distribution
00015  *   constitute any such warranty, and no responsibility is assumed by the
00016  *   USGS in connection therewith.
00017  *
00018  *   For additional information, launch
00019  *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html
00020  *   in a browser or see the Privacy & Disclaimers page on the Isis website,
00021  *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
00022  *   http://www.usgs.gov/privacy.html.
00023  */
00024 #include <string>
00025 #include <vector>
00026 #include <numeric>
00027 #include <iostream>
00028 #include <iomanip>
00029 #include <sstream>
00030 
00031 #include "SpiceSegment.h"
00032 #include "IString.h"
00033 #include "FileName.h"
00034 #include "Cube.h"
00035 #include "Camera.h"
00036 #include "iTime.h"
00037 #include "NaifStatus.h"
00038 #include "IException.h"
00039 
00040 #include "naif/SpiceUsr.h"
00041 
00042 using namespace std;
00043 
00044 namespace Isis {
00045 
00046 
00047   /** Initialize  */
00048 SpiceSegment::SpiceSegment() {
00049   init();
00050 }
00051 
00052 /** Initialize with a cube extracting BLOB content */
00053 SpiceSegment::SpiceSegment(Cube &cube) {
00054   init(cube);
00055 }
00056 
00057 /** Set the segment Id that will be written to the kernel */
00058 void SpiceSegment::setId(const QString &name) {
00059   _name = name;
00060   return;
00061 }
00062 
00063 
00064 /**
00065  * @brief Provide on-demand loading of a kernel type in the NAIF pool
00066  *
00067  * This method provides the ability for users to load particular kernels
00068  * associated with an ISIS cube (or segment) when the need arises.  This
00069  * commonly occurs when transforming states and/or frames and body ids.  This is
00070  * implemented through the Kernels class so that documentation would be useful
00071  * to review for usage details.
00072  *
00073  *
00074  * @param ktypes  Optional string type of kernel to load (e.g., "LSK,FK").
00075  *
00076  * @return int  Number of kernels loaded for the requested type
00077  */
00078 int SpiceSegment::LoadKernelType(const QString &ktypes) const {
00079   return (_kernels.Load(ktypes));
00080 }
00081 
00082 /**
00083  * @brief Unload specific kernels from the NAIF pool
00084  *
00085  * This is the compliment of the LoadKernelType() method that will unload
00086  * kernels that were requested through that method.
00087  *
00088  * @param ktypes   Optional string type of kernel to unload (e.g., "LSK,FK").
00089  *
00090  * @return int Number kernels unloaded
00091  */
00092 int SpiceSegment::UnloadKernelType(const QString &ktypes) const {
00093   return (_kernels.UnLoad(ktypes));
00094 }
00095 
00096 /**
00097  * @brief Initializes an ISIS cube converting it into a SPICE segment
00098  *
00099  * This method is called to extract the perinent contents of an ISIS cube file
00100  * and accumulate generic information that is used to create the output SPICE
00101  * kernel segment.  Other specific kernel types can use this class as its base
00102  * class and add to it additional elements to complete the needed content for
00103  * the NAIF kernel.
00104  *
00105  * @param cube ISIS cube file to accumulate information from
00106  */
00107 void SpiceSegment::init(Cube &cube) {
00108 
00109   _kernels.UnLoad();  // Unload all active, owned kernels
00110   init();            // Init local variables
00111 
00112   _fname = cube.fileName();
00113 
00114   //  Extract ISIS CK blob and transform to CK 3 content
00115   NaifStatus::CheckErrors();
00116   try {
00117 
00118     // Order is somewhat important here.  The call to initialize Kernels
00119     // object checks the NAIF pool for existance.  It logs their NAIF
00120     // status as loaded which may cause trouble from here on...
00121     Pvl *label = cube.label();
00122     _kernels.Init(*label);
00123     Camera *camera = cube.camera();
00124 
00125     //  Determine segment ID from product ID if it exists, otherwise basename
00126     if ( _name.isEmpty() ) {
00127       _name = getKeyValue(*label, "ProductId");
00128       if (_name.isEmpty() ) {
00129         _name = FileName(_fname).baseName();
00130       }
00131     }
00132 
00133     // Get instrument and target ids
00134     QString value("");
00135     value = getKeyValue(*label, "InstrumentId");
00136     if (!value.isEmpty()) { _instId = value; }
00137     value = getKeyValue(*label, "TargetName");
00138     if (!value.isEmpty()) { _target = value; }
00139 
00140     // Get default times for sorting purposes
00141     setStartTime(camera->cacheStartTime().Et());
00142     setEndTime(camera->cacheEndTime().Et());
00143 
00144   } catch ( IException &ie  ) {
00145     ostringstream mess;
00146     mess << "Failed to construct Spice Segment basics from ISIS file " << _fname;
00147     throw IException(ie, IException::User, mess.str(), _FILEINFO_);
00148   }
00149 
00150   return;
00151 }
00152 
00153 /**
00154  * @brief Get specified keyword values from an ISIS label
00155  *
00156  * This routine provides access to an ISIS label w/out regard for structure.  In
00157  * other words, it will traverse the label looking for the first occurance of
00158  *the specified keyword and return the first value of the first occurance.
00159  *
00160  *
00161  * @param label   Label to search the keyword
00162  * @param keyword Nanme of keyword to find
00163  *
00164  * @return QString Returns first value in the found keyword.  If the keyword
00165  *         does not exist, an empty string is returned.
00166  */
00167 QString SpiceSegment::getKeyValue(PvlObject &label,
00168                                       const QString &keyword) {
00169   QString value("");
00170   if ( label.HasKeyword(keyword,Pvl::Traverse) ) {
00171     value = label.FindKeyword(keyword,Pvl::Traverse)[0];
00172   }
00173   return (value);
00174 }
00175 
00176 
00177 /**
00178  * @brief Reentrant initializer for the variables of this object
00179  *
00180  * All variables are set to their respective defaults.  Strings are empty,
00181  * binaries are 0 and the Kernels object is cleared.
00182  *
00183  */
00184 void SpiceSegment::init() {
00185   _name = _fname = _instId = _target = "";
00186   _startTime = _endTime = 0.0;
00187   _utcStartTime = _utcEndTime = "";
00188   _kernels.Clear();
00189 }
00190 
00191 /**
00192  * @brief Retrieve and convert image times from labels
00193  *
00194  * This method retrieves the start and end times of the image observation from
00195  * the labels.  It mimicks what the spiceinit application does when making this
00196  * determination.
00197  *
00198  * @param lab   Label to get times from
00199  * @param start Returns start time of the image from the Instrument/StartTime
00200  *              keyword if it exists
00201  * @param end   Returns end time of the image from the Instrument/EndTime
00202  *              keyword if it exists
00203  *
00204  * @return bool Always returns true
00205  */
00206 bool SpiceSegment::getImageTimes(Pvl &lab, double &start, double &end) const {
00207 
00208   _kernels.Load("LSK,SCLK");
00209   PvlObject &cube = lab.FindObject("IsisCube");
00210   // Get the start and end time for the cube
00211   start = UTCtoET((QString) cube.FindGroup("Instrument")["StartTime"]);
00212   if(cube.FindGroup("Instrument").HasKeyword("StopTime")) {
00213     end = UTCtoET((QString) cube.FindGroup("Instrument")["StopTime"]);
00214   }
00215   else {
00216     end = UTCtoET (cube.FindGroup("Instrument")["StartTime"]);
00217   }
00218 
00219   return (true);
00220 }
00221 
00222 /**
00223  * @brief Add elements to top and bottom of a matrix
00224  *
00225  * This method is to expand a matrix to add additional records for padding
00226  * purposes. The parameter ntop indicate the number to add to the top of the
00227  * matrix. nbot indicates the number to add to the bottom
00228  *
00229  * Elements added to the top have the contents of the first element of the
00230  * input matrix copied to it. Elements added to the bottom have the last
00231  * element copied to it.
00232  *
00233  * The new matrix has the contents of the original copied to it place
00234  * immediately after the number of elements added to it.
00235  *
00236  * @author Kris Becker - 4/6/2011
00237  *
00238  * @param ntop Number of elements to add to the top
00239  * @param vec  number of elements to add to the bottom
00240  * @param matrix Matrix to add elements to
00241  *
00242  *  @return SpiceSegment::SMatrix Expanded matrix
00243  */
00244 SpiceSegment::SMatrix SpiceSegment::expand(int ntop, int nbot,
00245                                            const SpiceSegment::SMatrix &matrix)
00246                                            const {
00247   //  Add lines to matrix at top and bottom
00248   int ndim(matrix.dim1());
00249   ntop = std::max(0, ntop);
00250   nbot = std::max(0, nbot);
00251   int nlines(ndim+ntop+nbot);
00252   SMatrix mat(nlines, matrix.dim2());
00253 
00254 
00255   // Duplicate top lines from first input matrix line
00256   for (int n = 0 ; n < ntop ; n++) {
00257     for (int s = 0 ; s < matrix.dim2() ; s++) {
00258       mat[n][s] = matrix[0][s];
00259     }
00260   }
00261 
00262   // Copy the contents of the input matrix to the output
00263   for (int n = 0 ; n < ndim ; n++) {
00264     for (int s = 0 ; s < matrix.dim2() ; s++) {
00265       mat[n+ntop][s] = matrix[n][s];
00266     }
00267   }
00268 
00269   // Duplicate bottom lines from last input matrix lines
00270   for (int n = 0 ; n < nbot ; n++) {
00271     for (int s = 0 ; s < matrix.dim2() ; s++) {
00272       mat[nlines-1-n][s] = matrix[ndim-1][s];
00273     }
00274   }
00275 
00276   return (mat);
00277 }
00278 
00279 /**
00280  * @brief Add elements to top and bottom of a vector
00281  *
00282  * This method is to expand a vector to add additional records for padding
00283  * purposes. The parameter ntop indicate the number to add to the top of the
00284  * vector. nbot indicates the number to add to the bottom
00285  *
00286  * Elements added to the top have the contents of the first element of the
00287  * input vector copied to it. Elements added to the bottom have the last
00288  * element copied to it.
00289  *
00290  * The new vector has the contents of the original copied to it place
00291  * immediately after the number of elements added to it.
00292  *
00293  * @author Kris Becker - 4/6/2011
00294  *
00295  * @param ntop Number of elements to add to the top
00296  * @param vec  number of elements to add to the bottom
00297  * @param vector Vector to add elements to
00298  *
00299  *  @return SpiceSegment::SVector Expanded vector
00300  */
00301 SpiceSegment::SVector SpiceSegment::expand(int ntop, int nbot,
00302                                            const SpiceSegment::SVector &vec)
00303                                            const {
00304   //  Add lines to matrix at top and bottom
00305   int ndim(vec.dim1());
00306   ntop = std::max(0, ntop);
00307   nbot = std::max(0, nbot);
00308   int nvals(ndim+ntop+nbot);
00309   SVector myvec(nvals);
00310 
00311   // Duplicate top elements to expanded elements
00312   for (int n = 0 ; n < ntop ; n++) {
00313     myvec[n] = vec[0];
00314   }
00315 
00316   // Copy elements from input vector to output
00317   for (int n = 0 ; n < vec.dim1() ; n++) {
00318     myvec[n+ntop] = vec[n];
00319   }
00320 
00321 
00322   // Duplicate bottom elements to expanded elements
00323   for (int n = 0 ; n < nbot ; n++) {
00324     myvec[nvals-1-n] = vec[ndim-1];
00325   }
00326 
00327   return (myvec);
00328 }
00329 
00330 
00331 /** Sets start time  */
00332 void SpiceSegment::setStartTime(double et) {
00333   _startTime = et;
00334   _utcStartTime = toUTC(_startTime);
00335 }
00336 
00337 /** Sets end time */
00338 void SpiceSegment::setEndTime(double et) {
00339   _endTime = et;
00340   _utcEndTime = toUTC(_endTime);
00341 }
00342 
00343 /**
00344  * @brief Convert NAIF code to frame or body name
00345  *
00346  * This routine will convert a NAIF integer code to either the frame (first) or
00347  * body (second) name.
00348  *
00349  * @author kbecker (3/26/2011)
00350  *
00351  * @param naifid NAIF integer code to convert to a name
00352  *
00353  * @return QString Returns the frame or body name.
00354  */
00355 QString SpiceSegment::getNaifName(int naifid) const {
00356   SpiceChar naifBuf[40];
00357   frmnam_c ( (SpiceInt) naifid, sizeof(naifBuf), naifBuf);
00358   string cframe(naifBuf);
00359 
00360   if ( cframe.empty() ) {
00361     SpiceBoolean found;
00362     bodc2n_c((SpiceInt) naifid, sizeof(naifBuf), naifBuf, &found);
00363     if ( found ) cframe = naifBuf;
00364   }
00365 
00366   // If it fails, just report it missing
00367   if ( cframe.empty() ) {
00368     string mess = "Failed to convert FrameId (" + IString(naifid) +
00369                   ") to string - perhaps the frame kernel is missing or not" +
00370                   " loaded.";
00371     cframe = "_UNKNOWN_";
00372   //  throw iException::Message(iException::User, mess.c_str(), _FILEINFO_);
00373   }
00374 
00375 
00376   return (cframe.c_str());
00377 }
00378 
00379 /** Converts and ET time to UTC string */
00380 QString SpiceSegment::toUTC(const double &et) const {
00381   const int UTCLEN = 80;
00382   char utcout[UTCLEN];
00383   et2utc_c(et, "ISOC", 3, UTCLEN, utcout);
00384   return (QString(utcout));
00385 }
00386 
00387 /** Converts a UTC time string to ET  */
00388 double SpiceSegment::UTCtoET(const QString &utc) const {
00389   SpiceDouble et;
00390   utc2et_c(utc.toAscii().data(), &et);
00391   return (et);
00392 }
00393 
00394 };  // namespace Isis
00395