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