openModeller  Version 1.4.0
envelope_score.cpp
Go to the documentation of this file.
00001 
00031 #include "envelope_score.hh"
00032 
00033 #include <openmodeller/Configuration.hh>
00034 
00035 #include <openmodeller/Exceptions.hh>
00036 
00037 #include <string.h>
00038 #include <stdio.h>
00039 #include <math.h>
00040 
00041 /****************************************************************/
00042 /********************** Algorithm's Metadata ********************/
00043 
00044 #define NUM_PARAM 0
00045 
00046 
00047 /*************************************/
00048 /*** Algorithm parameters metadata ***/
00049 
00050 //static AlgParamMetadata parameters[NUM_PARAM] = {};
00051 
00052 
00053 /************************************/
00054 /*** Algorithm's general metadata ***/
00055 
00056 static AlgMetadata metadata = {
00057 
00058   "ENVSCORE",   // Id.
00059   "Envelope Score",   // Name.
00060   "0.1",       // Version.
00061 
00062   // Overview
00063   "Uses the minimum and maximum observed value for each\
00064  environmental variable to define bioclimatic envelopes.\
00065  Probability of occurrence for a point is determined by\
00066  the number of environmental variables within which the\
00067  environmental values at the point fall into the min/max\
00068  criteria.",
00069   // Description.
00070   "Implements a lax Bioclimatic Envelope Algorithm. For\
00071  each given environmental variable the algorithm finds\
00072  the minimum and maximum at all occurrence sites. During\
00073  model projection, the probability of occurrences is\
00074  determined as:\n\n\
00075  p = layers within min-max threshold / number of layers\n\n\
00076  Thus choosing a threshold of p=1 gives you the same model\
00077  output as the original Bioclim model taking both the\
00078  Suitable & Marginal classes as predicted presences.\
00079  The Envelope Score algorithm is equivalent to the\
00080  inclusive 'OR' implementation of Bioclim described\
00081  in Pineiro et al (2007).",
00082 
00083   "Nix, H. A.",  // Author
00084 
00085   // Bibliography.
00086   "Nix, H.A. (1986) A biogeographic analysis of Australian elapid\
00087  snakes. In: Atlas of Elapid Snakes of Australia. (Ed.) R. Longmore,\
00088  pp. 4-15. Australian Flora and Fauna Series Number 7. Australian\
00089  Government Publishing Service: Canberra.\n\n\
00090  PiƱeiro, R., Aguilar, J. F., Munt, D. D. & Feliner, G. N. (2007)\
00091  Ecology matters: Atlantic-Mediterranean disjunction in the sand-dune\
00092  shrub Armeria pungens (Plumbaginaceae).\
00093  Molecular Ecology. 16, 2155-2171.",
00094 
00095   "Tim Sutton and Chris Yesson",             // Code author.
00096   "tim [at] linfiniti.com", // Code author's contact.
00097 
00098   0,  // Does not accept categorical data.
00099   0,  // Does not need (pseudo)absence points.
00100 
00101   NUM_PARAM   // Algorithm's parameters.
00102 
00103 };
00104 
00105 
00106 
00107 /****************************************************************/
00108 /****************** Algorithm's factory function ****************/
00109 
00110 OM_ALG_DLL_EXPORT
00111 AlgorithmImpl *
00112 algorithmFactory()
00113 {
00114   return new EnvelopeScore();
00115 }
00116 
00117 OM_ALG_DLL_EXPORT
00118 AlgMetadata const *
00119 algorithmMetadata()
00120 {
00121   return &metadata;
00122 }
00123 
00124 
00125 /****************************************************************/
00126 /**************************** EnvelopeScore ***************************/
00127 
00128 /*******************/
00129 /*** constructor ***/
00130 
00131 EnvelopeScore::EnvelopeScore() :
00132   AlgorithmImpl( &metadata ),
00133   _done( false ),
00134   _minimum(),
00135   _maximum()
00136 { }
00137 
00138 
00139 /******************/
00140 /*** destructor ***/
00141 
00142 EnvelopeScore::~EnvelopeScore()
00143 {
00144 }
00145 
00146 
00147 /******************/
00148 /*** initialize ***/
00149 int
00150 EnvelopeScore::initialize()
00151 {
00152   
00153   // Number of independent variables.
00154   int dim = _samp->numIndependent();
00155   Log::instance()->info( "Reading %d-dimensional occurrence points.\n", dim );
00156 
00157   // Check the number of sampled points.
00158   int npnt = _samp->numPresence();
00159   if (  npnt < 1 ) {
00160     Log::instance()->error( "EnvelopeScore needs at least 1 point inside the mask!\n" );
00161     return 0;
00162   }
00163 
00164   Log::instance()->info( "Using %d points to find the bioclimatic envelope.\n", npnt );
00165 
00166   computeStats( _samp->getPresences() );
00167 
00168   _done = true;
00169 
00170   return 1;
00171 }
00172 
00173 
00174 /***************/
00175 /*** iterate ***/
00176 int
00177 EnvelopeScore::iterate()
00178 {
00179   return 1;
00180 }
00181 
00182 
00183 /************/
00184 /*** done ***/
00185 int
00186 EnvelopeScore::done() const
00187 {
00188   // This is not an iterative algorithm.
00189   return _done;
00190 }
00191 
00192 
00193 /*****************/
00194 /*** get Value ***/
00195 Scalar
00196 EnvelopeScore::getValue( const Sample& x ) const
00197 {
00198 
00199   unsigned int myMatchCount=0;
00200   unsigned int myLayerCount = x.size();
00201 
00202   for( unsigned int i=0; i<x.size(); i++) {
00203 
00204     if ( (x[i] >= _minimum[i]) && (x[i] <= _maximum[i]) ) {
00205       ++myMatchCount;
00206     }
00207   }
00208   if (myMatchCount==0) {
00209     return 0;
00210   }
00211   Scalar myProbability = myMatchCount / static_cast<double>(myLayerCount)  ;
00212 
00213   return myProbability;
00214 }
00215 
00216 
00217 /***********************/
00218 /*** get Convergence ***/
00219 int
00220 EnvelopeScore::getConvergence( Scalar * const val ) const
00221 {
00222   *val = 1.0;
00223   return 1;
00224 }
00225 
00226 
00227 /*******************/
00228 /*** get Minimum ***/
00229 void
00230 EnvelopeScore::computeStats( const OccurrencesPtr& occs )
00231 {
00232 
00233   // Compute minimum and maximum.
00234   {
00235     OccurrencesImpl::const_iterator oc = occs->begin();
00236     OccurrencesImpl::const_iterator end = occs->end();
00237 
00238     // Initialize _minimum and _maximum to the values of the first point
00239     // and increment to get it out of the loop.
00240     Sample const & sample = (*oc)->environment();
00241     _minimum = sample;
00242     _maximum = sample;
00243     
00244     ++oc;
00245     
00246     // For each Occurrence, update the statistics for _minimum and
00247     // _maximum.
00248     while ( oc != end ) {
00249       
00250       Sample const& sample = (*oc)->environment();
00251       
00252       _minimum &= sample;
00253       _maximum |= sample;
00254 
00255       ++oc;
00256     }
00257 
00258   }
00259 
00260 }
00261 
00262 /****************************************************************/
00263 /****************** configuration *******************************/
00264 void
00265 EnvelopeScore::_getConfiguration( ConfigurationPtr& config ) const
00266 {
00267   if ( !_done )
00268     return;
00269 
00270   ConfigurationPtr model_config( new ConfigurationImpl("EnvelopeScore") );
00271   config->addSubsection( model_config );
00272 
00273   model_config->addNameValue( "Minimum", _minimum );
00274   model_config->addNameValue( "Maximum", _maximum );
00275 
00276 }
00277 
00278 void
00279 EnvelopeScore::_setConfiguration( const ConstConfigurationPtr& config )
00280 {
00281   ConstConfigurationPtr model_config = config->getSubsection("EnvelopeScore");
00282 
00283   if (!model_config)
00284     return;
00285 
00286   _done = true;
00287 
00288   _minimum = model_config->getAttributeAsSample( "Minimum" );
00289   _maximum = model_config->getAttributeAsSample( "Maximum" );
00290 
00291   return;
00292 }
00293 
00294 /********************/
00295 /*** log Envelope ***/
00296 void
00297 EnvelopeScore::logEnvelope()
00298 {
00299   Log::instance()->info( "Envelope with %d dimensions (variables).\n\n", _minimum.size() );
00300 
00301   for ( unsigned int i = 0; i < _minimum.size(); i++ )
00302     {
00303       Log::instance()->info( "Variable %02d:", i );
00304       Log::instance()->info( " Minimum  : %f\n", _minimum[i] );
00305       Log::instance()->info( " Maximum  : %f\n", _maximum[i] );
00306       Log::instance()->info( "\n" );
00307     }
00308 }
00309