USGS

Isis 3.0 Application Source Code Reference

Home

cnetextract.cpp

Go to the documentation of this file.
00001 #include "Isis.h"
00002 
00003 #include <map>
00004 #include <set>
00005 #include <sstream>
00006 
00007 #include "CameraFactory.h"
00008 #include "ControlNet.h"
00009 #include "ControlPoint.h"
00010 #include "CubeManager.h"
00011 #include "FileList.h"
00012 #include "iException.h"
00013 #include "iString.h"
00014 #include "ProjectionFactory.h"
00015 #include "Pvl.h"
00016 #include "SerialNumber.h"
00017 #include "UserInterface.h"
00018 
00019 using namespace std; 
00020 using namespace Isis;
00021 
00022 bool NotInLatLonRange( double lat, double lon, double minlat,
00023                        double maxlat, double minlon, double maxlon );
00024 void WriteCubeOutList( ControlNet cnet, map<iString,iString> sn2file );
00025 
00026 // Main program
00027 void IsisMain() {
00028   UserInterface &ui = Application::GetUserInterface();
00029 
00030   // Gets the input parameters
00031   FileList inList( ui.GetFilename("FROMLIST") );
00032   ControlNet inNet( ui.GetFilename("CNET") );
00033 
00034   bool noIgnore        = ui.GetBoolean("NOIGNORE");
00035   bool noHeld          = ui.GetBoolean("NOHELD");
00036   bool noSingleMeasure = ui.GetBoolean("NOSINGLEMEASURE");
00037   bool reference       = ui.GetBoolean("REFERENCE");
00038   bool cubePoints      = ui.WasEntered("CUBEPOINTS");
00039   bool cubeMeasures    = ui.GetBoolean("CUBEMEASURES");
00040   bool pointsEntered   = ui.WasEntered("POINTLIST");
00041   bool latLon          = ui.GetBoolean("LATLON");
00042 
00043   if( !(noIgnore || noHeld || noSingleMeasure || reference || cubePoints || pointsEntered || latLon) ) {
00044     std::string msg = "At least one filter must be selected [";
00045     msg += "NOIGNORE,NOHELD,NOSINGLEMEASURE,REFERENCE,CUBEPOINTS,CUBEMEASURES,";
00046     msg += "POINTLIST,LATLON]";
00047     throw iException::Message(iException::User,msg,_FILEINFO_);
00048   }
00049   else if( cubeMeasures  &&  !cubePoints ) {
00050     std::string msg = "When CUBEMEASURES is selected, CUBEPOINTS must be given";
00051     msg += " a list of cubes.";
00052     throw iException::Message(iException::User,msg,_FILEINFO_);
00053   }
00054 
00055   // Set up the Serial Number to Filename mapping
00056   map<iString,iString> sn2filename;
00057   for( int cubeIndex=0; cubeIndex < (int)inList.size(); cubeIndex ++ ) {
00058     iString sn = SerialNumber::Compose( inList[cubeIndex] );
00059     sn2filename[sn] = inList[cubeIndex];
00060   }
00061 
00062 
00063   Progress progress;
00064   progress.SetMaximumSteps(inNet.Size());
00065   progress.CheckStatus();
00066 
00067   // Set up verctor records of how points/measures are removed
00068   PvlKeyword ignoredPoints( "IgnoredPoints" );
00069   PvlKeyword ignoredMeasures( "IgnoredMeasures" );
00070   PvlKeyword heldPoints( "HeldPoints" );
00071   PvlKeyword singlePoints( "SingleMeasurePoints" );
00072   PvlKeyword nonReferenceMeasures( "NonReferenseMeasures" );
00073   PvlKeyword nonCubePoints( "NonCubePoints" );
00074   PvlKeyword nonCubeMeasures( "NonCubeMeasures" );
00075   PvlKeyword noMeasurePoints( "NoMeasurePoints" );
00076   PvlKeyword nonListedPoints( "NonListedPoints" );
00077   PvlKeyword nonLatLonPoints( "LatLonOutOfRangePoints" );
00078   PvlKeyword cannotGenerateLatLonPoints( "NoLatLonPoints" );
00079 
00080   // Set up comparison data
00081   vector<iString> serialNumbers;
00082   if( cubePoints ) {
00083     FileList cubeList( ui.GetFilename("CUBEPOINTS") );
00084     for( int cubeIndex=0; cubeIndex < (int)cubeList.size(); cubeIndex ++ ) {
00085       iString sn = SerialNumber::Compose( cubeList[cubeIndex] );
00086       serialNumbers.push_back( sn );
00087     }
00088   }
00089 
00090   // Set up output values
00091   ControlNet outNet;
00092   outNet.SetType( inNet.Type() );
00093   outNet.SetTarget( inNet.Target() );
00094 
00095   if( ui.WasEntered("NETWORKID") )
00096     outNet.SetNetworkId( ui.GetString("NETWORKID") );
00097   else
00098     outNet.SetNetworkId( inNet.NetworkId() );
00099 
00100   outNet.SetUserName( Isis::Application::UserName() );
00101   outNet.SetDescription( ui.GetString("DESCRIPTION") );
00102 
00103   for(int cp=0; cp < inNet.Size(); cp ++) {
00104     progress.CheckStatus();
00105 
00106     // Do preliminary exclusion checks
00107     if( noIgnore && inNet[cp].Ignore() ) {
00108       ignoredPoints += inNet[cp].Id();
00109       continue;
00110     }
00111     else if( noHeld && inNet[cp].Held() ) {
00112       heldPoints += inNet[cp].Id();
00113       continue;
00114     }
00115     else if( noSingleMeasure ) {
00116       bool invalidPoint = false;
00117       invalidPoint |= noIgnore && (inNet[cp].NumValidMeasures() < 2);
00118       invalidPoint |= inNet[cp].Size() < 2 && (inNet[cp].Type() != ControlPoint::Ground);
00119 
00120       if( invalidPoint ) {
00121         singlePoints+= inNet[cp].Id();
00122         continue;
00123       }
00124     }
00125 
00126     // Begin constructing the new Control Point
00127     ControlPoint outPoint = inNet[cp];
00128 
00129     // Build the new Control Point
00130     for( int cm = outPoint.Size()-1; cm >= 0; cm --) {
00131       if(noIgnore && outPoint[cm].Ignore()) {
00132         ignoredMeasures += "(" + outPoint.Id() + "," + outPoint[cm].CubeSerialNumber() + ")";
00133         outPoint.Delete( cm );
00134       }
00135       else if( reference && !outPoint[cm].IsReference() ) {
00136         nonReferenceMeasures += "(" + outPoint.Id() + "," + outPoint[cm].CubeSerialNumber() + ")";
00137         outPoint.Delete( cm );
00138       }
00139       else if( cubeMeasures ) {
00140         bool hasSerialNumber = false;
00141 
00142         for( unsigned int sn = 0; sn < serialNumbers.size() && !hasSerialNumber; sn ++) {
00143           if(serialNumbers[sn] == outPoint[cm].CubeSerialNumber()) hasSerialNumber = true;
00144         }
00145 
00146         if( !hasSerialNumber ) { 
00147           nonCubeMeasures += "(" + outPoint.Id() + "," + outPoint[cm].CubeSerialNumber() + ")";
00148           outPoint.Delete( cm );
00149         }
00150       }
00151     }
00152 
00153 
00154     // Do not add outPoint if it has too few measures
00155     if( noSingleMeasure ) {
00156       bool invalidPoint = false;
00157       invalidPoint |= noIgnore && (outPoint.NumValidMeasures() < 2);
00158       invalidPoint |= outPoint.Size() < 2 && outPoint.Type() != ControlPoint::Ground;
00159 
00160       if( invalidPoint ) {
00161         singlePoints += inNet[cp].Id();
00162         continue;
00163       }
00164     }
00165 
00166     // Do not add outPoint if it does not have a cube in CUBEPOINTS as asked
00167     if( cubePoints && !cubeMeasures ) {
00168       bool hasSerialNumber = false;
00169 
00170       for( int cm = 0; cm < outPoint.Size() && !hasSerialNumber; cm ++) {
00171         for( unsigned int sn = 0; sn < serialNumbers.size() && !hasSerialNumber; sn ++) {
00172           if(serialNumbers[sn] == outPoint[cm].CubeSerialNumber()) hasSerialNumber = true;
00173         }
00174       }
00175 
00176       if( !hasSerialNumber ) {
00177         nonCubePoints += outPoint.Id();
00178         continue;
00179       }
00180     }
00181 
00182     if( outPoint.Size() == 0 ) {
00183       noMeasurePoints += outPoint.Id();
00184       continue;
00185     }
00186 
00187     outNet.Add( outPoint );
00188   }
00189 
00190 
00191   /**
00192    * Use another pass to check for Ids, since string comparisons are expensive
00193    */
00194   if( pointsEntered ) {
00195     FileList listedPoints( ui.GetFilename("POINTLIST") );
00196 
00197     for( int cp = outNet.Size()-1; cp >= 0; cp -- ) {
00198       bool isInList = false;
00199       for( int pointId = 0; pointId < (int)listedPoints.size()  &&  !isInList; pointId ++ ) {
00200         isInList = outNet[cp].Id().compare( listedPoints[pointId] ) == 0;
00201       }
00202 
00203       if( !isInList ) {
00204         nonListedPoints += outNet[cp].Id();
00205         outNet.Delete( cp );
00206       }
00207     }
00208   }
00209 
00210 
00211   /** 
00212    *  Use another pass on outNet, because this is by far the most time consuming
00213    *  process, and time could be saved by using the usually smaller outNet instead
00214    *  of inNet
00215    */
00216   if( latLon ) {
00217     double minlat = ui.GetDouble("MINLAT");
00218     double maxlat = ui.GetDouble("MAXLAT");
00219     double minlon = ui.GetDouble("MINLON");
00220     double maxlon = ui.GetDouble("MAXLON");
00221 
00222     Progress progress;
00223     progress.SetText("Calculating lat/lon");
00224     progress.SetMaximumSteps(outNet.Size());
00225     progress.CheckStatus();
00226 
00227     CubeManager manager;
00228     manager.SetNumOpenCubes( 50 ); //Should keep memory usage to around 1GB
00229 
00230     for( int cp = outNet.Size()-1; cp >= 0; cp --) {
00231       progress.CheckStatus();
00232 
00233       if( outNet[cp].Type() == Isis::ControlPoint::Ground ) {
00234         if( NotInLatLonRange( outNet[cp].UniversalLatitude(),
00235                               outNet[cp].UniversalLongitude(),
00236                               minlat, maxlat, minlon, maxlon ) ) {
00237           nonLatLonPoints += outNet[cp].Id();
00238           outNet.Delete( cp );
00239         }
00240       }
00241 
00242       /** 
00243        * If the point is not a Ground Point then we need to calculate lat/lon on our own
00244        */
00245       else {
00246 
00247         // Find a cube in the Control Point to get the lat/lon from
00248         int cm = 0;
00249         iString sn = "";
00250         double lat = 0.0;
00251         double lon = 0.0;
00252         double radius = 0.0;
00253   
00254         // First check the reference Measure
00255         if( outNet[cp].HasReference() ) {
00256           cm = outNet[cp].ReferenceIndex();
00257           if( !sn2filename[outNet[cp][cm].CubeSerialNumber()].empty() ) {
00258             sn = outNet[cp][cm].CubeSerialNumber();
00259           }
00260         }
00261   
00262         // Search for other Control Measures if needed
00263         if( sn.empty() ) {
00264           // Find the Serial Number if it exists
00265           for( int cm = 0; (cm < outNet[cp].Size()) && sn.empty(); cm ++ ) {
00266             if( !sn2filename[outNet[cp][cm].CubeSerialNumber()].empty() ) {
00267               sn = outNet[cp][cm].CubeSerialNumber();
00268             }
00269           }
00270         }
00271   
00272         // Connot fine a cube to get the lat/lon from
00273         if( sn.empty() ) {
00274           cannotGenerateLatLonPoints += outNet[cp].Id();
00275           outNet.Delete( cp );
00276         }
00277         
00278         // Calculate the lat/lon and check for validity
00279         else {
00280           bool remove = false;
00281 
00282           Cube *cube = manager.OpenCube( sn2filename[sn] );
00283           Camera *camera = cube->Camera();
00284 
00285           if (camera == NULL) {
00286             try {
00287               Projection *projection = ProjectionFactory::Create( (*(cube->Label())) );
00288 
00289               if(!projection->SetCoordinate(outNet[cp][cm].Sample(),outNet[cp][cm].Line())) {
00290                 nonLatLonPoints += outNet[cp].Id();
00291                 remove = true;
00292               }
00293 
00294               lat = projection->Latitude();
00295               lon = projection->Longitude();
00296               radius = projection->LocalRadius();
00297 
00298               delete projection;
00299               projection = NULL;
00300             } catch ( iException &e ) {
00301               remove = true;
00302               e.Clear();
00303             }
00304           }
00305           else {
00306             if(!camera->SetImage(outNet[cp][cm].Sample(),outNet[cp][cm].Line())) {
00307               nonLatLonPoints += outNet[cp].Id();
00308               remove = true;
00309             }
00310 
00311             lat = camera->UniversalLatitude();
00312             lon = camera->UniversalLongitude();
00313             radius = camera->LocalRadius();
00314 
00315             camera = NULL;
00316           }
00317 
00318           cube = NULL;
00319   
00320           if( remove  ||  NotInLatLonRange( lat, lon, minlat, maxlat, minlon, maxlon ) ) {
00321             nonLatLonPoints += outNet[cp].Id();
00322             outNet.Delete( cp );
00323           }
00324           else { // Add the reference lat/lon/radius to the Control Point
00325             outNet[cp].SetUniversalGround( lat, lon, radius );
00326           }
00327         }
00328       }
00329 
00330     }
00331 
00332     manager.CleanCubes();
00333   }
00334 
00335 
00336 
00337   // Write the filenames associated with outNet
00338   WriteCubeOutList( outNet, sn2filename );
00339 
00340   Progress outProgress;
00341   outProgress.SetText("Writing Control Network");
00342   outProgress.SetMaximumSteps( 5 );
00343   outProgress.CheckStatus();
00344 
00345   // Create the points included file
00346   PvlGroup included("NewControlNet");
00347   included.AddKeyword( PvlKeyword( "Size", outNet.Size() ) );
00348   PvlKeyword newPoints( "Points" );
00349   for( int cp = 0; cp < outNet.Size(); cp ++ ) {
00350     newPoints.AddValue( outNet[cp].Id() );
00351   }
00352   included.AddKeyword( newPoints );
00353 
00354   outProgress.CheckStatus();
00355 
00356   // Write the extracted Control Network
00357   outNet.Write( ui.GetFilename("OUTNET") );
00358 
00359   outProgress.CheckStatus();
00360 
00361   // Adds the remove history to the summary and results group
00362   PvlGroup summary("ResultSummary");
00363   PvlGroup results("Results");
00364 
00365   if( noIgnore ) {
00366     summary.AddKeyword( PvlKeyword( "IgnoredPoints", ignoredPoints.Size() ) ); 
00367     results.AddKeyword( ignoredPoints );
00368     summary.AddKeyword( PvlKeyword( "IgnoredMeasures", ignoredMeasures.Size() ) ); 
00369     results.AddKeyword( ignoredMeasures );
00370   }
00371   if( noHeld ) {
00372     summary.AddKeyword( PvlKeyword( "HeldPoints", heldPoints.Size() ) ); 
00373     results.AddKeyword( heldPoints );
00374   }
00375   if( noSingleMeasure ) {
00376     summary.AddKeyword( PvlKeyword( "SingleMeasurePoints", singlePoints.Size() ) ); 
00377     results.AddKeyword( singlePoints );
00378   }
00379   if( reference ) {
00380     summary.AddKeyword( PvlKeyword( "NonReferenceMeasures", nonReferenceMeasures.Size() ) ); 
00381     results.AddKeyword( nonReferenceMeasures );
00382   }
00383   if( cubePoints ) {
00384     summary.AddKeyword( PvlKeyword( "NonCubePoints", nonCubePoints.Size() ) ); 
00385     results.AddKeyword( nonCubePoints );
00386   }
00387   if( noMeasurePoints.Size() != 0 ) {
00388     summary.AddKeyword( PvlKeyword( "NonCubeMeasure", noMeasurePoints.Size() ) ); 
00389     results.AddKeyword( noMeasurePoints );
00390   }
00391   if( cubeMeasures ) {
00392     summary.AddKeyword( PvlKeyword( "NoMeasurePoints", nonCubeMeasures.Size() ) ); 
00393     results.AddKeyword( nonCubeMeasures );
00394   }
00395   if( pointsEntered ) {
00396     summary.AddKeyword( PvlKeyword( "NonListedPoints", nonListedPoints.Size() ) ); 
00397     results.AddKeyword( nonListedPoints );
00398   }
00399   if( latLon ) {
00400     summary.AddKeyword( PvlKeyword( "LatLonOutOfRange", nonLatLonPoints.Size() ) ); 
00401     results.AddKeyword( nonLatLonPoints );
00402     summary.AddKeyword( PvlKeyword( "NoLatLonPoints", cannotGenerateLatLonPoints.Size() ) ); 
00403     results.AddKeyword( cannotGenerateLatLonPoints );
00404   }
00405 
00406   outProgress.CheckStatus();
00407   
00408   // Log Control Net results
00409   Application::Log(included);
00410   Application::Log(summary);
00411   results.AddComment( "Each keyword represents a filter parameter used." \
00412                       " Check the documentation for specific keyword descriptions." );
00413   Application::Log(results);
00414 
00415   outProgress.CheckStatus();
00416 
00417 }
00418 
00419 
00420 
00421 /**
00422  * Checks for correct lat/lon range, handling the meridian correctly
00423  *  
00424  * @param lat The latitude to check 
00425  * @param lon The longitude to check
00426  * @param minlat Minimum Latitude Minimum valid latitude
00427  * @param maxlat Maximum Latitude Maximum valid latitude
00428  * @param minlon Minimum Longitude Minimum valid longitude
00429  * @param maxlon Maximum Longitude Maximum valid longitude
00430  * 
00431  * @return bool True when the range is valid
00432  */
00433 bool NotInLatLonRange( double lat, double lon, double minlat,
00434                        double maxlat, double minlon, double maxlon ) {
00435   bool inRange = true;
00436 
00437   // Check latitude range
00438   if( inRange && minlat > maxlat ) {
00439     inRange &= (lat <= maxlat || lat >= minlat);
00440   }
00441   else if( inRange ) {
00442     inRange &= (lat >= minlat && lat <= maxlat);
00443   }
00444 
00445   // Check longitude range
00446   if( inRange && minlon > maxlon ) {
00447     inRange &= (lon <= maxlon || lon >= minlon);
00448   }
00449   else if( inRange ){
00450     inRange &= (lon >= minlon && lon <= maxlon);
00451   }
00452 
00453   return !inRange;
00454 }
00455 
00456 
00457 /**
00458  * Finds and writes all input cubes contained within the given Control Network 
00459  * to the output file list 
00460  * 
00461  * @param cnet The Control Network to list the filenames contained within
00462  * @param sn2file The map for converting the Control Network's serial numbers 
00463  *                to filenames 
00464  */
00465 void WriteCubeOutList( ControlNet cnet, map<iString,iString> sn2file ) {
00466   UserInterface &ui = Application::GetUserInterface();
00467 
00468   Progress p;
00469   p.SetText("Writing Cube List");
00470   try {
00471     p.SetMaximumSteps(cnet.Size());
00472     p.CheckStatus();
00473   } catch( iException &e ) {
00474     e.Clear();
00475     string msg = "The provided filters have resulted in an empty Control Network.";
00476     throw Isis::iException::Message(Isis::iException::User,msg, _FILEINFO_);
00477   }
00478 
00479   set<iString> outputsn;
00480   for( int cp = 0; cp < cnet.Size(); cp ++ ) {
00481     for( int cm = 0; cm < cnet[cp].Size(); cm ++ ) {
00482       outputsn.insert( cnet[cp][cm].CubeSerialNumber() );
00483     }
00484     p.CheckStatus();
00485   }
00486 
00487   std::string toList = ui.GetFilename("TOLIST");
00488   ofstream out_stream;
00489   out_stream.open(toList.c_str(), std::ios::out);
00490   out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file
00491 
00492   for( set<iString>::iterator sn = outputsn.begin(); sn != outputsn.end(); sn ++ ) {
00493     if( !sn2file[(*sn)].empty() ) {
00494       out_stream << sn2file[(*sn)] << endl;
00495     }
00496   }
00497 
00498   out_stream.close();
00499 }
00500