Archive for September 14th, 2009

Bio++ and namespaces

Monday, September 14th, 2009

My RSI is acting up these days, so it will be a little while before I continue my tutorial on Bio++, but there is just a few more things I want to share with you from the Utils library.  Well, the first thing is something that I think should be in the Utils library but really isn’t so I am going to implement it here and lobby to get it in…

Parameter namespaces

In my last post I talked about parameter parsing, but one thing I didn’t cover was namespaces.  I knew that there was some support for this, but just couldn’t find it in the library.

I had a talk with Julien today about it, and it turns out that it is hidden in the NumCalc library as part of their “function” concept and that is why I couldn’t find it in Utils.

Anyway, using the namespace implementation in NumCalc is a bit complicated and requires that you implement a Parametrizable object, so not something you would use for general option parsing, so I have my own take on it here.

But first let me explain how namespaces work in Bio++.

It is just a convention, really, but the idea is that you have options separated by dots.  It looks similar to attributes of objects in this way, but it is really just handled as long strings and the dots do not have any special meaning in how the options are parsed.

Anyway, if you have some sub-system of your application, say a substitution model with two parameters, you can call your model “foo” and define the two parameters, bar and baz, to it as

foo.bar = barValue
foo.baz = bazValue

in your options file or on the command line.

The prefix is then used to avoid name collisions with other models or sub-components with parameters bar and baz.

To read the options you can use their full name in calls to the ApplicationTools:

bpp::ApplicationTools::getStringParameter("foo.bar", parameters, "default");

Not really a problem, but if you need to change the name of your module later, say if it collides with another model using the same prefix, you would need to change the prefix all the places you access the parameter.

A better solution is to define the namespace once and just refer to the parameters enclosed in it.

The code below does exactly that.  It simply defines a function for extracting from the general parameters list all the parameters with a given prefix – “foo.” in this case – and puts it in a separate parameters list.

#include <Utils/ApplicationTools.h>
#include <Utils/AttributesTools.h>

namespace bpp {  namespace namespace_tools {
  // just to make it easier on the typing...
  typedef std::map< std::string, std::string >  ParameterMap;

  ParameterMap extractNamespace(const std::string nameSpaceName,
                                const ParameterMap &params)
  {
    ParameterMap newNameSpace;
    unsigned int nameLength = nameSpaceName.size();

    ParameterMap::const_iterator itr;
    for (itr = params.begin(); itr != params.end(); ++itr) {
      if (bpp::TextTools::startsWith(itr->first, nameSpaceName)) {
        std::string newName = itr->first.substr(nameLength+1, itr->first.size());
        newNameSpace[newName] = itr->second;
    }
  }
  return newNameSpace;
 }
}}

int main(int argc, char * argv[])
{
  using namespace bpp;
  using namespace bpp::namespace_tools;
  using namespace std;

  map< string, string > parameters;
  parameters = AttributesTools::parseOptions(argc, argv);

  string bar = ApplicationTools::getStringParameter("bar", parameters, "default");
  ApplicationTools::displayResult("Parameter 'bar'", bar);

  string foobar = ApplicationTools::getStringParameter("foo.bar", parameters, "default");
  ApplicationTools::displayResult("Parameter 'foo.bar'", foobar);

  map< string, string > fooParameters = extractNamespace("foo", parameters);
  string nsBar = ApplicationTools::getStringParameter("bar", fooParameters, "default");

  ApplicationTools::displayMessage("Names in namespace 'foo':");
  map< string, string >::const_iterator itr;
  for (itr = fooParameters.begin(); itr != fooParameters.end(); ++itr) {
    ApplicationTools::displayResult(itr->first, itr->second);
  }

  return 0;
}

I’ve put the function in a (C++) namespace instead of a static class, but I guess that is just a matter of taste.

Running the program – using just command line arguments here instead of an options file – looks like this:

$ ./build/Debug/ParameterNamespaces bar=qux foo.bar=qax foo.qux=quux
Parameter 'bar'........................: qux
Parameter 'foo.bar'....................: qax
Names in namespace 'foo':
bar....................................: qax
qux....................................: quux

“Procedure” parameters

Another nice approach to namespaces – that is implemented in the Utils library – is “procedure” arguments.

They give you a way of both choosing a model and at the same time providing arguments to it.

So say you have the choice between two methods for a given sub-module, “foo” and “bar”, where these take different parameters.  You can choose the method and set arguments like this:

method = foo(a=1,b=1)

or

method = bar(c=3.14)

and parse it up in the code like this:

#include <Utils/ApplicationTools.h>
#include <Utils/AttributesTools.h>
#include <Utils/KeyvalTools.h>

int main(int argc, char * argv[])
{
  using namespace bpp;
  using namespace std;

  map< string, string > parameters;
  parameters = AttributesTools::parseOptions(argc, argv);

  string model = ApplicationTools::getStringParameter("model", parameters, "foo");
  string modelName;
  map<string, string> modelArgs;
  KeyvalTools::parseProcedure(model, modelName, modelArgs);

  std::cout << "The model was " << modelName << '.' << std::endl;

  if (modelName == "foo") {
    int a = ApplicationTools::getIntParameter("a", modelArgs, 0);
    int b = ApplicationTools::getIntParameter("b", modelArgs, 0);
    std::cout << "You chose foo(" << a << ',' << b << ')' << std::endl;
  } else if (modelName == "bar") {
    double c = ApplicationTools::getDoubleParameter("c", modelArgs, 0.0);
    std::cout << "You chose bar(" << c << ')' << std::endl;
  } else {
    cerr << "Unknown model: " << model << '.' << std::endl;
  }

  return 0;
}

You then use the program like this:

$ ./build/Debug/ParameterNamespaces "model=foo(a=1,b=2)"
The model was foo.
You chose foo(1,2)
$ ./build/Debug/ParameterNamespaces "model=bar(c=3.14)"
The model was bar.
You chose bar(3.14)
$ ./build/Debug/ParameterNamespaces "model=qux(d=42)"
The model was qux.
Unknown model: qux(d=42).

Nice, eh?

257-288=-31

Missing links

Monday, September 14th, 2009

…no, not transitional forms, but you are excused for thinking that ;-)

No, this post is just the three links I wanted to include in my weekly summary this morning, but couldn’t get to because MulticoreInfo was down:

257-287=-30

Last week in the blogs

Monday, September 14th, 2009

Evolution

Programming

Research life

Science

Teaching

257-286=-29