Contents

hide

5.1 Building a C++ plugin

This section is probably not up-to-date... to be revised.

Implementing your inversion problem in C++ is probably the best choice to enjoy the best performances and the full features of Dinver. An example of a basic inversion plugin is provided in Sesarray package called dinvercpp.

This chapter is divided in three sections:

Demo of the plugin in dinver framework

TODO

Code explanations

All files details here below are located in dinvercpp/src.

An inversion plugin contains basically two objects:

Inside project dinvercpp, these two objects are implemented in file <rastrigin.cpp>

The interface object

The interface object implements the dynamic link between the misfit computation and dinver graphical user interface.

Minimal definition of interface object
#include <math.h>
#include <QObject>
#include <qplugin.h>
#include "qtbdinverinterface.h"
#include "dinvercppversion.h"

class QtbCppPlugin: public QObject, public QtbDinverInterface
{
  Q_OBJECT
  Q_INTERFACES( QtbDinverInterface );
public:
  virtual QString tag() const;
  virtual QString title() const;
  virtual QString version() const;
  virtual QtbInversionThread * createNewThread(bool doInitialize);
};

// Unique tag to identify in .report files models generated by this plugin.
QString QtbCppPlugin::tag() const
{
  return "DinverCpp";
}

// User friendly title, displayed at Dinver startup.
QString QtbCppPlugin::title() const
{
  return tr("C++ template");
}

// Version of the plugin
QString QtbCppPlugin::version() const
{
  return DINVERCPP_VERSION;
}

// Create the inversion object and set parameter space
QtbInversionThread * QtbCppPlugin::createNewThread(bool doInitialize)
{
  if (!doInitialize) return new QtbCppInversion;
  QtbInversionThread * t=new QtbCppInversion;
  /* The Rastrigin function 2D is used as an example

     F(X) = A n + Sum [i=1,...,n] xi^2-A cos ( w xi )

     We use:
       n = 2
       A = 10
       -5 < xi > 5

     Two parameters: x1 and x2, from -5 to 5
     We impose that x<y, further on we also use a secondary complex condition that [x, y] must be inside circle
     of radius 5, hence x1^2+x2^2<25. The last condition is checked during misfit computation.
  */
  QtbParam * x1Param = t->addParam( "x1", "", -5.0, 5.0 );
  QtbParam * x2Param = t->addParam( "x2", "", -5.0, 5.0 );
  x1Param->addCondition( QtbParamCondition::LessThan, 1.0, x2Param, -2.0 );

  // Build parameter space with only the variable parameters
  t->setVariableParam();

  /* In this case the misfit value is directly given by the Rastrigin's Function
     Usually, it is also necessary to initialize or load a target curve, the misfit being calculated for instance
     with a Root Mean Square
  */

  if (t->checkParam()) {
    return t;
  } else {
    delete t;
    return 0;
  }
}

// Qt macro to define this library as a plugin
Q_EXPORT_PLUGIN2( dinvercpp, QtbCppPlugin );

The inversion object

This object is responsible for the computation of the misfit value. Usually it is also used for storing the reference curves (if any) necessary for the misfit computation. In this case, other member function might be usefull (constructor, destructor, save/restore target from XML stream,...).

Minimal definition of inversion object
#include "qtbinversionthread.h"

class QtbCppInversion : public QtbInversionThread
{
protected:
  virtual double misfit(double * model, bool& ok);
};

// na_model is a vector of nDimensions() containing parameter values
double QtbCppInversion::misfit( double * na_model, bool& ok )
{
  // Check complex condition
  if ( na_model[0]*na_model[0]+na_model[1]*na_model[1] >= 25.0 ) {
    ok = false;
    return 0.0;
  }

  // Compute misfit value
  double misfit = 20.0;
  for (int i = 0; i<2; i++ ) {
    misfit += na_model[i]*na_model[i] - 10 * cos ( 2 * M_PI * na_model[i] );
  }
  
  return misfit;
}

Creating a new plugin

If you are confortable with Qt, you can ignore this section. However, some features of the method described here below might be of interest. [TODO: do not refer to devpro, instead use directly qmake tool, the rest of paragraph is outdated]. First of all, download and install devpro scripts.

Creating a new project
$ mkdir yourpluginname
$ cd yourpluginname
$ dpinit
Current directory: /home/mwathele/yourpluginname
Create a new project in this directory? (yes/no) [no] yes
Organisation name: [geopsy] yourcompany
Package name: [yourpluginname] yourpluginname
Copyright: [Copyright © 2006 Marc Wathelet. All rights reserved.] Copyright © 2006 Your Name. All rights reserved.
Contact paragraph in headers: [See http://www.geopsy.org or contact ...] See your our site or contact our mail for more information
Mail for bugs reports : [bug@yourdomain.org] your mail
Web site for bugs reports : [https://bug.geopsy.org] your web site
Template? app | lib [app]lib
Console? yes | no [no]no
Has share files to add to distribution? yes | no [no]no
Has internationalisation files to add to distribution? yes | no [no]yes
...
$ ./configure  -prefix "/usr/local/sesarray" -debug
$ dstableh                      # build src/stable.h file for precompiled headers
                                # takes all includes from Qt within < > to
				# optimize compilation.

Now that you have a skeleton project, you can create two objects, one for the plugin interface and another one for the initialization and the misfit computation (see above example for more information).

Adding new objects to the project
$ dpclass
Enter class name:
QtbCppInversion
Enter the list of inherited objects, one per line
(format: public|private|protected object1name):
public QtbInversionThread

QtbCppInversion is ready to use
$ dpclass
Enter class name:
QtbCppPlugin
Enter the list of inherited objects, one per line
(format: public|private|protected object1name):
public QObject
public QtbDinverInterface

QtbCppInversion is ready to use
$ dpconfigure   # re-configure and add these objects to the project

Implement the functions as in the example above. Before compilation and linking you must set the necessary library dependencies.

Setting minimal library dependencies
$ cat ../dinvercpp/share/admin/info   # an example of minimal dependencies
...
EXTLIBS="-lqtbdebugtools -lqtbtools -ldinvercore"
WIN_EXTLIBS="-lqtbdebugtools0 -lqtbtools1 -ldinvercore1"
$ vi admin/info
...
EXTLIBS="-lqtbdebugtools -lqtbtools -ldinvercore"
WIN_EXTLIBS="-lqtbdebugtools0 -lqtbtools1 -ldinvercore1"
$ dpconfigure
$ make
$ make install

If the installation path set by option "-prefix" is the same as dinver or if the installation path is listed in dinver's search paths, you should see your new library into the list of available plugins. On the first time, you must refresh the list by clicking on "search". To generate a package ready for free distribution (mandatory step to conform with GPL terms):

Generating distribution package
$ dpdist

A .tar.gz file is ready in directory dist.