openModeller  Version 1.4.0
niche_mosaic.cpp
Go to the documentation of this file.
00001 
00027 #include "niche_mosaic.hh"
00028 
00029 #include <openmodeller/Configuration.hh>
00030 
00031 #include <openmodeller/Random.hh>
00032 
00033 #include <stdio.h>
00034 #include <math.h>
00035 #include <stdlib.h>
00036 #include <time.h>
00037 
00038 /****************************************************************/
00039 /********************** Algorithm's Metadata ********************/
00040 
00041 #define NUM_PARAM 1
00042 
00043 #define NUMITERATIONS_ID "NumberOfIterations"
00044 
00045 /*************************************/
00046 /*** Algorithm parameters metadata ***/
00047 
00048 static AlgParamMetadata parameters[NUM_PARAM] = {
00049 
00050   // Metadata of the first parameter.
00051   {
00052     NUMITERATIONS_ID,       // Id
00053     "Number of iterations", // Name.
00054     Integer,                // Type.
00055 
00056     // Overview
00057     "Number of iterations.",
00058 
00059     // Description.
00060     "Number of iterations.",
00061 
00062     1,       // Not zero if the parameter has lower limit.
00063     1000,    // Parameter's lower limit.
00064     0,       // Not zero if the parameter has upper limit.
00065     0,       // Parameter's upper limit.
00066     "2000"   // Parameter's typical (default) value.
00067   },
00068 };
00069 
00070 /************************************/
00071 /*** Algorithm's general metadata ***/
00072 
00073 static AlgMetadata metadata = {
00074 
00075   "NICHE_MOSAIC",   // Id.
00076   "Niche Mosaic",   // Name.
00077   "0.1",    // Version.
00078 
00079   // Overview
00080   "This algorithm is still experimental. You may not use it in publications without the author's permission.",
00081 
00082   // Description.
00083   "This algorithm is still experimental. You may not use it in publications without the author's permission.",
00084 
00085   "Missae Yamamoto",  // Author
00086 
00087   // Bibliography.
00088   "",
00089 
00090   "Missae Yamamoto",         // Code author.
00091   "missae [at] dpi.inpe.br", // Code author's contact.
00092 
00093   0,  // Does not accept categorical data.
00094   0,  // Does not need (pseudo)absence points.
00095 
00096   NUM_PARAM,   // Algorithm's parameters.
00097   parameters
00098 };
00099 
00100 /****************************************************************/
00101 /****************** Algorithm's factory function ****************/
00102 
00103 OM_ALG_DLL_EXPORT
00104 AlgorithmImpl *
00105 algorithmFactory()
00106 {
00107   return new NicheMosaic();
00108 }
00109 
00110 OM_ALG_DLL_EXPORT
00111 AlgMetadata const *
00112 algorithmMetadata()
00113 {
00114   return &metadata;
00115 }
00116 
00117 /*************************************************************/
00118 /************************ Niche Mosaic ***********************/
00119 
00120 NicheMosaic::NicheMosaic() :
00121   AlgorithmImpl( &metadata ),
00122   _num_iterations(0),
00123   _num_points(0),
00124   _num_points_test(0),
00125   _num_points_absence_test(0),
00126   _num_layers(0),
00127   _minimum(),
00128   _maximum(),
00129   _delta(),
00130   _my_presences(0),
00131   _my_presences_test(0),
00132   _my_absence_test(0),
00133   _bestCost(0),
00134   _done( false ),
00135   _progress( 0.0 )
00136 {
00137 }
00138 
00139 NicheMosaic::~NicheMosaic()
00140 {
00141 }
00142 
00143 /******************/
00144 /*** initialize ***/
00145 int
00146 NicheMosaic::initialize()
00147 {
00148   // Check the number of presences
00149   int num_presences = _samp->numPresence();
00150 
00151   if ( num_presences < 10 ) {
00152 
00153     Log::instance()->warn( "Niche Mosaic needs at least 10 presence points.\n" );
00154     return 0;
00155   }
00156 
00157   // Check number of layers
00158   _num_layers = _samp->numIndependent();
00159 
00160   if ( _num_layers < 2 ) 
00161   {
00162     std::string msg = "Niche Mosaic needs at least 2 layers.\n";
00163 
00164     Log::instance()->error( msg.c_str() );
00165     return 0;
00166   }
00167 
00168   // Get parameters
00169   if ( ! getParameter( NUMITERATIONS_ID, &_num_iterations ) ) {
00170 
00171     Log::instance()->error( "Parameter '" NUMITERATIONS_ID "' not passed.\n" );
00172     return 0;
00173   }
00174 
00175   if ( _num_iterations < 1000 ) {
00176 
00177     Log::instance()->error( "Parameter '" NUMITERATIONS_ID "' must be greater than 999.\n" );
00178     return 0;
00179   }
00180   
00181   // remove discrepancy presence points
00182   OccurrencesPtr cleanPresences = cleanOccurrences( _samp->getPresences() );
00183   _sampp = createSampler( _samp->getEnvironment(), cleanPresences, _samp->getAbsences() );
00184 
00185   // generate pseudo absence points using simple algorithm.
00186   size_t num_abs = (size_t)(0.40 * num_presences);
00187   if (num_abs < 10) num_abs = 10;
00188   int dim = _sampp->numIndependent();
00189   Sample minimum(dim), maximum(dim);
00190   OccurrencesPtr pres = _sampp->getPresences();
00191   pres->getMinMax( &minimum, &maximum );
00192 
00193   double delta;
00194   for( unsigned int i=0; i<minimum.size(); i++) {
00195     delta = (maximum[i] - minimum[i]) * 0.10;
00196     minimum[i] = minimum[i] - delta;
00197     maximum[i] = maximum[i] + delta;
00198   }
00199 
00200   _my_absence_test = _sampp->getPseudoAbsences( num_abs, &minimum, &maximum ); 
00201 
00202   _num_points_absence_test = _my_absence_test->numOccurrences(); 
00203 
00204   _my_presences = new OccurrencesImpl( _my_absence_test->label(), _my_absence_test->coordSystem() );
00205 
00206   _my_presences_test = new OccurrencesImpl( _my_absence_test->label(), _my_absence_test->coordSystem() );
00207 
00208   return 1;
00209 }
00210 
00211 /***************/
00212 /*** iterate ***/
00213 int
00214 NicheMosaic::iterate()
00215 {
00216   std::vector<Scalar> deltaBest( _num_layers );
00217   size_t costBest, num_points_train_test, bestCost2=0;
00218   int bestIter = 0;
00219 
00220   num_points_train_test = _sampp->getPresences()->numOccurrences();
00221   _model_min_best.resize( num_points_train_test );
00222   _model_max_best.resize( num_points_train_test );
00223 
00224   for ( unsigned int i = 0; i < _model_min_best.size(); i++ ) {
00225   _model_min_best[i] = ScalarVector( _num_layers );
00226     _model_max_best[i] = ScalarVector( _num_layers );
00227   }//end for
00228 
00229 
00230   // Split sampler in test/train
00231   splitOccurrences( _sampp->getPresences(), _my_presences, _my_presences_test );
00232   _num_points_test = _my_presences_test->numOccurrences();
00233   _num_points = _my_presences->numOccurrences();
00234   
00235   if ( 0 == setMinMaxDelta() ) {return 0;}
00236   
00237   int endDo = _num_layers * 10;
00238   do{
00239     findSolution(costBest, deltaBest, bestIter, bestCost2);
00240 
00241   _num_iterations = _num_iterations + 8000;
00242   if (_num_iterations > 30000) break;
00243   }while( (bestIter < endDo) || (costBest < (size_t)(_num_points_test*0.8)) );
00244 
00245   if ( (size_t)(_num_points_absence_test*0.6) > bestCost2 ){
00246 
00247     int dim = _sampp->numIndependent();
00248     Sample minimum(dim), maximum(dim);
00249     OccurrencesPtr pres = _sampp->getPresences();
00250     pres->getMinMax( &minimum, &maximum );
00251 
00252     double delta;
00253     for( unsigned int i=0; i<minimum.size(); i++) {
00254       delta = (maximum[i] - minimum[i]) * 0.10;
00255       minimum[i] = minimum[i] - delta;
00256       maximum[i] = maximum[i] + delta;
00257     }
00258 
00259     _my_absence_test = _sampp->getPseudoAbsences( 100, &minimum, &maximum ); 
00260 
00261     
00262   _num_points_absence_test = _my_absence_test->numOccurrences();  
00263 
00264   _num_iterations = 10000;
00265     findSolution(costBest, deltaBest, bestIter, bestCost2);
00266   }
00267 
00268   if (costBest < _num_points_test)
00269     improveModel(deltaBest);
00270 
00271   _done = 1;
00272 
00273   return 1;
00274 }
00275 
00276 float 
00277 NicheMosaic::getProgress() const
00278 {
00279   if (done()) {
00280 
00281     return 1.0;
00282   }
00283   else {
00284 
00285     return _progress;
00286   }
00287 }
00288 
00289 /*****************/
00290 /*** get Value ***/   /********matchRules classes******/
00291 Scalar
00292 NicheMosaic::getValue( const Sample& x ) const
00293 {
00294   int i, j, k = 0;
00295   Scalar percent;
00296 
00297   //_num_points represents the number of rules
00298   for (i = 0; i < _num_points; i++) {
00299     for (j = 0; j < _num_layers; j++) {
00300 
00301       if ( ( _model_min_best[i][j] <= x[j] ) && ( x[j] <= _model_max_best[i][j] ) )
00302         continue;
00303       else
00304         break;
00305     }//end for
00306 
00307     if ( j == _num_layers ) {
00308       k++;
00309     }//end if
00310   }//end for
00311 
00312   percent = (Scalar)k /(Scalar)_num_points;
00313   if (percent == 0.0) return 0.0;
00314   else if (percent < 0.10) return 0.5;
00315   else if (percent < 0.25) return 0.7;
00316   else if (percent < 0.90) return 0.9;
00317   else return 1.0; 
00318 }
00319 
00320 
00321 int 
00322 NicheMosaic::setMinMaxDelta()
00323 {
00324   OccurrencesImpl::const_iterator oc = _my_presences->begin();
00325   OccurrencesImpl::const_iterator end = _my_presences->end();
00326 
00327   Sample const & sample = (*oc)->environment();
00328   _minimum = sample;
00329   _maximum = sample;
00330   ++oc;
00331 
00332   while ( oc != end ) {
00333     Sample const& sample = (*oc)->environment();
00334     _minimum &= sample;
00335     _maximum |= sample;
00336     ++oc;
00337   }
00338 
00339   _delta = _maximum;
00340   _delta -= _minimum;
00341 
00342   for ( int j = 0; j < _num_layers; j++ ) {
00343     if (_delta[j] == 0.0) {
00344       Log::instance()->error( "No delta for layer %d\n", j );
00345       return 0;
00346     }
00347   }
00348 
00349   return 1;
00350 }
00351 
00352 void 
00353 NicheMosaic::createModel( std::vector<ScalarVector> &model_min, std::vector<ScalarVector> &model_max, const std::vector<Scalar> &delta )
00354 {
00355   size_t i=0;
00356   OccurrencesImpl::const_iterator oc = _my_presences->begin();
00357   OccurrencesImpl::const_iterator end = _my_presences->end();
00358 
00359   while ( oc != end ) {
00360     Sample const& sample = (*oc)->environment();
00361 
00362     for ( int j = 0; j < _num_layers; j++ ) {
00363       model_min[i][j] = sample[j] - delta[j];
00364       model_max[i][j] = sample[j] + delta[j];
00365     }//end for
00366 
00367     ++oc;
00368     ++i;
00369   }//end while
00370 }
00371 
00372 void 
00373 NicheMosaic::editModel( std::vector<ScalarVector> &model_min, std::vector<ScalarVector> &model_max, const std::vector<Scalar> &delta, size_t i_layer )
00374 {
00375   size_t i=0;
00376   OccurrencesImpl::const_iterator oc = _my_presences->begin();
00377   OccurrencesImpl::const_iterator end = _my_presences->end();
00378 
00379   while ( oc != end ) {
00380     Sample const& sample = (*oc)->environment();
00381 
00382     model_min[i][i_layer] = sample[i_layer] - delta[i_layer];
00383     model_max[i][i_layer] = sample[i_layer] + delta[i_layer];
00384 
00385     ++oc;
00386     ++i;
00387   }//end while
00388 }
00389 
00390 size_t
00391 NicheMosaic::calculateCostPres( const std::vector<ScalarVector> &model_min, const std::vector<ScalarVector> &model_max )
00392 {
00393   OccurrencesImpl::iterator it = _my_presences_test->begin(); 
00394   OccurrencesImpl::iterator last = _my_presences_test->end();
00395 
00396   int i, j, npresence = 0;
00397 
00398   //presence
00399   while ( it != last ) {
00400 
00401     Sample const& sample = (*it)->environment();
00402 
00403     //_num_points eh o numero de regras do modelo
00404     for (i = 0; i < _num_points; i++) {
00405 
00406       for (j = 0; j < _num_layers; j++) {
00407 
00408         if ( ( model_min[i][j] <= sample[j] ) && ( sample[j] <= model_max[i][j] ) )
00409           continue;
00410         else
00411           break;
00412       }//end for
00413 
00414       if ( j == _num_layers ) {
00415         npresence++;
00416     break;
00417       }//end if
00418     }//end for
00419     ++it;
00420   }//end while
00421 
00422   return npresence;
00423 }
00424 
00425 size_t
00426 NicheMosaic::calculateCostAus( const std::vector<ScalarVector> &model_min, const std::vector<ScalarVector> &model_max )
00427 {
00428   int i, j, nabsence = 0;
00429 
00430   //absence
00431   OccurrencesImpl::iterator it_absence = _my_absence_test->begin(); 
00432   OccurrencesImpl::iterator last_absence = _my_absence_test->end();
00433 
00434   while ( it_absence != last_absence ) 
00435   {     
00436     Sample const& samp = (*it_absence)->environment();
00437 
00438     for (i = 0; i < _num_points; i++){ //_num_points eh o numero de regras do modelo
00439 
00440       for (j = 0; j < _num_layers; j++){
00441 
00442         if ( ( model_min[i][j] <= samp[j] ) && ( samp[j] <= model_max[i][j] ) )
00443           continue;
00444         else
00445           break;
00446       }//end for
00447 
00448       if ( j == _num_layers )
00449         break;
00450     }//end for
00451 
00452     if ( i == _num_points)
00453       nabsence++;
00454 
00455     ++it_absence;
00456   }//end while
00457 
00458   return nabsence;
00459 }
00460 
00461 size_t 
00462 NicheMosaic::getRandomLayerNumber()
00463 {
00464   Random random;
00465 
00466   return random( 0, _num_layers );
00467 }
00468 
00469 Scalar 
00470 NicheMosaic::getRandomPercent(const std::vector<Scalar> &delta, const size_t i_layer, size_t &costPres)
00471 {
00472   int size = 100, r;
00473 
00474   double min_percent = 0.12, max_percent = 0.4;
00475 
00476   double new_percent, half_percent = (max_percent - min_percent) / 2 + min_percent;
00477 
00478   Random random;
00479 
00480   r = random( 0, size );
00481   new_percent = (max_percent - min_percent) * ( (double) r / (double) size ) + min_percent;
00482     
00483   if ( (costPres < _num_points_test) && (new_percent < half_percent) ){
00484 
00485     new_percent = new_percent + half_percent - min_percent;
00486   }
00487 
00488   return new_percent;
00489 }
00490 
00491 void
00492 NicheMosaic::renewTabuDegree(std::vector<size_t> &tabuDegree)
00493 {
00494   for (int i = 0; i < _num_layers; i++) {
00495 
00496     if (tabuDegree[i] > 0)
00497       tabuDegree[i] = tabuDegree[i] - 1;
00498   }
00499 }
00500 
00501 void
00502 NicheMosaic::saveBestModel(const std::vector<ScalarVector> &model_min, const std::vector<ScalarVector> &model_max)
00503 {
00504   for (int i = 0; i < _num_points; i++) {
00505     for (int j = 0; j < _num_layers; j++) {
00506       _model_min_best[i][j] = model_min[i][j];
00507       _model_max_best[i][j] = model_max[i][j];
00508     }
00509   }
00510 }
00511 
00512 void 
00513 NicheMosaic::improveModel( const std::vector<Scalar> &deltaBest )
00514 {
00515   OccurrencesImpl::iterator it = _my_presences_test->begin(); 
00516   OccurrencesImpl::iterator last = _my_presences_test->end();
00517 
00518   int i, j, flag = 0, n = _num_points;
00519 
00520   while ( it != last ) {
00521 
00522     Sample const& sample = (*it)->environment();
00523 
00524     //_num_points eh o numero de regras do modelo
00525     for (i = 0; i < n; i++) {
00526 
00527       for (j = 0; j < _num_layers; j++) {
00528 
00529         if ( ( _model_min_best[i][j] <= sample[j] ) && ( sample[j] <= _model_max_best[i][j] ) )
00530           continue;
00531         else
00532           break;
00533       }//end for
00534 
00535       if ( j == _num_layers ) {
00536         flag = 1;
00537     break;
00538       }//end if
00539     }//end for
00540   if (flag){
00541     flag = 0;
00542   }else {
00543       for (j = 0; j < _num_layers; j++) {
00544           _model_min_best[n][j] = sample[j] - deltaBest[j];
00545       _model_max_best[n][j] = sample[j] + deltaBest[j];
00546 
00547     }//end for
00548     n++;
00549   }//end if
00550     ++it;
00551   }//end while
00552   _num_points = n;
00553 }
00554 
00555 void 
00556 NicheMosaic::findSolution(size_t &costBest, std::vector<Scalar> &deltaBest, int &bestIter, size_t &bestCost2)
00557 {
00558   size_t cost1, cost2, i_layer;
00559   Scalar importance = 1.0, cost, deltaIni=0.4;
00560   std::vector<Scalar> delta( _num_layers );
00561 
00562   size_t nTabu = (size_t)floor(sqrt((double)(_num_layers)));
00563   std::vector<size_t> tabuDegree( _num_layers );
00564 
00565   for( int l = 0; l < _num_layers; l++ ) 
00566     tabuDegree[l] = 0;
00567 
00568   //model
00569   std::vector<ScalarVector> model_min( _num_points );
00570   std::vector<ScalarVector> model_max( _num_points );
00571 
00572   for ( unsigned int i = 0; i < model_min.size(); i++ ) {
00573     model_min[i] = ScalarVector( _num_layers );
00574     model_max[i] = ScalarVector( _num_layers );
00575   }//end for
00576 
00577   for ( int j = 0; j < _num_layers; j++ ){
00578 
00579     delta[j] = _delta[j] * deltaIni;
00580   deltaBest[j] = delta[j];
00581   }//end for
00582 
00583   createModel( model_min, model_max, delta );
00584   cost1 = calculateCostPres( model_min, model_max );
00585   costBest = cost1;
00586   cost2 = calculateCostAus( model_min, model_max );
00587   cost = (Scalar)cost1*importance + (Scalar)cost2;
00588 
00589  _bestCost = cost;
00590   saveBestModel(model_min, model_max);
00591   if (_bestCost == ((Scalar)_num_points_test*importance + (Scalar)_num_points_absence_test) )
00592     return;
00593 
00594   for (int iter=0; iter < _num_iterations; iter++) {
00595 
00596     _progress = (float)iter/(float)_num_iterations;
00597   i_layer = getRandomLayerNumber();
00598 
00599   Scalar deltaAux = delta[i_layer];
00600   delta[i_layer] = _delta[i_layer] * getRandomPercent(delta, i_layer, cost1);
00601   editModel( model_min, model_max, delta, i_layer );
00602   cost1 = calculateCostPres( model_min, model_max );
00603   cost2 = calculateCostAus( model_min, model_max );
00604   cost = (Scalar)cost1*importance + (Scalar)cost2;
00605 
00606   if ( (cost > _bestCost) || ( (cost == _bestCost) && (cost1 >= costBest) ) ) {
00607     renewTabuDegree(tabuDegree);
00608     tabuDegree[i_layer] = nTabu;
00609     costBest = cost1;
00610     _bestCost = cost;
00611     deltaBest[i_layer] = delta[i_layer];
00612     saveBestModel(model_min, model_max);
00613     bestIter = iter;
00614     bestCost2=cost2;
00615 
00616     if (_bestCost == ((Scalar)_num_points_test*importance + (Scalar)_num_points_absence_test) )
00617     break;
00618   }else {
00619     if (tabuDegree[i_layer] == 0) {
00620       renewTabuDegree(tabuDegree);
00621       tabuDegree[i_layer] = nTabu;
00622     }else{
00623       delta[i_layer] = deltaAux;
00624       editModel( model_min, model_max, delta, i_layer );
00625     }//end if
00626   }//end if
00627   }//end for
00628 }
00629 
00630 /****************************************************************/
00631 /****************** configuration *******************************/
00632 void
00633 NicheMosaic::_getConfiguration( ConfigurationPtr& config ) const
00634 {
00635 
00636   if ( !_done )
00637     return;
00638 
00639   ConfigurationPtr model_config( new ConfigurationImpl( "NicheMosaic" ) );
00640   config->addSubsection( model_config );
00641 
00642   model_config->addNameValue( "NumLayers", _num_layers );
00643   model_config->addNameValue( "NumPoints", _num_points );
00644 
00645   for (int i = 0; i < _num_points; i++) {
00646 
00647     ConfigurationPtr rule_config( new ConfigurationImpl( "Rule" ) );
00648   model_config->addSubsection( rule_config );
00649 
00650     Sample min_best( _model_min_best[i] );
00651     Sample max_best( _model_max_best[i] );
00652 
00653     rule_config->addNameValue( "Min", min_best );
00654     rule_config->addNameValue( "Max", max_best );
00655 
00656   }
00657 }
00658 
00659 void
00660 NicheMosaic::_setConfiguration( const ConstConfigurationPtr& config )
00661 {
00662   ConstConfigurationPtr model_config = config->getSubsection( "NicheMosaic" );
00663 
00664   if (!model_config)
00665     return;
00666 
00667   _num_layers = model_config->getAttributeAsInt( "NumLayers", 0 );
00668   _num_points = model_config->getAttributeAsInt( "NumPoints", 0 );
00669 
00670   _model_min_best.resize( _num_points );
00671   _model_max_best.resize( _num_points );
00672 
00673   Configuration::subsection_list subelements = model_config->getAllSubsections();
00674 
00675   Configuration::subsection_list::iterator subelement = subelements.begin();
00676   Configuration::subsection_list::iterator last_subelement = subelements.end();
00677 
00678   int i = 0;
00679 
00680   for ( ; subelement != last_subelement; ++subelement ) {
00681 
00682     if ( (*subelement)->getName() == "Rule" ) {
00683 
00684       _model_min_best[i] = (*subelement)->getAttributeAsVecDouble( "Min" );
00685       _model_max_best[i] = (*subelement)->getAttributeAsVecDouble( "Max" );
00686 
00687       ++i;
00688     }
00689   }
00690 
00691   _done = true;
00692 
00693   return;
00694 }
00695 
00696 OccurrencesPtr
00697 NicheMosaic::cleanOccurrences( const OccurrencesPtr& occurrences )
00698 {
00699   OccurrencesPtr presence( new OccurrencesImpl(0.0) );
00700   OccurrencesPtr presenceAux( new OccurrencesImpl(0.0) );
00701   
00702   double dist, distLimit=8.0, x, y, xmin, xmax, ymin, ymax, deltax, deltay;
00703   unsigned int flag = 0, i = 0, itrain=0, ktrain=0, ioccur=0;
00704   std::vector<double> occurTransformx( occurrences->numOccurrences() );
00705   std::vector<double> occurTransformy( occurrences->numOccurrences() );
00706   std::vector<int> testId( occurrences->numOccurrences() );
00707 
00708   OccurrencesImpl::const_iterator it = occurrences->begin();
00709   OccurrencesImpl::const_iterator fin = occurrences->end();
00710   
00711   xmin = xmax = (*it)->x();
00712   ymin = ymax = (*it)->y();
00713   
00714   ++it;
00715   while( it != fin ) {
00716     if ( (*it)->x() < xmin ) xmin = (*it)->x();
00717   else  if ( (*it)->x() > xmax) xmax = (*it)->x();
00718   if ( (*it)->y() < ymin) ymin = (*it)->y();
00719   else  if ( (*it)->y() > ymax) ymax = (*it)->y();
00720     ++it;
00721   }
00722   deltax = xmax - xmin;
00723   deltay = ymax - ymin;
00724 
00725   it = occurrences->begin();
00726   while( it != fin ) {
00727     occurTransformx[i] = 100 * ( (*it)->x() - xmin ) / deltax;
00728     occurTransformy[i] = 100 * ( (*it)->y() - ymin ) / deltay;
00729     i++;
00730     ++it;
00731   }
00732 
00733   flag = 0, itrain=0, ktrain=0, ioccur=0;
00734 
00735   it = occurrences->begin();
00736 
00737   presenceAux->insert( new OccurrenceImpl( *(*it) ) );
00738 
00739   ++it;
00740   testId[ktrain] = ioccur;
00741   ktrain++;
00742   ioccur++;
00743 
00744   while( it != fin ) {
00745 
00746     for ( i = 0; i < ktrain; i++ ) {
00747       itrain = testId[i];
00748     x = occurTransformx[ioccur] - occurTransformx[itrain];
00749     y = occurTransformy[ioccur] - occurTransformy[itrain];
00750       dist = sqrt(  (x*x) + (y*y)  );
00751 
00752       if ( dist < distLimit) {
00753         presence->insert( new OccurrenceImpl( *(*it) ) );
00754       flag = 1;
00755       break;
00756       }
00757   }
00758 
00759     if (!flag){
00760       presenceAux->insert( new OccurrenceImpl( *(*it) ) );
00761       testId[ktrain] = ioccur;
00762     ktrain++;
00763   }else{
00764       flag = 0;
00765   }
00766   ioccur++;
00767     ++it;
00768   }
00769   
00770   //verify presenceAux points 
00771   SamplerPtr samp = createSampler( _samp->getEnvironment(), presence, _samp->getAbsences() );
00772   Sample mean;
00773   Sample deviation;
00774   computeMeanDeviation( presence, mean, deviation  );
00775 
00776   OccurrencesImpl::const_iterator itt = presenceAux->begin();
00777   OccurrencesImpl::const_iterator finn = presenceAux->end();
00778 
00779   double prob;
00780   OccurrencePtr occ;
00781   while( itt != finn ) {
00782     occ = (*itt);
00783 
00784   Sample dif = occ->environment();
00785     dif -= mean;
00786     prob = 1.0;
00787     for( unsigned int i=0; i<dif.size(); i++) {
00788       Scalar cutoff = deviation[i];
00789 
00790       if ( dif[i] > cutoff || dif[i] < -cutoff ) {
00791         prob = 0.0;
00792     break;
00793       }
00794     }
00795 
00796     if ( prob == 1.0 ){
00797       presence->insert( new OccurrenceImpl( *(*itt) ) );
00798     }
00799     ++itt;
00800   }
00801 
00802   return presence;
00803 }
00804 
00805 void
00806 NicheMosaic::computeMeanDeviation( const OccurrencesPtr& occs, Sample& mean, Sample& deviation  )
00807 {
00808   // compute mean
00809   OccurrencesImpl::const_iterator oc = occs->begin();
00810   OccurrencesImpl::const_iterator end = occs->end();
00811 
00812   Sample min, max;
00813 
00814   Sample const & sample = (*oc)->environment();
00815   min = sample;
00816   max = sample;
00817   mean = sample;   
00818   ++oc;
00819  
00820   while ( oc != end ) {
00821       
00822     Sample const& sample = (*oc)->environment();
00823       
00824     mean += sample;
00825     min &= sample;
00826     max |= sample;
00827 
00828     ++oc;
00829   }
00830   mean /= Scalar( occs->numOccurrences() );
00831 
00832   // compute the std deviation 
00833   deviation.resize( mean.size() );
00834   oc = occs->begin();
00835 
00836   // compute the variance.
00837   while ( oc != end ) {
00838     Sample tmp( (*oc)->environment() );
00839     tmp -= mean;
00840     tmp *= tmp;
00841     deviation += tmp;
00842     ++oc;
00843   }
00844 
00845   // divide by (npnt - 1)
00846   Scalar npts = Scalar( occs->numOccurrences() - 1 );
00847   deviation /= npts;
00848   deviation.sqrt();
00849   deviation *= 5.0;
00850 }