openModeller  Version 1.5.0
Environment.cpp
Go to the documentation of this file.
1 
30 
32 #include <openmodeller/Log.hh>
36 #include <openmodeller/Random.hh>
40 
41 #if defined (HAVE_VALUES_H) && !defined(WIN32)
42 #include <values.h>
43 #else
44 #include <float.h>
45 #define MAXFLOAT FLT_MAX
46 #endif
47 
48 using std::string;
49 using std::vector;
50 
51 #undef DEBUG_GET
52 
53 /****************************************************************/
54 /*********************** factory methods ************************/
55 EnvironmentPtr createEnvironment( const std::vector<std::string>& categs,
56  const std::vector<std::string>& maps,
57  const std::string& mask_file )
58 {
59  return EnvironmentPtr( new EnvironmentImpl( categs, maps, mask_file ) );
60 }
61 
62 EnvironmentPtr createEnvironment( const std::vector<std::string>& categs,
63  const std::vector<std::string>& maps )
64 {
65  return EnvironmentPtr( new EnvironmentImpl( categs, maps, "" ) );
66 }
67 
69 {
70  EnvironmentPtr env( new EnvironmentImpl() );
71 
72  env->setConfiguration( config );
73 
74  return env;
75 }
76 
78 {
79  return EnvironmentPtr( new EnvironmentImpl( ) );
80 }
81 
82 
83 /****************************************************************/
84 /******************* static utility functions *******************/
85 
87 EnvironmentImpl::getLayerConfig( const layer& l, bool basicConfig ) {
88 
90 
91  cfg->addNameValue( "Id", l.first );
92 
93  if ( ! basicConfig ) {
94 
95  cfg->addNameValue( "IsCategorical", l.second->isCategorical() );
96 
97  if ( l.second->hasMinMax() ) {
98 
99  Scalar min;
100  Scalar max;
101  l.second->getMinMax( &min, &max );
102  cfg->addNameValue( "Min", min );
103  cfg->addNameValue( "Max", max );
104  }
105  }
106 
107  return cfg;
108 }
109 
112 
113  string filename = config->getAttribute( "Id" );
114  // map should already have the categorical attribute set!
115  //int categ = config->getAttributeAsInt( "IsCategorical", 0 );
116 
117  layer l = makeLayer( filename, map );
118 
119  try {
120 
121  // The calls to getAttribute( string ) will throw if
122  // the attribute is not found.
123  config->getAttribute("Min");
124  config->getAttribute("Max");
125 
126  // If we make it here, the attributes exist, and the
127  // hard coded default value of 0.0 will not be used.
128  double min = config->getAttributeAsDouble( "Min", 0.0 );
129  double max = config->getAttributeAsDouble( "Max", 0.0 );
130 
131  l.second->setMinMax( min, max );
132  }
133  catch (AttributeNotFound& e) {
134 
135  UNUSED(e);
136  }
137 
138  return l;
139 }
140 
142 EnvironmentImpl::makeLayer( const string& filename, int categ ) {
143 
144  Map *map = new Map( RasterFactory::instance().create( filename, categ ) );
145 
146  return makeLayer( filename, map );
147 }
148 
150 EnvironmentImpl::makeLayer( const string& filename, Map *map ) {
151 
152  layer l;
153 
154  if ( !map ) {
155 
156  Log::instance()->warn( "Cannot read environment file: '%s'\n", filename.c_str() );
157  }
158  else {
159 
160  l.first = filename;
161  l.second = map;
162  }
163 
164  return l;
165 }
166 
167 
168 /****************************************************************/
169 /************************* EnvironmentImpl **************************/
170 
171 /*******************/
172 /*** constructor ***/
173 
175  _layers(),
176  _mask(),
177  _xmin(0),
178  _ymin(0),
179  _xmax(0),
180  _ymax(0),
181  _normalizerPtr(0)
182 {
183 }
184 
185 EnvironmentImpl::EnvironmentImpl( const std::vector<std::string>& categs,
186  const std::vector<std::string>& maps,
187  const std::string& mask )
188 {
189  initialize( categs, maps, mask );
190 }
191 
192 void
193 EnvironmentImpl::initialize( const std::vector<std::string>& categs,
194  const std::vector<std::string>& maps,
195  const std::string& mask )
196 {
197  _normalizerPtr = 0;
198 
199  // Initialize mask and read its region.
200  changeMask( mask );
201  changeLayers( categs, maps );
202 }
203 
204 
205 /******************/
206 /*** destructor ***/
207 
209 {
210  clearLayers();
211  clearMask();
212 
213  if ( _normalizerPtr ) {
214 
215  delete _normalizerPtr;
216  }
217 }
218 
219 
220 /*****************/
221 /*** deep copy ***/
222 
225 {
226  std::vector<std::string> categs;
227  std::vector<std::string> maps;
228 
229  layers::const_iterator lay = _layers.begin();
230  layers::const_iterator end = _layers.end();
231 
232  while ( lay != end ) {
233 
234  if ( lay->second->isCategorical() ) {
235 
236  categs.push_back( lay->first );
237  }
238  else {
239 
240  maps.push_back( lay->first );
241  }
242 
243  ++lay;
244  }
245 
246  EnvironmentImpl* clone = new EnvironmentImpl( categs, maps, _mask.first );
247 
248  if ( _normalizerPtr ) {
249 
250  clone->normalize( _normalizerPtr );
251  }
252 
253  return clone;
254 }
255 
256 void
258  if (_layers.size() < 1) {
259  return;
260  }
261  layers::iterator first = _layers.begin();
262  layers::iterator end = _layers.end();
263  for ( ; first != end; ++ first ) {
264  delete (*first).second;
265  }
266  _layers.clear();
267 }
268 
269 void
271  if ( _mask.second )
272  delete _mask.second;
273 
274  _mask.first = "";
275  _mask.second = 0;
276 }
277 
278 /*********************/
279 /*** configuration ***/
280 
283 {
284  ConfigurationPtr config( new ConfigurationImpl("Environment") );
285 
286  config->addNameValue( "NumLayers", (int) _layers.size() );
287 
288  layers::const_iterator l = _layers.begin();
289  layers::const_iterator end = _layers.end();
290 
291  for( ; l != end; ++l ) {
292 
293  ConfigurationPtr cfg( getLayerConfig( *l ) );
294  cfg->setName("Map");
295  config->addSubsection( cfg );
296  }
297 
298  if ( _mask.second ) {
299 
300  bool onlyBasicConfig = true;
301  ConfigurationPtr maskcfg( getLayerConfig( _mask, onlyBasicConfig ) );
302  maskcfg->setName( "Mask" );
303  config->addSubsection( maskcfg );
304  }
305 
306  return config;
307 }
308 
309 void
311 {
312  clearMask();
313  clearLayers();
314 
315  // Store configuration references for each layer
316  // Important: users can mix continuous and categorical layers, but oM
317  // requires categorical layers to be first, so having two
318  // vectors can handle this.
319  std::vector<ConstConfigurationPtr> categ_layer_confs;
320  std::vector<ConstConfigurationPtr> cont_layer_confs;
321 
322  // Need to have separate containers, since loadLayers requires
323  // knowing if the layer is categorical or not.
324  std::vector<string> categ_layer_ids;
325  std::vector<Map*> categ_layer_refs;
326  std::vector<string> cont_layer_ids;
327  std::vector<Map*> cont_layer_refs;
328 
329  // Mask config
330  ConstConfigurationPtr mask_conf = config->getSubsection( "Mask", false );
331  std::vector<string> mask_id;
332  std::vector<Map*> mask_ref;
333 
334  // Suck in all the filenames.
335  Configuration::subsection_list subs = config->getAllSubsections();
336  Configuration::subsection_list::const_iterator it = subs.begin();
337  while( it != subs.end() ) {
338 
339  string subname = (*it)->getName();
340  string id = (*it)->getAttribute("Id");
341 
342  if ( subname == "Mask" && mask_id.size() == 0 ) {
343 
344  // Mask
345 
346  mask_id.push_back(id);
347  mask_ref.push_back(0);
348  }
349  else {
350 
351  // Environmental layer
352 
353  int categ = (*it)->getAttributeAsInt( "IsCategorical", 0 );
354 
355  if ( categ == 0 ) {
356 
357  cont_layer_ids.push_back(id);
358  cont_layer_refs.push_back(0);
359  const ConstConfigurationPtr lconf = (*it);
360  cont_layer_confs.push_back(lconf);
361  }
362  else {
363 
364  categ_layer_ids.push_back(id);
365  categ_layer_refs.push_back(0);
366  const ConstConfigurationPtr lconf = (*it);
367  categ_layer_confs.push_back(lconf);
368  }
369  }
370 
371  ++it;
372  }
373 
374  loadLayers( categ_layer_ids, categ_layer_refs, 1 );
375  loadLayers( cont_layer_ids, cont_layer_refs, 0 );
376 
377  // Fill _layers attribute
378  for( unsigned int i = 0; i< categ_layer_confs.size(); i++ ) {
379 
380  // Call makeLayer with the config object! This implementation is more complete
381  // than just calling it with id and categorical attributes.
382  _layers.push_back( makeLayer( categ_layer_confs[i], categ_layer_refs[i] ) );
383  }
384 
385  for( unsigned int i = 0; i< cont_layer_confs.size(); i++ ) {
386 
387  // Call makeLayer with the config object! This implementation is more complete
388  // than just calling it with id and categorical attributes.
389  _layers.push_back( makeLayer( cont_layer_confs[i], cont_layer_refs[i] ) );
390  }
391 
392  // Assign mask
393  if ( mask_id.size() ) {
394 
395  loadLayers( mask_id, mask_ref, 0 );
396  _mask = makeLayer( mask_conf, mask_ref[0] );
397  }
398 
399  calcRegion();
400 }
401 
402 /*******************/
403 /*** load Layers ***/
404 void
405 EnvironmentImpl::loadLayers( const std::vector<string>& map_ids, std::vector<Map*>& map_refs, int categ )
406 {
407  bool unfinished_loading = true;
408  bool got_one = false;
409 
410  while ( unfinished_loading ) {
411 
412  unfinished_loading = false;
413  got_one = false;
414 
415  for( unsigned int i = 0; i< map_ids.size(); i++ ) {
416 
417  if ( map_refs[i] == 0 ) {
418 
419  try {
420 
421  map_refs[i] = new Map( RasterFactory::instance().create( map_ids[i], categ ) );
422  got_one = true;
423  }
424  catch ( RasterException& e ) {
425 
426  if ( e.getCode() == 1 ) {
427 
428  // layer is being downloaded by other process,
429  // so skip it for now and try others
430  unfinished_loading = true;
431  }
432  else {
433 
434  throw;
435  }
436  }
437  }
438  }
439 
440  if ( unfinished_loading && !got_one ) {
441 
442  Sleep(5000);
443  }
444  }
445 }
446 
447 /*********************/
448 /*** change Layers ***/
449 int
450 EnvironmentImpl::changeLayers( const std::vector<std::string>& categs,
451  const std::vector<std::string>& maps )
452 {
453  if ( ! (categs.size() + maps.size()) )
454  return 0;
455 
456  clearLayers();
457 
458  // STL maps with layer ids (unique) pointing to Map*s
459 
460  // categorical data
461  std::vector<Map*> categ_layer_refs;
462  for( unsigned int i = 0; i< categs.size(); i++ ) {
463 
464  categ_layer_refs.push_back(0);
465  }
466 
467  loadLayers( categs, categ_layer_refs, 1 );
468 
469  // continuous data
470  std::vector<Map*> cont_layer_refs;
471  for( unsigned int i = 0; i< maps.size(); i++ ) {
472 
473  cont_layer_refs.push_back(0);
474  }
475 
476  loadLayers( maps, cont_layer_refs, 0 );
477 
478  // Fill _layers attribute
479  for( unsigned int i = 0; i< categs.size(); i++ ) {
480 
481  _layers.push_back( makeLayer(categs[i], categ_layer_refs[i]) );
482  }
483 
484  for( unsigned int i = 0; i< maps.size(); i++ ) {
485 
486  _layers.push_back( makeLayer(maps[i], cont_layer_refs[i]) );
487  }
488 
489  calcRegion();
490 
491  return categs.size() + maps.size();
492 }
493 
494 
495 /*******************/
496 /*** change Mask ***/
497 int
498 EnvironmentImpl::changeMask( const std::string& mask_file )
499 {
500  int ret = 1;
501 
502  clearMask();
503 
504  // New mask
505  if ( !mask_file.empty() ) {
506 
507  bool unfinished_loading = true;
508 
509  while ( unfinished_loading ) {
510 
511  unfinished_loading = false;
512 
513  try {
514 
515  _mask = makeLayer( mask_file, 0 );
516  }
517  catch ( RasterException& e ) {
518 
519  if ( e.getCode() == 1 ) {
520 
521  // mask is being downloaded by other process
522  unfinished_loading = true;
523  Sleep(5000);
524  }
525  else {
526 
527  throw;
528  }
529  }
530  }
531 
532  if ( !_mask.second ) {
533 
534  ret = 0;
535  }
536  }
537 
538  calcRegion();
539 
540  return ret;
541 }
542 
543 
544 /******************************/
545 /*** num Categorical Layers ***/
546 size_t
548 {
549  size_t size = 0;
550 
551  layers::const_iterator lay = _layers.begin();
552  layers::const_iterator end = _layers.end();
553 
554  while ( lay != end && lay->second->isCategorical() ) {
555 
556  ++size;
557  ++lay;
558  }
559 
560  return size;
561 }
562 
563 
564 /*****************/
565 /*** get Type ***/
566 int
568 {
569  return _layers[i].second->isCategorical();
570 }
571 
572 
573 /******************/
574 /*** get MinMax ***/
575 void
577 {
578  int i = 0;
579 
580  layers::const_iterator lay = _layers.begin();
581  layers::const_iterator end = _layers.end();
582 
583  while ( lay != end ) {
584 
585  Map *map = lay->second;
586 
587  Scalar mapMin, mapMax;
588  map->getMinMax( &mapMin, &mapMax );
589  (*min)[i] = mapMin;
590  (*max)[i] = mapMax;
591 
592  ++lay;
593  i++;
594  }
595 }
596 
597 /*****************/
598 /*** normalize ***/
599 void
601 
602  if ( normalizerPtr ) {
603 
604  _normalizerPtr = normalizerPtr->getCopy();
605  }
606  else {
607 
609  }
610 }
611 
612 
613 /***************************/
614 /*** reset Normalization ***/
615 void
617 
618  if ( _normalizerPtr ) {
619 
620  delete _normalizerPtr;
621 
622  _normalizerPtr = 0;
623  }
624 }
625 
626 /*********************************/
627 /*** get Unnormalized Internal ***/
628 void
630 {
631  // layers and the mask, if possible.
632  if ( ! checkCoordinates( x, y ) ) {
633 #if defined(DEBUG_GET)
634  Log::instance()->debug( "EnvironmentImpl::get() Coordinate (%f,%f) is not in common region\n",x,y);
635 #endif
636  return;
637  }
638 
639  // Create the return value.
640  sample->resize( _layers.size() );
641 
642  // Read variables values from the layers.
643  layers::const_iterator lay = _layers.begin();
644  layers::const_iterator end = _layers.end();
645  Sample::iterator s = sample->begin();
646 
647  while ( lay != end ) {
648 
649  if ( ! lay->second->get( x, y, s ) ) {
650 #if defined(DEBUG_GET)
651  Log::instance()->debug( "EnvironmentImpl::get() Coordinate (%f,%f) does not have data in layer %s\n",x,y,lay->first.c_str());
652 #endif
653  sample->resize(0);
654  return;
655  }
656  ++lay;
657  ++s;
658  }
659 }
660 
661 Sample
663 {
664  Sample sample;
665  getUnnormalizedInternal( &sample, x, y );
666  return sample;
667 }
668 
669 Sample
671 {
672  Sample sample;
673  getUnnormalizedInternal( &sample, x, y);
674 
676 
677  if ( _normalizerPtr ) {
678 
679  _normalizerPtr->normalize( &sample );
680  }
681 
682  return sample;
683 }
684 
685 Sample
687 {
688  if ( _normalizerPtr ) {
689 
690  return getNormalized(x,y);
691  }
692  else {
693 
694  return getUnnormalized(x,y);
695  }
696 }
697 
698 Sample
700 {
701  Random myrand;
702  Coord x, y;
703 
704  Sample s;
705 
706  int max_loop = 5000;
707 
708  int loop = 0;
709 
710  do {
711 
712  x = myrand( _xmin, _xmax );
713  y = myrand( _ymin, _ymax );
714 
715  s = get( x, y );
716 
717  loop++;
718 
719  } while ( s.size() == 0 && loop < max_loop );
720 
721  if ( loop == max_loop ) {
722 
723  std::string msg = "Exceeded maximum number of attempts to generate pseudo point.\n";
724 
725  Log::instance()->error( msg.c_str() );
726 
727  throw OmException( msg );
728  }
729 
730  if ( xout != 0 )
731  *xout = x;
732  if ( yout != 0 )
733  *yout = y;
734 
735  return s;
736 }
737 
738 
739 /*************************/
740 /*** check Coordinates ***/
741 int
743 {
744  // Accept the point, regardless of mask, if
745  // it falls in a common region among all layers.
746  if ( x < _xmin || x > _xmax || y < _ymin || y > _ymax ) {
747 #if defined(DEBUG_GET)
748  Log::instance()->debug( "EnvironmentImpl::checkCoordinates() Coordinate (%f,%f) not in extent of all regions\n",x,y);
749 #endif
750 
751  return 0;
752  }
753 
754  // If there's no mask, accept the point.
755  if ( ! _mask.second ) {
756 
757  return 1;
758  }
759 
760  Scalar val;
761 
762  bool hasmaskevalue = ( _mask.second->get( x, y, &val ) > 0 );
763 
764  if ( ! hasmaskevalue ) {
765 #if defined(DEBUG_GET)
766  Log::instance()->debug( "EnvironmentImpl::check() Coordinate (%f,%f) has no mask value\n",x,y);
767 #endif
768  }
769 
770  return hasmaskevalue;
771 }
772 
773 
774 /******************/
775 /*** get Region ***/
776 int
777 EnvironmentImpl::getRegion( Coord *xmin, Coord *ymin, Coord *xmax, Coord *ymax ) const
778 {
779  *xmin = _xmin;
780  *ymin = _ymin;
781  *xmax = _xmax;
782  *ymax = _ymax;
783 
784  return 1;
785 }
786 
787 int
789 {
790  int nlayers = _layers.size();
791  min->resize( nlayers );
792  max->resize( nlayers );
793 
794  layers::const_iterator map = _layers.begin();
795 
796  for ( int i = 0; i < nlayers; i++ ) {
797  Scalar amin, amax;
798  map->second->getMinMax( &amin, &amax );
799  (*min)[i] = amin;
800  (*max)[i] = amax;
801  ++map;
802  }
803 
804  if ( _normalizerPtr ) {
805 
806  _normalizerPtr->normalize( min );
807  _normalizerPtr->normalize( max );
808  }
809 
810  return 1;
811 }
812 
813 
814 /*******************/
815 /*** calc Region ***/
816 void
818 {
819  Coord xmin, ymin, xmax, ymax;
820 
821  _xmin = _ymin = -MAXFLOAT;
822  _xmax = _ymax = MAXFLOAT;
823 
824  // The mask region is the default.
825  if ( _mask.second )
826  _mask.second->getExtent( &_xmin, &_ymin, &_xmax, &_ymax );
827 
828  // Crop region to fit all layers.
829  layers::const_iterator lay = _layers.begin();
830  layers::const_iterator end = _layers.end();
831  while ( lay != end ) {
832  lay->second->getExtent( &xmin, &ymin, &xmax, &ymax );
833  ++lay;
834 
835  if ( xmin > _xmin )
836  _xmin = xmin;
837 
838  if ( ymin > _ymin )
839  _ymin = ymin;
840 
841  if ( xmax < _xmax )
842  _xmax = xmax;
843 
844  if ( ymax < _ymax )
845  _ymax = ymax;
846  }
847 
848  if ( (_xmin >= _xmax) || ( _ymin >= _ymax ) ) {
849  Log::instance()->warn( "Maps intersection is empty (boundaries: xmin=%f, xmax=%f, ymin=%f, ymax=%f)\n", _xmin, _xmax, _ymin, _ymax );
850  }
851 }
852 
853 
854 /********************/
855 /*** remove Layer ***/
856 void
857 EnvironmentImpl::removeLayer(unsigned int index)
858 {
859  if ( index >= numLayers() ) {
860 
861  return;
862  }
863 
864  layers::iterator it = _layers.begin();
865 
866  unsigned int tmp = 0;
867 
868  while ( tmp < index ) {
869 
870  ++tmp;
871  ++it;
872  }
873 
874  _layers.erase( it );
875 
876  calcRegion();
877 }
EnvironmentImpl * clone() const
void getMinMax(Sample *min, Sample *max) const
void warn(const char *format,...)
'Warn' level.
Definition: Log.cpp:273
Normalizer * _normalizerPtr
Normalize the environment.
Definition: Environment.hh:230
void setCategoricalThreshold(std::size_t index)
Definition: Sample.cpp:191
std::vector< ConfigurationPtr > subsection_list
double Scalar
Type of map values.
Definition: om_defs.hh:39
void initialize(const std::vector< std::string > &categs, const std::vector< std::string > &maps, const std::string &mask_file="")
Sample getNormalized(Coord x, Coord y) const
int checkCoordinates(Coord x, Coord y) const
virtual ConfigurationPtr getConfiguration() const
std::pair< std::string, Map * > layer
Definition: Environment.hh:85
unsigned int numLayers() const
Definition: Environment.hh:108
void resetNormalization()
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Definition: Log.cpp:45
void removeLayer(unsigned int index)
Coord _xmin
Intersection of all layers.
Definition: Environment.hh:225
Sample getRandom(Coord *x=0, Coord *y=0) const
virtual void setConfiguration(const ConstConfigurationPtr &)
void getUnnormalizedInternal(Sample *, Coord x, Coord y) const
EnvironmentPtr createEnvironment(const std::vector< std::string > &categs, const std::vector< std::string > &maps, const std::string &mask_file)
Definition: Environment.cpp:55
Coord _ymax
Intersection of all layers.
Definition: Environment.hh:228
size_t numCategoricalLayers() const
#define Sleep(x)
Definition: os_specific.hh:70
iterator begin()
Definition: Sample.hh:87
void error(const char *format,...)
'Error' level.
Definition: Log.cpp:290
int getRegion(Coord *xmin, Coord *ymin, Coord *xmax, Coord *ymax) const
Definition: Random.hh:44
#define MAXFLOAT
Definition: Environment.cpp:45
Coord _xmax
Intersection of all layers.
Definition: Environment.hh:227
Coord _ymin
Intersection of all layers.
Definition: Environment.hh:226
void resize(std::size_t size)
Definition: Sample.cpp:153
#define UNUSED(symbol)
Definition: os_specific.hh:55
void normalize(Normalizer *normalizerPtr)
int isCategorical(int i)
virtual void normalize(Sample *samplePtr)=0
int getExtremes(Sample *min, Sample *max) const
int getMinMax(Scalar *min, Scalar *max) const
Definition: Map.hh:84
Definition: Map.hh:49
static ConfigurationPtr getLayerConfig(const layer &l, bool basicConfig=false)
Definition: Environment.cpp:87
Scalar * iterator
Definition: Sample.hh:86
static void loadLayers(const std::vector< std::string > &map_ids, std::vector< Map * > &map_refs, int categ=0)
std::size_t size() const
Definition: Sample.hh:70
static RasterFactory & instance()
ReferenceCountedPointer< EnvironmentImpl > EnvironmentPtr
Definition: Environment.hh:46
int changeLayers(const std::vector< std::string > &categs, const std::vector< std::string > &maps)
Sample getUnnormalized(Coord x, Coord y) const
double Coord
Type of map coordinates.
Definition: om_defs.hh:38
Sample get(Coord x, Coord y) const
layer _mask
Mask (can be 0).
Definition: Environment.hh:223
layers _layers
Vector with all layers that describe the variables.
Definition: Environment.hh:222
static layer makeLayer(const ConstConfigurationPtr &config, Map *map)
void debug(const char *format,...)
'Debug' level.
Definition: Log.cpp:237
int min(int v1, int v2)
Definition: rules_base.cpp:56
virtual Normalizer * getCopy()=0
int changeMask(const std::string &mask_file)
Definition: Sample.hh:25