USGS

Isis 3.0 Application Source Code Reference

Home

HiJitCube.cpp

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