Back to the table of contents|
Developing a new tool
Suppose you have a machine learning tool that you would like to add to Waffles. This page will walk you through the steps of adding your new tool.
- The first step is to decide which application is the best home for your tool. Let's suppose that you wish to add a new tool that transposes a dataset. (That is, it swaps the rows with the columns.) A tool like this probably belongs in the waffles_transform tool, so we'll put it there.
- Next, we dig into the source code. So, let's open waffles/src/transform/main.cpp in your favorite text editor. We know that execution begins with a function named "main", so search for this function. (It's at the very bottom.) You will see that this method contains a great big switch statement that looks something like this:
if(args.size() < 1) ThrowError("Expected a command");
else if(args.if_pop("add")) addMatrices(args);
else if(args.if_pop("addindexcolumn")) AddIndexAttribute(args);
else if(args.if_pop("addnoise")) addNoise(args);
else if(args.if_pop("aggregatecols")) aggregateCols(args);
else if(args.if_pop("aggregaterows")) aggregateRows(args);
else if(args.if_pop("align")) align(args);
else if(args.if_pop("autocorrelation")) autoCorrelation(args);
else if(args.if_pop("center")) center(args);
else if(args.if_pop("cholesky")) cholesky(args);
else if(args.if_pop("correlation")) correlation(args);
else if(args.if_pop("cumulativecolumns")) cumulativeColumns(args);
else if(args.if_pop("determinant")) determinant(args);
else if(args.if_pop("discretize")) Discretize(args);
This switch statement just tells it to execute the tool that is specified by the first argument to the application. Since we are going to add a new tool that transposes a matrix, we will add a new line like this:
else if(args.if_pop("transpose")) transpose(args);
- Now, we are ready to implement our tool. So, we add a function that transposes a matrix:
void Transpose(GArgReader& args)
GMatrix* pData = loadData(args.pop_string());
GMatrix* pTransposed = pData->transpose();
The first line in this function loads the dataset specified by the next command-line argument.
The second line constructs a "holder" object that will delete(pData) in its destructor. (This is better than just calling delete(pData) at the end of your function, because it will clean up the memory even if an exception is thrown.)
The third line is the one that really does the job. In this case, it was easy to implement because the GMatrix class already has a method that transposes the data.
The fourth line constructs a "holder" object that will delete(pTransposed) in its destructor.
The last line prints the transposed matrix to stdout.
- Then, rebuild Waffles, test your new tool, and fix your bugs. This tutorial cannot possibly tell you how to fix your bugs. You're just going to have to figure that part out on your own.
- Wait! You're not done. No tool is really complete until it is documented. The documentation for all of the tools in Waffles is found in "waffles/src/wizard/usage.cpp". So, let's open this file in your favorite text editor. You will see that it is a great big file containing lots of usage information. Basically, we are going to add an entry (just like all the others) for our new tool.
Since we put our new tool in the waffles_transform application, let's search for a function named "makeTransformUsageTree". This function contains all of the usage information for this tool. We add the following entry:
pRoot->add("transpose [dataset]=m.arff", "Transpose the data such that columns become rows and rows become columns.");
Now, re-build Waffles and enter:
You will see that your new tool is now described in the usage information of the waffles_transform tool. If you use Linux, BASH command-completion should also now work automatically with your new tool. (How slick is that!?)
Finally, don't forget to push your changes into our Git repository. You want the whole world to have your new tool, right?
Back to the table of contents