openModeller  Version 1.4.0
distance_to_average.cpp
Go to the documentation of this file.
00001 
00028 #include "distance_to_average.hh"
00029 
00030 #include <openmodeller/Configuration.hh>
00031 #include <openmodeller/Exceptions.hh>
00032 #include <openmodeller/ScaleNormalizer.hh>
00033 
00034 #include <stdio.h>
00035 #include <math.h>
00036 
00037 /****************************************************************/
00038 /********************** Algorithm's Metadata ********************/
00039 
00040 #define NUM_PARAM     1
00041 #define PARAM_MAXDIST "MaxDist"
00042 
00043 
00044 /*************************************/
00045 /*** Algorithm parameters metadata ***/
00046 
00047 static AlgParamMetadata parameters[NUM_PARAM] = {
00048 
00049   // Metadata of the first parameter.
00050   {
00051     PARAM_MAXDIST,      // Id
00052     "Maximum distance", // Name
00053     Real,               // Type.
00054     "Maximum cartesian distance to be considered", // Overview
00055     "Maximum cartesian distance to be considered", // Description
00056 
00057     1,         // Not zero if the parameter has lower limit.
00058     0.0,       // Parameter's lower limit.
00059     1,         // Not zero if the parameter has upper limit.
00060     1.0,       // Parameter's upper limit.
00061     "0.1"      // Parameter's typical (default) value.
00062   },
00063 };
00064 
00065 
00066 /************************************/
00067 /*** Algorithm's general metadata ***/
00068 
00069 static AlgMetadata metadata = {
00070 
00071   "DistanceToAverage",    // Id.
00072   "Distance to average",  // Name.
00073   "0.1",                  // Version.
00074 
00075   // Overview
00076   "Probability is inversely proportional to the cartesian distance\
00077  in environmental space to the mean point (calculated with all\
00078  presence points).",
00079 
00080   // Description.
00081   "Normalizes the environmental variables values and the\
00082  parameter (according to the number of environmental variables).\
00083  Calculates the mean point in environmental space\
00084  considering all given presence points. When projecting the\
00085  result, it calculates the Euclidean distance between the\
00086  average point and each point in the environmental space.\
00087  If the distance 'dist' is in [0, MAXDIST] then the probability\
00088  of occurrence will be in [1,0] (linear decay).\
00089  If 'dist' > MAXDIST then the probability will be zero.",
00090 
00091   "Mauro E. S. Munoz",  // Algorithm author
00092   "",               // Bibliography.
00093 
00094   "Mauro E. S. Munoz",       // Code author.
00095   "mauro [at] cria.org.br",  // Code author contact.
00096 
00097   0,  // Does not accept categorical data.
00098   0,  // Does not needs absence points to run.
00099 
00100   NUM_PARAM,   // Algorithm's parameters.
00101   parameters
00102 };
00103 
00104 
00105 
00106 /****************************************************************/
00107 /****************** Algorithm's factory function ****************/
00108 
00109 OM_ALG_DLL_EXPORT
00110 AlgorithmImpl *
00111 algorithmFactory()
00112 {
00113   return new DistanceToAverage();
00114 }
00115 
00116 OM_ALG_DLL_EXPORT
00117 AlgMetadata const *
00118 algorithmMetadata()
00119 {
00120   return &metadata;
00121 }
00122 
00123 /****************************************************************/
00124 /************************ Distance To Average *******************/
00125 
00126 /*******************/
00127 /*** constructor ***/
00128 
00129 DistanceToAverage::DistanceToAverage() :
00130   AlgorithmImpl( &metadata ),
00131   _done( false ),
00132   _dist( 0.0 ),
00133   _min( 0.0 ),
00134   _max( 0.0 ),
00135   _avg()
00136 {
00137   _normalizerPtr = new ScaleNormalizer( 0.0, 1.0, true );
00138 }
00139 
00140 
00141 /******************/
00142 /*** destructor ***/
00143 
00144 DistanceToAverage::~DistanceToAverage()
00145 {
00146   if ( _done ) {
00147 
00148     Log::instance()->info( "\nMinimum distance found: %f\n", _min );
00149     Log::instance()->info( "\nMaximum distance found: %f\n\n", _max );
00150   }
00151 }
00152 
00153 
00154 /******************/
00155 /*** initialize ***/
00156 int
00157 DistanceToAverage::initialize()
00158 {
00159   if ( ! getParameter( PARAM_MAXDIST, &_dist ) )
00160     return 0;
00161 
00162   Log::instance()->info( "Parameter %s: %f\n", PARAM_MAXDIST, _dist );
00163 
00164   // Distance should range from 0 to 1
00165   if ( _dist > 1.0 )  _dist = 1.0;
00166   else if ( _dist < 0.0 ) _dist = 0.0;
00167 
00168   int dim = _samp->numIndependent();
00169 
00170   // Normalize the distance parameter according to the number
00171   // of layers.
00172   _dist *= sqrt( (double) dim );
00173 
00174   Log::instance()->info( "\nEnvironmental layers: %d\n", dim );
00175   Log::instance()->info( "Parameter normalized: %f\n\n", _dist );
00176 
00177   //
00178   // Generate model from the average of given points.
00179   //
00180 
00181   Log::instance()->info( "Reading %d-dimensional occurrence points.\n", dim );
00182 
00183   int npnt = _samp->numPresence();
00184   if ( npnt == 0 ) {
00185     Log::instance()->info( "All occurrences are outside the mask!\n" );
00186     return 0;
00187   }
00188 
00189   // Read all presence occurence points.
00190   OccurrencesPtr presences = _samp->getPresences();
00191   OccurrencesImpl::const_iterator pres = presences->begin();
00192   OccurrencesImpl::const_iterator fin = presences->end();
00193 
00194   Log::instance()->info( "Finding average from %d occurrences.\n", npnt );
00195 
00196   // Redimension _avg.
00197   _avg.resize( dim );
00198 
00199   while ( pres != fin ) {
00200     _avg += (*pres)->environment();
00201     ++pres;
00202   }
00203 
00204   _avg /= npnt;
00205 
00206   Log::instance()->info( "Average related to occurrences: " );
00207   for ( int d = 0; d < dim; d++ )
00208     Log::instance()->info( "%f ", _avg[d] );
00209   Log::instance()->info( "\n\n" );
00210 
00211   _done = true;
00212 
00213   return 1;
00214 }
00215 
00216 
00217 /***************/
00218 /*** iterate ***/
00219 int
00220 DistanceToAverage::iterate()
00221 {
00222   return 1;
00223 }
00224 
00225 
00226 /************/
00227 /*** done ***/
00228 int
00229 DistanceToAverage::done() const
00230 {
00231   return _done;
00232 }
00233 
00234 
00235 /*****************/
00236 /*** get Value ***/
00237 Scalar
00238 DistanceToAverage::getValue( const Sample& x ) const
00239 {
00240   static int first_time = 1;
00241 
00242   // Calculate distance between *x and _avg.
00243   
00244   Sample dif = x;
00245   dif -= _avg;
00246   Scalar dist = dif.norm();
00247 
00248   // Minimum and maximum distances found. Only for log!
00249   if ( first_time )
00250     {
00251       _min = _max = dist;
00252       first_time = 0;
00253     }
00254   else
00255     {
00256       if ( dist < _min ) _min = dist;
00257       if ( dist > _max ) _max = dist;
00258     }
00259 
00260   return (dist <= _dist) ? 1.0 - (dist / _dist) : 0.0;
00261 }
00262 
00263 
00264 /***********************/
00265 /*** get Convergence ***/
00266 int
00267 DistanceToAverage::getConvergence( Scalar *val )
00268 {
00269   *val = 1.0;
00270   return 1;
00271 }
00272 
00273 /****************************************************************/
00274 /****************** configuration *******************************/
00275 void
00276 DistanceToAverage::_getConfiguration( ConfigurationPtr& config ) const
00277 {
00278   if (!_done )
00279     return;
00280 
00281   ConfigurationPtr model_config( new ConfigurationImpl("DistanceToAverage") );
00282   config->addSubsection( model_config );
00283 
00284   model_config->addNameValue( "Distance", _dist );
00285   model_config->addNameValue( "Average", _avg );
00286 }
00287 
00288 void
00289 DistanceToAverage::_setConfiguration( const ConstConfigurationPtr& config )
00290 {
00291   ConstConfigurationPtr model_config = config->getSubsection( "DistanceToAverage",false );
00292 
00293   if (!model_config)
00294     return;
00295 
00296   _done = true;
00297   _dist = model_config->getAttributeAsDouble( "Distance", 0.0 );
00298   _avg = model_config->getAttributeAsSample( "Average" );
00299 
00300 }