openModeller
Version 1.4.0
|
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 }