Isis 3.0 Application Source Code Reference |
Home |
00001 /** 00002 * @file 00003 * $Revision: 1.7 $ 00004 * $Date: 2009/12/29 23:03:52 $ 00005 * 00006 * Unless noted otherwise, the portions of Isis written by the USGS are public 00007 * domain. See individual third-party library and package descriptions for 00008 * intellectual property information,user agreements, and related information. 00009 * 00010 * Although Isis has been used by the USGS, no warranty, expressed or implied, 00011 * is made by the USGS as to the accuracy and functioning of such software 00012 * and related material nor shall the fact of distribution constitute any such 00013 * warranty, and no responsibility is assumed by the USGS in connection 00014 * therewith. 00015 * 00016 * For additional information, launch 00017 * $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see 00018 * the Privacy & Disclaimers page on the Isis website, 00019 * http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on 00020 * http://www.usgs.gov/privacy.html. 00021 */ 00022 00023 #include <string> 00024 #include <sstream> 00025 #include <iostream> 00026 00027 #include "naif/SpiceUsr.h" 00028 00029 #include "HiJitCube.h" 00030 #include "iException.h" 00031 #include "Instrument.hh" 00032 #include "Pvl.h" 00033 #include "PvlGroup.h" 00034 #include "Filename.h" 00035 00036 using namespace UA::HiRISE; 00037 using std::string; 00038 using std::endl; 00039 using std::ostringstream; 00040 00041 00042 namespace Isis { 00043 00044 00045 static geos::geom::GeometryFactory geosFactory; 00046 bool HiJitCube::naifLoaded = false; 00047 int npSamp0[] = {0, 1971, 3964, 5963, 7970, 7971, 7971, 9975, 9976, 9976, 11981, 13986, 15984, 17982}; 00048 int npSamps[] = {2021, 2043, 2048, 2052, 2055, 2053, 2053, 2053, 2054, 2055, 2051, 2049, 2043, 2018}; 00049 bool sampinit = false; 00050 bool originst; 00051 00052 /** 00053 * @brief Default constructor with no cube 00054 */ 00055 HiJitCube::HiJitCube() { 00056 initLocal(); 00057 } 00058 00059 /** 00060 * @brief Constructor with file to open 00061 */ 00062 HiJitCube::HiJitCube(const std::string &filename) { 00063 initLocal(); 00064 OpenCube(filename); 00065 } 00066 00067 /** 00068 * @brief Constructor with file to open and potential shift applied 00069 */ 00070 HiJitCube::HiJitCube(const std::string &filename, PvlObject &shift) { 00071 initLocal(); 00072 OpenCube(filename, shift); 00073 } 00074 00075 00076 /** 00077 * @brief Destructor 00078 */ 00079 HiJitCube::~HiJitCube() { 00080 delete fpGeom; 00081 close(); 00082 } 00083 00084 void HiJitCube::setSampleOffset(int soff) { 00085 jdata.sampOffset = soff; 00086 if(isOpen()) computePoly(); 00087 return; 00088 } 00089 00090 void HiJitCube::setLineOffset(int loff) { 00091 jdata.lineOffset = loff; 00092 if(isOpen()) computePoly(); 00093 return; 00094 } 00095 00096 00097 void HiJitCube::OpenCube(const std::string &filename) { 00098 open(filename); 00099 Init(); 00100 return; 00101 } 00102 00103 void HiJitCube::OpenCube(const std::string &filename, PvlObject &shift) { 00104 OpenCube(filename); 00105 00106 // Determine if a shift of the CCD exists in the definitions file 00107 if(shift.HasGroup(jdata.ccdName)) { 00108 PvlGroup &ccddef = shift.FindGroup(jdata.ccdName, Pvl::Traverse); 00109 if(ccddef.HasKeyword("SampleOffset")) { 00110 jdata.sampOffset = (int) ccddef["SampleOffset"]; 00111 } 00112 if(ccddef.HasKeyword("LineOffset")) { 00113 jdata.lineOffset = (int) ccddef["LineOffset"]; 00114 } 00115 computePoly(); 00116 } 00117 00118 return; 00119 } 00120 00121 double HiJitCube::getLineTime(double line) const { 00122 return (((line - 1.0) * jdata.linerate) + jdata.obsStartTime); 00123 } 00124 00125 void HiJitCube::Compatable(HiJitCube &cube) { 00126 JitInfo other = cube.GetInfo(); 00127 00128 if(jdata.summing != other.summing) { 00129 ostringstream msg; 00130 msg << "Summing mode (" << jdata.summing 00131 << ") in file " << getFilename() << " is not equal to summing mode (" 00132 << other.summing << ") in file " << cube.getFilename() << endl; 00133 throw iException::Message(iException::User, msg.str(), _FILEINFO_); 00134 } 00135 return; 00136 } 00137 00138 00139 bool HiJitCube::intersects(const HiJitCube &cube) const { 00140 return (fpGeom->intersects(cube.Poly())); 00141 } 00142 00143 bool HiJitCube::overlap(const HiJitCube &cube, Corners &ovlCorners) { 00144 geos::geom::Geometry *ovl = fpGeom->intersection(cube.Poly()); 00145 // cout << "Overlap: " << ovl->toString() << std::endl; 00146 ovlCorners = FocalPlaneToImage(getCorners(*ovl)); 00147 delete ovl; 00148 return (ovlCorners.good); 00149 } 00150 00151 00152 void HiJitCube::loadNaifTiming() { 00153 if(!naifLoaded) { 00154 // Load the NAIF kernels to determine timing data 00155 Isis::Filename leapseconds("$base/kernels/lsk/naif????.tls"); 00156 leapseconds.HighestVersion(); 00157 00158 Isis::Filename sclk("$mro/kernels/sclk/MRO_SCLKSCET.?????.65536.tsc"); 00159 sclk.HighestVersion(); 00160 00161 // Load the kernels 00162 string lsk = leapseconds.Expanded(); 00163 string sClock = sclk.Expanded(); 00164 furnsh_c(lsk.c_str()); 00165 furnsh_c(sClock.c_str()); 00166 00167 // Ensure it is loaded only once 00168 naifLoaded = true; 00169 } 00170 return; 00171 } 00172 00173 void HiJitCube::computeStartTime() { 00174 loadNaifTiming(); 00175 00176 // Compute the unbinned and binned linerates in seconds 00177 jdata.unBinnedRate = ((Instrument::LINE_TIME_PRE_OFFSET + 00178 (jdata.dltCount / Instrument::HIRISE_CLOCK_SUBTICK_MICROS)) 00179 / 1000000.0); 00180 jdata.linerate = jdata.unBinnedRate * ((double) jdata.summing); 00181 00182 if(!jdata.scStartTime.empty()) { 00183 string scStartTimeString = jdata.scStartTime; 00184 scs2e_c(-74999, scStartTimeString.c_str(), &jdata.obsStartTime); 00185 // Adjust the start time so that it is the effective time for 00186 // the first line in the image file 00187 jdata.obsStartTime -= (jdata.unBinnedRate * (((double(jdata.tdiMode / 2.0) 00188 - 0.5)))); 00189 // Effective observation 00190 // time for all the TDI lines used for the 00191 // first line before doing binning 00192 jdata.obsStartTime += (jdata.unBinnedRate * (((double) jdata.summing / 2.0) 00193 - 0.5)); 00194 } 00195 return; 00196 } 00197 00198 void HiJitCube::initLocal() { 00199 jdata.filename = "_none_"; 00200 jdata.productId = "__undetermined__"; 00201 jdata.lines = 0; 00202 jdata.samples = 0; 00203 jdata.sampOffset = 0; 00204 jdata.lineOffset = 0; 00205 jdata.tdiMode = 0; 00206 jdata.summing = 0; 00207 jdata.channelNumber = 0; 00208 jdata.cpmmNumber = 0; 00209 jdata.ccdName = "_unknown_"; 00210 jdata.dltCount = 0.0; 00211 jdata.UTCStartTime = ""; 00212 jdata.scStartTime = ""; 00213 jdata.obsStartTime = 0.0; 00214 jdata.unBinnedRate = 0.0; 00215 jdata.linerate = 0.0; 00216 jdata.fpSamp0 = 0; 00217 jdata.fpLine0 = 0; 00218 jdata.pixpitch = 0.0; 00219 00220 fpGeom = 0; 00221 } 00222 00223 void HiJitCube::Init() { 00224 // Get required keywords from instrument group 00225 Pvl *label(getLabel()); 00226 Isis::PvlGroup inst; 00227 Isis::PvlGroup idinst; 00228 jdata.filename = getFilename(); 00229 Isis::PvlGroup &archive = label->FindGroup("Archive", Isis::Pvl::Traverse); 00230 jdata.productId = (string) archive["ProductId"]; 00231 00232 jdata.lines = getLineCount(); 00233 if(label->FindObject("IsisCube").HasGroup("OriginalInstrument")) { 00234 inst = label->FindGroup("OriginalInstrument", Isis::Pvl::Traverse); 00235 originst = true; 00236 } 00237 else { 00238 inst = label->FindGroup("Instrument", Isis::Pvl::Traverse); 00239 originst = false; 00240 } 00241 jdata.tdiMode = inst["Tdi"]; 00242 jdata.summing = inst["Summing"]; 00243 if(label->FindObject("IsisCube").HasGroup("Instrument") && originst) { 00244 idinst = label->FindGroup("Instrument", Isis::Pvl::Traverse); 00245 jdata.pixpitch = idinst["PixelPitch"]; 00246 jdata.summing = (int)(jdata.pixpitch / .012); 00247 } 00248 if(originst && jdata.summing != 1 && !sampinit) { 00249 for(int i = 0; i < 14; i++) { 00250 npSamps[i] = (int)(npSamps[i] / (float)jdata.summing + 0.5); 00251 npSamp0[i] = (int)(npSamp0[i] / (float)jdata.summing + 0.5); 00252 } 00253 sampinit = true; 00254 } 00255 jdata.channelNumber = inst["ChannelNumber"]; 00256 jdata.cpmmNumber = inst["CpmmNumber"]; 00257 if(originst) { 00258 jdata.samples = npSamps[jdata.cpmmNumber]; 00259 } 00260 else { 00261 jdata.samples = getSampleCount(); 00262 } 00263 jdata.ccdName = Instrument::CCD_NAMES[jdata.cpmmNumber]; 00264 jdata.dltCount = inst["DeltaLineTimerCount"]; 00265 jdata.UTCStartTime = (string) inst["StartTime"]; 00266 jdata.scStartTime = (string) inst["SpacecraftClockStartCount"]; 00267 00268 try { 00269 if(originst) { 00270 jdata.fpSamp0 = npSamp0[jdata.cpmmNumber]; 00271 } 00272 else { 00273 jdata.fpSamp0 = Instrument::focal_plane_x_offset(jdata.cpmmNumber, 00274 jdata.summing); 00275 } 00276 } 00277 catch(Exception hiExc) { 00278 ostringstream msg; 00279 msg << "Summing mode (" << jdata.summing 00280 << ") is illegal (must be > 0) or CPMM number (" << jdata.cpmmNumber 00281 << ") is invalid in file " << getFilename() << endl; 00282 throw iException::Message(iException::User, msg.str(), _FILEINFO_); 00283 } 00284 00285 // It is assumed all images start at the line location in the focal plane 00286 jdata.fpLine0 = 0; 00287 00288 // Validate channel number and adjust starting sample 00289 if((jdata.channelNumber > 2) || (jdata.channelNumber < 0)) { 00290 ostringstream msg; 00291 msg << "Channel number (" << jdata.channelNumber 00292 << ") is invalid (must be 0, 1 or 2) in file " << getFilename() 00293 << endl; 00294 throw iException::Message(iException::User, msg.str(), _FILEINFO_); 00295 } 00296 else { 00297 if(originst) { 00298 if(jdata.channelNumber == 0) jdata.fpSamp0 += npSamps[jdata.cpmmNumber]; 00299 } 00300 else { 00301 if(jdata.channelNumber == 0) jdata.fpSamp0 += getSampleCount(); 00302 } 00303 } 00304 00305 // Determine starting time of image and compute the binning rates 00306 computeStartTime(); 00307 00308 // Compute the focal plane polygon for this image 00309 computePoly(); 00310 return; 00311 } 00312 00313 00314 int HiJitCube::getBinModeIndex(int summing) const { 00315 for(unsigned int i = 0 ; i < Instrument::TOTAL_BINNING_FACTORS ; i++) { 00316 int binFactor = Instrument::BINNING_FACTORS[i]; 00317 if(binFactor == summing) return (i); 00318 } 00319 00320 ostringstream msg; 00321 msg << "Invalid summing mode (" << summing << ") for file " << 00322 getFilename() << std::endl; 00323 throw iException::Message(iException::User, msg.str(), _FILEINFO_); 00324 } 00325 00326 00327 void HiJitCube::computePoly() { 00328 00329 // Compute sample and line coordinates in the focal plane 00330 int samp0, sampN; 00331 if(originst) { 00332 samp0 = jdata.fpSamp0 + jdata.sampOffset; 00333 sampN = samp0 + npSamps[jdata.cpmmNumber] - 1; 00334 } 00335 else { 00336 samp0 = jdata.fpSamp0 + jdata.sampOffset; 00337 sampN = samp0 + getSampleCount() - 1; 00338 } 00339 int line0(jdata.fpLine0 + jdata.lineOffset), lineN(line0 + getLineCount() - 1); 00340 00341 // Allocate a new coordinate sequence and define it 00342 geos::geom::CoordinateSequence *pts = new geos::geom::CoordinateArraySequence(); 00343 pts->add(geos::geom::Coordinate(samp0, lineN)); 00344 pts->add(geos::geom::Coordinate(sampN, lineN)); 00345 pts->add(geos::geom::Coordinate(sampN, line0)); 00346 pts->add(geos::geom::Coordinate(samp0, line0)); 00347 pts->add(geos::geom::Coordinate(samp0, lineN)); 00348 00349 00350 // Make this reentrant and delete previous one if it exists and get the 00351 // new one 00352 delete fpGeom; 00353 fpGeom = geosFactory.createPolygon(geosFactory.createLinearRing(pts), 0); 00354 return; 00355 } 00356 00357 HiJitCube::Corners HiJitCube::FocalPlaneToImage(const Corners &fp) const { 00358 Corners image; 00359 if(fp.good) { 00360 double samp0; 00361 // Compute sample and line coordinates in the focal plane 00362 if(originst) { 00363 samp0 = 0; 00364 } 00365 else { 00366 samp0 = jdata.fpSamp0 + jdata.sampOffset; 00367 } 00368 double line0(jdata.fpLine0 + jdata.lineOffset); 00369 00370 image.topLeft.sample = fp.topLeft.sample - samp0 + 1.0; 00371 image.topLeft.line = fp.topLeft.line - line0 + 1.0; 00372 image.lowerRight.sample = fp.lowerRight.sample - samp0 + 1.0; 00373 image.lowerRight.line = fp.lowerRight.line - line0 + 1.0; 00374 image.good = true; 00375 } 00376 return (image); 00377 } 00378 00379 HiJitCube::Corners HiJitCube::getCorners(const geos::geom::Geometry &poly) const { 00380 Corners corners; 00381 if((poly.isValid()) && (!poly.isEmpty())) { 00382 00383 // Get the coordinate list 00384 geos::geom::CoordinateSequence *clist = poly.getCoordinates(); 00385 const geos::geom::Coordinate *minpt = clist->minCoordinate(); 00386 // cout << "MinPoint: " << minpt->x << ", " << minpt->y << std::endl; 00387 00388 geos::geom::Coordinate maxpt(clist->getAt(0)); 00389 for(unsigned int i = 1 ; i < clist->getSize() ; i++) { 00390 geos::geom::Coordinate pt = clist->getAt(i); 00391 if((pt.x >= maxpt.x) && (pt.y >= maxpt.y)) maxpt = pt; 00392 } 00393 // cout << "MaxPoint: " << maxpt.x << ", " << maxpt.y << std::endl; 00394 00395 corners.topLeft.sample = minpt->x; 00396 corners.topLeft.line = minpt->y; 00397 corners.lowerRight.sample = maxpt.x; 00398 corners.lowerRight.line = maxpt.y; 00399 corners.good = true; 00400 00401 delete clist; 00402 } 00403 return (corners); 00404 } 00405 00406 00407 }