openModeller  Version 1.5.0
request_file.cpp
Go to the documentation of this file.
1 
28 #include "request_file.hh"
29 
30 #include <openmodeller/om.hh>
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 
37 
38 /**************************************************************/
39 /************************ Request File ************************/
40 
42  _occurrencesSet(0),
43  _environmentSet(0),
44  _projectionSet(0),
45  _presences(),
46  _absences(),
47  _nonNativeProjection( false ),
48  _projectionCategoricalMap(),
49  _projectionMap(),
50  _inputMask(),
51  _outputMask(),
52  _inputModelFile(),
53  _outputModelFile(),
54  _projectionFile(),
55  _outputFormat(),
56  _spatiallyUnique( false ),
57  _environmentallyUnique( false ),
58  _calcConfusionMatrix( true ),
59  _calcAuc( true )
60 {
61 }
62 
64 {
65 }
66 
67 /*****************/
68 /*** configure ***/
69 int
70 RequestFile::configure( OpenModeller *om, char *request_file )
71 {
72  std::string input_file( request_file );
73  FileParser fp( input_file );
74 
75  _inputModelFile = fp.get( "Input model" );
76 
77  _occurrencesSet = _setOccurrences( om, fp );
78  _environmentSet = _setEnvironment( om, fp );
79 
80  // Optional sampler filters
81  std::string spatially_unique = fp.get( "Spatially unique" );
82 
83  if ( spatially_unique == "true" ) {
84 
85  _spatiallyUnique = true;
86  }
87 
88  std::string environmentally_unique = fp.get( "Environmentally unique" );
89 
90  if ( environmentally_unique == "true" ) {
91 
93  }
94 
95  // Optional model statistics
96  std::string confusion_matrix = fp.get( "Confusion matrix" );
97 
98  if ( confusion_matrix == "false" ) {
99 
100  _calcConfusionMatrix = false;
101  }
102 
103  std::string auc = fp.get( "AUC" );
104 
105  if ( auc == "false" ) {
106 
107  _calcAuc = false;
108  }
109 
110  _projectionSet = _setProjection ( om, fp );
111  _algorithmSet = _setAlgorithm ( om, fp );
112 
113  _outputModelFile = fp.get( "Output model" );
114 
115  // Returns ZERO if all was set correctly.
116  return 4 - _occurrencesSet - _environmentSet -
118 }
119 
120 
121 /***********************/
122 /*** set Occurrences ***/
123 int
125 {
126  // Obtain the Well Known Text string for the localities
127  // coordinate system.
128  std::string oc_cs = fp.get( "WKT coord system" );
129 
130  // Get the name of the file containing localities
131  std::string oc_file = fp.get( "Occurrences source" );
132 
133  if ( oc_file.empty() ) {
134 
135  oc_file = fp.get( "Species file" ); // backwards compatibility
136  }
137 
138  // Get the name of the taxon being modelled!
139  std::string oc_name = fp.get( "Occurrences group" );
140 
141  if ( oc_name.empty() ) {
142 
143  oc_name = fp.get( "Species" ); // backwards compatibility
144  }
145 
146  // If user provided a serialized model
147  if ( ! _inputModelFile.empty() ) {
148 
149  // Warn if unnecessary parameters were specified
150  if ( ! oc_cs.empty() )
151  Log::instance()->warn( "'WKT coord system' will be ignored since 'Input model' has been specified...\n" );
152 
153  if ( ! oc_file.empty() )
154  Log::instance()->warn( "'Occurrences source'/'Species file' will be ignored since 'Input model' has been specified...\n" );
155 
156  if ( ! oc_name.empty() )
157  Log::instance()->warn( "'Occurrences group'/'Species' will be ignored since 'Input model' has been specified...\n" );
158 
159  return 1;
160  }
161 
162  // When a model needs to be created, 'WKT coord system' and
163  // 'Species file' are mandatory parameters
164  if ( oc_cs.empty() ) {
165  Log::instance()->error( "'WKT coord system' keyword was not specified in the request file!\n" );
166  return 0;
167  }
168 
169  if ( oc_file.empty() ) {
170 
171  Log::instance()->error( "'Occurrences source' keyword was not specified in the request file!\n" );
172  return 0;
173  }
174 
175  // Populate the occurences list from the localities file
176  Log::instance()->info( "Reading occurrences...\r" );
177 
178  OccurrencesReader* oc_reader = OccurrencesFactory::instance().create( oc_file.c_str(), oc_cs.c_str() );
179 
180  _presences = oc_reader->getPresences( oc_name.c_str() );
181 
182  _absences = oc_reader->getAbsences( oc_name.c_str() );
183 
184  delete oc_reader;
185 
186  if ( _absences )
187  {
188  Log::instance()->info( "Reading occurrences...done\n" );
189 
190  return om->setOccurrences( _presences, _absences );
191  }
192  else if ( _presences ) {
193 
194  Log::instance()->info( "Reading occurrences...done\n" );
195  return om->setOccurrences( _presences );
196  }
197  else {
198 
199  Log::instance()->error( "Could not read any occurrences!\n" );
200 
201  return 0;
202  }
203 }
204 
205 
206 /***********************/
207 /*** set Environment ***/
208 int
210 {
211  // Mask to select the desired species occurrence points
212  _inputMask = fp.get( "Mask" );
213 
214  // Initiate the environment with all maps.
215  std::vector<std::string> cat = fp.getAll( "Categorical map" );
216  std::vector<std::string> map = fp.getAll( "Map" );
217 
218  // If user provided a serialized model
219  if ( ! _inputModelFile.empty() ) {
220 
221  // Warn if unnecessary parameters were specified
222  if ( ! _inputMask.empty() )
223  Log::instance()->warn( "'Mask' will be ignored since 'Input model' has been specified...\n" );
224 
225  if ( cat.size() > 0 )
226  Log::instance()->warn( "'Categorical map' will be ignored since 'Input model' has been specified...\n" );
227 
228  if ( map.size() > 0 )
229  Log::instance()->warn( "'Map' will be ignored since 'Input model' has been specified...\n" );
230 
231  return 1;
232  }
233 
234  // When a model needs to be created, there should be at least one input map
235  if ( ! (cat.size() + map.size()) ) {
236 
237  Log::instance()->error( "At least one 'Map' or 'Categorical map' needs to be specified!\n" );
238  return 0;
239  }
240 
241  // Mask is also mandatory
242  if ( _inputMask.empty() ) {
243  Log::instance()->error( "'Mask' was not specified!\n" );
244  return 0;
245  }
246 
247  // Set input environment
248  Log::instance()->info( "Reading layers...\r" );
249  om->setEnvironment( cat, map, _inputMask );
250  Log::instance()->info( "Reading layers...done\n" );
251 
252  return 1;
253 }
254 
255 
256 /**********************/
257 /*** set Projection ***/
258 int
260 {
261  _projectionFile = fp.get( "Output file" );
262 
263  if ( _projectionFile.empty() ) {
264 
265  Log::instance()->warn( "'Output file' was not specified.\n" );
266  return 1;
267  }
268 
269  // Categorical environmental maps and the number of these maps.
270  _projectionCategoricalMap = fp.getAll( "Categorical output map" );
271 
272  // Continuous environmental maps and the number of these maps.
273  _projectionMap = fp.getAll( "Output Map" );
274 
275  // If user provided a serialized model
276  if ( !_inputModelFile.empty() ) {
277 
278  // note: should we accept native projections using environment from serialized models?
279  _nonNativeProjection = true;
280 
281  // So, assume that in this case projection maps are mandatory.
282  if ( ! (_projectionCategoricalMap.size() + _projectionMap.size()) ) {
283 
284  Log::instance()->error( "At least one 'Output map' or 'Categorical output map' needs to be specified!\n" );
285  return 0;
286  }
287  }
288  else {
289 
290  // It is ok to not set the projection.
291  if ( ! (_projectionCategoricalMap.size() + _projectionMap.size()) ) {
292 
293  Log::instance()->info("Projection not set: using training Environment for projection\n");
294  _nonNativeProjection = false;
295  }
296  else {
297 
298  _nonNativeProjection = true;
299  }
300  }
301 
302  // Get the output mask
303  _outputMask = fp.get( "Output mask" );
304 
305  if ( _nonNativeProjection && _outputMask.empty() ) {
306 
307  Log::instance()->error( "'Output mask' was not specified!\n" );
308  return 0;
309  }
310 
311  // Template header to be used by the generated map
312  std::string format = fp.get( "Output format" );
313 
314  if ( ! format.empty() ) {
315 
316  _outputFormat = MapFormat( format.c_str() );
317  }
318 
319  // File type
320  std::string fileType = fp.get( "Output file type" );
321 
322  if ( ! fileType.empty() ) {
323 
324  _outputFormat.setFormat( fileType );
325  }
326 
327  // Overwrite output extent with values from mask
328  const std::string maskFile = ( _nonNativeProjection ) ? _outputMask.c_str() : _inputMask.c_str();
329 
330  Raster* mask = RasterFactory::instance().create( maskFile );
331 
332  Header h = mask->header();
333 
338 
339  delete mask;
340 
341  return 1;
342 }
343 
344 
345 /***********************/
346 /*** set Algorithm ***/
347 int
349 {
350  // Find out which model algorithm is to be used.
351  AlgMetadata const *metadata;
352  std::string alg_id = fp.get( "Algorithm" );
353 
354  // If user provided a serialized model
355  if ( ! _inputModelFile.empty() ) {
356  // Warn if unnecessary parameters were specified
357  if ( ! alg_id.empty() )
358  Log::instance()->warn( "'Algorithm' will be ignored since 'Input model' has been specified...\n" );
359 
360  return 1;
361  }
362 
363  // Note: console tries to get an algorithm from user input
364  // if it was not specified in the request file.
365  if ( alg_id.empty() )
366  return 0;
367 
368  // Try to use the algorithm specified in the request file.
369  // If it cannot be used, return 0.
370  try {
371 
372  // An exception here means that the algorithm wasn't found.
373  metadata = om->algorithmMetadata( alg_id.c_str() );
374  }
375  catch (...) {
376 
377  Log::instance()->error( "Algorithm '%s' specified in the request file was not found\n",
378  alg_id.c_str() );
379  return 0;
380  }
381 
382  // Obtain any model parameter specified in the request file.
383  // read parameters from file into req_param parameters
384  std::vector<std::string> req_param = fp.getAll( "Parameter" );
385 
386  // For resulting parameters storage.
387  int nparam = metadata->nparam;
388  AlgParameter *param = new AlgParameter[nparam];
389 
390  // Read from console the parameters not set by request
391  // file. Fills 'param' with all 'metadata->nparam' parameters
392  // set.
393  _readParameters( param, metadata, req_param );
394 
395  // Set the model algorithm to be used by the controller
396  int resp = om->setAlgorithm( metadata->id, nparam, param );
397 
398  if ( resp == 0 ) {
399 
400  Log::instance()->error( "Could not set the algorithm to be used\n" );
401  }
402 
403  delete[] param;
404 
405  return resp;
406 }
407 
408 /*********************/
409 /*** get Presences ***/
412 {
413  if ( ! _presences ) {
414 
415  Log::instance()->error( "Could not read occurrences from request file. Make sure 'Occurrences source' has been specified.\n" );
416  }
417 
418  return _presences;
419 }
420 
421 
422 /*********************/
423 /*** get Absences ***/
426 {
427  return _absences;
428 }
429 
430 /***********************/
431 /*** read Parameters ***/
432 int
434  AlgMetadata const *metadata,
435  std::vector<std::string> str_param )
436 {
437  AlgParamMetadata *param = metadata->param;
438  AlgParamMetadata *end = param + metadata->nparam;
439 
440  // For each algorithm parameter metadata...
441  for ( ; param < end; param++, result++ ) {
442 
443  // The resulting name is equal the name set in
444  // algorithm's metadata.
445  result->setId( param->id );
446 
447  // Read the resulting value from str_param.
448  std::string value = extractParameter( result->id(), str_param );
449 
450  // If the parameter is not referenced in the file, set it
451  // with the default value extracted from the parameter
452  // metadata.
453  if ( value.empty() )
454  value = param->typical;
455 
456  result->setValue( value.c_str() );
457  }
458 
459  return metadata->nparam;
460 }
461 
462 
463 /*************************/
464 /*** extract Parameter ***/
465 std::string
466 RequestFile::extractParameter( std::string const name,
467  std::vector<std::string> vet )
468 {
469  int length = name.length();
470  std::vector<std::string>::iterator it = vet.begin();
471  std::vector<std::string>::iterator end = vet.end();
472 
473  while ( it != end ) {
474 
475  if ( name == (*it).substr( 0, length ) ) {
476 
477  std::string value = (*it).substr( length );
478 
479  // Left trim the value
480  std::string::size_type pos = value.find_first_not_of(' ');
481 
482  if ( pos != std::string::npos ) {
483 
484  value.erase( 0, pos );
485  }
486 
487  return value;
488  }
489 
490  ++it;
491  }
492 
493  return "";
494 }
495 
496 /****************************/
497 /*** requested Projection ***/
498 bool
500 {
501  return ! _projectionFile.empty();
502 }
503 
504 /******************/
505 /*** make Model ***/
506 void
508 {
509  // No serialized model - create model with all settings from the request file
510  if ( _inputModelFile.empty() ) {
511 
512  // Apply sampler filters if requested by user
513  if ( _spatiallyUnique ) {
514 
515  SamplerPtr sampler = om->getSampler();
516 
517  if ( sampler ) {
518 
519  sampler->spatiallyUnique();
520  }
521  else {
522 
523  Log::instance()->warn( "Cannot set spatially unique filter: no sampler available\n" );
524  }
525  }
526 
527  if ( _environmentallyUnique ) {
528 
529  SamplerPtr sampler = om->getSampler();
530 
531  if ( sampler ) {
532 
533  sampler->environmentallyUnique();
534  }
535  else {
536 
537  Log::instance()->warn( "Cannot set environmentally unique filter: no sampler available\n" );
538  }
539  }
540  }
541  // If user provided a serialized model, just load it
542  else {
543 
544  Log::instance()->info( "Loading serialized model\n" );
545 
546  char* file_name = new char [_inputModelFile.size() + 1];
547  strcpy( file_name, _inputModelFile.c_str() );
548 
549  ConfigurationPtr conf = Configuration::readXml( file_name );
550 
551  om->setModelConfiguration( conf );
552 
553  delete[] file_name;
554 
555  return;
556  }
557 
558  // Build model
559  if ( ! om->createModel() ) {
560 
561  Log::instance()->error( "Error during model creation: %s\n", om->error() );
562  return;
563  }
564 
565  if ( calcConfusionMatrix() ) {
566 
567  // Calculate confusion matrix to store in the serialized model
568  om->getConfusionMatrix();
569  }
570 
571  if ( calcAuc() ) {
572 
573  // Calculate ROC curve to store in the serialized model
574  om->getRocCurve()->getTotalArea();
575  }
576 
577  // Serialize model, if requested
578  if ( _inputModelFile.empty() && ! _outputModelFile.empty() ) {
579 
580  char* file_name = new char [_outputModelFile.size() + 1];
581  strcpy( file_name, _outputModelFile.c_str() );
582 
584  Configuration::writeXml( cfg, file_name );
585 
586  delete[] file_name;
587  }
588 }
589 
590 
591 /***********************/
592 /*** make Projection ***/
593 void
595 {
596  if ( _projectionSet == 0 ) {
597 
598  Log::instance()->error( "Error during projection: Request not properly initialized\n" );
599  return;
600  }
601 
602  if ( !_nonNativeProjection ) {
603 
604  om->createMap( _projectionFile.c_str(), _outputFormat );
605  }
606  else {
607 
609 
610  om->createMap( env, _projectionFile.c_str(), _outputFormat );
611  }
612 }
int configure(OpenModeller *om, char *request_file)
void warn(const char *format,...)
'Warn' level.
Definition: Log.cpp:273
static ConfigurationPtr readXml(char const *filename)
bool calcConfusionMatrix()
Definition: request_file.hh:71
std::string _outputModelFile
Coord xmin
Definition: Header.hh:74
Coord xmax
Definition: Header.hh:76
const ConfusionMatrix *const getConfusionMatrix()
char * error()
void setValue(std::string const val)
Definition: AlgParameter.hh:68
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Definition: Log.cpp:45
std::string _projectionFile
static OccurrencesFactory & instance()
bool calcAuc()
Definition: request_file.hh:72
A common interface to rasters.
Definition: Raster.hh:44
ConfigurationPtr getModelConfiguration() const
virtual OccurrencesPtr getAbsences(const char *groupId)
std::string id
Identifier to be used by programmers.
Definition: AlgMetadata.hh:75
OccurrencesPtr _absences
bool _spatiallyUnique
EnvironmentPtr createEnvironment(const std::vector< std::string > &categs, const std::vector< std::string > &maps, const std::string &mask_file)
Definition: Environment.cpp:55
AlgParamMetadata * param
Definition: AlgMetadata.hh:91
int _setEnvironment(OpenModeller *om, FileParser &fp)
Definition: Header.hh:45
void makeModel(OpenModeller *om)
void setYMin(Coord ymin)
Definition: MapFormat.cpp:220
int createMap(const EnvironmentPtr &env, char const *output_file, MapFormat &format)
void error(const char *format,...)
'Error' level.
Definition: Log.cpp:290
OccurrencesPtr _presences
Definition: om_niche.cpp:54
OccurrencesPtr _absences
Definition: om_niche.cpp:55
Coord ymin
Definition: Header.hh:75
bool _calcConfusionMatrix
bool _environmentallyUnique
std::string _inputMask
virtual OccurrencesPtr getPresences(const char *groupId)
std::string typical
Typical parameter value.
Definition: AlgMetadata.hh:62
int setOccurrences(const OccurrencesPtr &presence, const OccurrencesPtr &absence=OccurrencesPtr())
Coord ymax
Definition: Header.hh:77
AlgMetadata const * algorithmMetadata(char const *algorithm_id)
int _readParameters(AlgParameter *result, AlgMetadata const *metadata, std::vector< std::string > str_param)
int _setOccurrences(OpenModeller *om, FileParser &fp)
std::string id
Identifier to be used by programmers.
Definition: AlgMetadata.hh:52
static void writeXml(const ConstConfigurationPtr &config, char const *fileaname)
OccurrencesPtr getAbsences()
std::vector< std::string > getAll(const std::string &key) const
Definition: FileParser.cpp:185
std::string _inputModelFile
int nparam
Number of parameters.
Definition: AlgMetadata.hh:89
static RasterFactory & instance()
int setAlgorithm(std::string const id, int nparam, AlgParameter const *param)
int _setAlgorithm(OpenModeller *om, FileParser &fp)
std::string const id() const
Definition: AlgParameter.hh:56
void setXMax(Coord xmax)
Definition: MapFormat.cpp:225
std::vector< std::string > _projectionMap
OccurrencesPtr getPresences()
MapFormat _outputFormat
bool _nonNativeProjection
int _setProjection(OpenModeller *om, FileParser &fp)
void setId(std::string const id)
Definition: AlgParameter.hh:59
void info(const char *format,...)
'Info' level.
Definition: Log.cpp:256
void setEnvironment(std::vector< std::string > categ_map, std::vector< std::string > continuous_map, const std::string &mask)
void setFormat(int format)
Definition: MapFormat.cpp:151
Raster * create(const string &source, int categ=0)
const SamplerPtr & getSampler() const
bool requestedProjection()
std::string extractParameter(std::string const name, std::vector< std::string > vet)
std::vector< std::string > _projectionCategoricalMap
Header & header()
Definition: Raster.hh:75
void makeProjection(OpenModeller *om)
RocCurve *const getRocCurve()
OccurrencesPtr _presences
std::string get(const std::string &key) const
Definition: FileParser.cpp:145
double getTotalArea()
Definition: RocCurve.cpp:602
void setXMin(Coord xmin)
Definition: MapFormat.cpp:215
void setYMax(Coord ymax)
Definition: MapFormat.cpp:230
std::string _outputMask
AlgMetadata metadata
Definition: garp.cpp:134
void setModelConfiguration(const ConstConfigurationPtr &)
OccurrencesReader * create(const char *source, const char *coordSystem)