|
Isis 3.0 Application Source Code Reference |
Home |
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