Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

omgmodellerlocalplugin.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Tim Sutton   *
00003  *   tim@linfiniti.com   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "omgmodellerlocalplugin.h"
00021 #include "omgalgorithm.h"
00022 #include "omgomlogcallback.h"
00023 #include "omgui.h" //ancilliary helper methods
00024 #include <omggdal.h>
00025 //qt includes
00026 #include <QStringList>
00027 #include <QFile>
00028 #include <QDir>
00029 #include <QDomDocument>
00030 #include <QDomElement>
00031 #include <QDomText>
00032 #include <QSettings>
00033 #include <QTimer>
00034 //needed for Q_EXPORT_PLUGIN macro at the end of this file
00035 #include <QtPlugin>
00036 
00037 
00038 //om includes
00039 #include <openmodeller/om.hh>
00040 #include <openmodeller/AlgMetadata.hh>
00041 #include <openmodeller/Configuration.hh>
00042 #include <openmodeller/Exceptions.hh>
00043 
00044 //
00045 //Standard includes
00046 #include <istream>
00047 #include <stdlib.h>
00048 #include <stdio.h>
00049 #include <iostream>  // I/O 
00050 #include <fstream>   // file I/O
00051 #include <sstream>     // treat string as a stream
00052 #include <string>
00053 
00054 #include <stdexcept>
00055 
00056 //
00057 // A global variable needed to set up the call back for loggin from openModeller
00058 //
00059 QTextStream* output;
00060 bool OmgModellerLocalPlugin::mAlgFactoryStartedFlag=false;
00061 
00062 OmgModellerLocalPlugin::OmgModellerLocalPlugin( QObject * parent) : 
00063       QObject (parent),
00064       OmgModellerPluginInterface(), 
00065       mpOpenModeller(new OpenModeller()),
00066       mpLogCallBack (new OmgOmLogCallback(*(output)))
00067 {
00068   //qDebug("Creating modeller local plugin");
00069   initialise();
00070 }
00071 
00072 OmgModellerLocalPlugin::~OmgModellerLocalPlugin()
00073 {
00074     disconnect (mpLogCallBack);
00076     Log::instance()->setCallback( 0 );
00077     delete mpOpenModeller;
00078     //qDebug("Destroying modeller local plugin");
00079 }
00080 
00081 bool OmgModellerLocalPlugin::initialise()
00082 {
00083   // qDebug(tr("-------Modeller Plugin Initialising---------").toLocal8Bit());
00084   QSettings mySettings;
00085   bool myVerboseFlag = mySettings.value("openModeller/modellerVerboseLogFlag",false).toBool();
00086   if (myVerboseFlag)
00087   {
00088     Log::instance()->setLevel( Log::Debug );
00089   }
00090   else
00091   {
00092     Log::instance()->setLevel( Log::Info); 
00093   }
00094   // Note this function searches for om plugins - and should only
00095   // ever be run once in the life of the openModeller desktop application session
00096   //
00097   if (!OmgModellerLocalPlugin::mAlgFactoryStartedFlag)
00098   {
00099     //qDebug("Initialising openmodeller local plugin...calling AlgorithmFactory::searchDefaultDirs()");
00100     AlgorithmFactory::searchDefaultDirs();
00101     OmgModellerLocalPlugin::mAlgFactoryStartedFlag=true;
00102   }
00103   else
00104   {
00105     //qDebug("Initialising openmodeller local plugin...NOT calling AlgorithmFactory::searchDefaultDirs()");
00106     //do nothing
00107   }
00108   //set up callbacks
00109   Log::instance()->setCallback(mpLogCallBack );
00110   //Log::Debug for verbose, Log::Info for NB only
00111   //connect up our messenger class which delegates signals
00112   //since a plugin in Qt cannot directly inherit from qobject
00113   connect(mpLogCallBack, SIGNAL(omLogMessage(QString,QString)),
00114       &mMessenger, SLOT(emitModelMessage(QString,QString)));
00115   connect(mpLogCallBack, SIGNAL(omLogError(QString,QString)),
00116       &mMessenger, SLOT(emitModelError(QString,QString)));
00117   //connect to this class's logger too so we can insert logs into OmgModel
00118   //when create and project are called
00119   connect(mpLogCallBack, SIGNAL(omLogMessage(QString,QString)),
00120       this, SLOT(appendToLog(QString,QString)));
00121   connect(mpLogCallBack, SIGNAL(omLogError(QString,QString)),
00122       this, SLOT(appendToLog(QString,QString)));
00123   mpOpenModeller->setModelCallback( modelCallback, this );
00124   mpOpenModeller->setMapCallback( mapCallback, this );
00125   return true;
00126 
00127 }
00128 
00129 QString OmgModellerLocalPlugin::createModel(OmgModel * thepModel)
00130 {
00131   QSettings mySettings;
00132   bool myVerboseFlag = mySettings.value("openModeller/modellerVerboseLogFlag",false).toBool();
00133   if (myVerboseFlag)
00134   {
00135     Log::instance()->setLevel( Log::Debug );
00136   }
00137   else
00138   {
00139     Log::instance()->setLevel( Log::Info); 
00140   }
00141   thepModel->setError(false);
00142   mModelLog="";
00143   QString myModelResult;
00144   QString myFileName = thepModel->taxonName();
00145   mModelGuid = thepModel->guid();
00146   mpLogCallBack->setModelGuid(thepModel->guid());
00147   myFileName = myFileName.replace(" ","_");
00148   mMessenger.emitModelMessage(mModelGuid,tr("Running model for : ") + myFileName.toLocal8Bit());
00149   mMessenger.emitModelCreationProgress(mModelGuid,0);
00150   //get the file path in the format of the host OS as we will be passing this
00151   //over to om which wont automatically convert (qt classes do)
00152   QString myWorkDir = QDir::toNativeSeparators(thepModel->workDir());
00153   //std::string myFileNameString(myFileName.toLocal8Bit());
00154   // now use the local om lib to run the model
00155   qDebug("About to run model...");
00156   try 
00157   {
00158     std::ostringstream myOutputStream ;
00159     QString myModelXml = thepModel->toModelCreationXml().trimmed();
00160     //for local models we need to append the modelparameters outer tag
00161     myModelXml = "<ModelParameters>\n"+ myModelXml + "\n</ModelParameters>";
00162     //first write the model xml to a file - this is just for user reference / debugging
00163     if (!Omgui::createTextFile(myWorkDir + QDir::separator() + myFileName+"_create.xml",myModelXml))
00164     {
00165       QString myWarning(tr("Unable to open ") + myFileName.toLocal8Bit() + tr(" for writing!"));
00166       mMessenger.emitModelError(mModelGuid,myWarning);
00167       thepModel->setLog(mModelLog);
00168       thepModel->setError(true);
00169       return QString("");
00170     }    
00171     mMessenger.emitModelMessage(mModelGuid,tr("Reading creation xml"));
00172     std::string myXml(myModelXml.toLocal8Bit().data());
00173     std::istringstream myStream;
00174     myStream.str(myXml);
00175     mMessenger.emitModelMessage(mModelGuid,tr("Reading openModeller configuration from xml"));
00176     ConfigurationPtr c = Configuration::readXml( myStream );
00177     mMessenger.emitModelMessage(mModelGuid,tr("Setting openModeller configuration from xml"));
00178     // This next line is where the crash is occurring for Athene cunicularia!!
00179     mpOpenModeller->setModelConfiguration(c);
00180     mMessenger.emitModelMessage(mModelGuid,tr("About to run the odel"));
00181     mpOpenModeller->createModel();
00182     mMessenger.emitModelMessage(mModelGuid,tr("Completed model creation for : ") + myFileName.toLocal8Bit());
00183     ConfigurationPtr myConfiguration = mpOpenModeller->getModelConfiguration();
00184     Configuration::writeXml( myConfiguration, myOutputStream);
00185     mMessenger.emitModelMessage(mModelGuid,tr("Configuration obtained for : ") + myFileName.toLocal8Bit());
00186     mMessenger.emitModelDone(mModelGuid);
00187     myModelResult=QString::fromStdString(myOutputStream.str());
00188     //qDebug( myModelResult.toLocal8Bit());
00189     mModelProgress=0;
00190     mMessenger.emitModelCreationProgress(mModelGuid,100);
00191     thepModel->setLog(mModelLog);
00192     //ConfusionMatrix matrix;
00193     //Do not delete - the returned pointer is managed by mpOpenModeller 
00194     const ConfusionMatrix * const mypMatrix = mpOpenModeller->getConfusionMatrix();
00195     thepModel->setAccuracy(mypMatrix->getAccuracy() * 100 );
00196     thepModel->setOmission(mypMatrix->getOmissionError() * 100 );
00197     thepModel->setCommission(mypMatrix->getCommissionError() * 100 );
00198     //get the Roc Curve Statistics
00199     //Do not delete - the returned pointer is managed by mpOpenModeller 
00200     const RocCurve * const  mypRoc = mpOpenModeller->getRocCurve();
00201     double myRocArea = mypRoc->getArea();
00202     thepModel->setRocScore(myRocArea);
00204     thepModel->clearRocPoints();
00205     int myPointCount= mypRoc->numPoints();
00206     for ( int i = 0; i < myPointCount ; ++i ) 
00207     {
00208       QPair<double,double> myPair;
00209       myPair.first = 1.0 - mypRoc->getSpecificity( i );
00210       myPair.second = mypRoc->getSensitivity( i );
00211       thepModel->addRocPoint(myPair);
00212     }
00213     return myModelResult;
00214   }
00215   catch( std::exception& e ) 
00216   {
00217     QString myError = tr("Exception caught!\n") + 
00218         QString::fromStdString(e.what());
00219     mMessenger.emitModelError(mModelGuid,myError);
00220     thepModel->appendToLog(mModelLog);
00221     thepModel->appendToLog(myError);
00222     thepModel->setError(true);
00223     return QString("");
00224   }
00225 }
00226 
00227 void  OmgModellerLocalPlugin::projectModel(OmgModel * thepModel)
00228 {
00229   QSettings mySettings;
00230   bool myVerboseFlag = mySettings.value("openModeller/modellerVerboseLogFlag",false).toBool();
00231   if (myVerboseFlag)
00232   {
00233     Log::instance()->setLevel( Log::Debug );
00234   }
00235   else
00236   {
00237     Log::instance()->setLevel( Log::Info); 
00238   }
00239   mModelLog="";
00240   QString myFileName = thepModel->taxonName();
00241   mModelGuid = thepModel->guid();
00242   mpLogCallBack->setModelGuid(thepModel->guid());
00243   myFileName = myFileName.replace(" ","_");
00244   mMessenger.emitModelMessage(mModelGuid,tr("Projecting model for : ") + myFileName.toLocal8Bit());
00245   //get the file path in the format of the host OS as we will be passing this
00246   //over to om which wont automatically convert (qt classes do)
00247   QString myWorkDir = QDir::toNativeSeparators(thepModel->workDir());
00248   //std::string myFileNameString(myFileName.toLocal8Bit());
00249   // now use the local om lib to run the model
00250   try 
00251   {
00252     std::ostringstream myOutputStream ;
00253     QString myModelXml = thepModel->toModelProjectionXml().trimmed();
00254     //for local models we need to append the modelparameters outer tag
00255     myModelXml = "<ProjectionParameters xmlns=\"http://openmodeller.cria.org.br/xml/1.0\">\n"
00256       + myModelXml + "\n</ProjectionParameters>";
00257     //first write the model xml to a file - this is just for user reference / debugging
00258     if (!Omgui::createTextFile(myWorkDir + QDir::separator() + myFileName+"_project.xml",myModelXml))
00259     {
00260       QString myWarning(tr("Unable to open ") + myFileName.toLocal8Bit() + tr(" for writing!"));
00261       mMessenger.emitModelError(mModelGuid,myWarning);
00262     }
00263     std::string myXml(myModelXml.toLocal8Bit().data());
00264     std::istringstream myModelStream;
00265     myModelStream.str(myXml);
00266     ConfigurationPtr mypConfiguration = Configuration::readXml( myModelStream );
00267     mpOpenModeller->setProjectionConfiguration(mypConfiguration);
00268     //cout << "Loading Projection Environment " << theEnvironment << endl;
00269     std::string myEnvironmentXml = thepModel->projectionLayersXml().toLocal8Bit().data();
00270     std::istringstream myEnvironmentStream;
00271     myEnvironmentStream.str(myEnvironmentXml);
00272     mypConfiguration =  Configuration::readXml( myEnvironmentStream );
00273     EnvironmentPtr mypEnvironment = createEnvironment( mypConfiguration );
00274     //cout << "Projecting to file " << theOutput << endl;
00275     QString myRawImageFileName =  myWorkDir + QDir::separator() + myFileName+"_projection."  + Omgui::getOutputFormatExtension();
00276     mpOpenModeller->createMap( mypEnvironment, myRawImageFileName.toLocal8Bit().data() );
00277     //store the model image file name in the model object
00278     thepModel->setRawImageFileName(myFileName+"_projection."  + Omgui::getOutputFormatExtension());
00279 
00280     //Area stats
00281     //we must delete this after using - the returned pointer is NOT managed by mpOpenModeller 
00282     AreaStats * mypStats = mpOpenModeller->getActualAreaStats();
00283     thepModel->setPercentCellsPresent(mypStats->getAreaPredictedPresent() / (double) mypStats->getTotalArea() * 100);
00284     thepModel->setTotalCells(  mypStats->getTotalArea() );
00285 
00286     delete mypStats;
00287 
00288     //finish up
00289     mModelProgress=0;
00290     mMessenger.emitModelProjectionProgress(mModelGuid,100);
00291     thepModel->appendToLog(mModelLog);
00292   }
00293   catch( std::exception& e ) 
00294   {
00295     QString myError = tr("Exception caught!\n") + 
00296         QString::fromStdString(e.what());
00297     mMessenger.emitModelError(mModelGuid,myError);
00298     thepModel->appendToLog(mModelLog);
00299     thepModel->appendToLog(myError);
00300     thepModel->setError(true);
00301     return;
00302   }
00303 }
00304 
00305 const QStringList OmgModellerLocalPlugin::getAlgorithmList()
00306 { 
00307   //qDebug("OmgModellerLocalPlugin::getAlgorithmList() called");
00308   const AlgMetadata **mypAlgorithmMetadataArray = mpOpenModeller->availableAlgorithms();
00309   const AlgMetadata *mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00310   QStringList myAlgList;
00311 
00312   while ( mypAlgorithmMetadata  )
00313   {
00314     myAlgList.append(mypAlgorithmMetadata->name);
00315     *mypAlgorithmMetadataArray++;
00316     mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00317   }
00318   myAlgList.sort();
00319   return myAlgList;
00320 }
00321 
00322 const OmgAlgorithmSet OmgModellerLocalPlugin::getAlgorithmSet()
00323 {
00324   const AlgMetadata **mypAlgorithmMetadataArray = mpOpenModeller->availableAlgorithms();
00325   const AlgMetadata *mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00326 
00327   OmgAlgorithmSet myAlgorithmSet;
00328   myAlgorithmSet.setName("Local Plugin Algorithms");
00329   myAlgorithmSet.setDescription("These are the algorithms available on your local machine ");
00330   
00331   while ( mypAlgorithmMetadata  )
00332   {
00333     QString myName(mypAlgorithmMetadata->name);
00334     QString myId(mypAlgorithmMetadata->id);
00335     OmgAlgorithm myAlgorithm = getAlgorithm(myId);
00336     myAlgorithmSet.addAlgorithm(myAlgorithm);
00337     *mypAlgorithmMetadataArray++;
00338     mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00339   }
00340   return myAlgorithmSet; 
00341 }
00342 
00343 const OmgAlgorithm OmgModellerLocalPlugin::getAlgorithm( QString theId )
00344 {       
00345   const AlgMetadata **mypAlgorithmMetadataArray = mpOpenModeller->availableAlgorithms();
00346   const AlgMetadata *mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00347 
00348   while ( mypAlgorithmMetadata  )
00349   {
00350     QString myId(mypAlgorithmMetadata->id);
00351     if (myId==theId)
00352     {
00353       OmgAlgorithm myAlgorithm;
00354       myAlgorithm.setId( QString( mypAlgorithmMetadata->id ));
00355       myAlgorithm.setName( QString(  mypAlgorithmMetadata->name ));
00356       myAlgorithm.setVersion(  QString( mypAlgorithmMetadata->version));
00357       myAlgorithm.setGuid();
00358       myAlgorithm.setCategorical(  mypAlgorithmMetadata->categorical);
00359       myAlgorithm.setAbsence( mypAlgorithmMetadata->absence);
00360       myAlgorithm.setAuthor(  QString( mypAlgorithmMetadata->author));
00361       myAlgorithm.setCodeAuthor(  QString( mypAlgorithmMetadata->code_author));
00362       myAlgorithm.setContact(  QString( mypAlgorithmMetadata->contact));
00363       myAlgorithm.setOverview(  QString( mypAlgorithmMetadata->overview));
00364       myAlgorithm.setDescription(  QString( mypAlgorithmMetadata->description));
00365       myAlgorithm.setBibliography(  QString( mypAlgorithmMetadata->biblio));
00366 
00367       //qDebug ("getting algorithm parameters from metadata");
00368       int myParameterCountInt = mypAlgorithmMetadata->nparam;
00369       AlgParamMetadata * myParameter = mypAlgorithmMetadata->param;
00370       //interate through parameters adding the correct control type
00371       for ( int i = 0; i < myParameterCountInt; i++, myParameter++ )
00372       {
00373         //qDebug("Getting next parameter");
00374         OmgAlgorithmParameter myOmgParameter;
00375         AlgParamDatatype myType = myParameter->type;
00376         switch (myType)
00377         {
00378           case Integer:
00379             myOmgParameter.setType ( "Integer" );
00380             break;
00381           case Real:
00382             myOmgParameter.setType ( "Real" );
00383             break;
00384           case String:
00385             myOmgParameter.setType ( "String" );
00386             break;
00387           default:
00388             myOmgParameter.setType ( "Integer" );
00389             break;
00390         }
00391 
00392         myOmgParameter.setName( QString (myParameter->name ));
00393         myOmgParameter.setId( QString (myParameter->id ));
00394         if (!myParameter->has_min==0)
00395         {
00396           myOmgParameter.setMinimum( QString::number (myParameter->min_val ));
00397         }
00398         else
00399         {
00401           myOmgParameter.setMinimum( QString::number(INT_MIN) );
00402         }
00403         if (!myParameter->has_max==0)
00404         {
00405           myOmgParameter.setMaximum( QString::number (myParameter->max_val ));
00406         }
00407         else
00408         {
00410           myOmgParameter.setMaximum( QString::number(INT_MAX ));
00411         }
00412         myOmgParameter.setDefault(QString ( myParameter->typical ));
00413         myOmgParameter.setOverview(QString ( myParameter->overview ));
00414         myOmgParameter.setDescription(QString ( myParameter->description ));
00415         myAlgorithm.addParameter(myOmgParameter);
00416         //qDebug(myOmgParameter.toString().toLocal8Bit());
00417       }
00418       //define the origin of the algorithm - this is used by e.g. the algmanager
00419       //in the gui to differentiate between user profiles and profiles 
00420       //obtained from the plugin
00421       myAlgorithm.setOrigin(OmgAlgorithm::ADAPTERPROFILE);
00422       //Exit loop because we have found the correct algorithm
00423       return myAlgorithm;
00424     }
00425     *mypAlgorithmMetadataArray++;
00426     mypAlgorithmMetadata = *mypAlgorithmMetadataArray;
00427   }
00428   //not found
00429   //qDebug("Algorithm not found for id"+theId.toLocal8Bit());
00430   return OmgAlgorithm();
00431 }//getAlgorithm( QString theId )
00432 
00433 void OmgModellerLocalPlugin::setCreationProgress (int theProgress)
00434 {
00435   //qDebug("setCreationProgress: " + mModelGuid.toLocal8Bit() + " " + QString::number(theProgress).toLocal8Bit());
00436   if (mModelProgress != theProgress)
00437   {
00438     mModelProgress=theProgress;
00439     mMessenger.emitModelCreationProgress(mModelGuid,theProgress);
00440   }
00441 }
00442 void OmgModellerLocalPlugin::setProjectionProgress (int theProgress)
00443 {
00444   //qDebug("setProjectionProgress: " + mModelGuid.toLocal8Bit() + " " +  QString::number(theProgress).toLocal8Bit());
00445   if (mModelProgress != theProgress)
00446   {
00447     mMapProgress=theProgress;
00448     mMessenger.emitModelProjectionProgress(mModelGuid,theProgress);
00449   }
00450 }
00451 
00452 void OmgModellerLocalPlugin::appendToLog( QString theGuid, QString theMessage)
00453 {
00454   mModelLog += "\n" + theMessage;
00455 }
00456  
00457 const QString OmgModellerLocalPlugin::getLayers(QString theBaseDir)
00458 {
00459   QTimer *mypTimer = new QTimer(this);
00460   connect(mypTimer, SIGNAL(timeout()), &mMessenger, SLOT(refresh()));
00461   mypTimer->start(1000);
00462   QString myLayers = Omgui::getLayers(theBaseDir);
00463   mypTimer->stop();
00464   delete mypTimer;
00465   return myLayers;
00466 }
00467 
00468 
00469 //
00470 // non member callback functions
00471 //
00472 void modelCallback( float theProgress, void *thepPlugin )
00473 {
00474  //cast the plugin to a local plugin
00475  //qDebug("modelCallBack: " + QString::number(theProgress).toLocal8Bit());
00476  OmgModellerLocalPlugin * mypPlugin = (OmgModellerLocalPlugin *) thepPlugin;
00477  mypPlugin->setCreationProgress(static_cast<int>(theProgress*100));
00478 }
00479 void mapCallback( float theProgress, void *thepPlugin )
00480 {
00481  //qDebug("mapCallBack: " + QString::number(theProgress).toLocal8Bit());
00482  //cast the plugin to a local plugin
00483  OmgModellerLocalPlugin * mypPlugin = (OmgModellerLocalPlugin *) thepPlugin;
00484  mypPlugin->setProjectionProgress(static_cast<int>(theProgress*100));
00485 }
00486     
00487 // Entry point for the Qt plugin:
00488 Q_EXPORT_PLUGIN2(local_modeller_plugin, OmgModellerLocalPlugin);

Generated on Mon Apr 28 15:07:57 2008 for openModellerDesktop by  doxygen 1.4.1-20050210