USGS

Isis 3.0 Application Source Code Reference

Home

cnetcheck.cpp

Go to the documentation of this file.
00001 #include "Isis.h"
00002 
00003 #include <set>
00004 #include <stack>
00005 #include <sstream>
00006 
00007 #include "UserInterface.h"
00008 #include "ControlNet.h"
00009 #include "Filename.h"
00010 #include "FileList.h"
00011 #include "SerialNumber.h"
00012 #include "CameraFactory.h"
00013 #include "ProjectionFactory.h"
00014 #include "PvlGroup.h"
00015 #include "PvlKeyword.h"
00016 #include "iString.h"
00017 
00018 using namespace std; 
00019 using namespace Isis;
00020 
00021 map< string, set<string> > constructPointSets(set<string> &index,
00022                                               ControlNet &innet);
00023 vector< set<string> > findIslands(set<string> &index, map< string,
00024                                             set<string> > &adjCubes);
00025 void WriteOutput( map<string,string> num2cube, string suffix,
00026                   set<string> &sns, map< string, set<string> > &cps );
00027 
00028 // Main program
00029 void IsisMain() {
00030   Progress progress;
00031   UserInterface &ui = Application::GetUserInterface();
00032   ControlNet innet( ui.GetFilename("CNET"), NULL, true );
00033   iString prefix(ui.GetString("PREFIX"));
00034   bool ignore = ui.GetBoolean("IGNORE");
00035 
00036   // Sets up the list of serial numbers for
00037   FileList inlist(ui.GetFilename("FROMLIST"));
00038   set<iString> inListNums;
00039   map<iString,int> netSerialNumCount;
00040   vector<iString> listedSerialNumbers;
00041   map< string, string > num2cube;
00042 
00043   if (inlist.size() > 0) {
00044     progress.SetText("Initializing");
00045     progress.SetMaximumSteps(inlist.size());
00046     progress.CheckStatus();
00047   }
00048 
00049   for(int index = 0; index < (int)inlist.size(); index ++) {
00050     iString st = SerialNumber::Compose(inlist[index]);
00051     inListNums.insert(st);
00052     listedSerialNumbers.push_back(st);  // Used with nonListedSerialNumbers
00053     num2cube[st] = inlist[index];  // Used as a SerialNumber to Cube index
00054     progress.CheckStatus();
00055   }
00056 
00057   vector<iString> nonListedSerialNumbers;
00058 
00059   set<string> singleMeasureSerialNumbers;
00060   map< string, set<string> > singleMeasureControlPoints;
00061 
00062   set<string> duplicateSerialNumbers;
00063   map< string, set<string> > duplicateControlPoints;
00064 
00065   set<string> noLatLonSerialNumbers;
00066   map< string, set<string> > noLatLonControlPoints;
00067   set<string> latlonchecked;
00068 
00069   if (innet.Size() > 0) {
00070     progress.SetText("Calculating");
00071     progress.SetMaximumSteps(innet.Size());
00072     progress.CheckStatus();
00073   }
00074 
00075   for(int cp = 0; cp < innet.Size(); cp ++) {
00076     if(ignore && innet[cp].Ignore()) continue;
00077 
00078     ControlPoint controlpt(innet[cp]);
00079 
00080     // Checks for lat/Lon production
00081     if( ui.GetBoolean("NOLATLON") ) {
00082       for (int cm = 0; cm < controlpt.Size(); cm ++) {
00083         ControlMeasure controlms= controlpt[cm];
00084 
00085         // Make sure a cube is not checked twice
00086         if ( !num2cube[controlms.CubeSerialNumber()].empty()  &&
00087              latlonchecked.find(controlms.CubeSerialNumber()) == latlonchecked.end() ) {
00088           latlonchecked.insert( controlms.CubeSerialNumber() );
00089 
00090           Pvl pvl( num2cube[controlms.CubeSerialNumber()] );
00091           Camera *camera( CameraFactory::Create( pvl ) );
00092           if (camera == NULL) {
00093             try {
00094               // Checking if the Projection can be made
00095               delete ProjectionFactory::Create( pvl );
00096             } catch ( iException &e ) {
00097               noLatLonSerialNumbers.insert(controlms.CubeSerialNumber());
00098               noLatLonControlPoints[controlms.CubeSerialNumber()].insert( controlpt.Id() );
00099               e.Clear();
00100             }
00101           }
00102           else if(!camera->SetImage(controlms.Sample(), controlms.Line())) {
00103             noLatLonSerialNumbers.insert(controlms.CubeSerialNumber());
00104             noLatLonControlPoints[controlms.CubeSerialNumber()].insert( controlpt.Id() );
00105           }
00106           delete camera;
00107         }
00108       }
00109     }
00110 
00111     // Checks of the ControlPoint has only 1 Measure
00112     if(controlpt.NumValidMeasures() == 1) {
00113       string sn = controlpt[0].CubeSerialNumber();
00114       singleMeasureSerialNumbers.insert(sn);
00115       singleMeasureControlPoints[sn].insert( controlpt.Id() );
00116     }
00117     else {
00118       // Checks for duplicate Measures for the same SerialNumber
00119       vector<ControlMeasure> controlMeasures;
00120       for(int cm = 0; cm < controlpt.Size(); cm ++) {
00121         if( ignore  &&  controlpt[cm].Ignore() ) continue;
00122 
00123         controlMeasures.push_back(controlpt[cm]);
00124         iString currentsn = controlpt[cm].CubeSerialNumber();
00125 
00126         // Compares previous ControlMeasure SerialNumbers with the current
00127         for(int pre_cm = controlMeasures.size()-1-1; pre_cm >= 0; pre_cm --) {
00128           if( controlMeasures[pre_cm].CubeSerialNumber() == currentsn ) {
00129             duplicateSerialNumbers.insert(currentsn); //serial number duplication
00130             duplicateControlPoints[currentsn].insert( controlpt.Id() );
00131           }
00132         }
00133 
00134         // Removes from the serial number list, cubes that are included in the cnet
00135         inListNums.erase( currentsn );
00136         netSerialNumCount[currentsn] ++;
00137 
00138         // Records if the currentsnum is not in the input cube list
00139         bool contains = false;
00140         for(int sn = 0; sn < (int)listedSerialNumbers.size()  &&  !contains; sn ++) {
00141           if(currentsn == listedSerialNumbers[sn]) {
00142             contains = true;
00143           }
00144         }
00145         // Check if already added
00146         for(int sn = 0; sn < (int)nonListedSerialNumbers.size()  &&  !contains; sn ++) {
00147           if(currentsn == nonListedSerialNumbers[sn]) {
00148             contains = true;
00149           }
00150         }
00151 
00152         if(!contains) {
00153           nonListedSerialNumbers.push_back(currentsn);
00154         }
00155       }
00156     }
00157 
00158     progress.CheckStatus();
00159 
00160   }
00161 
00162 
00163   // Checks/detects islands
00164   set<string> index;
00165   map< string, set<string> > adjCubes = constructPointSets(index, innet);
00166   vector< set<string> > islands = findIslands(index, adjCubes);
00167 
00168   // Output islands in the file-by-file format
00169   //  Islands that have no cubes listed in the input list will
00170   //  not be shown.
00171   for(int i=0; i < (int)islands.size(); i++) {
00172     string name(Filename(prefix + "Island." + iString(i+1)).Expanded());
00173     ofstream out_stream;
00174     out_stream.open(name.c_str(), std::ios::out);
00175     out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file
00176 
00177     bool hasList = false;
00178     for(set<string>::iterator island = islands[i].begin();
00179          island != islands[i].end(); island++) {
00180       if (((string)num2cube[*island]).compare("") != 0) {
00181         out_stream << Filename(num2cube[*island]).Name() << " " << *island;
00182         out_stream << "\n";
00183 
00184         hasList = true;
00185       }
00186     }
00187 
00188     out_stream.close();
00189 
00190     if (!hasList) {
00191       remove(name.c_str());
00192     }
00193   }
00194 
00195 
00196   // Output the results to screen and files accordingly
00197 
00198   PvlGroup results("Results");
00199 
00200   stringstream ss (stringstream::in | stringstream::out);
00201 
00202   results.AddKeyword( PvlKeyword("Islands",iString((BigInt)islands.size())) );
00203   ss << endl << "----------------------------------------" \
00204                 "----------------------------------------" << endl;
00205   if(islands.size() == 1) {
00206     ss << "The cubes are fully connected by the Control Network." << endl;
00207   }
00208   else if(islands.size() == 0) {
00209     ss << "There are no control points in the provided Control Network [";
00210     ss << Filename(ui.GetFilename("CNET")).Name() << "]" << endl;
00211   }
00212   else {
00213     ss << "The cubes are NOT fully connected by the Control Network." << endl;
00214     ss << "There are " << islands.size() << " disjoint sets of cubes." << endl;
00215   }
00216 
00217   if(ui.GetBoolean("SINGLE")  &&  singleMeasureSerialNumbers.size() > 0) {
00218     results.AddKeyword( 
00219       PvlKeyword("SingleMeasure",iString((BigInt)singleMeasureSerialNumbers.size())) );
00220 
00221     string name(Filename(prefix + "SinglePointCubes.txt").Expanded());
00222     WriteOutput( num2cube, name,
00223                  singleMeasureSerialNumbers, singleMeasureControlPoints );
00224 
00225     ss << "----------------------------------------" \
00226           "----------------------------------------" << endl;
00227     ss << "There are " << singleMeasureSerialNumbers.size();
00228     ss << " cubes in Control Points with only a single";
00229     ss << " Control Measure." << endl;
00230     ss << "The serial numbers of these measures are listed in [";
00231     ss <<  Filename(name).Name() + "]" << endl;
00232   }
00233 
00234   if(ui.GetBoolean("DUPLICATE")  &&  duplicateSerialNumbers.size() > 0) {
00235     results.AddKeyword(
00236       PvlKeyword("DuplicateMeasures",iString((BigInt)duplicateSerialNumbers.size())) );
00237 
00238     string name(Filename(prefix + "DuplicateMeasures.txt").Expanded());
00239     WriteOutput( num2cube, name,
00240                  duplicateSerialNumbers, duplicateControlPoints );
00241 
00242     ss << "----------------------------------------" \
00243           "----------------------------------------" << endl;
00244     ss << "There are " << duplicateSerialNumbers.size();
00245     ss << " duplicate Control Measures in the";
00246     ss << " Control Net." << endl;
00247     ss << "The serial numbers of these duplicate Control Measures";
00248     ss << " are listed in [" + Filename(name).Name() + "]" << endl;
00249   }
00250 
00251   if(ui.GetBoolean("NOLATLON")  &&  noLatLonSerialNumbers.size() > 0) {
00252     results.AddKeyword(
00253       PvlKeyword("NoLatLonCubes",iString((BigInt)noLatLonSerialNumbers.size())) );
00254 
00255     string name(Filename(prefix + "NoLatLon.txt").Expanded());
00256     WriteOutput( num2cube, name,
00257                  noLatLonSerialNumbers, noLatLonControlPoints );
00258 
00259     ss << "----------------------------------------" \
00260           "----------------------------------------" << endl;
00261     ss << "There are " << noLatLonSerialNumbers.size();
00262     ss << " serial numbers in the Control Network which are listed in the";
00263     ss << " input list and cannot compute latitude and longitudes." << endl;
00264     ss << "These serial numbers, filenames, and control points are listed in [";
00265     ss << Filename(name).Name() + "]" << endl;
00266   }
00267 
00268   // At this point, inListNums is the list of cubes NOT included in the
00269   //  ControlNet, and inListNums are their those cube's serial numbers.
00270   if(ui.GetBoolean("NOCONTROL") && !inListNums.empty() ) {
00271     results.AddKeyword( PvlKeyword("NoControl",iString((BigInt)inListNums.size())) );
00272 
00273     string name(Filename(prefix + "NoControl.txt").Expanded());
00274     ofstream out_stream;
00275     out_stream.open(name.c_str(), std::ios::out);
00276     out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file
00277     
00278     for( set<iString>::iterator sn = inListNums.begin();
00279          sn != inListNums.end();
00280          sn ++) {
00281       out_stream << (*sn);
00282       out_stream << "\t" << Filename(num2cube[(*sn)]).Name();
00283       out_stream << "\n";
00284     }
00285     
00286     out_stream.close();
00287     
00288     ss << "----------------------------------------" \
00289           "----------------------------------------" << endl;
00290     ss << "There are " << inListNums.size();
00291     ss << " cubes in the input list [" << Filename(ui.GetFilename("FROMLIST")).Name();
00292     ss << "] which do not exist or are ignored in the Control Network [";
00293     ss << Filename(ui.GetFilename("CNET")).Name() << "]" << endl;
00294     ss << "These cubes are listed in [" + Filename(name).Name() + "]" << endl;
00295   }
00296 
00297   // In addition, nonListedSerialNumbers should be the SerialNumbers of
00298   //  ControlMeasures in the ControlNet that do not have a correlating
00299   //  cube in the input list.
00300   if(ui.GetBoolean("NOCUBE")  &&  nonListedSerialNumbers.size() > 0) {
00301     results.AddKeyword(
00302       PvlKeyword("NoCube",iString((BigInt)nonListedSerialNumbers.size())) );
00303 
00304     string name(Filename(prefix + "NoCube.txt").Expanded());
00305     ofstream out_stream;
00306     out_stream.open(name.c_str(), std::ios::out);
00307     out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file
00308 
00309     for(int sn=0; sn < (int)nonListedSerialNumbers.size(); sn++) {
00310       out_stream << nonListedSerialNumbers[sn];
00311       out_stream << "\n";
00312     }
00313 
00314     out_stream.close();
00315 
00316     ss << "----------------------------------------" \
00317           "----------------------------------------" << endl;
00318     ss << "There are " << nonListedSerialNumbers.size();
00319     ss << " serial numbers in the Control Net [";
00320     ss << Filename(ui.GetFilename("CNET")).Basename();
00321     ss << "] which do not exist in the input list [";
00322     ss << Filename(ui.GetFilename("FROMLIST")).Name() << "]" << endl;
00323     ss << "These serial numbers are listed in [";
00324     ss << Filename(name).Name() + "]" << endl;
00325   }
00326 
00327 
00328   ss << "----------------------------------------" \
00329         "----------------------------------------" << endl << endl;
00330   std::string log = ss.str();
00331 
00332   Application::Log(results);
00333 
00334   if (ui.IsInteractive()) {
00335     Application::GuiLog(log);
00336   }
00337   else {
00338     cout << ss.str();
00339   }
00340 
00341 }
00342 
00343 
00344 // Links cubes to other cubes it shares control points with
00345 map< string, set<string> > constructPointSets(set<string> &index,
00346                                                ControlNet &innet) {
00347   map< string, set<string > > adjPoints;
00348 
00349   bool ignore = Application::GetUserInterface().GetBoolean("IGNORE");
00350   for(int cp=0; cp < innet.Size(); cp++) {
00351 
00352     if(ignore && innet[cp].Ignore()) continue;
00353 
00354     if(innet[cp].NumValidMeasures() < 2) continue;
00355 
00356     ControlPoint controlpt = innet[cp];
00357     // Map SerialNumbers together based on ControlMeasures
00358     for(int cm1=0; cm1 < controlpt.Size(); cm1++) {
00359       if(ignore && controlpt.Ignore()) continue;
00360 
00361       std::string sn = controlpt[cm1].CubeSerialNumber();
00362       index.insert(sn);
00363       for(int cm2=0; cm2 < controlpt.Size(); cm2++) {
00364         if(ignore && controlpt[cm2].Ignore()) continue;
00365 
00366         if(cm1 != cm2) {
00367           adjPoints[ sn ].insert( controlpt[cm2].CubeSerialNumber() );
00368         }
00369       }
00370     }
00371 
00372   }
00373 
00374   return adjPoints;
00375 }
00376 
00377 
00378 // Uses a depth-first search to construct the islands
00379 vector< set<string> > findIslands(set<string> &index,
00380                                    map< string, set<string> > &adjCubes) {
00381   vector< set<string> > islands;
00382 
00383   while(index.size() != 0) {
00384     set<string> connectedSet;
00385 
00386     stack<string> str_stack;
00387     set<string>::iterator first = index.begin();
00388     str_stack.push(*first);
00389 
00390     // Depth search
00391     while(true) {
00392       index.erase(str_stack.top());
00393       connectedSet.insert(str_stack.top());
00394             
00395       // Find the first connected unvisited node
00396       std::string nextNode = "";
00397       set<string> neighbors = adjCubes[str_stack.top()];
00398       for (set<string>::iterator i = neighbors.begin(); i != neighbors.end(); i++) {
00399         if (index.count(*i) == 1) {
00400           nextNode = *i;
00401           break;
00402         }
00403       }
00404             
00405       if (nextNode != "") {
00406         // Push the unvisited node
00407         str_stack.push(nextNode);
00408       }
00409       else {
00410         // Pop the visited node
00411         str_stack.pop();
00412 
00413         if (str_stack.size() == 0) break;
00414       }
00415     }
00416 
00417     islands.push_back(connectedSet);
00418   }
00419 
00420   return islands;
00421 }
00422 
00423 
00424 // Writes the list of cubes [ SerialNumber, Filename, ControlPoints ] to the output file
00425 void WriteOutput( map<string,string> num2cube, string filename,
00426                   set<string> &sns, map< string, set<string> > &cps ) {
00427 
00428   // Set up the output file for writing
00429   ofstream out_stream;
00430   out_stream.open(filename.c_str(), std::ios::out);
00431   out_stream.seekp(0,std::ios::beg); //Start writing from beginning of file
00432 
00433   for( set<string>::iterator sn = sns.begin();
00434                       sn != sns.end(); sn++ ) {
00435     // Serial Number of cube
00436     out_stream << *sn;
00437 
00438     // Filename of cube if given
00439     if( !num2cube[*sn].empty() ) {
00440       out_stream << "\t" << Filename(num2cube[*sn]).Name();
00441     }
00442     else {
00443       out_stream << "\tUnknownFilename";
00444     }
00445 
00446     // Control Points where the cube was found to have the issue
00447     for( set<string>::iterator cp = cps[*sn].begin();
00448          cp != cps[*sn].end(); cp++ ) {
00449       out_stream << "\t" << *cp;
00450     }
00451 
00452     out_stream << "\n";
00453   }
00454 
00455   out_stream.close();
00456 }