openModeller  Version 1.4.0
om_project.cpp
Go to the documentation of this file.
00001 /*************************************************************************************
00002  * This code simply loads a previously created model, loads a reprojection 
00003  * environment, and projects the model into that environment,
00004  * then writes the model out.
00005  *    -------------------
00006  *       begin                : November 2005
00007  *       copyright            : (C) 2005 by T.Sutton, Kevin Ruland, Renato De Giovanni
00008  *       email                : tim@linfiniti.com
00009  *************************************************************************************/
00010 
00011 /***************************************************************************
00012  *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include <openmodeller/om.hh>
00021 #include <openmodeller/Log.hh>
00022 #include <openmodeller/os_specific.hh>
00023 
00024 #include "getopts/getopts.h"
00025 
00026 #include "om_cmd_utils.hh"
00027 
00028 #include <fstream>   // file I/O for XML
00029 #include <sstream>   // ostringstream datatype
00030 #include <stdio.h>   // file I/O for log
00031 #include <time.h>    // used to limit the number of times that the progress is written to a file
00032 #include <string>    // string library
00033 #include <stdexcept> // try/catch
00034 
00035 #ifdef MPI_FOUND
00036 #include "mpi.h"
00037 #endif
00038 
00039 using namespace std;
00040 
00041 int main( int argc, char **argv ) {
00042 
00043   Options opts;
00044   int option;
00045 
00046   // command-line parameters (short name, long name, description, take args)
00047   opts.addOption( "v", "version"    , "Display version info"                        , false );
00048   opts.addOption( "r", "xml-req"    , "Projection request file in XML"              , true );
00049   opts.addOption( "o", "model"      , "File with serialized model (native projection)", true );
00050   opts.addOption( "t", "template"   , "Raster template for the distribution map (native projection)", true );
00051   opts.addOption( "f", "format"     , "File format for the distribution map (native projection)", true );
00052   opts.addOption( "m", "dist-map"   , "File to store the generated model"           , true );
00053   opts.addOption( "" , "log-level"  , "Set the log level (debug, warn, info, error)", true );
00054   opts.addOption( "" , "log-file"   , "Log file"                                    , true );
00055   opts.addOption( "" , "prog-file"  , "File to store projection progress"           , true );
00056   opts.addOption( "" , "stat-file"  , "File to store projection statistics"         , true );
00057   opts.addOption( "c", "config-file", "Configuration file for openModeller"         , true );
00058 
00059   std::string log_level("info");
00060   std::string request_file;
00061   std::string model_file;
00062   std::string tmpl_file;
00063   std::string format;
00064   std::string map_file;
00065   std::string log_file;
00066   std::string progress_file;
00067   std::string statistics_file;
00068   std::string config_file;
00069 
00070   if ( ! opts.parse( argc, argv ) ) {
00071 
00072     opts.showHelp( argv[0] ); 
00073     exit(0);
00074   }
00075 
00076   // Set up any related external resources
00077   setupExternalResources();
00078 
00079   OpenModeller om;
00080 
00081   while ( ( option = opts.cycle() ) >= 0 ) {
00082 
00083     switch ( option ) {
00084 
00085       case 0:
00086         printf( "om_project %s\n", om.getVersion().c_str() );
00087         printf("This is free software; see the source for copying conditions. There is NO\n");
00088         printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
00089         exit(0);
00090         break;
00091       case 1:
00092         request_file = opts.getArgs( option );
00093         break;
00094       case 2:
00095         model_file = opts.getArgs( option );
00096         break;
00097       case 3:
00098         tmpl_file = opts.getArgs( option );
00099         break;
00100       case 4:
00101         format = opts.getArgs( option );
00102         break;
00103       case 5:
00104         map_file = opts.getArgs( option );
00105         break;
00106       case 6:
00107         log_level = opts.getArgs( option );
00108         break;
00109       case 7:
00110         log_file = opts.getArgs( option );
00111         break;
00112       case 8:
00113         progress_file = opts.getArgs( option );
00114         break;
00115       case 9:
00116         statistics_file = opts.getArgs( option );
00117         break;
00118       case 10:
00119         config_file = opts.getArgs( option );
00120         break;
00121       default:
00122         break;
00123     }
00124   }
00125 
00126   // om configuration
00127   if ( ! config_file.empty() ) { 
00128 
00129     Settings::loadConfig( config_file );
00130   }
00131 
00132   // Log stuff
00133 
00134   Log::Level level_code = getLogLevel( log_level );
00135 
00136   if ( ! log_file.empty() ) {
00137 
00138     Log::instance()->set( level_code, log_file, "" );
00139   }
00140   else {
00141  
00142     // Just set the level - things will go to stderr
00143     Log::instance()->setLevel( level_code );
00144   }
00145 
00146   // Check parameters
00147 
00148   if ( request_file.empty() && model_file.empty() ) {
00149 
00150     printf( "Please specify either a projection request file in XML or a serialized model\n");
00151     exit(-1);
00152   }
00153 
00154   if ( (! request_file.empty()) && ( (! model_file.empty()) || (! tmpl_file.empty()) || (! format.empty() ) ) ) {
00155 
00156     Log::instance()->warn( "When a request file is specified, --model, --template and --format are ignored" );
00157   }
00158 
00159   if ( map_file.empty() ) {
00160 
00161     printf( "Please specify a file to store the distribution map\n");
00162     exit(-1);
00163   }
00164 
00165   // Initialize progress data if user wants to track progress
00166   progress_data prog_data;
00167 
00168   if ( ! progress_file.empty() ) { 
00169 
00170     prog_data.file_name = progress_file;
00171 
00172     time( &prog_data.timestamp );
00173 
00174     prog_data.progress = -1.0; // queued
00175 
00176     // Always create initial file with progress 0
00177     progressFileCallback( 0.0, &prog_data );
00178   }
00179 
00180   // Real work
00181 
00182   try {
00183 
00184     #ifdef MPI_FOUND
00185       Log::instance()->info( "Running parallel projection version\n" );
00186       MPI_Init( &argc, &argv );
00187       int rank;
00188       MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00189       Log::instance()->debug( "Rank of calling process: %d\n", rank );
00190       MPI_Barrier( MPI_COMM_WORLD );
00191     #else
00192       Log::instance()->info( "Running serial projection version\n" );
00193     #endif
00194 
00195     // Load algorithms and instantiate controller class
00196     AlgorithmFactory::searchDefaultDirs();
00197 
00198     // If user wants to track progress
00199     if ( ! progress_file.empty() ) { 
00200 
00201       // Set callback to write to a file
00202       om.setMapCallback( progressFileCallback, &prog_data );
00203     }
00204     else if ( ! statistics_file.empty() ) {
00205 
00206       // Default callback will display progress on screen when a statistics file was specified
00207       // (which means statistics won't be sent to stdout)
00208       om.setMapCallback( progressDisplayCallback );
00209     }
00210 
00211     std::ostringstream model_output;
00212 
00213     if ( ! request_file.empty() ) {
00214 
00215       ConfigurationPtr input = Configuration::readXml( request_file.c_str() );
00216       om.setProjectionConfiguration( input );
00217       om.createMap( map_file.c_str() );
00218     }
00219     else {
00220 
00221       // Native projection - get original environment from serialized model
00222       ConfigurationPtr input = Configuration::readXml( model_file.c_str() );
00223 
00224       om.setModelConfiguration( input );
00225 
00226       EnvironmentPtr env = om.getEnvironment();
00227 
00228       MapFormat tmpl;
00229 
00230       if ( tmpl_file.empty() ) {
00231 
00232         // Use first layer as reference
00233         std::string first_layer = env->getLayerPath(0);
00234 
00235         tmpl = MapFormat( first_layer.c_str() );
00236       }
00237       else {
00238 
00239         tmpl = MapFormat( tmpl_file.c_str() );
00240       }
00241 
00242       if ( ! format.empty() ) {
00243 
00244         tmpl.setFormat( format );
00245       }
00246 
00247       om.createMap( env, map_file.c_str(), tmpl );
00248     }
00249 
00250     AreaStats * stats = om.getActualAreaStats();
00251 
00252     ConfigurationPtr stats_cfg = stats->getConfiguration();
00253 
00254     std::ostringstream statistics_output;
00255 
00256     Configuration::writeXml( stats_cfg, statistics_output );
00257 
00258     std::cerr << flush;
00259 
00260     // Write statistics output to file, if requested
00261     if ( ! statistics_file.empty() ) {
00262 
00263       ofstream file( statistics_file.c_str() );
00264       file << statistics_output.str();
00265       file.close();
00266     }
00267     else {
00268 
00269       // Otherwise send it to stdout
00270       std::cout << statistics_output.str().c_str() << endl << flush;
00271     }
00272 
00273     delete stats;
00274 
00275     // If user wants to track progress
00276     if ( ! progress_file.empty() ) { 
00277 
00278       // Check if job was completed
00279       if ( prog_data.progress != 1 ) {
00280 
00281         // -2 means aborted
00282         progressFileCallback( -2.0, &prog_data );
00283       }
00284     }
00285   }
00286   catch ( runtime_error e ) {
00287 
00288     // If user is tracking progress
00289     if ( ! progress_file.empty() ) { 
00290 
00291       // -2 means aborted
00292       progressFileCallback( -2.0, &prog_data );
00293     }
00294 
00295     printf( "om_project aborted: %s\n", e.what() );
00296   }
00297 
00298   #ifdef MPI_FOUND
00299   MPI_Barrier( MPI_COMM_WORLD ); 
00300   MPI_Finalize();
00301   #endif
00302 
00303 }