43 #define CUTOFF_ID "StandardDeviationCutoff"
54 "Standard deviation cutoff",
58 "The envelope is determined by multiplying this parameter and the\
62 "Standard deviation cutoff for all bioclimatic envelopes.\n\
63 Examples of (fraction of inclusion, parameter value) are:\n\
64 (50.0%, 0.674); (68.3%, 1.000); (90.0%, 1.645); (95.0%, 1.960);\
86 "Uses mean and standard deviation for each environmental\
87 variable separately to calculate bioclimatic envelopes.\
88 Level of fitness between the environmental values on a point\
89 and the respective envelopes classifies points as\
90 Suitable, Marginal, or Unsuitable for presence.",
93 "Implements the Bioclimatic Envelope Algorithm.\
94 For each given environmental variable the algorithm finds the mean\
95 and standard deviation (assuming normal distribution) associated\
96 to the occurrence points. Each variable has its own envelope\
97 represented by the interval [m - c*s, m + c*s], where 'm' is the\
98 mean; 'c' is the cutoff input parameter; and 's' is the standard\
99 deviation. Besides the envelope, each environmental variable has\
100 additional upper and lower limits taken from the maximum and\
101 minimum values related to the set of occurrence points.\nIn this\
102 model, any point can be classified as:\n\
103 Suitable: if all associated environmental values fall within\
104 the calculated envelopes;\n\
105 Marginal: if one or more associated environmental value falls\
106 outside the calculated envelope, but still within the upper and\
108 Unsuitable: if one or more associated enviromental value falls\
109 outside the upper and lower limits.\n\
110 Bioclim's categorical output is mapped to probabilities\
111 of 1.0, 0.5 and 0.0 respectively.",
116 "Nix, H.A. (1986) A biogeographic analysis of Australian elapid\
117 snakes. In: Atlas of Elapid Snakes of Australia. (Ed.) R. Longmore,\
118 pp. 4-15. Australian Flora and Fauna Series Number 7. Australian\
119 Government Publishing Service: Canberra.",
121 "Mauro Muņoz , // Code author.
"mesmunoz [at] gmail.com", // Code author's contact.
0, // Does not accept categorical data.
0, // Does not need (pseudo)absence points.
NUM_PARAM, // Algorithm's parameters.
parameters
};
/****************************************************************/
/****************** Algorithm's factory function ****************/
OM_ALG_DLL_EXPORT
AlgorithmImpl *
algorithmFactory()
{
return new Bioclim();
}
OM_ALG_DLL_EXPORT
AlgMetadata const *
algorithmMetadata()
{
return &metadata;
}
/****************************************************************/
/**************************** Bioclim ***************************/
/*******************/
/*** constructor ***/
Bioclim::Bioclim() :
AlgorithmImpl( &metadata ),
_done( false ),
_minimum(),
_maximum(),
_mean(),
_std_dev()
{ }
/******************/
/*** destructor ***/
Bioclim::~Bioclim()
{
}
/******************/
/*** initialize ***/
int
Bioclim::initialize()
{
Scalar cutoff = 0.0;
// Read and check the standard deviation cutoff parameter.
if ( ! getParameter( CUTOFF_ID, &cutoff ) ) {
Log::instance()->error( "Parameter " CUTOFF_ID " not set properly.\n" );
return 0;
}
if ( cutoff <= 0 ) {
Log::instance()->warn( "Bioclim - parameter out of range: %f\n", cutoff );
return 0;
}
// Number of independent variables.
int dim = _samp->numIndependent();
Log::instance()->info( "Reading %d-dimensional occurrence points.\n", dim );
// Check the number of sampled points.
int npnt = _samp->numPresence();
if ( npnt < 2 ) {
Log::instance()->error( "Bioclim needs at least 2 points inside the mask!\n" );
return 0;
}
Log::instance()->info( "Using %d points to find the bioclimatic envelope.\n", npnt );
computeStats( _samp->getPresences() );
_std_dev *= cutoff;
_done = true;
return 1;
}
/***************/
/*** iterate ***/
int
Bioclim::iterate()
{
return 1;
}
/************/
/*** done ***/
int
Bioclim::done() const
{
// This is not an iterative algorithm.
return _done;
}
/*****************/
/*** get Value ***/
Scalar
Bioclim::getValue( const Sample& x ) const
{
// Zero if some point valuble is outside its respective envelope.
Scalar outside_envelope = 0;
// Finds the distance from each variable mean to the respective
// point value.
Sample dif = x;
dif -= _mean;
for( unsigned int i=0; i<x.size(); i++) {
if ( x[i] < _minimum[i] || x[i] > _maximum[i] ) {
return 0.0;
}
if ( ! outside_envelope ) {
Scalar cutoff = _std_dev[i];
// If some x[i] is out of its bioclimatic envelope, predicts
// no occurrence.
if ( dif[i] > cutoff || dif[i] < -cutoff ) {
outside_envelope = 1;
}
}
}
// If all point values are within the envelope, returns probability
// 1.0. Else, if some point is outside the envelope but inside
// the upper and lower ranges, returns 0.5 of probability.
return outside_envelope ? 0.5 : 1.0;
}
/***********************/
/*** get Convergence ***/
int
Bioclim::getConvergence( Scalar * const val ) const
{
*val = 1.0;
return 1;
}
/*******************/
/*** get Minimum ***/
void
Bioclim::computeStats( const OccurrencesPtr& occs )
{
// Compute min, max, and mean
{
OccurrencesImpl::const_iterator oc = occs->begin();
OccurrencesImpl::const_iterator end = occs->end();
// Intialize _minimum, _maximum, and _mean
// to the values of the first point, and increment
// to get it out of the loop.
Sample const & sample = (*oc)->environment();
_minimum = sample;
_maximum = sample;
_mean = sample;
++oc;
// For each Occurrence, update the
// statistics for _minimum, _maximum, and _mean
while ( oc != end ) {
Sample const& sample = (*oc)->environment();
_mean += sample;
_minimum &= sample;
_maximum |= sample;
++oc;
}
// Divide for the mean.
_mean /= Scalar( occs->numOccurrences() );
}
// Now compute the std deviation by first computing the variance.
{
_std_dev.resize( _mean.size() );
OccurrencesImpl::const_iterator oc = occs->begin();
OccurrencesImpl::const_iterator end = occs->end();
// Now we compute the variance.
while ( oc != end ) {
Sample tmp( (*oc)->environment() );
tmp -= _mean;
tmp *= tmp;
_std_dev += tmp;
++oc;
}
// In variance, we divide by (npnt - 1), not npnt!
Scalar npts = Scalar( occs->numOccurrences() - 1 );
// Now divide and root to get deviation.
_std_dev /= npts;
_std_dev.sqrt();
}
}
/****************************************************************/
/****************** configuration *******************************/
void
Bioclim::_getConfiguration( ConfigurationPtr& config ) const
{
if ( !_done )
return;
ConfigurationPtr model_config( new ConfigurationImpl("Bioclim") );
config->addSubsection( model_config );
model_config->addNameValue( "Mean", _mean );
model_config->addNameValue( "StdDev", _std_dev );
model_config->addNameValue( "Minimum", _minimum );
model_config->addNameValue( "Maximum", _maximum );
}
void
Bioclim::_setConfiguration( const ConstConfigurationPtr& config )
{
ConstConfigurationPtr model_config = config->getSubsection( "Bioclim" );
if (!model_config)
return;
_done = true;
_mean = model_config->getAttributeAsSample( "Mean" );
_std_dev = model_config->getAttributeAsSample( "StdDev" );
_minimum = model_config->getAttributeAsSample( "Minimum" );
_maximum = model_config->getAttributeAsSample( "Maximum" );
return;
}
/********************/
/*** log Envelope ***/
void
Bioclim::logEnvelope()
{
Log::instance()->info( "Envelope with %d dimensions (variables).\n\n", _mean.size() );
for ( unsigned int i = 0; i < _mean.size(); i++ )
{
Log::instance()->info( "Variable %02d:", i );
Log::instance()->info( " Mean : %f\n", _mean[i] );
Log::instance()->info( " Deviation: %f\n", _std_dev[i] );
Log::instance()->info( " Minimum : %f\n", _minimum[i] );
Log::instance()->info( " Maximum : %f\n", _maximum[i] );
Log::instance()->info( "\n" );
}
}
",
122 "mesmunoz [at] gmail.com",
193 int dim =
_samp->numIndependent();
197 int npnt =
_samp->numPresence();
203 Log::instance()->
info(
"Using %d points to find the bioclimatic envelope.\n", npnt );
240 Scalar outside_envelope = 0;
247 for(
unsigned int i=0; i<x.
size(); i++) {
253 if ( ! outside_envelope ) {
259 if ( dif[i] > cutoff || dif[i] < -cutoff ) {
260 outside_envelope = 1;
269 return outside_envelope ? 0.5 : 1.0;
297 Sample const & sample = (*oc)->environment();
307 while ( oc != end ) {
309 Sample const& sample = (*oc)->environment();
331 while ( oc != end ) {
332 Sample tmp( (*oc)->environment() );
358 config->addSubsection( model_config );
360 model_config->addNameValue(
"Mean",
_mean );
361 model_config->addNameValue(
"StdDev",
_std_dev );
362 model_config->addNameValue(
"Minimum",
_minimum );
363 model_config->addNameValue(
"Maximum",
_maximum );
377 _mean = model_config->getAttributeAsSample(
"Mean" );
378 _std_dev = model_config->getAttributeAsSample(
"StdDev" );
379 _minimum = model_config->getAttributeAsSample(
"Minimum" );
380 _maximum = model_config->getAttributeAsSample(
"Maximum" );
392 for (
unsigned int i = 0; i <
_mean.
size(); i++ )
Sample _maximum
Mininum value for each variable.
void warn(const char *format,...)
'Warn' level.
static AlgParamMetadata parameters[NUM_PARAM]
double Scalar
Type of map values.
Sample _minimum
is true if the algorithm is finished.
int getConvergence(Scalar *const val) const
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Scalar getValue(const Sample &x) const
void error(const char *format,...)
'Error' level.
int getParameter(std::string const &name, std::string *value)
void computeStats(const OccurrencesPtr &)
void _getConfiguration(ConfigurationPtr &) const
void resize(std::size_t size)
OM_ALG_DLL_EXPORT AlgMetadata const * algorithmMetadata()
Sample _std_dev
Mean of sampled points.
Sample _mean
Maximum value for each variable.
void _setConfiguration(const ConstConfigurationPtr &)
void info(const char *format,...)
'Info' level.
static AlgMetadata metadata
OM_ALG_DLL_EXPORT AlgorithmImpl * algorithmFactory()
std::vector< OccurrencePtr >::const_iterator const_iterator