openModeller
Version 1.4.0
|
00001 00028 #include "minimum_distance.hh" 00029 00030 #include <string.h> 00031 #include <stdio.h> 00032 #include <stdlib.h> 00033 #include <math.h> 00034 00035 #include <openmodeller/ScaleNormalizer.hh> 00036 00037 //debug 00038 #include <iostream> 00039 00040 00041 /****************************************************************/ 00042 /********************** Algorithm's Metadata ********************/ 00043 00044 #define NUM_PARAM 1 00045 00046 #define MAXDIST_ID "MaximumDistance" 00047 00048 00049 /******************************/ 00050 /*** Algorithm's parameters ***/ 00051 00052 static AlgParamMetadata parameters[NUM_PARAM] = { 00053 00054 // Metadata of the first parameter. 00055 { 00056 MAXDIST_ID, // Id. 00057 "Maximum distance", // Name. 00058 Real, // Type. 00059 "Maximum cartesian distance to closest point", // Overview 00060 "Maximum cartesian distance to closest point", // Description. 00061 00062 1, // Not zero if the parameter has lower limit. 00063 0.0, // Parameter's lower limit. 00064 1, // Not zero if the parameter has upper limit. 00065 1.0, // Parameter's upper limit. 00066 "0.1" // Parameter's typical (default) value. 00067 }, 00068 }; 00069 00070 00071 /************************************/ 00072 /*** Algorithm's general metadata ***/ 00073 00074 static AlgMetadata metadata = { 00075 00076 "MinimumDistance", // Id. 00077 "Minimum distance", // Name. 00078 "0.2", // Version. 00079 00080 // Overview 00081 "Probability is inversely proportional to the cartesian\ 00082 distance in environmental space to the nearest presence point.", 00083 00084 // Description. 00085 "Normalizes the environmental variables values and the\ 00086 parameter (according to the number of environmental variables).\ 00087 Calculates the distance between the given environmental conditions\ 00088 to each occurrence point and selects the closest distance.\n\ 00089 If distance 'dist' is within [0, MaxDist] then probability will\ 00090 be in [0,1]. If 'dist' > MaxDist then probability will be zero.", 00091 00092 00093 "Mauro E. S. Munoz", // Algorithm author. 00094 "", // Bibliography. 00095 00096 "Mauro E. S. Munoz", // Code author. 00097 "mauro [at] cria.org.br", // Code author's contact. 00098 00099 0, // Does not accept categorical data. 00100 0, // Does not need (pseudo)absence points. 00101 00102 NUM_PARAM, // Algorithm's parameters. 00103 parameters 00104 }; 00105 00106 00107 00108 /****************************************************************/ 00109 /****************** Algorithm's factory function ****************/ 00110 00111 OM_ALG_DLL_EXPORT 00112 AlgorithmImpl * 00113 algorithmFactory() 00114 { 00115 return new MinimumDistance(); 00116 } 00117 00118 OM_ALG_DLL_EXPORT 00119 AlgMetadata const * 00120 algorithmMetadata() 00121 { 00122 return &metadata; 00123 } 00124 00125 /****************************************************************/ 00126 /************************ Minimum Distance **********************/ 00127 00128 /*******************/ 00129 /*** constructor ***/ 00130 00131 MinimumDistance::MinimumDistance() : 00132 AlgorithmImpl( &metadata ), 00133 _done( false ), 00134 _dist(0.0), 00135 _hasCategorical( false ), 00136 _numLayers( 0 ) 00137 { 00138 _normalizerPtr = new ScaleNormalizer( 0.0, 1.0, true ); 00139 } 00140 00141 00142 /******************/ 00143 /*** destructor ***/ 00144 00145 MinimumDistance::~MinimumDistance() 00146 { 00147 } 00148 00149 00150 /******************/ 00151 /*** initialize ***/ 00152 int 00153 MinimumDistance::initialize() 00154 { 00155 if ( ! getParameter( MAXDIST_ID, &_dist ) ) { 00156 Log::instance()->error("Parameter '" MAXDIST_ID "' not set properly.\n"); 00157 return 0; 00158 } 00159 00160 // Distance should range from 0 to 1 00161 if (_dist > 1.0) _dist = 1.0; 00162 else if (_dist < 0.0) _dist = 0.0; 00163 00164 int dim = _samp->numIndependent(); 00165 00166 _dist *= sqrt( (double) dim ); 00167 00168 if ( _samp->numPresence() == 0 ) { 00169 Log::instance()->warn( "MinDistance: No occurrences inside the mask!\n" ); 00170 return 0; 00171 } 00172 00173 OccurrencesPtr presences = _samp->getPresences(); 00174 00175 // Load vector with samples containing the environmental 00176 // values at each presence point 00177 OccurrencesImpl::const_iterator p_iterator = presences->begin(); 00178 OccurrencesImpl::const_iterator p_end = presences->end(); 00179 00180 while ( p_iterator != p_end ) { 00181 00182 Sample point = (*p_iterator)->environment(); 00183 00184 _envPoints.push_back(point); 00185 00186 ++p_iterator; 00187 } 00188 00189 // Identify categorical layers 00190 _numLayers = _samp->numIndependent(); 00191 _isCategorical.resize( _numLayers ); 00192 00193 for( int i = 0; i < _numLayers; ++i ) { 00194 if ( _samp->isCategorical( i ) ) { 00195 _hasCategorical = true; 00196 _isCategorical[i] = 1.0; 00197 } 00198 } 00199 00200 _done = true; 00201 00202 return 1; 00203 00204 } 00205 00206 00207 /***************/ 00208 /*** iterate ***/ 00209 int 00210 MinimumDistance::iterate() 00211 { 00212 return 1; 00213 } 00214 00215 00216 /************/ 00217 /*** done ***/ 00218 int 00219 MinimumDistance::done() const 00220 { 00221 return _done; 00222 } 00223 00224 00225 /*****************/ 00226 /*** get Value ***/ 00227 Scalar 00228 MinimumDistance::getValue( const Sample& x ) const 00229 { 00230 // Calculate the smallest distance between *x and the occurrence 00231 // points. 00232 Scalar min = -1; 00233 00234 for( unsigned int i=0; i<_envPoints.size(); i++) { 00235 00236 Scalar dist = findDist( x, _envPoints[i] ); 00237 00238 if ( (dist >= 0) && (dist < min || min < 0) ) 00239 min = dist; 00240 } 00241 00242 // Too far away or categories didn't match any occurrence 00243 if ( min < 0 || min > _dist ) 00244 return 0.0; 00245 00246 return 1.0 - (min / _dist); 00247 00248 } 00249 00250 00251 /***********************/ 00252 /*** get Convergence ***/ 00253 int 00254 MinimumDistance::getConvergence( Scalar *val ) 00255 { 00256 *val = 1.0; 00257 return 1; 00258 } 00259 00260 00261 /*****************/ 00262 /*** find Dist ***/ 00263 Scalar 00264 MinimumDistance::findDist( const Sample& x, const Sample& pnt ) const 00265 { 00266 00267 if ( _hasCategorical ) { 00268 for( int i=0; i< _numLayers ; ++i ) { 00269 if ( _isCategorical[i] ) { 00270 if ( x[i] != pnt[i] ) { 00271 return -1.0; 00272 } 00273 } 00274 } 00275 } 00276 00277 Sample dif = x; 00278 dif -= pnt; 00279 00280 return dif.norm(); 00281 00282 } 00283 00284 00285 /****************************************************************/ 00286 /****************** configuration *******************************/ 00287 void 00288 MinimumDistance::_getConfiguration( ConfigurationPtr& config ) const 00289 { 00290 if (!_done ) 00291 return; 00292 00293 ConfigurationPtr model_config( new ConfigurationImpl("MinimumDistance") ); 00294 config->addSubsection( model_config ); 00295 00296 model_config->addNameValue( "IsCategoricalLayer", _isCategorical ); 00297 model_config->addNameValue( "Distance", _dist ); 00298 00299 ConfigurationPtr envpoints_config( new ConfigurationImpl("EnvironmentalReferences") ); 00300 model_config->addSubsection( envpoints_config ); 00301 00302 for( unsigned int i=0; i<_envPoints.size(); i++) { 00303 00304 ConfigurationPtr point_config( new ConfigurationImpl("Reference") ); 00305 envpoints_config->addSubsection( point_config ); 00306 00307 point_config->addNameValue( "Value", _envPoints[i] ); 00308 } 00309 } 00310 00311 void 00312 MinimumDistance::_setConfiguration( const ConstConfigurationPtr& config ) 00313 { 00314 ConstConfigurationPtr model_config = config->getSubsection( "MinimumDistance",false ); 00315 00316 if (!model_config) 00317 return; 00318 00319 // Information about categorical layers 00320 _isCategorical = model_config->getAttributeAsSample( "IsCategoricalLayer" ); 00321 _numLayers = (int)_isCategorical.size(); 00322 00323 for( int i=0; i<_numLayers; i++) { 00324 00325 if ( _isCategorical[i] ) { 00326 00327 _hasCategorical = true; 00328 break; 00329 } 00330 } 00331 00332 // Maximum distance 00333 _dist = model_config->getAttributeAsDouble( "Distance", 0.0 ); 00334 00335 // Environmental points 00336 ConstConfigurationPtr envpoints_config = model_config->getSubsection( "EnvironmentalReferences",false ); 00337 00338 Configuration::subsection_list subs = envpoints_config->getAllSubsections(); 00339 00340 Configuration::subsection_list::iterator begin = subs.begin(); 00341 Configuration::subsection_list::iterator end = subs.end(); 00342 for ( ; begin != end; ++begin ) { 00343 00344 if ( (*begin)->getName() != "Reference" ) 00345 continue; 00346 00347 Sample point = (*begin)->getAttributeAsSample( "Value" ); 00348 00349 _envPoints.push_back( point ); 00350 } 00351 00352 _done = true; 00353 }