The Initialize Function


aboucher - Posted on 10 April 2009

The initialize function is passed two arguments: a list of all parameters input by the user and an object to which errors in the parameters are reported. The aim of the function is to initialize the member variables identified when implemented the execute function. Errors in the parameters are reported to the errors handler object. In order to retrieve the value of a parameter, it is necessary to know the parameter keyword and attributes. The keywords were input to Designer, but the attribute names are imposed by the Designer widgets.

For example, a QLineEdit parameter has a single attribute called value. An InputVariogram widget has a nb_of_structures and a nugget_effect attribute. In order to know the attribute names, the easiest solution is to compile the plug-in (only the name and create_new_interface functions have to be defined for the plug-in to loaded by SGeMS), start SGeMS, select the new algorithm input some parameters and save them to a file. The saved parameter file will contain all parameters with their keywords and attributes.

Once the keywords and attributes are known, it is possible to extract the parameter values and initialize the parameters of the algorithm.
Following is the initialize function for the MovingAverage class:


bool MovingAverage::initialize( const Parameters_handler* parameters,
                        Error_messages_handler* errors ) {
 
  // get the name of the grid we will work on
  std::string grid_name =
    parameters->value( "Simul_Grid.value" );

  // use utility function "create" to initialize our grid_ pointer.
  // "create" will retrieve the address of grid "grid_name" and set pointer
  // grid_ to point to the requested grid. If the requested grid does not
  // exist, the function return false;
  bool ok = geostat_utils::create( grid_, grid_name, "Simul_Grid", errors );
  if( !ok ) return false;

  // get the name of the property we will work on
  std::string property_name =
    parameters->value( "Hdata_Property.value" );
 
GsTLGridProperty* prop = grid_->property( property_name );
  errors->report( prop==0, "
Hdata_Property", "no such property in selected grid" );

  // get the name of the new property that will contain the result
  std::string new_property_name =
    parameters->value( "Simul_Property.value" );
 
  // tell the grid to add a new property
  // If the name of the new property is already used, the grid won't add
  // the new property. Utility function "add_property_to_grid" makes sure
  // that the name of the new property is unique (if the name input by the
  // user is already used, "add_property_to_grid" modifies that name to make
  // it unique).
  GsTLGridProperty* new_property =
    geostat_utils::add_property_to_grid( grid_, new_property_name );

  // get the 3 anisotropy ranges. The 3 numbers are in a single string and
  // need to be converted into numbers (float).
  std::string ranges_str =
    parameters->value( "Ranges.value" );

  // function "to_number" will convert the string into a vector of numbers
  // vector ranges will then contain all the number in string "ranges_str"
  std::vector<float> ranges = String_Op::to_numbers<float>( ranges_str );
 
  // tell the grid to create a new neighborhood
  neighborhood_ = grid_->neighborhood( ranges[0], ranges[1], ranges[2],
                                       0, 0, 0 );

  // set-up the neighborhood: max_size() set the maximum number of neighbors
  // to consider, select_property tells the neighborhood which property to
  // work on, and includes_center tells the neighborhood to consider the center
  // of the neighborhood as a neighbor: if we search for neighbors of node u,
  // u will be one of the neighbors of u.
  neighborhood_->max_size( 100000 );
  neighborhood_->select_property( property_name );
  neighborhood_->includes_center( true );

  // tell the grid to work on the new property
  grid_->select_property( new_property->name() );

  if( !errors->empty() ) return false;

  return true;

 

The initiliaze function returns true if everything was fine, false otherwise.

The name function

The name function simply returns the name of the algorithm. Note that the ".ui" file must be the same as the algorithm name. For example, if the name function returns "moving_average", the interface file must be called "moving_average.ui".

The create_new_interface function

This is a static function that creates a new instance of the algorithm object. For example, in the case of MovingAverage:


Named_interface* MovingAverage::create_new_interface( std::string& ) {
  return new MovingAverage;
}




Final Step

The last step is to add the GEOSTAT_PLUGIN macro at the end of the implementation file (.cpp). The macro takes as argument the name of the class that defines the new algorithm:


Named_interface* MovingAverage::create_new_interface( std::string& ) {
  return new MovingAverage;
}

GEOSTAT_PLUGIN(MovingAverage);



Compile the C++ files to obtain a .so (or .dll) library file and place it along with the .ui file into the plugins/Geostat directory.

Of course, it is possible to define several algorithms into a single plug-in. The plug-in will then be composed of a .so (or .dll) file and one .ui file for each algorithm. To define several algorithms into a single plug-in, define a function called plugin_init as extern "C" in one of your .cpp files (this file must include all the files defining the algorithms to be included into the plug-in). Then use macro BIND_GEOSTAT_ALGO to add each algorithm. The maccro is defined in <GsTLAppli/utils/gstl_plugins.h>. For example, if we have 2 algorithms implemented in classes MovingAverage and CubicSmoothing, add the following function to one of the cpp files:



extern "C" int plugin_init() {
  BIND_GEOSTAT_ALGO( MovingAverage );
  
BIND_GEOSTAT_ALGO( CubicSmoothing );
  return 0;
}