<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2153282598923359387</id><updated>2011-12-03T01:20:46.684Z</updated><category term='ruby'/><category term='clustering'/><category term='gvim'/><category term='LibSVM'/><category term='jfreechart'/><category term='programming'/><category term='WEKA'/><category term='GNU GSL'/><category term='RSRuby'/><category term='svm_toolkit'/><category term='XML'/><category term='graphs'/><category term='jruby'/><category term='statistics'/><category term='sciruby'/><category term='wxruby'/><category term='netbeans'/><category term='R'/><category term='Octave'/><title type='text'>Ruby for Scientific Research</title><subtitle type='html'>Using Ruby with open-source software for scientific research.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-5924809983522202254</id><published>2011-12-03T00:16:00.004Z</published><updated>2011-12-03T01:20:46.694Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='svm_toolkit'/><title type='text'>Customised evaluators in svm_toolkit</title><content type='html'>A new version of &lt;a href="https://rubygems.org/gems/svm_toolkit"&gt;svm_toolkit&lt;/a&gt; today, and I've bumped this to version 1.0.0, as it includes the main functionality I need for now.  The biggest change is support for customised methods for evaluating a model against a dataset.&lt;br /&gt;&lt;br /&gt;Why are different evaluations methods needed?  For many real-world datasets, simply measuring overall accuracy will not produce the most useful models.  This is usually the case when the  dataset has an imbalanced distribution of classes.  For example, consider a test dataset with 900 positive instances and 100 negative instances.  If the model puts every instance into the positive class, it gets 90% correct.  However, the model is useless, as it gives no information about the negative class.&lt;br /&gt;&lt;br /&gt;The geometric mean is one way to give each class equal prominence, irrespective of the frequency of instances of that class.  The geometric mean first computes the accuracy of each class separately, multiplies them together and takes the nth root (where n is the number of classes).  In the example above, the geometric mean would come out as zero, the worst score possible, because none of the negative instances are correctly classified by the model.  Precision and recall are evaluation measures which highlight the performance of one class, usually the minority class.&lt;br /&gt;&lt;br /&gt;The cross-validation process must select a model using an evaluation technique appropriate to the domain if the model is going to be useful in later tests.  For example, in information retrieval the best choice may be to find a model with the best recall of the minority class, as the model is more likely to  pick out all members of the class of interest, even if these are mixed with many instances from the other class.&lt;br /&gt;&lt;br /&gt;Four evaluation types are currently provided with the svm_toolkit:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Evaluator::OverallAccuracy, to compute the proportion of correctly classified instances.&lt;/li&gt;&lt;li&gt;Evaluator::GeometricMean, to compute the geometric mean of the accuracy of each separate class.&lt;/li&gt;&lt;li&gt;Evaluator::ClassPrecision(class), to compute the precision of the model for the given class.&lt;/li&gt;&lt;li&gt;Evaluator::ClassRecall(class), to compute the recall of the model for the given class.&lt;/li&gt;&lt;/ol&gt;The first two are class names, and the second are methods which generate class definitions for the given class label.  They are used by passing them to the new &lt;span style="font-family: courier new;"&gt;:evaluator&lt;/span&gt; parameter in &lt;span style="font-family: courier new;"&gt;evaluate_dataset&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;cross_validation_search&lt;/span&gt;, as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# evaluate based on Overall Accuracy&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;puts model&lt;font color="#990000"&gt;.&lt;/font&gt;evaluate_dataset&lt;font color="#990000"&gt;(&lt;/font&gt;Dataset&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;evaluator &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Evaluator&lt;font color="#990000"&gt;::&lt;/font&gt;OverallAccuracy&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# evaluate based on geometric mean of accuracies for separate classes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;puts model&lt;font color="#990000"&gt;.&lt;/font&gt;evaluate_dataset&lt;font color="#990000"&gt;(&lt;/font&gt;Dataset&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;evaluator &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Evaluator&lt;font color="#990000"&gt;::&lt;/font&gt;GeometricMean&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# evaluate based on precision of class labelled 1&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;puts model&lt;font color="#990000"&gt;.&lt;/font&gt;evaluate_dataset&lt;font color="#990000"&gt;(&lt;/font&gt;Dataset&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;evaluator &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Evaluator&lt;font color="#990000"&gt;::&lt;/font&gt;ClassPrecision&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# evaluate based on recall of class labelled 1&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;puts model&lt;font color="#990000"&gt;.&lt;/font&gt;evaluate_dataset&lt;font color="#990000"&gt;(&lt;/font&gt;Dataset&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;evaluator &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Evaluator&lt;font color="#990000"&gt;::&lt;/font&gt;ClassRecall&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;User-Defined Evaluators&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;It is easy to define a new evaluator class.  The class must support the following methods:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;add_result(actual, prediction)&lt;/span&gt;&lt;/span&gt;, which is called with the actual and predicted classification for every instance in the dataset.&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;value&lt;/span&gt;, to retrieve a number giving the performance of the model.&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;better_than?(eval)&lt;/span&gt;&lt;/span&gt;,  to compare this evaluation with a given one (which may be nil), returning true if the model yielding this evaluation should be kept over the given one.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;For example, the class for OverallAccuracy is implemented as:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Measures accuracy as the percentage of instances &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# correctly classified out of all the available instances.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; OverallAccuracy &lt;br /&gt;    attr_reader &lt;font color="#990000"&gt;:&lt;/font&gt;num_correct&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;      &lt;font color="#009900"&gt;@num_correct&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;      &lt;font color="#009900"&gt;@total&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# As each instance result is added, store the total number &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# of instances and the number of correct predictions.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; add_result&lt;font color="#990000"&gt;(&lt;/font&gt;actual&lt;font color="#990000"&gt;,&lt;/font&gt; prediction&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;      &lt;font color="#009900"&gt;@total&lt;/font&gt; &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;      &lt;font color="#009900"&gt;@num_correct&lt;/font&gt; &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; prediction &lt;font color="#990000"&gt;==&lt;/font&gt; actual&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# This object is better than given object, if the &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# given object is an instance of nil, or the accuracy &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# is better&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; better_than? other&lt;br /&gt;      other&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;?&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;or&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;value &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; other&lt;font color="#990000"&gt;.&lt;/font&gt;value&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# Return the accuracy as a percentage.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; value&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@total&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;zero? &lt;br /&gt;        &lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;else&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;        &lt;font color="#993399"&gt;100.0&lt;/font&gt; &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#009900"&gt;@num_correct&lt;/font&gt; &lt;font color="#990000"&gt;/&lt;/font&gt; &lt;font color="#009900"&gt;@total&lt;/font&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; to_s&lt;br /&gt;      &lt;font color="#FF0000"&gt;"Overall accuracy: #{value}%"&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Finding the Best Model&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The process of finding a good model with a radial-basis function (RBF) kernel is fairly straightforward.  Once the training and cross-validation sets have been created, and lists of cost and gamma values created to search over, the best model can be found using:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;best_model &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;cross_validation_search&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;  TrainingData&lt;font color="#990000"&gt;,&lt;/font&gt; CrossSet&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  Costs&lt;font color="#990000"&gt;,&lt;/font&gt; Gammas&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;show_plot &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;evaluator &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Evaluator&lt;font color="#990000"&gt;::&lt;/font&gt;GeometricMean&lt;br /&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-family: courier new;"&gt;:show_plot&lt;/span&gt; parameter is given if you want a contour plot of the grid search results.  The &lt;span style="font-family: courier new;"&gt;:evaluator&lt;/span&gt; parameter is used to give the class name of the evaluation technique to use in evaluating the models on the cross-validation set.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-5924809983522202254?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/5924809983522202254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/12/customised-evaluators-in-svmtoolkit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5924809983522202254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5924809983522202254'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/12/customised-evaluators-in-svmtoolkit.html' title='Customised evaluators in svm_toolkit'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4017360822072277610</id><published>2011-11-22T17:18:00.006Z</published><updated>2011-11-22T17:46:39.984Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='svm_toolkit'/><title type='text'>Demo program for svm_toolkit</title><content type='html'>Support vector machines are a complex learning algorithm, and simple visualisations can help in understanding the effects of the different parameters.  The libsvm website contains an applet, which lets you see how changing parameters can change the models created for a simple two-dimensional classification task.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;svm_toolkit&lt;/span&gt; now includes a program &lt;span style="font-style: italic;"&gt;svm-demo&lt;/span&gt;, which recreates the libsvm applet  as a simple application, coded in jruby.  The main display, as with libsvm's applet, allows the user to click on a window to enter instances of different classes.  Some controls on the right allow the user to set up a kernel and  parameters: there are separate fields for entering the &lt;span style="font-style: italic;"&gt;cost&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;gamma&lt;/span&gt; values, and a spinner box for selecting a value for &lt;span style="font-style: italic;"&gt;degree&lt;/span&gt;.  Once set up, a click on &lt;span style="font-style: italic;"&gt;train&lt;/span&gt; updates the display, colouring the background to show which regions are considered as falling in which class.&lt;br /&gt;&lt;br /&gt;Below are two screen shots.  Both contain the same set of instances: a cluster of blue dots surrounded by some green ones.  And in both we use the RBF kernel.&lt;br /&gt;&lt;br /&gt;The first has a value for cost of 1, and a value for gamma of 1:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-DekU6ORMu38/TsvdFn5BxGI/AAAAAAAAAZQ/EcyNPFIjCwk/s1600/demo-1.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 472px; height: 269px;" src="http://1.bp.blogspot.com/-DekU6ORMu38/TsvdFn5BxGI/AAAAAAAAAZQ/EcyNPFIjCwk/s320/demo-1.png" alt="" id="BLOGGER_PHOTO_ID_5677874843907900514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Notice how the decision boundary is curved, but is still not very  different from a straight line. The boundary makes three errors: one blue dot is in the green region, and two green dots are in the blue region.  We can force the boundary to take more account of errors, by increasing cost, and also to take on a more complicated shape, by increasing gamma.  The second example has a value for cost of 10, and a value for gamma of 10:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-iGyHAoIRUs8/TsvdOrQQLjI/AAAAAAAAAZc/oJlK4qwRksQ/s1600/demo-2.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 464px; height: 265px;" src="http://4.bp.blogspot.com/-iGyHAoIRUs8/TsvdOrQQLjI/AAAAAAAAAZc/oJlK4qwRksQ/s320/demo-2.png" alt="" id="BLOGGER_PHOTO_ID_5677874999429443122" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Notice how the area marked for blue is now almost circular: as the value for gamma is increased, the RBF kernel can generate increasingly complex decision boundaries.  Now, the model does not make any errors on the training data.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;gamma&lt;/span&gt; parameter is only used by the RBF and sigmoid kernels, and the &lt;span style="font-style: italic;"&gt;degree&lt;/span&gt; parameter is only used by the polynomial kernel. Below is an example of using the polynomial kernel:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-T8-2_gPTxws/TsveSqsBo5I/AAAAAAAAAZo/8bQ1v6JHp_I/s1600/demo-3.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 442px; height: 252px;" src="http://1.bp.blogspot.com/-T8-2_gPTxws/TsveSqsBo5I/AAAAAAAAAZo/8bQ1v6JHp_I/s320/demo-3.png" alt="" id="BLOGGER_PHOTO_ID_5677876167508599698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;When you install &lt;span style="font-style: italic;"&gt;svm_toolkit&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;svm-demo&lt;/span&gt; is made available on the same path as &lt;span style="font-style: italic;"&gt;jruby&lt;/span&gt;, and so it should be easy to run from the command line.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4017360822072277610?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4017360822072277610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/demo-program-for-svmtoolkit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4017360822072277610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4017360822072277610'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/demo-program-for-svmtoolkit.html' title='Demo program for svm_toolkit'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-DekU6ORMu38/TsvdFn5BxGI/AAAAAAAAAZQ/EcyNPFIjCwk/s72-c/demo-1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-6305741741169780190</id><published>2011-11-19T18:35:00.002Z</published><updated>2011-11-19T19:00:46.918Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='svm_toolkit'/><title type='text'>Creating RBF models with svm_toolkit</title><content type='html'>Support-vector machine models are very sensitive to their parameter settings.  When creating a model, we need to test a range of parameters and select the parameters which give the best generalisation performance.  Radial-basis functions are a popular kernel choice, but have two parameters which need tuning: &lt;span style="font-style: italic;"&gt;cost&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;gamma&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="https://rubygems.org/gems/svm_toolkit"&gt;svm_toolkit&lt;/a&gt; contains some methods to make this search process simpler.  The main addition is &lt;span style="font-family: courier new;"&gt;Svm.cross_validation_search&lt;/span&gt;, which takes five parameters:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;a dataset for training, this is an instance of the Problem class.&lt;/li&gt;&lt;li&gt;a dataset to use for cross-validation, this is also an instance of the Problem class.&lt;/li&gt;&lt;li&gt;an array of values to use for the &lt;span style="font-style: italic;"&gt;cost&lt;/span&gt; parameter: it is recommended these be exponentially growing, in powers of two.&lt;/li&gt;&lt;li&gt;an array of values to use for the &lt;span style="font-style: italic;"&gt;gamma&lt;/span&gt; parameter: these are also recommended to be exponentially growing, in powers of two.&lt;/li&gt;&lt;li&gt;optionally, a fifth parameter value of &lt;span style="font-style: italic;"&gt;true&lt;/span&gt; will generate a contour plot of the cross-validation performance against the two parameters.&lt;/li&gt;&lt;/ol&gt;The method returns the best performing model, based on minimising the number of errors on the cross-validation dataset.  (A future extension will support measures of performance other than overall accuracy.)&lt;br /&gt;&lt;br /&gt;The image below shows an example contour plot.  (The contour plot is drawn using  &lt;a href="http://homepage.mac.com/jhuwaldt/java/Packages/Plot/PlotPackage.html"&gt;PlotPackage&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-TRm3nKQN75s/Tsf3KbJyuuI/AAAAAAAAAZE/a2eHPZqP2dM/s1600/contour-plot.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://1.bp.blogspot.com/-TRm3nKQN75s/Tsf3KbJyuuI/AAAAAAAAAZE/a2eHPZqP2dM/s320/contour-plot.png" alt="" id="BLOGGER_PHOTO_ID_5676777613783382754" border="0" /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Rescaling Features&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Problem class provides a &lt;span style="font-style: italic;"&gt;rescale&lt;/span&gt; method, which rescales each feature in the current problem to fall in a given range: the default is for the features to end up in the range [0, 1].  For example,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;problem.rescale&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;will make sure the problem's features are all in the range [0, 1]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Training and Evaluation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Assuming our data are divided into training, cross-validation and test sets, the following  program will train, optimise and evaluate an RBF model:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"svm_toolkit"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# load in datasets to use for training, cross validation, and testing&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;TrainingData &lt;font color="#990000"&gt;=&lt;/font&gt; Problem&lt;font color="#990000"&gt;.&lt;/font&gt;from_file &lt;font color="#FF0000"&gt;"training_set.dat"&lt;/font&gt;&lt;br /&gt;CrossValData &lt;font color="#990000"&gt;=&lt;/font&gt; Problem&lt;font color="#990000"&gt;.&lt;/font&gt;from_file &lt;font color="#FF0000"&gt;"cross_val_set.dat"&lt;/font&gt;&lt;br /&gt;TestData     &lt;font color="#990000"&gt;=&lt;/font&gt; Problem&lt;font color="#990000"&gt;.&lt;/font&gt;from_file &lt;font color="#FF0000"&gt;"test_set.dat"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Make sure all features are in range [0, 1]&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;TrainingData&lt;font color="#990000"&gt;.&lt;/font&gt;rescale&lt;br /&gt;CrossValData&lt;font color="#990000"&gt;.&lt;/font&gt;rescale&lt;br /&gt;TestData&lt;font color="#990000"&gt;.&lt;/font&gt;rescale&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# decide on the range of costs and gammas to search over&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;Costs &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;13&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;n&lt;font color="#990000"&gt;|&lt;/font&gt; &lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;n&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;Gammas &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[-&lt;/font&gt;&lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;12&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;9&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;n&lt;font color="#990000"&gt;|&lt;/font&gt; &lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;n&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# create the best model, and display the contour plot of results&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;best_model &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;cross_validation_search&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;  TrainingData&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  CrossValData&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  Costs&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  Gammas&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# evaluate model on the test set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Test set errors: #{best_model.evaluate_dataset(TestData)}"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# save the model for later use&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;best_model&lt;font color="#990000"&gt;.&lt;/font&gt;save &lt;font color="#FF0000"&gt;"model.dat"&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-6305741741169780190?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/6305741741169780190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/creating-rbf-models-with-svmtoolkit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6305741741169780190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6305741741169780190'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/creating-rbf-models-with-svmtoolkit.html' title='Creating RBF models with svm_toolkit'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-TRm3nKQN75s/Tsf3KbJyuuI/AAAAAAAAAZE/a2eHPZqP2dM/s72-c/contour-plot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-361333485794846269</id><published>2011-11-18T11:05:00.004Z</published><updated>2011-11-18T11:40:35.167Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='svm_toolkit'/><title type='text'>svm_toolkit: Examples</title><content type='html'>The svm_toolkit gem is now functional.  There are some examples bundled with the gem, to illustrate how to use the library.&lt;br /&gt;&lt;br /&gt;There are three stages to using libsvm:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;create or load a problem definition (an instance of class &lt;span style="font-family: courier new;"&gt;Problem&lt;/span&gt;)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;train a model with given parameters&lt;/li&gt;&lt;li&gt;evaluate the model&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The Problem Definition&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Loading a problem definition from file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A fairly standard data format for training SVM models is the svmlight format.  This format represents one instance per line.  The line is separated into tokens by spaces.  The first token is the class for the instance.  The remaining tokens are index:value pairs, separated by colons.  The advantage of this data format is where many features have the value of 0.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;-1 1:1 3:-0.535714 5:-0.692308&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The above line defines an instance with:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;class value of -1&lt;/li&gt;&lt;li&gt;index 1 has value 1&lt;/li&gt;&lt;li&gt;index 2 has value 0 (default value)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;index 3 has value -0.535714&lt;/li&gt;&lt;li&gt;index 4 has value 0 (default value)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;index 5 has value -0.692308&lt;/li&gt;&lt;/ul&gt;Load a file in this format using the command:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Problem.from_file("australian_scale.txt")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Creating a problem definition in code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sometimes, your data will need constructing, or some preprocessing from a different file format.  The toolkit supports generating problem definitions from two arrays: an array of instance definitions, and an array of the instance labels.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt; &lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Sample dataset: the 'Play Tennis' dataset &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# from T. Mitchell, Machine Learning (1997)&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# --------------------------------------------&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Labels for each instance in the training set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#    1 = Play, 0 = Not&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;Labels &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Recoding the attribute values into range [0, 1]&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;Instances &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The above definition creates 14 instances.  Each row in the array &lt;span style="font-family: courier new;"&gt;Instances&lt;/span&gt; represents one instance, and simply lists the value for each feature.  Each entry in the array &lt;span style="font-family: courier new;"&gt;Labels&lt;/span&gt; represents the label for the corresponding row in &lt;span style="font-family: courier new;"&gt;Instances&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;For example, the third instance has feature values [0.5,1.0,1.0,0.0] and label 1.&lt;br /&gt;&lt;br /&gt;Create a problem definition from these two arrays using the command:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Problem.from_array(Instances, Labels)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Train a Model&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The most complex part of training a model is setting the parameters to use.  The parameters depend on the problem to be solved, and the chosen kernel; more complete descriptions are available on the &lt;a href="http://www.csie.ntu.edu.tw/%7Ecjlin/libsvm/"&gt;libsvm&lt;/a&gt; website.  The most important two parameters are &lt;span style="font-family: courier new;"&gt;svm_type&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;kernel_type&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;svm_type&lt;/span&gt; determines the type of problem to solve.  A typical classification problem has type &lt;span style="font-family: courier new;"&gt;Parameter::C_SVC&lt;/span&gt;; libsvm also supports &lt;span style="font-family: courier new;"&gt;NU_SVC, ONE_CLASS, EPSILON_SVR, &lt;span style="font-family: verdana;"&gt;and&lt;/span&gt; NU_SVR&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;kernel_type&lt;/span&gt; determines the kernel to use for building the model.  There is a choice of &lt;span style="font-family: courier new;"&gt;Parameter::RBF&lt;/span&gt;, &lt;span style="font-family: courier new;"&gt;Parameter::LINEAR&lt;/span&gt;, &lt;span style="font-family: courier new;"&gt;Parameter::SIGMOID&lt;/span&gt;, and &lt;span style="font-family: courier new;"&gt;Parameter::POLY&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Depending on the kernel type, you will also want to set one or more of:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;cost&lt;/span&gt; (for all kernel types)&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;degree&lt;/span&gt; (for the polynomial type)&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;gamma&lt;/span&gt; (for the radial-basis function and sigmoid types)&lt;/li&gt;&lt;/ul&gt;There are other settings for training purposes, but the above are enough for most purposes.&lt;br /&gt;&lt;br /&gt;A Parameter instance is created, passing in default values for the above in map format, for example, to create a simple classification problem with an RBF kernel:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;params &lt;font color="#990000"&gt;=&lt;/font&gt; Parameter&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;svm_type &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;C_SVC&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;kernel_type &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;RBF&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;cost &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;:&lt;/font&gt;gamma &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;4&lt;/font&gt;&lt;br /&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;After creating the parameters, training the model on a given problem set is as a simple as:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;model &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;svm_train&lt;font color="#990000"&gt;(&lt;/font&gt;TrainingSet&lt;font color="#990000"&gt;,&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Evaluate a Model&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is a convenience method to evaluate a model on a given dataset, returning a simple count of the number of errors made:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;model.evaluate_dataset(TrainingSet, true)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second boolean value is optional.  Passing 'true' makes the method print out the expected and actual output of the model for each instance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-361333485794846269?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/361333485794846269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/svmtoolkit-examples.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/361333485794846269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/361333485794846269'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/svmtoolkit-examples.html' title='svm_toolkit: Examples'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-7661719098801041260</id><published>2011-11-15T09:00:00.007Z</published><updated>2011-11-18T11:04:29.821Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='svm_toolkit'/><title type='text'>svm_toolkit: Creating a gem</title><content type='html'>I'm using the Java version of &lt;a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm"&gt; libsvm&lt;/a&gt; through JRuby for some experiments.  There is a common pattern to these experiments, to do with loading the data, perhaps manipulating the data to scale it into the correct ranges, and dividing up into train/test/cross-validation splits. And that is before I get to doing grid searches and worrying about how to evaluate the performance of the models.&lt;br /&gt;&lt;br /&gt;I intend to create a gem containing everything needed to use libsvm through JRuby, including an implementation of libsvm.  (In future, I expect to add some extensions to libsvm, such as further kernel types, or support for active learning.)&lt;br /&gt;&lt;br /&gt;Creating a gem is not, on the face of it, too hard, although it takes a little while initially to get everything in place.  The project code must be laid out in the correct format, and a gemspec file created to define all the components.  The gem is built from the gemspec file, and then the gem can be distributed and installed.  A useful guide is available on the &lt;a href="http://guides.rubygems.org/make-your-own-gem/"&gt;rubygems website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Project Files&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My project files currently look as follows:&lt;br /&gt;&lt;br /&gt;svm_toolkit/README.txt&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;svm_toolkit/svm_toolkit.gemspec&lt;/span&gt;&lt;br /&gt;svm_toolkit/examples/example1.rb&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;svm_toolkit/lib/svm_toolkit.rb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;svm_toolkit/lib/svm/libsvm.jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The jar file contains my packed version of libsvm: later, I'll explore how to provide the java source files in the gem, so that the jar file can be compiled during installation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Gem Spec&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The specification for a Gem includes information about the author, a summary and the version numbers.  The list of &lt;span style="font-style: italic;"&gt;files&lt;/span&gt; must contain the name of each file to be included within the Gem package.  By setting &lt;span style="font-style: italic;"&gt;platform&lt;/span&gt; to the current platform, the gem will also be labelled with the current Java settings.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;Gem&lt;font color="#990000"&gt;::&lt;/font&gt;Specification&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;s&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;name &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"svm_toolkit"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;platform &lt;font color="#990000"&gt;=&lt;/font&gt; Gem&lt;font color="#990000"&gt;::&lt;/font&gt;Platform&lt;font color="#990000"&gt;::&lt;/font&gt;CURRENT&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;author &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"Peter Lane"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;version &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"0.0.1"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;email &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"peter.lane@bcs.org.uk"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;homepage &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"http://rubyforscientificresearch.blogspot.com/"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;summary &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"A JRuby wrapper around an extended version of the libsvm library."&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;license &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"GPL3"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;description &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;-&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;END&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  Support&lt;font color="#990000"&gt;-&lt;/font&gt;vector machines are a popular tool &lt;b&gt;&lt;font color="#0000FF"&gt;in&lt;/font&gt;&lt;/b&gt; data mining&lt;font color="#990000"&gt;.&lt;/font&gt;  &lt;br /&gt;  This package supports common &lt;b&gt;&lt;font color="#0000FF"&gt;and&lt;/font&gt;&lt;/b&gt; extended techniques &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; working with the &lt;br /&gt;  Java implementation of the libsvm library&lt;font color="#990000"&gt;,&lt;/font&gt; through JRuby&lt;font color="#990000"&gt;.&lt;/font&gt;  The package &lt;br /&gt;  includes an amended version of libsvm&lt;font color="#990000"&gt;,&lt;/font&gt; to better support JRuby &lt;b&gt;&lt;font color="#0000FF"&gt;and&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;  techniques such as active learning&lt;font color="#990000"&gt;.&lt;/font&gt; &lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;END&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;files &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;"README.txt"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;    &lt;font color="#FF0000"&gt;"lib/svm_toolkit.rb"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;    &lt;font color="#FF0000"&gt;"lib/svm/libsvm.jar"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;    &lt;font color="#FF0000"&gt;"examples/example-1.rb"&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;require_path &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"lib"&lt;/font&gt;&lt;br /&gt;  s&lt;font color="#990000"&gt;.&lt;/font&gt;has_rdoc &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;svm_toolkit.rb&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;The gem currently does not do much.  It simply provides the imports needed to write scripts using libsvm:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# svm_toolkit&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"java"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"svm/libsvm"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Parameter"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Model"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Problem"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Node"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Svm"&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Building and Installing the Gem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here, I had a little problem with JRuby (version 1.6.5) and its 1.8/1.9 compatibility.  I have JRuby set to use --1.9 by default.  But building a gem in this way led to problems with including the jar file, so:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ jruby --1.8 -S gem build svm_toolkit.gemspec&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which generates the file: "svm_toolkit-0.0.1-universal-java-1.6.gem"&lt;br /&gt;&lt;br /&gt;The gem can then be installed with:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ jruby -S gem install svm_toolkit-0.0.1-universal-java-1.6.gem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Edit: this problem has now been fixed.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Publishing the Gem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After pushing the gem, it is now available from RubyGems as the &lt;a href="https://rubygems.org/gems/svm_toolkit"&gt;svm_toolkit&lt;/a&gt;.  Let me know if it works!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-7661719098801041260?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/7661719098801041260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/svmtoolkit-creating-gem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7661719098801041260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7661719098801041260'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/svmtoolkit-creating-gem.html' title='svm_toolkit: Creating a gem'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-8790501216215234168</id><published>2011-11-14T15:20:00.007Z</published><updated>2011-11-14T15:59:13.870Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='statistics'/><category scheme='http://www.blogger.com/atom/ns#' term='sciruby'/><category scheme='http://www.blogger.com/atom/ns#' term='R'/><title type='text'>SciRuby: pre-alpha release</title><content type='html'>SciRuby has recently been released, in &lt;a href="http://sciruby.com/blog/2011/11/02/first-pre-alpha-release/"&gt;pre-alpha&lt;/a&gt; form.  Version 0.1.3 is available from &lt;a href="http://rubygems.org/gems/sciruby"&gt;rubygems&lt;/a&gt;.  SciRuby aims to provide a science and visualisation library for Ruby, and perhaps bring together some related efforts.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are a lot of dependencies for sciruby, and you may need to install additional packages or development libraries, depending on your current setup.  My system is running Ubuntu 11.04, and I already had the gtk2 gem installed.  The install process prompted me to get the development libraries for &lt;span style="font-style: italic;"&gt;rsvg&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Two gem dependencies that did not come up until I tried to run a test script were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://rubygems.org/gems/bundler"&gt;bundler&lt;/a&gt;, and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://rubygems.org/gems/gtksourceview2"&gt;gtksourceview2&lt;/a&gt;, which also required  the development libraries for &lt;span style="font-style: italic;"&gt;gtksourceview2.0-dev&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;You may of course have more or less dependencies to work through, so some patience is needed.  Once done a simple&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;require "sciruby"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;at the top of your Ruby script will give you access to the library.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;First Visualisation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://sciruby.com/blog/2011/11/02/first-pre-alpha-release/"&gt;blog post&lt;/a&gt; says the Plotter library is currently the most useful component.  This library provides a way to interact with &lt;a href="http://rubyvis.rubyforge.org/"&gt;Rubyvis&lt;/a&gt;.  To display the editor, call:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SciRuby::Editor.new&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You should get the image on the left.  Clicking 'plot' will generate the image on the right.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-h5eIuL5BQLs/TsE2WSDl2TI/AAAAAAAAAY4/gT6cW91r6XQ/s1600/image2.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 499px; height: 319px;" src="http://2.bp.blogspot.com/-h5eIuL5BQLs/TsE2WSDl2TI/AAAAAAAAAY4/gT6cW91r6XQ/s320/image2.png" alt="" id="BLOGGER_PHOTO_ID_5674876761895459122" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The visualisation can be altered by changing the script in the editor, and replotting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Visualisation from a File&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A similar visualisation can be created from within a Ruby program.  The Plotter library can be asked to create an image using some Rubyvis code passed in as a string:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"sciruby"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;SciRuby&lt;font color="#990000"&gt;::&lt;/font&gt;Plotter&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;SciRuby&lt;font color="#990000"&gt;::&lt;/font&gt;Plotter&lt;font color="#990000"&gt;.&lt;/font&gt;create_handle&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'(editor)'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;-&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;END&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;Rubyvis&lt;font color="#990000"&gt;::&lt;/font&gt;Panel&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  width &lt;font color="#993399"&gt;300&lt;/font&gt;&lt;br /&gt;  height &lt;font color="#993399"&gt;200&lt;/font&gt;&lt;br /&gt;  bar &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    data &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.3&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;    width &lt;font color="#993399"&gt;20&lt;/font&gt;&lt;br /&gt;    height &lt;font color="#FF0000"&gt;{&lt;/font&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;d&lt;font color="#990000"&gt;|&lt;/font&gt; d &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#993399"&gt;120&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    bottom&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    left &lt;font color="#FF0000"&gt;{&lt;/font&gt; index &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#993399"&gt;37&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;END&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Visualisation from a Live File&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A more dynamic visualisation is also possible.  Sciruby provides an executable called 'sciruby-plotter' to display the contents of a file as a visualisation.  The contents of the file will be the Rubyvis code, such as:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;Rubyvis&lt;font color="#990000"&gt;::&lt;/font&gt;Panel&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  width &lt;font color="#993399"&gt;300&lt;/font&gt;&lt;br /&gt;  height &lt;font color="#993399"&gt;200&lt;/font&gt;&lt;br /&gt;  bar &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    data &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.3&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;    width &lt;font color="#993399"&gt;20&lt;/font&gt;&lt;br /&gt;    height &lt;font color="#FF0000"&gt;{&lt;/font&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;d&lt;font color="#990000"&gt;|&lt;/font&gt; d &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#993399"&gt;120&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    bottom&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    left &lt;font color="#FF0000"&gt;{&lt;/font&gt; index &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#993399"&gt;37&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Just save the above code in a file, say "data.rb", then call&lt;br /&gt;&lt;br /&gt;$ sciruby-plotter data.rb&lt;br /&gt;&lt;br /&gt;The interesting part of this visualisation is that it will change whenever you update the data file.&lt;br /&gt;&lt;br /&gt;To run this program I had to:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; find the sciruby-plotter program, which is stored with the gem: on my Ubuntu system this is at:  /var/lib/gems/1.9.1/gems/sciruby-0.1.3/bin&lt;/li&gt;&lt;li&gt; amend the shebang line on the sciruby-plotter program, to refer to the version of ruby I am using.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm hoping  this project will gain some momentum.  It already promises to bring together some areas which I'm interested in, such as using R and providing a decent statistics library.&lt;br /&gt;&lt;br /&gt;More information can be found at the sciruby webpage: &lt;a href="http://sciruby.com/"&gt;http://sciruby.com/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-8790501216215234168?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/8790501216215234168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/sciruby-pre-alpha-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/8790501216215234168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/8790501216215234168'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2011/11/sciruby-pre-alpha-release.html' title='SciRuby: pre-alpha release'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-h5eIuL5BQLs/TsE2WSDl2TI/AAAAAAAAAY4/gT6cW91r6XQ/s72-c/image2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4142358479852592520</id><published>2010-10-02T08:46:00.012+01:00</published><updated>2010-10-02T09:43:53.999+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WEKA'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>The Weka API: Matrix class</title><content type='html'>&lt;span style="font-family:verdana;"&gt;Weka includes a matrix library in weka.core.matrix.Matrix.  This library is adapted from the &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://math.nist.gov/javanumerics/jama/"&gt;JAMA package&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;, originally developed by NIST and the University of Maryland.  The aim of the library is to support functions for numerical linear algebra.    &lt;/span&gt;  &lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;Creating a&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt; Matrix&lt;span style="font-weight: bold;"&gt; Instance&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;To create a Matrix instance from jRuby, I use the following construction method.  It takes a two-dimensional Ruby array as argument, and returns an instance of the Matrix class.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;def make_matrix array_2d&lt;br /&gt;  matrix = Matrix.new(array_2d.length, array_2d[0].length)&lt;br /&gt;  array_2d.length.times do |i|&lt;br /&gt;      array_2d[0].length.times do |j|&lt;br /&gt;          matrix.set(i, j, array_2d[i][j])&lt;br /&gt;      end&lt;br /&gt;   end&lt;br /&gt;   return matrix&lt;br /&gt;end&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;For example:  &lt;span style="font-family:courier new;"&gt;puts make_matrix([[1,2,3], [4,5,6], [7,8,10]])&lt;/span&gt;&lt;br /&gt;displays&lt;br /&gt;&lt;br /&gt;1  2  3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt; 4  5  6&lt;br /&gt;7  8 10&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solving a Linear System&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The example within the Weka documentation solves the following problem:&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/TKbvpBA0rmI/AAAAAAAAATM/ic3R5aZ4tsQ/s1600/matrix-example.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 118px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/TKbvpBA0rmI/AAAAAAAAATM/ic3R5aZ4tsQ/s320/matrix-example.png" alt="" id="BLOGGER_PHOTO_ID_5523365480942055010" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Solving using jRuby is equally trivial:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;A = make_matrix [[1,2,3], [4,5,6], [7,8,10]]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;b = make_matrix [[0.1],[0.2],[0.3]]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;x = A.solve b&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Warning&lt;/span&gt;: although the matrices can be converted to strings using to_s, the result is limited in decimal places, which can be misleading.  Better to display the solution using explict 'get' statements, such as:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;puts "Solution: "&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;puts x.get(0,0), x.get(1,0), x.get(2,0)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Solution:&lt;br /&gt;-0.0333333333333334&lt;br /&gt;0.0666666666666667&lt;br /&gt;-3.46944695195361e-17&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Arithmetic on Matrices&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Matrix library supports several standard operations on matrices.  It is easy to add, subtract, or multiply two matrices which are of the right 'shape'.  For example, to find the 'residual' from the above solution:  ||Ax - b||&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-family:courier new;"&gt;r = A.times(x).minus(b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;puts r.normInf&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Here, 'normInf' is the infinity norm: the maximum value in the rows of the matrix 'r'.  The library supports other norms.  The popular "square root of sum of squares" is represented by 'normF', the Frobenius norm.)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4142358479852592520?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4142358479852592520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/10/weka-api-matrix-class.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4142358479852592520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4142358479852592520'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/10/weka-api-matrix-class.html' title='The Weka API: Matrix class'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-BL9uSD-L0k/TKbvpBA0rmI/AAAAAAAAATM/ic3R5aZ4tsQ/s72-c/matrix-example.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3789572386521110217</id><published>2010-09-10T18:20:00.005+01:00</published><updated>2010-09-10T19:30:53.738+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WEKA'/><title type='text'>The Weka API: Overview</title><content type='html'>&lt;span style="font-family: verdana;"&gt;The Weka data mining library makes available an extensive range of functionality, some of it hidden unless you delve into the API documentation.  So, over the next few weeks, I intend to work through some of this documentation, and get a clearer picture of what is available and how to use it from jRuby.  I am currently using &lt;/span&gt;&lt;span style="font-family: verdana;"&gt;the developer version 3.7, which you can find on the Weka website.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I start by opening up the Weka documentation in a browser, and this reveals a number of packages, some with many subpackages.  In alphabetical order, the main packages are:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-weight: bold;"&gt;weka.associations&lt;/span&gt;: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The items in this package are for learning association rules: such rules are relations between variables in the data.  There are two interfaces and several classes.  The classes include standard algorithms such as APriori. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-weight: bold;"&gt;weka.classifiers&lt;/span&gt;: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The items in this package are for constructing classification models: these are models which predict the value of a specified attribute from the remaining attributes.  This package is quite complex, and has several layers to it.  There are four interfaces and a number of classes.  The more familiar classifiers, such as J48 or LibSVM, are subclasses of the abstract class Classifier, and are grouped within subpackages.  Some of the other classes, such as EnsembleLibrary, are for handling groups of classifiers.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The subpackages bring together the main groups of classificaion algorithms, such as bayes, functions, trees etc.  These subpackages contain classes with concrete implementations of classification models, such as NaiveBayes and J48. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-weight: bold;"&gt;weka.clusterers&lt;/span&gt;: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This package contains concrete classes for a number of standard clustering algorithms, including Cobweb and SimpleKMeans: a clustering algorithm groups instances of data based on their similarity.  &lt;/span&gt;Also, some interfaces and abstract classes are present for organising the clustering algorithms into groups, such as those which can estimate density for an instance.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.core&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;This package contains many 'day-to-day' classes such as Instance and Instances.  There are also classes such as EuclideanDistance and EditDistance which compute distances between instances or strings, respectively.  MathematicalExpression is a class for evaluating strings containing expressions adhering to a simple grammar.  There are over 70 classes in total, so plenty to explore.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.datagenerators&lt;/span&gt; and &lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.estimators&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;These packages provide ways to generate and estimate data based on distributions of values. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.experiment&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;This package contains some interesting 'organisational' interfaces and classes.  For example, the 'ResultsProducer' is an interface for objects which work with different randomisations of a dataset.  The CrossValidationResultProducer is an implementation of this interface which organises a run of n-fold cross validation.&lt;br /&gt;&lt;br /&gt;A collection of classes starting 'Result' provide ways of outputting data in standard formats, such as for GnuPlot, HTML etc. &lt;br /&gt;&lt;br /&gt;This is the kind of material I tend to start coding myself, and perhaps I could save some time by using this package instead!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.filters&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;Filters are techniques for modifying the dataset, either by modifying the number or balance of instances, or by altering the values of attributes themselves.  Some useful examples include PrincipalComponents, which performs a transformation of the data, and RandomProjection, which reduces the dimensionality of data.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;weka.gui&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;Many of these classes are for the Weka graphical environment, but some components can be usefully reused in our own GUIs.  These include visualisations of trees and other datatypes, which are under subpackages such as treeviewer and visualize.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-3789572386521110217?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/3789572386521110217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/09/weka-api-overview.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3789572386521110217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3789572386521110217'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/09/weka-api-overview.html' title='The Weka API: Overview'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3592452210687794392</id><published>2010-08-25T16:41:00.008+01:00</published><updated>2010-08-28T11:26:14.843+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>Using libsvm from jruby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;The latest &lt;a href="http://www.csie.ntu.edu.tw/%7Ecjlin/libsvm/"&gt;libsvm&lt;/a&gt; distribution contains a Java version of the libsvm system.  I want to use this from jruby, but there is a problem.  The java version of libsvm has been written based directly on the C code, and this means class names do not have capital letters, which upsets the import process.&lt;br /&gt;&lt;br /&gt;Correcting this is fairly simple.  All the important classes need to have capital letter names. Having done this and recompiled the code, I am making it available &lt;a href="http://homepages.stca.herts.ac.uk/%7Ecomqpcl/Downloads/libsvm.jar"&gt;here&lt;/a&gt;.  You can unpack the code (using &lt;span style="font-family:courier new;"&gt;'jar xf libsvm.jar&lt;/span&gt;') to find the source files.  Or, you can just '&lt;span style="font-family: courier new;"&gt;require "libsvm"&lt;/span&gt;' to use the contents within a jruby program.&lt;br /&gt;&lt;br /&gt;Using this from jruby is not as smooth as it might be: some convenience functions to convert ruby data into the SVM format would be helpful, but for now here is a simple example of learning and then categorising some vectors.  (The example is adapted from that in &lt;a href="http://www.igvita.com/2008/01/07/support-vector-machines-svm-in-ruby/"&gt;a great introduction to SVMs&lt;/a&gt;.)&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"java"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"libsvm"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Parameter"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Model"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Problem"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Node"&lt;/font&gt;&lt;br /&gt;import &lt;font color="#FF0000"&gt;"libsvm.Svm"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Classification with LIBSVM"&lt;/font&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"--------------------------"&lt;/font&gt;&lt;br /&gt; &lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Sample dataset: the 'Play Tennis' dataset &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# from T. Mitchell, Machine Learning (1997)&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# --------------------------------------------&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Labels for each instance in the training set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#    1 = Play, 0 = Not&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@labels&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Recoding the attribute values into range [0, 1]&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@instances&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# create some arbitrary train/test split&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@training_labels&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;slice&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@training_instances&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@instances&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;slice&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@test_labels&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;slice&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;14&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@test_instances&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@instances&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;slice&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;14&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# convert vector of values into a vector of Nodes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; convert values&lt;br /&gt;  ns &lt;font color="#990000"&gt;=&lt;/font&gt; Node&lt;font color="#990000"&gt;[&lt;/font&gt;values&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;].&lt;/font&gt;new&lt;br /&gt;  values&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;v&lt;font color="#990000"&gt;,&lt;/font&gt; i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    n &lt;font color="#990000"&gt;=&lt;/font&gt; Node&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    n&lt;font color="#990000"&gt;.&lt;/font&gt;index &lt;font color="#990000"&gt;=&lt;/font&gt; i&lt;br /&gt;    n&lt;font color="#990000"&gt;.&lt;/font&gt;value &lt;font color="#990000"&gt;=&lt;/font&gt; v&lt;br /&gt;    ns&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; n&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; ns&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Define kernel parameters &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- changing these makes the difference between something working or not&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Parameter&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;C &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;svm_type &lt;font color="#990000"&gt;=&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;NU_SVC&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;degree &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;coef0 &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eps&lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0.001&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;probability &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;nu &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0.5&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;gamma &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;100&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@sp&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Problem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Add documents to the training set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;l &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@training_labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;&lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;x &lt;font color="#990000"&gt;=&lt;/font&gt; Node&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#009900"&gt;@@training_instances&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;][&lt;/font&gt;&lt;font color="#009900"&gt;@@training_instances&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;size&lt;font color="#990000"&gt;].&lt;/font&gt;new&lt;br /&gt;&lt;font color="#009900"&gt;@@training_instances&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;instance&lt;font color="#990000"&gt;,&lt;/font&gt; i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;v&lt;font color="#990000"&gt;,&lt;/font&gt; j&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    n &lt;font color="#990000"&gt;=&lt;/font&gt; Node&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    n&lt;font color="#990000"&gt;.&lt;/font&gt;index &lt;font color="#990000"&gt;=&lt;/font&gt; j&lt;br /&gt;    n&lt;font color="#990000"&gt;.&lt;/font&gt;value &lt;font color="#990000"&gt;=&lt;/font&gt; v&lt;br /&gt;    &lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;x&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;][&lt;/font&gt;j&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; n&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;y &lt;font color="#990000"&gt;=&lt;/font&gt; Java&lt;font color="#990000"&gt;::&lt;/font&gt;double&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#009900"&gt;@@training_labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;].&lt;/font&gt;new&lt;br /&gt;&lt;font color="#009900"&gt;@@training_labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;v&lt;font color="#990000"&gt;,&lt;/font&gt; i&lt;font color="#990000"&gt;|&lt;/font&gt; &lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;y&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; v&lt;font color="#FF0000"&gt;}&lt;/font&gt;  &lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Try four different Kernels&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@kernels&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;LINEAR&lt;font color="#990000"&gt;,&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;POLY&lt;font color="#990000"&gt;,&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;RBF&lt;font color="#990000"&gt;,&lt;/font&gt; Parameter&lt;font color="#990000"&gt;::&lt;/font&gt;SIGMOID &lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@kernel_names&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt; &lt;font color="#FF0000"&gt;'Linear'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'Polynomial'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'Radial basis function'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;'Sigmoid'&lt;/font&gt; &lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@kernels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;each_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;j&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt; &lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# Iterate and over each kernel type&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;kernel_type &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@kernels&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;j&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;  m &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;svm_train&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;@@pa&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  errors &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# Test kernel performance on the training set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;@@training_labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;each_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    pred &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;svm_predict&lt;font color="#990000"&gt;(&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;@@sp&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;x&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;    puts &lt;font color="#FF0000"&gt;"Prediction: #{pred}, True label: #{@@training_labels[i]}, Kernel: #{@@kernel_names[j]}"&lt;/font&gt;&lt;br /&gt;    errors &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@labels&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; pred&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"Kernel #{@@kernel_names[j]} made #{errors} errors on the training set"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# Test kernel performance on the test set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  errors &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  &lt;font color="#009900"&gt;@@test_labels&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;each_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    pred &lt;font color="#990000"&gt;=&lt;/font&gt; Svm&lt;font color="#990000"&gt;.&lt;/font&gt;svm_predict&lt;font color="#990000"&gt;(&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; convert&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@@test_instances&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]))&lt;/font&gt;&lt;br /&gt;    puts &lt;font color="#FF0000"&gt;"\t Prediction: #{pred}, True label: #{@@test_labels[i]}"&lt;/font&gt;&lt;br /&gt;    errors &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@test_labels&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; pred&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"Kernel #{@@kernel_names[j]} made #{errors} errors on the test set \n\n"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;In terms of performance, you don't appear to lose anything by switching to jruby and the java version of libsvm: I reran my experiment from an earlier &lt;a href="http://rubyforscientificresearch.blogspot.com/2009/11/working-with-rubysvm.html"&gt;post&lt;/a&gt; (with suitable changes to the code) and it ran in the same amount of time, and, of course, got pretty much the same result.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-3592452210687794392?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/3592452210687794392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/08/using-libsvm-from-jruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3592452210687794392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3592452210687794392'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/08/using-libsvm-from-jruby.html' title='Using libsvm from jruby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-293831402929721103</id><published>2010-07-30T14:56:00.003+01:00</published><updated>2010-07-30T15:03:21.669+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><title type='text'>Ruby and LibSVM - update</title><content type='html'>In a &lt;a href="http://rubyforscientificresearch.blogspot.com/2009/11/libsvm-and-ruby.html"&gt;previous post&lt;/a&gt; I explained how to get LibSVM working with Ruby 1.9.  There is now an updated version of RubySVM available at &lt;a href="http://sourceforge.net/projects/rubysvm/"&gt;Sourceforge&lt;/a&gt;.  Installation is fairly straightforward.  If you use Ubuntu or Debian though, you will also need to make sure 'mkmf' is installed: make sure you install 'ruby1.9-dev' first.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-293831402929721103?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/293831402929721103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/07/ruby-and-libsvm-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/293831402929721103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/293831402929721103'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/07/ruby-and-libsvm-update.html' title='Ruby and LibSVM - update'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-5059906373369959612</id><published>2010-05-14T23:11:00.004+01:00</published><updated>2010-05-15T00:07:51.538+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jfreechart'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>Generating Graphs with JFreeChart</title><content type='html'>&lt;span style="font-family: verdana;font-family:verdana;" &gt;jRuby gives us access to all the libraries available for the Java platform; I have recently started looking at &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.jfree.org/jfreechart/"&gt;JFreeChart&lt;/a&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;, which seems capable of generating all kinds of fancy graphs, with very little work.&lt;/span&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;  To write programs using JFreeChart you need to download the software, and extract the jar files: jcommon-X.jar and jfreechart-X.jar (where the -X stands for the version numbers).  I tend to rename the jar files to jcommon.jar and jfreechart.jar.&lt;br /&gt;&lt;br /&gt;Examples of using JFreeChart are available in different places: there are examples within the source code (in the folder source/org/jfree/chart/demos/), and an &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.informit.com/guides/content.aspx?g=java&amp;amp;seqNum=74"&gt;article at InformIT from 2004&lt;/a&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt; to help guide you into the &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.jfree.org/jfreechart/api/javadoc/index.html"&gt;APIs&lt;/a&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;.  Some examples are coming up for other scripting languages on the java platform, such as this example using &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://groovy.codehaus.org/Plotting+graphs+with+JFreeChart"&gt;Groovy to plot a simple piechart&lt;/a&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;.  Here's my own take, of a simple chart, for jRuby.&lt;/span&gt;   &lt;span style="font-family: verdana;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a style="font-family: verdana;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-BL9uSD-L0k/S-3Wg7Tx63I/AAAAAAAAASs/w1_cGbRr6uk/s1600/sample.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://4.bp.blogspot.com/_-BL9uSD-L0k/S-3Wg7Tx63I/AAAAAAAAASs/w1_cGbRr6uk/s320/sample.png" alt="" id="BLOGGER_PHOTO_ID_5471264983489833842" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;And the source code:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# jRuby implementation of simple PieChart example for JFreeChart&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"java"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"jcommon.jar"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"jfreechart.jar"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- Code to create a pie chart&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"org.jfree.data.general.DefaultPieDataset"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"org.jfree.chart.ChartPanel"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"org.jfree.chart.ChartFactory"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; create_chart&lt;br /&gt;  dataset &lt;font color="#990000"&gt;=&lt;/font&gt; DefaultPieDataset&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;  dataset&lt;font color="#990000"&gt;.&lt;/font&gt;set_value&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Comet Nuclei"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.26&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  dataset&lt;font color="#990000"&gt;.&lt;/font&gt;set_value&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Mars Asteroids"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;7.0&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  dataset&lt;font color="#990000"&gt;.&lt;/font&gt;set_value&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Apollo Objects"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.55&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  chart &lt;font color="#990000"&gt;=&lt;/font&gt; ChartFactory&lt;font color="#990000"&gt;.&lt;/font&gt;create_pie_chart&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;    &lt;font color="#FF0000"&gt;"Impact Craters greater than 20km radius per million square kilometers on Mars"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    dataset&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;false&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  ChartPanel&lt;font color="#990000"&gt;.&lt;/font&gt;new chart&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- Code to build the Swing Frame&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"javax.swing.JFrame"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"java.awt.BorderLayout"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; create_frame chart&lt;br /&gt;  frame &lt;font color="#990000"&gt;=&lt;/font&gt; JFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"jRuby using JFreeChart"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  frame&lt;font color="#990000"&gt;.&lt;/font&gt;content_pane&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;chart&lt;font color="#990000"&gt;,&lt;/font&gt; BorderLayout&lt;font color="#990000"&gt;::&lt;/font&gt;CENTER&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  frame&lt;font color="#990000"&gt;.&lt;/font&gt;setSize&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;600&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;400&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  frame&lt;font color="#990000"&gt;.&lt;/font&gt;visible &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;true&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  frame&lt;font color="#990000"&gt;.&lt;/font&gt;default_close_operation &lt;font color="#990000"&gt;=&lt;/font&gt; JFrame&lt;font color="#990000"&gt;::&lt;/font&gt;EXIT_ON_CLOSE&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;create_frame create_chart&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;(If you are interested, the numbers are from an &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://adsabs.harvard.edu/full/1965IrAJ....7...92O"&gt;article&lt;/a&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt; on Mariner IV and the Martian craters, by E.J. Opik.)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; font-family: verdana;font-family:verdana;" &gt;Finally...&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;  &lt;/span&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;The fun of using JFreeChart does not end with displaying the images on the screen.  A right-click on the image brings up a menu which lets you customise the image's colours, rescale, save to a file and even print.  This is an enormous amount of functionality rapidly available, and the images look great.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-5059906373369959612?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/5059906373369959612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/05/generating-graphs-with-jfreechart.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5059906373369959612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5059906373369959612'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2010/05/generating-graphs-with-jfreechart.html' title='Generating Graphs with JFreeChart'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-BL9uSD-L0k/S-3Wg7Tx63I/AAAAAAAAASs/w1_cGbRr6uk/s72-c/sample.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4909433550457614135</id><published>2009-11-08T09:00:00.002Z</published><updated>2009-11-08T09:00:01.890Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><title type='text'>Keeping wxRuby GUI Working with Threads</title><content type='html'>&lt;span style="font-family: verdana;"&gt;A big problem with GUI applications is the unresponsive interface, which happens when the program is busy working on a complex task, leaving no time for updating the graphical interface.  All graphical programs performing significant work will require at least two working threads: one thread to look after the graphical interface, redrawing the windows and buttons; and one thread to look after the task.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The following program illustrates the problem.  The display is a simple menu with a 'start' item on it.  Selecting 'start' will begin a thread displaying ten messages into the text control; the task is just to add up a lot of numbers.  Although this works, none of the messages appears until the entire 'busy_task' method is complete.  &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; MyFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Thread example"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_menu_bar menubar&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@text&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;TextCtrl&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;style &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;TE_MULTILINE&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@tasks&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; menubar&lt;br /&gt;    menubar &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuBar&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    file_menu &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Menu&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    about_item &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuItem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;file_menu&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"About"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;about_item&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt; &lt;font color="#009900"&gt;@text&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;append_text &lt;font color="#FF0000"&gt;"About\n"&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    file_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append_item about_item&lt;br /&gt;    start_item &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuItem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;file_menu&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Start"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;start_item&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt; busy_task&lt;font color="#FF0000"&gt;}&lt;/font&gt; &lt;br /&gt;&lt;br /&gt;    file_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append_item start_item&lt;br /&gt;&lt;br /&gt;    menubar&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;file_menu&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"File"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    menubar&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; busy_task&lt;br /&gt;    &lt;font color="#009900"&gt;@tasks&lt;/font&gt; &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;    tasks &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@tasks&lt;/font&gt;&lt;br /&gt;    &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;      &lt;font color="#009900"&gt;@text&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;append_text &lt;font color="#FF0000"&gt;"running #{tasks} ... #{Time.new}\n"&lt;/font&gt;&lt;br /&gt;      &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;1000_000&lt;font color="#990000"&gt;).&lt;/font&gt;inject &lt;font color="#990000"&gt;:+&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@text&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;append_text &lt;font color="#FF0000"&gt;"Thread #{tasks} done\n"&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;  MyFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Threads and Timers&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;We can improve on the above code by placing the work within the 'busy_task' method into a thread:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; busy_task&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# start task in a separate thread&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    Thread&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;      &lt;font color="#009900"&gt;@tasks&lt;/font&gt; &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;      tasks &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@tasks&lt;/font&gt;&lt;br /&gt;      &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;        &lt;font color="#009900"&gt;@text&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;append_text &lt;font color="#FF0000"&gt;"running #{tasks} ... #{Time.new}\n"&lt;/font&gt;&lt;br /&gt;        &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;1_00_000&lt;font color="#990000"&gt;).&lt;/font&gt;inject &lt;font color="#990000"&gt;:+&lt;/font&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;      &lt;font color="#009900"&gt;@text&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;append_text &lt;font color="#FF0000"&gt;"Thread #{tasks} done\n"&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This will indeed work.  The GUI stays responsive, and more than one thread can be active, by selecting the 'start' menu item again.  However, you may find the working thread seems to stop doing anything at times; this happens if I switch focus to another window, so the ruby application is running in the background.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The second improvement is to add a &lt;span style="font-family: courier new;"&gt;Timer&lt;/span&gt;.  This is created in the &lt;span style="font-family: courier new;"&gt;initialize&lt;/span&gt; method for the frame.  The &lt;span style="font-family: courier new;"&gt;Timer&lt;/span&gt;'s role is to wake up after a short period of time, and pass processing control to the next thread.  In this case, I make the &lt;span style="font-family: courier new;"&gt;Timer&lt;/span&gt; wake up after 10 milliseconds.  &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Thread example"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_menu_bar menubar&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# -- this timer interrupts every 100ms and gets next thread active&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# -- if you don't have the timer, the GUI does not update if window &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;#    in background&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    timer &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Timer&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_timer&lt;font color="#990000"&gt;(&lt;/font&gt;timer&lt;font color="#990000"&gt;.&lt;/font&gt;id&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;Thread&lt;font color="#990000"&gt;.&lt;/font&gt;pass&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    timer&lt;font color="#990000"&gt;.&lt;/font&gt;start&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@text&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;TextCtrl&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;style &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;TE_MULTILINE&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@tasks&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Worker Threads and a Timer to make sure the Threads are kept active is probably the key to keeping wxRuby's GUI active under large-running tasks, although I expect to have to do some experimenting in future.  For better information, Mario Steele has described the principles &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.ruby-forum.com/topic/188814"&gt;here&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; and in a &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://wxruby.rubyforge.org/wiki/wiki.pl?Sockets"&gt;tutorial&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4909433550457614135?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4909433550457614135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/keeping-wxruby-gui-working-with-threads.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4909433550457614135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4909433550457614135'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/keeping-wxruby-gui-working-with-threads.html' title='Keeping wxRuby GUI Working with Threads'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3805986831158968664</id><published>2009-11-07T15:30:00.010Z</published><updated>2009-11-07T17:23:12.601Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><title type='text'>Using LibSVM from Ruby with data in files</title><content type='html'>&lt;span style="font-family: verdana;"&gt;In previous posts, I looked at RubySVM and how to set up models with data held within the memory of a running Ruby process.  I have found this does not scale up to larger datasets of images, taking up to a gigabyte in storage on disk, and so I have adopted a different approach, constructing training/test files on disk and then calling the command line &lt;span style="font-family: courier new;"&gt;svm-train&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;svm-predict&lt;/span&gt; functions.  Ruby then drives the whole process, automating the construction of the datasets, selection of the best models, and final evaluation.  I use the UCI Letter Recognition dataset discussed earlier as an example, but the approach is fully general.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Calling System Commands&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The first step in controlling external programs is calling them, and for this Ruby's backtick syntax is ideal.  &lt;span style="font-family: courier new;"&gt;`ls`&lt;/span&gt; will call the ls command, returning the result as a string, which we can store with &lt;span style="font-family: courier new;"&gt;result = `ls`&lt;/span&gt;: &lt;span style="font-family: courier new;"&gt;result.split("\n")&lt;/span&gt; then produces an array of filenames in the current directory.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This backtick notation supports the interpolation of arbitrary Ruby code, just like in &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;strings.  Thus, writing &lt;span style="font-family: courier new;"&gt;`ls *.#{extension}`&lt;/span&gt; will use the value of &lt;span style="font-family: courier new;"&gt;extension&lt;/span&gt; to list file of the given extension only.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Try it from irb: &lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;peter@peter-desktop:~/Code$ irb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;irb(main):001:0&gt; `ls`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; "instances.html\njruby.jar\ntest-instances.rb\ntrial-kmeans.rb\nweather.arff\nweka.jar\n"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;irb(main):002:0&gt; result = `ls`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; "instances.html\njruby.jar\ntest-instances.rb\ntrial-kmeans.rb\nweather.arff\nweka.jar\n"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;irb(main):003:0&gt; result.split("\n")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; ["instances.html", "jruby.jar", "test-instances.rb", "trial-kmeans.rb", "weather.arff", "weka.jar"]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;irb(main):004:0&gt; extension = "rb"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; "rb"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;irb(main):005:0&gt; `ls *.#{extension}`.split("\n")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; ["test-instances.rb", "trial-kmeans.rb"]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Constructing the Datasets&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The data is read in, just like I did before, creating an array &lt;span style="font-family: courier new;"&gt;@@data&lt;/span&gt; containing instances of the &lt;span style="font-family: courier new;"&gt;LetterInstance&lt;/span&gt; datatype.  I then use input parameters to partition the dataset into training, cross-validation and test datasets:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Read in letter-recognition UCI data&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;LetterInstance &lt;font color="#990000"&gt;=&lt;/font&gt; Struct&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(:&lt;/font&gt;letter&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;width&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;height&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;on_pixels&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;xybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2ybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xy2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xegvy&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;y_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;yegvx&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@data&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"letter-recognition.data"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;f&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  f&lt;font color="#990000"&gt;.&lt;/font&gt;each_line &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;line&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; LetterInstance&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(*&lt;/font&gt;line&lt;font color="#990000"&gt;.&lt;/font&gt;strip&lt;font color="#990000"&gt;.&lt;/font&gt;split&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- using given proportion for training/cross-validation sets, create three files&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; ARGV&lt;font color="#990000"&gt;.&lt;/font&gt;length &lt;font color="#990000"&gt;!=&lt;/font&gt; &lt;font color="#993399"&gt;2&lt;/font&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"To use: ruby train-models.rb TRAINING_PROPORTION CROSS_PROPORTION"&lt;/font&gt;&lt;br /&gt;  exit&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@training_proportion&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_f&lt;br /&gt;&lt;font color="#009900"&gt;@@cross_validation_proportion&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_f&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@num_training&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;length &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#009900"&gt;@@training_proportion&lt;/font&gt;&lt;font color="#990000"&gt;).&lt;/font&gt;floor&lt;br /&gt;&lt;font color="#009900"&gt;@@num_cross&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@@num_training&lt;/font&gt; &lt;font color="#990000"&gt;*&lt;/font&gt; &lt;font color="#009900"&gt;@@cross_validation_proportion&lt;/font&gt;&lt;font color="#990000"&gt;).&lt;/font&gt;floor&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Select Train/Cross/Test sets&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- note, cross-validation size is taken out of the training-set&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;shuffle!&lt;br /&gt;&lt;br /&gt;TrainSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#009900"&gt;@@num_cross&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#009900"&gt;@@num_training&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;CrossSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#009900"&gt;@@num_cross&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;TestSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#009900"&gt;@@num_training&lt;/font&gt;&lt;font color="#990000"&gt;..-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The three datasets must now be saved onto disk, to form the datasets to pass to the SVM.  The file format for an SVM places each instance onto a single line in the file.  Each instance has its class first, and then its attribute values.  Every item is separated by a space.  The class must be a number, and the attribute values should be in the range [0,1] or [-1,1].  The attribute-values are written by writing the index of the attribute, followed by a colon, and then the value.  An example from the training file is:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;17 0:0.466666666666667 1:0.6 2:0.666666666666667 3:0.533333333333333 ....&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The advantage of this notation is that it supports sparse data - any attribute that has value 0 can simply be ignored.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The following code constructs the required data:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Create SVM format of features in instance, rescaling to [0,1]&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_data item&lt;br /&gt;  str &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;""&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;(&lt;/font&gt;item&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;).&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    str &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"#{i}:#{item[i+1].to_f/15.0} "&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  str&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; save_file&lt;font color="#990000"&gt;(&lt;/font&gt;dataset&lt;font color="#990000"&gt;,&lt;/font&gt; filename&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;f&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    dataset&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;item&lt;font color="#990000"&gt;,&lt;/font&gt; index&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      f&lt;font color="#990000"&gt;.&lt;/font&gt;puts &lt;font color="#FF0000"&gt;"#{item.letter.ord - 65} #{make_data(item)}"&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;save_file&lt;font color="#990000"&gt;(&lt;/font&gt;TrainSet&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"training-data.dat"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;save_file&lt;font color="#990000"&gt;(&lt;/font&gt;CrossSet&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"cross-data.dat"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;save_file&lt;font color="#990000"&gt;(&lt;/font&gt;TestSet&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"test-data.dat"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Training the Models&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I create each model using &lt;span style="font-family: courier new;"&gt;svm-train&lt;/span&gt;, supplying it a training data set and set of parameters.  As I am creating SVMs with an RBF kernel, there are two parameters that particularly interest me: &lt;span style="font-family: courier new;"&gt;cost&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;gamma&lt;/span&gt;. I will save a model file for each pair of parameters, embedding the parameter value in the name.  This is all done by string interpolation in the backtick call to &lt;span style="font-family: courier new;"&gt;svm-train&lt;/span&gt;.  &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- train models using Cost/Gamma values and external system&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;Costs &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;13&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;Gammas &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;12&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;9&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Costs&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;cost&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  Gammas&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;gamma&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    `svm&lt;font color="#990000"&gt;-&lt;/font&gt;train &lt;font color="#990000"&gt;-&lt;/font&gt;s &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;t &lt;font color="#993399"&gt;2&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;d &lt;font color="#993399"&gt;3&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;r &lt;font color="#993399"&gt;0&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;e &lt;font color="#993399"&gt;0.001&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;c &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;cost&lt;font color="#FF0000"&gt;}&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt;g &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;gamma&lt;font color="#FF0000"&gt;}&lt;/font&gt; training&lt;font color="#990000"&gt;-&lt;/font&gt;data&lt;font color="#990000"&gt;.&lt;/font&gt;dat l&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;cost&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;gamma&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;model`&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Evaluating a Model&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-family: courier new;"&gt;svm-predict&lt;/span&gt; is the command-line tool for evaluating a model on a given dataset.  It produces two sets of outputs.  A file containing the actual predictions of the model for each instance in the dataset, and a printed output of the model's accuracy.  This accuracy is a percentage correct.  We can retrieve it using a regular expression match on the result of running &lt;span style="font-family: courier new;"&gt;svm-predict&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Our models are defined by their cost and gamma values, using the format above.  Given the filename of a dataset to test on, the following function will run &lt;span style="font-family: courier new;"&gt;svm-predict&lt;/span&gt; and parse its output to produce the model's accuracy.  The actual predictions are sent to the same file - I don't want to keep them.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Test the model on given dataset, and parse output to get accuracy&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; get_accuracy&lt;font color="#990000"&gt;(&lt;/font&gt;cost&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;font color="#990000"&gt;,&lt;/font&gt; dataset&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  result &lt;font color="#990000"&gt;=&lt;/font&gt; `svm&lt;font color="#990000"&gt;-&lt;/font&gt;predict &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;dataset&lt;font color="#FF0000"&gt;}&lt;/font&gt; l&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;cost&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;gamma&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;model test&lt;font color="#990000"&gt;.&lt;/font&gt;out`&lt;br /&gt;  result&lt;font color="#990000"&gt;.&lt;/font&gt;match&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF6600"&gt;/\d+.\d+/&lt;/font&gt;&lt;font color="#990000"&gt;)[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_f&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Selecting a Model and Final Evaluation&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Having trained models for every combination of cost and gamma, we need to find the one that does best on the cross-validation dataset, and then evaluate it on the test set.  This is straightforward:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Search for best cost/gamma pairing, based on result on cross-validation dataset&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@best_cost&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Costs&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@best_gamma&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Gammas&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@best_accuracy&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0.0&lt;/font&gt;&lt;br /&gt;Costs&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;cost&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  Gammas&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;gamma&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    accuracy &lt;font color="#990000"&gt;=&lt;/font&gt; get_accuracy&lt;font color="#990000"&gt;(&lt;/font&gt;cost&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"cross-data.dat"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; accuracy &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#009900"&gt;@@best_accuracy&lt;/font&gt;&lt;br /&gt;      &lt;font color="#009900"&gt;@@best_accuracy&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;@@best_cost&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#009900"&gt;@@best_gamma&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; accuracy&lt;font color="#990000"&gt;,&lt;/font&gt; cost&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Best cost #{@@best_cost}, Best gamma #{@@best_gamma}"&lt;/font&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Test score is: #{get_accuracy(@@best_cost, @@best_gamma, "&lt;/font&gt;test&lt;font color="#990000"&gt;-&lt;/font&gt;data&lt;font color="#990000"&gt;.&lt;/font&gt;dat&lt;font color="#FF0000"&gt;")}"&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Running the letter-recognition task with 2000 training examples using files, instead of in memory, took 11 minutes in total, instead of the 35 minutes my in-memory solution required.  So the saving in time is considerable.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Accuracy with 2000 training examples was 82%.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I also ran the system using 72% of the data (14,400 instances) for training, 8% (1600 instances) as cross-validation, and the remaining 20% (4000 instances) as test data.  I searched across 121 combinations of Cost/Gamma pairs using an RBF kernel.  The best fit had a cost of 1/32, gamma of 32, and produced an &lt;span style="font-style: italic;"&gt;accuracy of 97.5%&lt;/span&gt;.  This took 6 hours to run.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-3805986831158968664?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/3805986831158968664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/using-libsvm-from-ruby-with-data-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3805986831158968664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3805986831158968664'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/using-libsvm-from-ruby-with-data-in.html' title='Using LibSVM from Ruby with data in files'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-7312024613366333657</id><published>2009-11-02T12:20:00.005Z</published><updated>2009-11-02T12:46:20.819Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><title type='text'>Working with RubySVM</title><content type='html'>&lt;span style="font-family:verdana;"&gt;A classification model is a tool for mapping a sequence of inputs to a predicted output.  To construct a classification model, we have to &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;train&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; it on some data where we have the expected output.  There are many kinds of classification models; here, I build SVM models using the RubySVM library.  For an explanation of SVMs and how to best use the SVM library, please see the LibSVM documentation; this post is an example of using the library from Ruby.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I use the UCI letter recognition example discussed in &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://rubyforscientificresearch.blogspot.com/2009/05/displaying-multi-column-data-in-wxruby.html"&gt;this earlier post&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;, and assume the SVM library has been installed, as also discussed &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://rubyforscientificresearch.blogspot.com/2009/11/libsvm-and-ruby.html"&gt;earlier&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;.&lt;br /&gt;&lt;br /&gt;In the letter recognition example, each letter has a "label" (called 'letter') and several attributes, such as 'x-box', 'width', 'height', etc.  The classification problem is to compute the label from the attributes.  To begin, we assume a dataset of examples which contain attributes and a label.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;General Method&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The pattern for constructing and using an SVM model is as follows:&lt;/span&gt; &lt;ol style="font-family: verdana;"&gt;&lt;li&gt;The data is partitioned into a training and a test set.  The test set is used at the end, to evaluate the model.  It is not used at all during model development or parameter selection.&lt;/li&gt;&lt;li&gt;The training set is partitioned into a cross-validation set and an actual training set.&lt;/li&gt;&lt;li&gt;Search through the parameter space of possible SVM models, training each model on the actual training set, and evaluating it on the cross-validation set.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Choose the parameter settings which produce the best performance on the cross-validation set.&lt;/li&gt;&lt;li&gt;Use the chosen parameter settings to evaluate the SVM model on the test set, and report this final figure.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family:verdana;"&gt;There are many improvements needed for serious work, but that pattern is enough to get an idea of how building a model works, and, most importantly, sort out the main requirements on a Ruby program to handle all the steps.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Creating a Classification Problem&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Our dataset used the following structure:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;LetterInstance &lt;font color="#990000"&gt;=&lt;/font&gt; Struct&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(:&lt;/font&gt;letter&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;width&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;height&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;on_pixels&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;      &lt;font color="#990000"&gt;:&lt;/font&gt;y2bar&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;xybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2ybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xy2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xegvy&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#990000"&gt;:&lt;/font&gt;y_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;yegvx&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The field 'letter' is the label, and the rest are the attributes.  Due to the way we read in and create instances of this structure, the attributes are actually strings.  We store all the data into a global array, called &lt;span style="font-family: courier new;"&gt;@@data&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The data for the SVM needs to be separated into the class 'labels' and the values for the attributes.  All the values need to be numeric.  For the labels, we can just assign integer values to each class.  For the attribute values, we need each number to be in the range [0,1] or [-1,1].  We achieve this by rescaling the actual attribute values to fit into the range.  For the letter task, each attribute value is a number from 0 to 15, inclusive; dividing by 15 to form a fractional number gets each attribute value into the right range.&lt;br /&gt;&lt;br /&gt;The following code provides two functions to collect the label and an array of attribute values for a given letter-recognition example:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@classes&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; datum&lt;font color="#990000"&gt;.&lt;/font&gt;letter&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;uniq&lt;font color="#990000"&gt;.&lt;/font&gt;sort&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_number char&lt;br /&gt;  &lt;font color="#009900"&gt;@@classes&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;index char&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; transform datum&lt;br /&gt;  data &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;  &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;upto&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;.&lt;/font&gt;members&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    data &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; datum&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;].&lt;/font&gt;to_f &lt;font color="#990000"&gt;/&lt;/font&gt; &lt;font color="#993399"&gt;15.0&lt;/font&gt; &lt;i&gt;&lt;font color="#9A1900"&gt;# all data in range [0,15]&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  data&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;We must now randomise the list (using &lt;span style="font-family: courier new;"&gt;shuffle&lt;/span&gt;), and collect samples for training, cross-validation, and testing.  This is easy using subranges:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;TrainSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#993399"&gt;2000&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; transform&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;TrainLabels &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#993399"&gt;2000&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; make_number&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;.&lt;/font&gt;letter&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;CrossSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;9000&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#993399"&gt;10000&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; transform&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;CrossLabels &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;9000&lt;/font&gt;&lt;font color="#990000"&gt;...&lt;/font&gt;&lt;font color="#993399"&gt;10000&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; make_number&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;.&lt;/font&gt;letter&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;TestSet &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;10000&lt;/font&gt;&lt;font color="#990000"&gt;..-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; transform&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;TestLabels &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;10000&lt;/font&gt;&lt;font color="#990000"&gt;..-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;datum&lt;font color="#990000"&gt;|&lt;/font&gt; make_number&lt;font color="#990000"&gt;(&lt;/font&gt;datum&lt;font color="#990000"&gt;.&lt;/font&gt;letter&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Training an Individual Model&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;To train a model, we create an instance of &lt;span style="font-family: courier new;"&gt;SVM::Problem&lt;/span&gt;, which is constructed by adding each instance from the training set, in turn, giving its label and attribute values; TrainProblem is constructed here, to hold the training data.  The model is trained by creating it using the Problem description and a set of Parameters.  The following function constructs an SVM model using a given problem and values for the Cost and Gamma parameters; other parameter values are set to default settings.  Here, I use an RBF kernel for the SVM, but others are available.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_problem&lt;font color="#990000"&gt;(&lt;/font&gt;data&lt;font color="#990000"&gt;,&lt;/font&gt; labels&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  problem &lt;font color="#990000"&gt;=&lt;/font&gt; SVM&lt;font color="#990000"&gt;::&lt;/font&gt;Problem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;  data&lt;font color="#990000"&gt;.&lt;/font&gt;each_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    problem&lt;font color="#990000"&gt;.&lt;/font&gt;addExample&lt;font color="#990000"&gt;(&lt;/font&gt;labels&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;],&lt;/font&gt; data&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  problem&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_rbf_svm_model&lt;font color="#990000"&gt;(&lt;/font&gt;problem&lt;font color="#990000"&gt;,&lt;/font&gt; cost&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  params &lt;font color="#990000"&gt;=&lt;/font&gt; SVM&lt;font color="#990000"&gt;::&lt;/font&gt;Parameter&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;C &lt;font color="#990000"&gt;=&lt;/font&gt; cost&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;gamma &lt;font color="#990000"&gt;=&lt;/font&gt; gamma&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;kernel_type &lt;font color="#990000"&gt;=&lt;/font&gt; SVM&lt;font color="#990000"&gt;::&lt;/font&gt;RBF&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# some default values&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;svm_type &lt;font color="#990000"&gt;=&lt;/font&gt; SVM&lt;font color="#990000"&gt;::&lt;/font&gt;NU_SVC&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;degree &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;coef0 &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  params&lt;font color="#990000"&gt;.&lt;/font&gt;eps &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0.001&lt;/font&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# construct the model&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  SVM&lt;font color="#990000"&gt;::&lt;/font&gt;Model&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;problem&lt;font color="#990000"&gt;,&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;TrainProblem &lt;font color="#990000"&gt;=&lt;/font&gt; make_problem&lt;font color="#990000"&gt;(&lt;/font&gt;TrainSet&lt;font color="#990000"&gt;,&lt;/font&gt; TrainLabels&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt; &lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Evaluating a Model&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Once we have trained a model, we can see what prediction it makes for a given instance and compare that with the true label (the one from the original dataset).  The following code runs through an array of examples and counts up the number of errors made by the given model:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; test_model&lt;font color="#990000"&gt;(&lt;/font&gt;model&lt;font color="#990000"&gt;,&lt;/font&gt; data&lt;font color="#990000"&gt;,&lt;/font&gt; labels&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  errors &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  labels&lt;font color="#990000"&gt;.&lt;/font&gt;each_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    prediction&lt;font color="#990000"&gt;,&lt;/font&gt; probs &lt;font color="#990000"&gt;=&lt;/font&gt; model&lt;font color="#990000"&gt;.&lt;/font&gt;predict_probability&lt;font color="#990000"&gt;(&lt;/font&gt;data&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;    errors &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; labels&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;!=&lt;/font&gt; prediction&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  errors&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Searching for the best Cost and Gamma&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The critical parameters for the Radial-Basis Function kernel are the Cost function and Gamma.  We need to&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;do a search across a range of possible values, to locate the model which performs the best. To evaluate the model, we use a cross-validation set, which is taken from the training data, but different from the test set, which we only use at the very end, once we have selected the SVM parameters. &lt;br /&gt;&lt;br /&gt;The following code performs a simple &lt;span style="font-style: italic;"&gt;grid search&lt;/span&gt; across a range of values for Cost and Gamma, evaluating the model generated by each set of parameters against the cross-validation set.  The model with the fewest errors is then selected. &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;Costs &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;13&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;Gammas &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;12&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;**&lt;/font&gt;&lt;font color="#993399"&gt;9&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;best_model &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;lowest_error &lt;font color="#990000"&gt;=&lt;/font&gt; CrossLabels&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;Costs&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;cost&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  Gammas&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;gamma&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    svm_model &lt;font color="#990000"&gt;=&lt;/font&gt; make_rbf_svm_model&lt;font color="#990000"&gt;(&lt;/font&gt;TrainProblem&lt;font color="#990000"&gt;,&lt;/font&gt; cost&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    cross_validation_result &lt;font color="#990000"&gt;=&lt;/font&gt; test_model&lt;font color="#990000"&gt;(&lt;/font&gt;svm_model&lt;font color="#990000"&gt;,&lt;/font&gt; CrossSet&lt;font color="#990000"&gt;,&lt;/font&gt; CrossLabels&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; cross_validation_result &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; lowest_error&lt;br /&gt;      best_model &lt;font color="#990000"&gt;=&lt;/font&gt; svm_model&lt;br /&gt;      lowest_error &lt;font color="#990000"&gt;=&lt;/font&gt; cross_validation_result&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    puts &lt;font color="#FF0000"&gt;"Testing: C = #{cost}  G = #{gamma} -&amp;gt; #{cross_validation_result}"&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Error rate is: #{test_model(best_model, TestSet, TestLabels)*100.0/TestLabels.size}%"&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Final Result&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The performance of the final model is evaluated by finding the number of errors it makes against the test dataset.  In this case, I get an error rate of around 16%, which is not too bad, as I only trained on 2000 of the 20000 examples. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Summary&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;This description has covered the very simplest &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;mechanics&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; of working with RubySVM to build SVM models of data.  To get good quality models and properly evaluate the results, you need to be more careful in your selection of parameters and use of cross-validation and test sets.  The LibSVM documentation is a good place to start.  For optimum performance, the selection of the Cost and Gamma values is critical, and needs finer scale searching than I used above.&lt;br /&gt;&lt;br /&gt;You do have to be patient with these techniques.  The grid search is not quick; it took around 35 minutes on my 2.8GHz machine to run through all the models, and this was a fairly crude search.  This is not the fault of Ruby, as the computation time is required for LibSVM to build the models.  Ruby manages the entire data collection, transformation and model selection process in about 80 lines of fairly straightforward code.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-7312024613366333657?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/7312024613366333657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/working-with-rubysvm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7312024613366333657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7312024613366333657'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/working-with-rubysvm.html' title='Working with RubySVM'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3957432180991333199</id><published>2009-11-01T08:00:00.004Z</published><updated>2009-11-01T10:14:24.571Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='LibSVM'/><title type='text'>LibSVM and Ruby</title><content type='html'>&lt;a style="font-family: verdana;" href="http://www.csie.ntu.edu.tw/%7Ecjlin/libsvm/"&gt;LibSVM&lt;/a&gt;&lt;span style="font-family:verdana;"&gt; is the standard library for using Support Vector Machines, a powerful machine-learning tool.  Installing LibSVM can be done through your usual package manager system, or through the LibSVM download page.   &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;There is Ruby-LibSVM library, available from &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://rubysvm.cilibrar.com/download/"&gt;http://rubysvm.cilibrar.com/download/&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;.  If you download the library, you will find the installation instructions do not work for Ruby 1.9.  However, the fix is relatively simple.  After downloading and unpacking Ruby-LibSVM, run &lt;span style="font-family:courier new;"&gt;./configure&lt;/span&gt;.  Before compiling, modify the &lt;span style="font-family:courier new;"&gt;main.cpp&lt;/span&gt; file to allow for the change between Ruby 1.8 and Ruby 1.9.  I had to make three changes:&lt;/span&gt; &lt;ol style="font-family: verdana;"&gt;&lt;li&gt;remove the line &lt;span style="font-family: courier new;"&gt;#include "node.h"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;change &lt;span style="font-family: courier new;"&gt;RARRAY(xs)-&gt;len&lt;/span&gt; on line 50 to &lt;span style="font-family: courier new;"&gt; RARRAY_LEN(xs)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;change &lt;span style="font-family: courier new;"&gt;RARRAY(xs)-&gt;len&lt;/span&gt; on line 579 to &lt;span style="font-family: courier new;"&gt;RARRAY_LEN(xs)&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family:verdana;"&gt;(Thanks to &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://writequit.org/blog/?p=247&amp;amp;cpage=1#comment-442"&gt;Lee Hinman&lt;/a&gt;&lt;span style="font-family:verdana;"&gt; for the clue as to what to do.)&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;After those changes, I could finally run '&lt;span style="font-family:courier new;"&gt;make'&lt;/span&gt; and then '&lt;span style="font-family:courier new;"&gt;sudo make install&lt;/span&gt;' to install the LibSVM library for Ruby. &lt;span style="font-family:verdana;"&gt; &lt;/span&gt;&lt;a href="http://www.igvita.com/2008/01/07/support-vector-machines-svm-in-ruby/"&gt;Ilya Grigorik&lt;/a&gt; has a nice example of using Ruby-LibSVM, which I used to check everything was working.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-3957432180991333199?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/3957432180991333199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/libsvm-and-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3957432180991333199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3957432180991333199'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/11/libsvm-and-ruby.html' title='LibSVM and Ruby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4388689004890661250</id><published>2009-10-31T16:29:00.003Z</published><updated>2009-10-31T21:10:23.981Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Displaying Multi Column Data in wxRuby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;This post is about using the ListCtrl widget within wxRuby to display data in a table format, using several columns naming the fields in the data.  The most straightforward way to manage the data is to construct an underlying &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;data model&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;, and use the &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;virtual&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; listctrl style to have your data displayed dynamically.  This method also efficiently displays large datasets.  &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;To demonstrate the simplest case, I will display some data from a CSV text file.  For example, the &lt;/span&gt;&lt;/span&gt;&lt;a style="font-family: verdana;" href="http://archive.ics.uci.edu/ml/datasets/Letter+Recognition"&gt;letter recognition&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; dataset from the UCI machine learning repository consists of two &lt;/span&gt;&lt;span style="font-family: verdana;font-family:verdana;" &gt;files.  The file ending '.data' contains the raw data.  Each line contains the class and attributes of an instance from the data set.  &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;span style="font-family: verdana;"&gt;Each instance can be represented using a Ruby struct.  Taking the attribute names from the file ending '.names', I build the following struct:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;LetterInstance &lt;font color="#990000"&gt;=&lt;/font&gt; Struct&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(:&lt;/font&gt;letter&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_box&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;width&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;height&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;on_pixels&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;xybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x2ybar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xy2bar&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xegvy&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                            &lt;font color="#990000"&gt;:&lt;/font&gt;y_ege&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;yegvx&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;I define the Struct with the attribute names in the order that they occur in the CSV file, as this makes reading the CSV file simple.  To read in the textfile to create an array of instances of this struct:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@data&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"letter-recognition.data"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;f&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  f&lt;font color="#990000"&gt;.&lt;/font&gt;each_line &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;line&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt; &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; LetterInstance&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(*&lt;/font&gt;line&lt;font color="#990000"&gt;.&lt;/font&gt;strip&lt;font color="#990000"&gt;.&lt;/font&gt;split&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Displaying the Data&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Building the list control is almost trivial.  I use two facts about Ruby Structs to help in constructing the table automatically.  First, the method '&lt;span style="font-family:courier new;"&gt;members&lt;/span&gt;' can be used to find all the field names within the Struct; these are used for the column headings. &lt;br /&gt;&lt;br /&gt;For example: &lt;span style="font-family: courier new;"&gt;@@data[0].members.join(", ")&lt;/span&gt;&lt;br /&gt;returns: "&lt;span style="font-family: courier new;"&gt;letter, x_box, y_box, width, height, on_pixels, x_bar, y_bar, x2bar, y2bar, xybar, x2ybar, xy2bar, x_ege, xegvy, y_ege, yegvx&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Second, fields within a Struct can be accessed using array indexes.  So, &lt;span style="font-family: courier new;"&gt;@@data[0][0]&lt;/span&gt; returns the value in the 'letter' field of the first item.&lt;br /&gt;&lt;br /&gt;The following few lines of code create a class for our own virtual list control, which extends &lt;span style="font-family:courier new;"&gt;Wx::ListCtrl&lt;/span&gt;.  We are building a particular kind of list control, which uses 'report format' and a 'virtual list data model'.  Other kinds exist, but are not covered here.  The &lt;span style="font-family: courier new;"&gt;initialize&lt;/span&gt; method builds the columns automatically, and sets the number of items.  &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;The method '&lt;span style="font-family:courier new;"&gt;on_get_item_text&lt;/span&gt;' is the one which makes this virtual list control so easy to use.  The method is called only when an item is to be displayed.  It is given the index of the item to display, and the column number.  Your method just has to return the string for this item and column: as our data is stored as an array of structs, the implementation is as simple as can be.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- show data in a ListCtrl&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; LetterDataList &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ListCtrl&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize parent&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;parent&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;style &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;LC_REPORT &lt;font color="#990000"&gt;|&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;LC_VIRTUAL&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;?&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;or&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;empty?&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# Directly retrieve field names in Struct to populate table with columns&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;members&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;name&lt;font color="#990000"&gt;,&lt;/font&gt; index&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      insert_column&lt;font color="#990000"&gt;(&lt;/font&gt;index&lt;font color="#990000"&gt;,&lt;/font&gt; name&lt;font color="#990000"&gt;.&lt;/font&gt;to_s&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    set_item_count &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# use array like indexing of fields in Struct to&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# directly retrieve data for display&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; on_get_item_text&lt;font color="#990000"&gt;(&lt;/font&gt;item&lt;font color="#990000"&gt;,&lt;/font&gt; column&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;item&lt;font color="#990000"&gt;][&lt;/font&gt;column&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; LetterDisplay &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Letter Recognition Data"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    LetterDataList&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;  LetterDisplay&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A screenshot of the result:&lt;/span&gt;    &lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SuyfCbnBNRI/AAAAAAAAASM/XY4ejXbPqGI/s1600-h/display-list.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 177px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SuyfCbnBNRI/AAAAAAAAASM/XY4ejXbPqGI/s320/display-list.png" alt="" id="BLOGGER_PHOTO_ID_5398864917430351122" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Handling Events&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The list control supports a number of events.  The most useful are for catching double clicks on a row or change in the highlighted row.  Double clicks are known as &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;activating&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; the item, and single clicks as &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;selecting&lt;/span&gt; the item.  The event &lt;strong&gt;evt_list_item_activated &lt;span style="font-weight: normal; font-family: verdana;font-family:verdana;" &gt;captures a &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family: verdana;"&gt;double click, and the event&lt;/span&gt; &lt;strong&gt;evt_list_item_selected &lt;/strong&gt;&lt;span style="font-family: verdana;"&gt;captures a change in the focussed item (through a single click or use of arrow keys).  Both events are easy to capture and redirect to a method to handle them.  The following code will just print out the item(s) now selected by walking through the list of selected indices obtained by calling &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;selections&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; LetterDataList &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ListCtrl&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize parent&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;parent&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;style &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;LC_REPORT &lt;font color="#990000"&gt;|&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;LC_VIRTUAL&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;?&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;or&lt;/font&gt;&lt;/b&gt; &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;empty?&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# Directly retrieve field names in Struct to populate table with columns&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;members&lt;font color="#990000"&gt;.&lt;/font&gt;each_with_index &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;name&lt;font color="#990000"&gt;,&lt;/font&gt; index&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      insert_column&lt;font color="#990000"&gt;(&lt;/font&gt;index&lt;font color="#990000"&gt;,&lt;/font&gt; name&lt;font color="#990000"&gt;.&lt;/font&gt;to_s&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    evt_list_item_selected&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt; selected_item &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_item_count &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# use array like indexing of fields in Struct to&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# directly retrieve data for display&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; on_get_item_text&lt;font color="#990000"&gt;(&lt;/font&gt;item&lt;font color="#990000"&gt;,&lt;/font&gt; column&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;item&lt;font color="#990000"&gt;][&lt;/font&gt;column&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; selected_item&lt;br /&gt;    get_selections&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;selection&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      puts &lt;font color="#009900"&gt;@@data&lt;/font&gt;&lt;font color="#990000"&gt;[&lt;/font&gt;selection&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4388689004890661250?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4388689004890661250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/displaying-multi-column-data-in-wxruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4388689004890661250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4388689004890661250'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/displaying-multi-column-data-in-wxruby.html' title='Displaying Multi Column Data in wxRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-BL9uSD-L0k/SuyfCbnBNRI/AAAAAAAAASM/XY4ejXbPqGI/s72-c/display-list.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4423418184609601383</id><published>2009-10-15T22:10:00.010+01:00</published><updated>2009-10-15T22:58:44.126+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WEKA'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><category scheme='http://www.blogger.com/atom/ns#' term='netbeans'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Using jRuby from Netbeans</title><content type='html'>&lt;span style="font-family:verdana;"&gt;&lt;a href="http://www.netbeans.org/"&gt;Netbeans&lt;/a&gt; is a great development platform which supports Ruby and jRuby.  In this post, I have collected together the steps I needed to write and run a jRuby script with a library file, such as &lt;a href="http://www.cs.waikato.ac.nz/ml/weka/"&gt;Weka&lt;/a&gt; or my own &lt;a href="http://homepages.feis.herts.ac.uk/%7Ecomqpcl/chrest-software.html"&gt;jChrest&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;First, you must download and install the Netbeans platform. ( I started by downloading the version for Java SE alone.)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Second, you must add the plugin to use Ruby programs.  To do this start up Netbeans, and select the 'plugins' option on the 'Tools' menu.  Under the tab for 'Available plugins', select the 'Ruby' plugin and install it.  (You may not need this step, if you downloaded a version with Ruby included in the previous step.)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Third, &lt;a href="http://jruby.org/download"&gt;download and install jRuby&lt;/a&gt;.  You need to download and unpack one of the 'binary' distributions.  Take note of the 'bin' directory, as you need to know this to tell Netbeans about your jRuby distribution.&lt;br /&gt;&lt;br /&gt;Fourth, start up Netbeans and create a new ruby project.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SteWObXGN0I/AAAAAAAAARs/CEivXb5F7R4/s1600-h/start-project.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 215px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SteWObXGN0I/AAAAAAAAARs/CEivXb5F7R4/s320/start-project.png" alt="" id="BLOGGER_PHOTO_ID_5392944253406426946" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;After clicking 'next' you need to specify the Ruby platform you want to use.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SteWZPkf4dI/AAAAAAAAAR0/xwg2bCJYfBw/s1600-h/new-ruby-project.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 203px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SteWZPkf4dI/AAAAAAAAAR0/xwg2bCJYfBw/s320/new-ruby-project.png" alt="" id="BLOGGER_PHOTO_ID_5392944439219970514" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;The first time we do this, we must tell Netbeans about our new jRuby installation, so click on 'Manage...' and select the 'jruby' executable in the 'bin' directory you installed in step 3.  Once you've done this, Netbeans will remember your jruby installation for future projects.&lt;br /&gt;&lt;br /&gt;Now, you can create some ruby code and click on 'Run Main Project' to see the output in the 'Output window'.  Two things may need changing.  First, to set a project to be the 'Main' project, the one which is run when you click the green triangle, you need to right click on the name of the project and select 'Set as Main Project'.  Second, you may need to change the ruby platform or version.  Again, right click on the name of the project and select 'Properties'.  Click on the 'Run' option on the left hand side and you can change the Ruby Platform in the choice box, and add options to the interpreter.  In the example below, you can see I have made jRuby use 1.9 mode:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-BL9uSD-L0k/SteXoOr4fII/AAAAAAAAAR8/TN4O7HD0dZA/s1600-h/project-properties.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 230px;" src="http://2.bp.blogspot.com/_-BL9uSD-L0k/SteXoOr4fII/AAAAAAAAAR8/TN4O7HD0dZA/s320/project-properties.png" alt="" id="BLOGGER_PHOTO_ID_5392945796192173186" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Accessing Java Libraries&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The final step in setting up the environment is to include a Java library within the project.  For example, to work with Weka, you need to access the file &lt;span style="font-family:courier new;"&gt;weka.jar&lt;/span&gt;.  To do this within Netbeans, go to the 'Java' option in the Properties dialog box shown above.  Select 'Add JAR/Folder' and add the jar file to the classpath for this project.  That's all there is to it.  The only change I needed to make to my scripts was to remove the line '&lt;span style="font-family:courier new;"&gt;require "weka"&lt;/span&gt;'; this is taken care of by adding the jar file to the project.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-BL9uSD-L0k/SteZ3mRjtKI/AAAAAAAAASE/Zop0OGcHp8I/s1600-h/netbeans-weka.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 260px;" src="http://3.bp.blogspot.com/_-BL9uSD-L0k/SteZ3mRjtKI/AAAAAAAAASE/Zop0OGcHp8I/s320/netbeans-weka.png" alt="" id="BLOGGER_PHOTO_ID_5392948259245503650" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4423418184609601383?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4423418184609601383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/10/using-jruby-from-netbeans.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4423418184609601383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4423418184609601383'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/10/using-jruby-from-netbeans.html' title='Using jRuby from Netbeans'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-BL9uSD-L0k/SteWObXGN0I/AAAAAAAAARs/CEivXb5F7R4/s72-c/start-project.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-6548532033464961467</id><published>2009-10-03T09:56:00.020+01:00</published><updated>2009-10-03T19:18:05.487+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RSRuby'/><category scheme='http://www.blogger.com/atom/ns#' term='R'/><title type='text'>Plotting Multiple Data Sources in RSRuby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;In this post, I look at plotting multiple data sources on a single graph from RSRuby, and also how to use Ruby to simplify the method of constructing such graphs.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Plotting Multiple Data Sources&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Consider the table below as a typical example, which contains some data on craters on different planetary bodies of the solar system.  There are three columns.  The first gives the parent body (planet) of the crater, the second gives the diameter of the crater, and the third gives the depth of the crater.  What we would like to see is a plot with the two axes holding the quantitative information, and the labels of the points showing the planet. (Note: these are not real data.)&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table style="font-family: verdana;" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Planetary Body&lt;/th&gt;&lt;th&gt;Diameter (km)&lt;/th&gt;&lt;th&gt;Depth (km)&lt;/th&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Moon&lt;/td&gt;&lt;td&gt;335&lt;/td&gt;&lt;td&gt;5.7&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Moon&lt;/td&gt;&lt;td&gt;66&lt;/td&gt;&lt;td&gt;3.0&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Moon&lt;/td&gt;&lt;td&gt;41&lt;/td&gt;&lt;td&gt;2.5&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Mars&lt;/td&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;1.0&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Mars&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;td&gt;1.5&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Ganymede&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;0.8&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Ganymede&lt;/td&gt;&lt;td&gt;70&lt;/td&gt;&lt;td&gt;1.0&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Ganymede&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;td&gt;0.9&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;In a previous post, I looked at plotting a single set of points.  For example, to make a simple graph of diameter vs depth for the Moon's craters, you could use the following code:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"mygraph.png"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;plot&lt;font color="#990000"&gt;([&lt;/font&gt;&lt;font color="#993399"&gt;335&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;66&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;41&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;5.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;3.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2.5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Diameter (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;ylab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Depth (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;main &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Crater diameter vs. depth"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;xlim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;350&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;ylim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;6&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;        &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"blue"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The points are plotted using a symbol, controlled by the number passed to :pch.  The range of numbers for :pch goes from 1 to 25.  &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.phaget4.org/R/plot.html"&gt;http://www.phaget4.org/R/plot.html&lt;/a&gt;&lt;span style="font-family:verdana;"&gt; has a diagram showing the effect of the different numbers, but it is good to experiment a little for your own graph. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;To add more points to the graph, with different symbols, we use the 'points' command for each group of data, before the 'eval' command:&lt;/span&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"mygraph.png"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;plot&lt;font color="#990000"&gt;([&lt;/font&gt;&lt;font color="#993399"&gt;335&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;66&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;41&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;5.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;3.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2.5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Diameter (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;ylab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Depth (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;main &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Crater diameter vs. depth"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;xlim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;350&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;ylim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;6&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;        &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"blue"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;points&lt;font color="#990000"&gt;([&lt;/font&gt;&lt;font color="#993399"&gt;50&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;19&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"green"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;points&lt;font color="#990000"&gt;([&lt;/font&gt;&lt;font color="#993399"&gt;20&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.9&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;4&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"red"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The resulting graph is:&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-BL9uSD-L0k/SseT0jcXC9I/AAAAAAAAARM/isrXor2mP6g/s1600-h/graph.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://3.bp.blogspot.com/_-BL9uSD-L0k/SseT0jcXC9I/AAAAAAAAARM/isrXor2mP6g/s320/graph.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5388438010248760274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Simplifying the Code&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Automation is a big benefit of doing the above kind of process from Ruby.  How can we simplify the code to make it as easy as possible to construct and save a graph from a new set of data?  For example, if we extend the above table with another two attributes, we might want to create all possible 6 graphs, one for each pair of attributes.  To make the call as easy as possible, we need to encapsulate the graph construction process within a single function with some suitable parameters.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;First, we need a structure to represent the data in a single group.  Ruby provides a &lt;tt&gt;Struct&lt;/tt&gt; data structure just for such purposes.  We create a &lt;tt&gt;Struct&lt;/tt&gt; holding the label, points and display information for the group of data.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;DataItems &lt;font color="#990000"&gt;=&lt;/font&gt; Struct&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(:&lt;/font&gt;name&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;x_points&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;y_points&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;pch&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Then, the graph construction function can process an array of these structures, adding the information to the graph.  The construction process adds all the data using the 'points' method in R.  For this to work, you &lt;em&gt;have&lt;/em&gt; to provide 'xlim' and 'ylim' in the parameters so the graph is drawn to the correct size.  The 'plot_graph' method works by iterating through a list of provided DataItems, and adding the points to the graph using the display attributes.  As an extra, there is a line to add a legend to the graph, again by collecting information from the DataItems array:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;module&lt;/font&gt;&lt;/b&gt; L&lt;br /&gt;  R &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;plot_graph&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; data&lt;font color="#990000"&gt;,&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;res &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#993399"&gt;100&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;plot&lt;font color="#990000"&gt;([],&lt;/font&gt; &lt;font color="#990000"&gt;[],&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    data&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;items&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      R&lt;font color="#990000"&gt;.&lt;/font&gt;points&lt;font color="#990000"&gt;(&lt;/font&gt;items&lt;font color="#990000"&gt;.&lt;/font&gt;x_points&lt;font color="#990000"&gt;,&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;y_points&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;pch&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;col&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;legend&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"bottomright"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; data&lt;font color="#990000"&gt;.&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;items&lt;font color="#990000"&gt;|&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;name&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;             &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; data&lt;font color="#990000"&gt;.&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;items&lt;font color="#990000"&gt;|&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;col&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;             &lt;font color="#990000"&gt;:&lt;/font&gt;pch &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; data&lt;font color="#990000"&gt;.&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;items&lt;font color="#990000"&gt;|&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;pch&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Finally, this is how to plot the same graph as above:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;L&lt;font color="#990000"&gt;.&lt;/font&gt;plot_graph&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"graph.png"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;             &lt;font color="#990000"&gt;[&lt;/font&gt;DataItems&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Moon"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;335&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;66&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;41&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;5.7&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;3.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2.5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#993399"&gt;15&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"blue"&lt;/font&gt;&lt;font color="#990000"&gt;),&lt;/font&gt;&lt;br /&gt;              DataItems&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Mars"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;50&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#993399"&gt;19&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"green"&lt;/font&gt;&lt;font color="#990000"&gt;),&lt;/font&gt;&lt;br /&gt;              DataItems&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Ganymede"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;20&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0.8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1.0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0.9&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#993399"&gt;4&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"red"&lt;/font&gt;&lt;font color="#990000"&gt;)],&lt;/font&gt;&lt;br /&gt;              &lt;font color="#990000"&gt;:&lt;/font&gt;xlim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;350&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;              &lt;font color="#990000"&gt;:&lt;/font&gt;ylim &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;6&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;              &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Diameter (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;              &lt;font color="#990000"&gt;:&lt;/font&gt;ylab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Depth (km)"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;              &lt;font color="#990000"&gt;:&lt;/font&gt;main &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Crater diameter vs. depth"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;There are still parts that could be included as parameters to the function, such as the location of the legend.  The advantage of an approach such as the above is not to make it into a general function, but to provide a pattern to copy and modify in a particular case.  With the above, the call to create a graph is a single method call, and that can make automation of graph construction a lot easier.  For example, to create a whole range of graphs from a table of data.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-6548532033464961467?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/6548532033464961467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/10/plotting-multiple-data-sources-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6548532033464961467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6548532033464961467'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/10/plotting-multiple-data-sources-in.html' title='Plotting Multiple Data Sources in RSRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-BL9uSD-L0k/SseT0jcXC9I/AAAAAAAAARM/isrXor2mP6g/s72-c/graph.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3852006879724404978</id><published>2009-09-06T12:48:00.009+01:00</published><updated>2009-09-07T13:34:19.770+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WEKA'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>Using the UCI Datasets with jRuby and WEKA</title><content type='html'>The &lt;a href="http://archive.ics.uci.edu/ml/"&gt;UCI Machine Learning Repository&lt;/a&gt; is one address which should be in every machine-learner's Bookmarks list.  The repository (as of now!) holds 177 datasets which have been used as applications and to test machine learning and data-mining algorithms for several decades.  Some of the datasets are relatively small and well explored, suitable for evaluating a new algorithm, but some of the datasets are large, and present a real data-mining challenge.  For instance, the Soybean dataset was contributed in 1988 and has around 600 instances in total, whereas the Poker Hand dataset was contributed in 2007 and has over a million instances.  There are datasets covering a wide variety of applications, from classification of attribute-value data, such as the Mushroom dataset, to regression on numeric data, such as the Auto MPG dataset.  My favourites are the various Molecular Biology datasets and the subset of the NASA dataset of Volcanoes on Venus.&lt;br /&gt;&lt;br /&gt;Working with these datasets is a useful exercise to learn about different machine-learning applications, and particularly for exploring the capabilities of learning algorithms with which you are unfamiliar. You can compare your own experimental results with those of previous researchers, and make sure you are using the algorithms correctly.  Also, if and when you create your own learning algorithm, you can evaluate its performance on these standard datasets, and hence compare it with previous algorithms.&lt;br /&gt;&lt;br /&gt;However, the format of the datasets is not consistent, although most of the data can be viewed in standard text editors.  Before we can begin exploring these datasets within a toolkit such as WEKA, we must convert the data into a format that WEKA can understand.  One way would be to write a tool to convert the original data format into WEKA's ARFF file format, and then work with the graphical tool.  A different way, which follows on from my &lt;a href="http://rubyforscientificresearch.blogspot.com/2009/08/accessing-weka-from-jruby.html"&gt;previous post&lt;/a&gt;, is to use jRuby to talk directly to WEKA; jRuby can then be used to read in and analyse the custom data format, before developing and evaluating machine-learning algorithms through the WEKA API.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Reading UCI Datasets&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using WEKA with files like the UCI datasets means converting an external data format into the internal format used within WEKA.  As I covered in my &lt;a href="http://rubyforscientificresearch.blogspot.com/2009/08/accessing-weka-from-jruby.html"&gt;previous post&lt;/a&gt;, WEKA instances must be constructed using a set of Attribute instances, where each Attribute describes its name, type (numeric or nominal) and the range of values it can hold, if nominal.  Setting up these attributes is the tedious step.  You have to look in the description of the data, and extract the attributes names, type and values, then code it into Ruby.  The following was created using information from the 'names' file of the Mushroom dataset, to create an array of Attributes and a Label attribute:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Convert provided arguments into a FastVector&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- use mainly in making nominal attributes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_vector &lt;font color="#990000"&gt;*&lt;/font&gt;args&lt;br /&gt;  atts &lt;font color="#990000"&gt;=&lt;/font&gt; FastVector&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;args&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  args&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;arg&lt;font color="#990000"&gt;|&lt;/font&gt; atts&lt;font color="#990000"&gt;.&lt;/font&gt;addElement arg&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; atts&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# == Create the attributes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Attributes &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"cap-shape"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"x"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"k"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"cap_surface"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"cap_colour"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"bruises?"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"t"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"odour"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"a"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"l"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"m"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"gill-attachment"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"a"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"d"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"gill-spacing"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"d"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"gill-size"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"gill-colour"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"k"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"h"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-shape"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"t"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-root"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"z"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"?"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-surface-above-ring"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"k"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-surface-below-ring"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"k"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-colour-above-ring"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"stalk-colour-below-ring"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"veil-type"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"veil-colour"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"ring-number"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"t"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"ring-type"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"f"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"l"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"z"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"spore-print-colour"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"k"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"h"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"o"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"population"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"a"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"c"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"n"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"s"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"v"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;)),&lt;/font&gt;&lt;br /&gt;  Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"habitat"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"g"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"l"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"m"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"u"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"w"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"d"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;Label &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"class"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"p"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"e"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The 'data' file of the Mushroom dataset contains lines of characters, in the following format:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;p,x,s,n,t,p,f,c,n,k,e,e,s,s,w,w,p,w,o,p,k,s,u&lt;br /&gt;e,x,s,y,t,a,f,c,b,k,e,c,s,s,w,w,p,w,o,p,n,n,g&lt;br /&gt;e,b,s,w,t,l,f,c,b,n,e,c,s,s,w,w,p,w,o,p,n,n,m&lt;br /&gt;p,x,y,w,t,p,f,c,n,n,e,e,s,s,w,w,p,w,o,p,k,s,u&lt;br /&gt;e,x,s,g,f,n,f,w,b,k,t,e,s,s,w,w,p,w,o,e,n,a,g&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Each line represents one instance, which later we will need to convert into a WEKA instance.  The trick with the WEKA instances is that each must be linked to the dataset in which it lies.  When I load the data, I don't know which dataset I will want each line to be added to.   So, I construct instances of the following class as I read in the data.  The class has a method which will build an instance and put it in the appropriate dataset, when called.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; UciInstance&lt;br /&gt;  attr_reader &lt;font color="#990000"&gt;:&lt;/font&gt;features&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;label&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;font color="#990000"&gt;(&lt;/font&gt;features&lt;font color="#990000"&gt;,&lt;/font&gt; class_label&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@features&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; features&lt;br /&gt;    &lt;font color="#009900"&gt;@label&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; class_label&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# Convert raw data into WEKA Instance and add to dataset&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# -- assumes features.length == Attributes.length&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_instance dataset&lt;br /&gt;    instance &lt;font color="#990000"&gt;=&lt;/font&gt; Instance&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;Attributes&lt;font color="#990000"&gt;.&lt;/font&gt;length &lt;font color="#990000"&gt;+&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    Attributes&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;Attributes&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;],&lt;/font&gt; features&lt;font color="#990000"&gt;[&lt;/font&gt;i&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;Label&lt;font color="#990000"&gt;,&lt;/font&gt; label&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    instance&lt;font color="#990000"&gt;.&lt;/font&gt;setDataset dataset&lt;br /&gt;    dataset&lt;font color="#990000"&gt;.&lt;/font&gt;add instance&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- routine to read in a UCI dataset, and return a list of UciInstances&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- modify the parts to extract the features and class label, based on &lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#    input data format&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; read_csv filename&lt;br /&gt;  data &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;  File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;f&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    f&lt;font color="#990000"&gt;.&lt;/font&gt;each_line &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;line&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      items &lt;font color="#990000"&gt;=&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;rstrip&lt;font color="#990000"&gt;.&lt;/font&gt;split&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;      features &lt;font color="#990000"&gt;=&lt;/font&gt; items&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; items&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;      class_label &lt;font color="#990000"&gt;=&lt;/font&gt; items&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;      data &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; UciInstance&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;features&lt;font color="#990000"&gt;,&lt;/font&gt; class_label&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; data&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;DataSet &lt;font color="#990000"&gt;=&lt;/font&gt; read_csv&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"agaricus-lepiota.data"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The above code will produce an array, &lt;tt&gt;DataSet&lt;/tt&gt;, containing the items from the original dataset.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Comparing Algorithms&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;WEKA contains a huge number of algorithms.  Just to name two, there is J48 for building decision-tree classifiers, and IB1 for constructing an instance-based classifier.  Which one should we use?  The answer to that question can be complex, and depends a lot on how intelligible we want the machine-learning model to be (decision trees and rules are much better for explaining outcomes than neural networks, for example).  But a straightforward empirical question is to ask which of the two produces the best result on a given dataset.   There is a fairly standard set of comparison techniques in machine learning, all based around the idea of a &lt;span style="font-style: italic;"&gt;held-out test set&lt;/span&gt;, which is a dataset not used in training the model.&lt;br /&gt;&lt;br /&gt;A held-out test set is required to prevent the following algorithm being the best learning algorithm:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;When learning, remember every training instance and its classification.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;When tested, see if the test instance is one of the ones we know. &lt;/li&gt;  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;If it is, then return the classification we already know.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If it is not, then return a random result.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;This algorithm will always produce perfect results on the training material, but will only give chance results on new data.  The algorithm does not &lt;span style="font-style: italic;"&gt;generalise&lt;/span&gt;.  We actually don't care how well the trained model performs on the training data, what we care about is how well the model performs on new data.  This is why we use a held-out test set to see how well the model works on new data.&lt;br /&gt;&lt;br /&gt;The simplest approach is to split the complete dataset into a Training and a Test partition.  We build the classifiers on the Training set and then evaluate both on the same Test set.  In this way, the only variable is the type of learning algorithm - the training data and test data are the same.  (A more precise way of evaluating algorithms is based on &lt;a href="http://en.wikipedia.org/wiki/Cross-validation_%28statistics%29"&gt;cross validation&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Constructing the datasets&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the earlier section, we used a function to construct an array of UciInstance objects from the data file.  To build the training and test sets, we first partition that array into two sections, based on a target proportion.  Then we need to construct a WekaTrainingSet and WekaTestSet, which are instances of the WEKA Instances class.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Randomly partition given array of items into two arrays, using given proportion&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; split_array&lt;font color="#990000"&gt;(&lt;/font&gt;array&lt;font color="#990000"&gt;,&lt;/font&gt; proportion&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  array1&lt;font color="#990000"&gt;,&lt;/font&gt; array2 &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[],&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;  array&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;item&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; rand &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; proportion&lt;br /&gt;      array1 &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; item&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;else&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;      array2 &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; item&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;array1&lt;font color="#990000"&gt;,&lt;/font&gt; array2&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;TrainingSet&lt;font color="#990000"&gt;,&lt;/font&gt; TestSet &lt;font color="#990000"&gt;=&lt;/font&gt; split_array&lt;font color="#990000"&gt;(&lt;/font&gt;DataSet&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0.1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;WekaTrainingSet &lt;font color="#990000"&gt;=&lt;/font&gt; Instances&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Mushrooms training dataset"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                          make_vector&lt;font color="#990000"&gt;(*(&lt;/font&gt;Attributes&lt;font color="#990000"&gt;.&lt;/font&gt;clone &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; Label&lt;font color="#990000"&gt;)),&lt;/font&gt; &lt;br /&gt;                          TrainingSet&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;WekaTrainingSet&lt;font color="#990000"&gt;.&lt;/font&gt;setClassIndex&lt;font color="#990000"&gt;(&lt;/font&gt;WekaTrainingSet&lt;font color="#990000"&gt;.&lt;/font&gt;numAttributes&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;WekaTestSet &lt;font color="#990000"&gt;=&lt;/font&gt; Instances&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Mushrooms test dataset"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                          make_vector&lt;font color="#990000"&gt;(*(&lt;/font&gt;Attributes&lt;font color="#990000"&gt;.&lt;/font&gt;clone &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; Label&lt;font color="#990000"&gt;)),&lt;/font&gt; &lt;br /&gt;                          TestSet&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;WekaTestSet&lt;font color="#990000"&gt;.&lt;/font&gt;setClassIndex&lt;font color="#990000"&gt;(&lt;/font&gt;WekaTestSet&lt;font color="#990000"&gt;.&lt;/font&gt;numAttributes&lt;font color="#990000"&gt;()&lt;/font&gt; &lt;font color="#990000"&gt;-&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;TrainingSet&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;font color="#FF0000"&gt;{&lt;/font&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;instance&lt;font color="#990000"&gt;|&lt;/font&gt; instance&lt;font color="#990000"&gt;.&lt;/font&gt;make_instance&lt;font color="#990000"&gt;(&lt;/font&gt;WekaTrainingSet&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;TestSet&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;font color="#FF0000"&gt;{&lt;/font&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;instance&lt;font color="#990000"&gt;|&lt;/font&gt; instance&lt;font color="#990000"&gt;.&lt;/font&gt;make_instance&lt;font color="#990000"&gt;(&lt;/font&gt;WekaTestSet&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Training set size: #{WekaTrainingSet.numInstances}"&lt;/font&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Test     set size: #{WekaTestSet.numInstances}"&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Constructing the models&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Building the models is simple using WEKA's API.  We simply create instances of the classifiers and train them on the training set:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# == kNN classifier&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.classifiers.lazy.IB1"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;ib1 &lt;font color="#990000"&gt;=&lt;/font&gt; IB1&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;ib1&lt;font color="#990000"&gt;.&lt;/font&gt;buildClassifier WekaTrainingSet&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# == J48 classifier&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.classifiers.trees.J48"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;j48 &lt;font color="#990000"&gt;=&lt;/font&gt; J48&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;j48&lt;font color="#990000"&gt;.&lt;/font&gt;buildClassifier WekaTrainingSet&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Evaluating&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The evaluation procedure can be wrapped into a function which takes a classifier and a dataset, and returns the percentage of the dataset which the classifier has got correct:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Check result of classifying each instance against the target result&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# and return percentage correct&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; evaluate_classifier&lt;font color="#990000"&gt;(&lt;/font&gt;classifier&lt;font color="#990000"&gt;,&lt;/font&gt; testset&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  num_correct &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;br /&gt;  testset&lt;font color="#990000"&gt;.&lt;/font&gt;numInstances&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; testset&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;font color="#990000"&gt;(&lt;/font&gt;i&lt;font color="#990000"&gt;).&lt;/font&gt;classValue &lt;font color="#990000"&gt;==&lt;/font&gt; classifier&lt;font color="#990000"&gt;.&lt;/font&gt;classifyInstance&lt;font color="#990000"&gt;(&lt;/font&gt;testset&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;font color="#990000"&gt;(&lt;/font&gt;i&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;        num_correct &lt;font color="#990000"&gt;+=&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt; &lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; java&lt;font color="#990000"&gt;.&lt;/font&gt;lang&lt;font color="#990000"&gt;.&lt;/font&gt;Exception&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; &lt;font color="#993399"&gt;100&lt;/font&gt;&lt;font color="#990000"&gt;*&lt;/font&gt;num_correct&lt;font color="#990000"&gt;.&lt;/font&gt;quo&lt;font color="#990000"&gt;(&lt;/font&gt;testset&lt;font color="#990000"&gt;.&lt;/font&gt;numInstances&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Performance of IB1 is: #{evaluate_classifier(ib1, WekaTestSet)}%"&lt;/font&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Performance of J48 is: #{evaluate_classifier(j48, WekaTestSet)}%"&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Result&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When the above is run, we get an output like:&lt;br /&gt;&lt;br /&gt;Training set size: 787&lt;br /&gt;Test     set size: 7337&lt;br /&gt;Performance of IB1 is: 100.0%&lt;br /&gt;Performance of J48 is: 99.90459315796647%&lt;br /&gt;&lt;br /&gt;which tells us that both algorithms do very well on the test set when trained on only 10% of the original dataset.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That is a lot of work, initially, to set up the functions to interact with WEKA.  Looking back, we see that UciInstance, evaluate_classifier, and the code to convert an array of UciInstance objects into an example of WEKA Instances are all reusable pieces of code.  They can be packaged up into a library file to be used in future work with WEKA and similar datasets.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-3852006879724404978?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/3852006879724404978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/09/using-uci-datasets-with-jruby-and-weka.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3852006879724404978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/3852006879724404978'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/09/using-uci-datasets-with-jruby-and-weka.html' title='Using the UCI Datasets with jRuby and WEKA'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-459961306578455006</id><published>2009-08-15T22:08:00.010+01:00</published><updated>2009-09-02T16:38:32.395+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WEKA'/><category scheme='http://www.blogger.com/atom/ns#' term='jruby'/><title type='text'>Accessing WEKA from jRuby</title><content type='html'>WEKA (&lt;a href="http://www.cs.waikato.ac.nz/ml/weka/"&gt;http://www.cs.waikato.ac.nz/ml/weka/&lt;/a&gt;) is a data mining platform and library, written in Java.  The platform contains implementations of numerous machine-learning algorithms and data-processing filters.  The best way of getting hold of the system is to download the zip file, described as 'for Linux'.  Unpack the zipped folder, and copy the 'weka.jar' file to your working directory; everything else in the folder is documentation or examples, and not necessary to work with WEKA.&lt;br /&gt;&lt;br /&gt;You will also need jruby (&lt;a href="http://jruby.codehaus.org/"&gt;http://jruby.codehaus.org/&lt;/a&gt;); I have renamed the jruby jar to simply &lt;span style="font-family: courier new;"&gt;jruby.jar&lt;/span&gt;.  When I wrote this, WEKA was at version 3.6.1 and jruby was at version 1.3.0.&lt;br /&gt;&lt;br /&gt;The graphical interface for WEKA can be called up by entering '&lt;span style="font-family: courier new;"&gt;java -jar weka.jar&lt;/span&gt;'  on the command prompt.  However, if you add weka.jar to the CLASSPATH, the classes in weka.jar become accessible as an API.  The API is documented in javadoc format: point your browser at the file 'documentation.html' within the weka folder, and click on 'Package Documentation'. &lt;br /&gt;&lt;br /&gt;Assuming weka.jar, jruby.jar, and your program are in the same folder, the calling format is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write a ruby program, and store in a file, say 'wekascript.rb'&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: courier new;"&gt;java -jar jruby.jar wekascript.rb&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Further command line arguments can be provided, and picked up in the Ruby program through ARGV, as we shall see shortly.  (You can streamline this process by adding weka.jar permanently to your CLASSPATH environment variable if you wish.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Clustering Data using WEKA from jRuby&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;jRuby provides easy access to Java classes and methods, and WEKA is no exception.  The following program builds a simple kmeans clusterer on a supplied input file, and then prints out the assigned cluster for each data instance.  The 'include_class' statements are there to simplify references to classes in the API.  When classifying each instance, we must watch for the exception thrown in case a classification cannot be made.  Finally, notice that the filename is passed as a command-line parameter: the parameters after the name of the jruby program are packaged up into ARGV in the usual ruby style.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Weka scripting from jruby&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Written by Peter Lane, 2009.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Run with: java -jar jruby.jar trial-kmeans.rb FILENAME.arff&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"java"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"weka"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"java.io.FileReader"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.clusterers.SimpleKMeans"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.core.Instances"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# load data file&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;file &lt;font color="#990000"&gt;=&lt;/font&gt; FileReader&lt;font color="#990000"&gt;.&lt;/font&gt;new ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;data &lt;font color="#990000"&gt;=&lt;/font&gt; Instances&lt;font color="#990000"&gt;.&lt;/font&gt;new file&lt;br /&gt; &lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# create the model&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;kmeans &lt;font color="#990000"&gt;=&lt;/font&gt; SimpleKMeans&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;kmeans&lt;font color="#990000"&gt;.&lt;/font&gt;buildClusterer data&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# print out the built model&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;print kmeans&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Display the cluster for each instance&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;data&lt;font color="#990000"&gt;.&lt;/font&gt;numInstances&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  cluster &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"UNKNOWN"&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    cluster &lt;font color="#990000"&gt;=&lt;/font&gt; kmeans&lt;font color="#990000"&gt;.&lt;/font&gt;clusterInstance&lt;font color="#990000"&gt;(&lt;/font&gt;data&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;font color="#990000"&gt;(&lt;/font&gt;i&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; java&lt;font color="#990000"&gt;.&lt;/font&gt;lang&lt;font color="#990000"&gt;.&lt;/font&gt;Exception&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"#{data.instance(i)},#{cluster}"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;We can see that the WEKA api makes it easy to pass in a data file.  Data can be in a number of formats, including ARFF and CSV.&lt;br /&gt;&lt;br /&gt;When run on the weather.arff example (in WEKA's 'data' folder), the output looks like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;kMeans&lt;br /&gt;======&lt;br /&gt;&lt;br /&gt;Number of iterations: 3&lt;br /&gt;Within cluster sum of squared errors: 16.237456311387238&lt;br /&gt;Missing values globally replaced with mean/mode&lt;br /&gt;&lt;br /&gt;Cluster centroids:&lt;br /&gt;                           Cluster#&lt;br /&gt;Attribute      Full Data          0          1&lt;br /&gt;                    (14)        (9)        (5)&lt;br /&gt;==============================================&lt;br /&gt;outlook            sunny      sunny   overcast&lt;br /&gt;temperature      73.5714    75.8889       69.4&lt;br /&gt;humidity         81.6429    84.1111       77.2&lt;br /&gt;windy              FALSE      FALSE       TRUE&lt;br /&gt;play                 yes        yes        yes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;sunny,85,85,FALSE,no,0&lt;br /&gt;sunny,80,90,TRUE,no,0&lt;br /&gt;overcast,83,86,FALSE,yes,0&lt;br /&gt;rainy,70,96,FALSE,yes,0&lt;br /&gt;rainy,68,80,FALSE,yes,0&lt;br /&gt;rainy,65,70,TRUE,no,1&lt;br /&gt;overcast,64,65,TRUE,yes,1&lt;br /&gt;sunny,72,95,FALSE,no,0&lt;br /&gt;sunny,69,70,FALSE,yes,0&lt;br /&gt;rainy,75,80,FALSE,yes,0&lt;br /&gt;sunny,75,70,TRUE,yes,1&lt;br /&gt;overcast,72,90,TRUE,yes,1&lt;br /&gt;overcast,81,75,FALSE,yes,0&lt;br /&gt;rainy,71,91,TRUE,no,1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-size:130%;"&gt;Using jRuby to Create Instances&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One of the advantages of using a language like jruby to talk to WEKA is that we should have more control on how our data is constructed and passed to the machine-learning algorithms.  A good start is how to construct our own set of instances, rather than reading them directly in from file.  There are some quirks to WEKA's construction of a set of Instances.  In particular, each attribute must be defined through an instance of the Attribute class.  This class gives a string name to the attribute and, if the attribute is a nominal attribute, the class also holds a vector of the nominal values.  Each instance can then be constructed and added to the growing set of Instances.  The code below shows how to 'by-hand' construct a dataset which can then be passed to one of WEKA's learning algorithms.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"java"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;"weka"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.clusterers.SimpleKMeans"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.core.Instances"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.core.Instance"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.core.Attribute"&lt;/font&gt;&lt;br /&gt;include_class &lt;font color="#FF0000"&gt;"weka.core.FastVector"&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Convert provided arguments into a FastVector&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- use mainly in making nominal attributes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_vector &lt;font color="#990000"&gt;*&lt;/font&gt;args&lt;br /&gt;  atts &lt;font color="#990000"&gt;=&lt;/font&gt; FastVector&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;args&lt;font color="#990000"&gt;.&lt;/font&gt;length&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  args&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;arg&lt;font color="#990000"&gt;|&lt;/font&gt; atts&lt;font color="#990000"&gt;.&lt;/font&gt;addElement arg&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; atts&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Create the five attributes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;outlook &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"outlook"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"overcast"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;temperature &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"temperature"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;humidity &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"humidity"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;windy &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"windy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;play &lt;font color="#990000"&gt;=&lt;/font&gt; Attribute&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"class"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Instances class will hold the complete dataset&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;dataset &lt;font color="#990000"&gt;=&lt;/font&gt; Instances&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;  &lt;font color="#FF0000"&gt;"weather dataset"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;  make_vector&lt;font color="#990000"&gt;(&lt;/font&gt;outlook&lt;font color="#990000"&gt;,&lt;/font&gt; temperature&lt;font color="#990000"&gt;,&lt;/font&gt; humidity&lt;font color="#990000"&gt;,&lt;/font&gt; windy&lt;font color="#990000"&gt;,&lt;/font&gt; play&lt;font color="#990000"&gt;),&lt;/font&gt; &lt;br /&gt;  &lt;font color="#993399"&gt;14&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Dataset&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;DATA &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;85&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;85&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;90&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"overcast"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;83&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;86&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;96&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;68&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;65&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"overcast"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;64&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;65&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;72&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;95&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;69&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"sunny"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"overcast"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;72&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;90&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"overcast"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;81&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"FALSE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"yes"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt;&lt;br /&gt;  &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"rainy"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;71&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;91&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"TRUE"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"no"&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Convert raw data into Instances&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;DATA&lt;font color="#990000"&gt;.&lt;/font&gt;each &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;defn&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  instance &lt;font color="#990000"&gt;=&lt;/font&gt; Instance&lt;font color="#990000"&gt;.&lt;/font&gt;new &lt;font color="#993399"&gt;5&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;outlook&lt;font color="#990000"&gt;,&lt;/font&gt; defn&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;temperature&lt;font color="#990000"&gt;,&lt;/font&gt; defn&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;humidity&lt;font color="#990000"&gt;,&lt;/font&gt; defn&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;windy&lt;font color="#990000"&gt;,&lt;/font&gt; defn&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setValue&lt;font color="#990000"&gt;(&lt;/font&gt;play&lt;font color="#990000"&gt;,&lt;/font&gt; defn&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;4&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;  instance&lt;font color="#990000"&gt;.&lt;/font&gt;setDataset dataset&lt;br /&gt;  dataset&lt;font color="#990000"&gt;.&lt;/font&gt;add instance&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Created dataset:"&lt;/font&gt;&lt;br /&gt;puts dataset &lt;i&gt;&lt;font color="#9A1900"&gt;# outputs ARFF format of data&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"\nClusters from k-means"&lt;/font&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# create the model&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;kmeans &lt;font color="#990000"&gt;=&lt;/font&gt; SimpleKMeans&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;kmeans&lt;font color="#990000"&gt;.&lt;/font&gt;buildClusterer dataset&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Display the cluster for each instance&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;dataset&lt;font color="#990000"&gt;.&lt;/font&gt;numInstances&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  cluster &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;"UNKNOWN"&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    cluster &lt;font color="#990000"&gt;=&lt;/font&gt; kmeans&lt;font color="#990000"&gt;.&lt;/font&gt;clusterInstance&lt;font color="#990000"&gt;(&lt;/font&gt;dataset&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;font color="#990000"&gt;(&lt;/font&gt;i&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; java&lt;font color="#990000"&gt;.&lt;/font&gt;lang&lt;font color="#990000"&gt;.&lt;/font&gt;Exception&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"#{dataset.instance(i)}, #{cluster}"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-459961306578455006?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/459961306578455006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/08/accessing-weka-from-jruby.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/459961306578455006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/459961306578455006'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/08/accessing-weka-from-jruby.html' title='Accessing WEKA from jRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-5351074681016960039</id><published>2009-08-14T18:30:00.003+01:00</published><updated>2009-08-14T18:49:16.432+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='gvim'/><title type='text'>Writing Ruby code in gvim</title><content type='html'>This post is about putting together a set of tools to improve the experience of writing Ruby code.   Software development, even of small programs, can be made easier and quicker if your editor supports the writing process and you have access to key information.  I look at some options for customising the gvim editor to support Ruby development and how standard Ruby tools, such as ri and the debugger, can be used from within gvim.  There are many very powerful ways of extending the gvim environment; this post only gives a pointer to the basics.&lt;br /&gt;&lt;br /&gt;Note: only tested on Ubuntu Linux (jaunty), with ruby 1.9.2 and gvim 7.1.&lt;br /&gt;&lt;br /&gt;gvim is can be customised whilst you are running the application, or the customisations can be preserved and used everytime your start gvim by editing the file ~/.gvimrc.  You should create this file if it does not exist.  Add the options as described below, or see the end for my complete .gvimrc&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;When Writing Ruby Code&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To make gvim aware of ruby code when you open a ruby program, you need to tell it to be aware of the language it is editing, and it can tell that from the file extension, or &lt;span style="font-style: italic;"&gt;filetype&lt;/span&gt;.   The following options make sure gvim uses the appropriate plugin when we open a program:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype on&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype plugin on&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are three code-specific functions I need from my text editor: syntax colouring, auto-indentation and auto-completion.  The first two improve the visual appearance of the code, and the last speeds up the typing process.&lt;br /&gt;&lt;br /&gt;Writing code in black-and-white is to be avoided at all costs.  The extra visual cues you get from having &lt;span style="color: rgb(204, 51, 204);"&gt;def-end&lt;/span&gt; pairs one colour, &lt;span style="color: rgb(102, 51, 0); font-weight: bold;"&gt;do-end&lt;/span&gt; blocks a second, etc is invaluable.   The colours soon become intuitive, and help in identifying syntax errors.  Also, I find the colours make it easier to recognise blocks and recurring patterns when refactoring code.  To turn on syntax highlighting, you need the option:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;syntax on&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Explore the options under the 'Edit/Colour Scheme' menu to find a colour scheme you like, then add the option (replace 'slate' with your favourite scheme name):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;colors slate&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The structure of a Ruby program is naturally captured with indentation.  For me, the 'right' level of indent is two spaces per level.  I also do not like tab characters, and prefer them expanded into spaces.  The following options turn on the automatic indentation, set the size of indentation to two, and convert all tab commands:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype indent on&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set tabstop=2&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set shiftwidth=2&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set expandtab&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Not an option as such, but something worth knowing.  When you are entering text, use CTRL-P to auto-complete your text.  gvim will complete the word you are entering, or present a list of available choices.  You can move through the list either using CTRL-P repeatedly, or using the cursor keys to move up and down and 'enter' to select the completion.  For example, if I were writing this text in gvim I could type 'comp&amp;lt;ctrl-p&amp;gt;' and expect to press 'enter' to complete the word 'completion'.  After a little while, this becomes second nature, and saves on typing.  In addition, it saves a lot of mistakes, as variables or method names completed through auto-completion should agree with each other!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Helpful Editor Functions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Other functions that are helpful include the ability to 'fold' long definitions.  I don't use this too much, but it can be helpful in large classes whose code is mostly static.  To fold a long definition: &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Put the cursor on the first line of the definition&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Type 'zf'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click with the mouse on the last line of the definition&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;To expand a folded definition, type 'za'.&lt;br /&gt;&lt;br /&gt;Another useful function is the ability to highlight and search for a particular name or variable.  The command 'gd' will highlight all occurrences of the name under the cursor, and 'n' 'p' will move you forwards and back through the list, as with the usual gvim search.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Ruby Tools&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Documentation through ri&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The 'ri' command-line tool allows access to the Ruby documentation, and can be a quick and easy way to check Class definitions or argument lists for methods in the standard library.  The following mapping connects the Function key 'F3' to a call to the 'ri' command-line tool.   After pressing &amp;lt;f3&amp;gt; the user must enter details of the Class or method name to be shown.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f3&amp;gt; :!ri &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-BL9uSD-L0k/SoWZ5_2U2UI/AAAAAAAAAQs/AiznuKNoMZk/s1600-h/ri-gvim.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 255px;" src="http://3.bp.blogspot.com/_-BL9uSD-L0k/SoWZ5_2U2UI/AAAAAAAAAQs/AiznuKNoMZk/s320/ri-gvim.png" alt="" id="BLOGGER_PHOTO_ID_5369867352380070210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Executing Code from gVim&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can execute the code in the current file you are editing from within gVim.  To do this, you would normally go into command mode (press ':') then enter '!ruby %'  which executes ruby as a shell command.  The '%' sign means to pass ruby the current filename.  The output is then shown in the window.&lt;br /&gt;&lt;br /&gt;You can make this a single key press by adding a key mapping terminated with &amp;lt;cr&amp;gt; to your .gvimrc file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f1&amp;gt; :!ruby %&amp;lt;cr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Final .gvimrc&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My complete .gvimrc file is below.  It contains some extra settings: &lt;span style="font-family:courier new;"&gt;incsearch&lt;/span&gt; so that searching is incremental, stepping to intermediate matches as you type; &lt;span style="font-family:courier new;"&gt;hlsearch&lt;/span&gt; to show all search results with a yellow highlight (use &lt;span style="font-family:courier new;"&gt;:noh&lt;/span&gt; to remove the highlighting); and &lt;span style="font-family:courier new;"&gt;scrolloff&lt;/span&gt; to encourage gvim to keep at least the given number of lines around the cursor when scrolling.  &lt;span style="font-family:courier new;"&gt;nowrap&lt;/span&gt; and the call to &lt;span style="font-family:courier new;"&gt;guioptions&lt;/span&gt; stops gvim wrapping long lines of source code, and provides a handy horizontal scrollbar where needed.  And yes, that is a key mapping to start up an instance of &lt;span style="font-family:courier new;"&gt;irb&lt;/span&gt; within the editor!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set nocompatible&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;syntax on&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype on&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype indent on&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;filetype plugin on&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set nowrap&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set guioptions+=b&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set tabstop=2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set shiftwidth=2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set expandtab&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set hlsearch&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set scrolloff=2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set incsearch&lt;/span&gt;  &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f1&amp;gt; :!ruby %&amp;lt;cr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f2&amp;gt; :!ruby -r debug %&amp;lt;cr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f3&amp;gt; :!irb&amp;lt;cr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;map &amp;lt;f4&amp;gt; :!ri &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-5351074681016960039?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/5351074681016960039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/08/writing-ruby-code-in-gvim.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5351074681016960039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5351074681016960039'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/08/writing-ruby-code-in-gvim.html' title='Writing Ruby code in gvim'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-BL9uSD-L0k/SoWZ5_2U2UI/AAAAAAAAAQs/AiznuKNoMZk/s72-c/ri-gvim.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-6166310057372716469</id><published>2009-06-16T16:08:00.007+01:00</published><updated>2009-06-16T16:56:55.960+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='clustering'/><category scheme='http://www.blogger.com/atom/ns#' term='RSRuby'/><title type='text'>Simple Clustering with RSRuby</title><content type='html'>Clustering is a technique for grouping objects which are similar. For example, given the following data instances:&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;A:&lt;/td&gt;&lt;td&gt;10,&lt;/td&gt;&lt;td&gt;20,&lt;/td&gt;&lt;td&gt;30,&lt;/td&gt;&lt;td&gt;40&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;B:&lt;/td&gt;&lt;td&gt;40,&lt;/td&gt;&lt;td&gt;30,&lt;/td&gt;&lt;td&gt;20,&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;C:&lt;/td&gt;&lt;td&gt;11,&lt;/td&gt;&lt;td&gt;21,&lt;/td&gt;&lt;td&gt;29,&lt;/td&gt;&lt;td&gt;39&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;D:&lt;/td&gt;&lt;td&gt;39,&lt;/td&gt;&lt;td&gt;29,&lt;/td&gt;&lt;td&gt;21,&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;We can see that A and C are 'closer' than B and D, so A and C can be grouped together, and B and D form a separate group.&lt;br /&gt;&lt;br /&gt;R supports a wide variety of clustering techniques, all of which require us to pass a &lt;span style="font-style: italic;"&gt;data frame&lt;/span&gt; object to the R interpreter.  This post describes a simple way of generating a data frame, passing it to a clustering algorithm, and reading back some of the results.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Creating a Data Frame&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The data frame is an R-specific data structure for holding data and its interpretation.  For clustering, we need to describe a number of instances (the rows within a standard table) based on their attributes (the columns).  For example, the following shows the first two instances from a weather dataset:&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;th&gt;instance&lt;/th&gt;&lt;th&gt;outlook&lt;/th&gt;&lt;th&gt;temperature&lt;/th&gt;&lt;th&gt;humidity&lt;/th&gt;&lt;th&gt;windy&lt;/th&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;85&lt;/td&gt;&lt;td&gt;85&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;td&gt;90&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;To define this in RSRuby, we need to set up a conversion tool, to handle the conversion from a hashmap to R's data frame. &lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby'&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby/dataframe'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;r &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;br /&gt;&lt;br /&gt;r&lt;font color="#990000"&gt;.&lt;/font&gt;class_table&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'data.frame'&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; lambda &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;x&lt;font color="#990000"&gt;|&lt;/font&gt; DataFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;x&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;set_default_mode&lt;font color="#990000"&gt;(&lt;/font&gt;RSRuby&lt;font color="#990000"&gt;::&lt;/font&gt;CLASS_CONVERSION&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The weather dataset can be defined and set up as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;outlooks &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;temps &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;85&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;83&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;68&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;65&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;64&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;72&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;69&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;72&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;81&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;71&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;humidities &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;85&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;90&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;86&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;96&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;65&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;95&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;80&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;70&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;90&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;75&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;91&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;winds &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;weather_data &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;{}&lt;/font&gt;&lt;br /&gt;weather_data&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'outlook'&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; outlooks&lt;br /&gt;weather_data&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'temperature'&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; temps&lt;br /&gt;weather_data&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'humidity'&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; humidities&lt;br /&gt;weather_data&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;'windy'&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; winds&lt;br /&gt;&lt;br /&gt;example &lt;font color="#990000"&gt;=&lt;/font&gt; r&lt;font color="#990000"&gt;.&lt;/font&gt;as_data_frame&lt;font color="#990000"&gt;(:&lt;/font&gt;x &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; weather_data&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Of course, the definition of the hashmap can be simplified, but I like this format as a template for constructing the data frames from other sources of data.  Note that the hashmap must be provided as the value of the &lt;em&gt;:x&lt;/em&gt; key when constructing the data frame.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Clustering&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To use any of the cluster techniques, we must include the 'cluster' library:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;r&lt;font color="#990000"&gt;.&lt;/font&gt;library&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"cluster"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;A simple form of clustering algorithm is called &lt;span style="font-style: italic;"&gt;clara&lt;/span&gt;.  This takes a data frame and a number of clusters, and then returns a set of results which describe the data in terms of those clusters; the result is returned as a hashmap for Ruby, and the cluster results can be retrieved using the "clustering" key:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;clara_result &lt;font color="#990000"&gt;=&lt;/font&gt; r&lt;font color="#990000"&gt;.&lt;/font&gt;clara&lt;font color="#990000"&gt;(&lt;/font&gt;example&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#993399"&gt;14&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;  puts &lt;font color="#FF0000"&gt;"Data: #{clara_result["&lt;/font&gt;data&lt;font color="#FF0000"&gt;"][i].join("&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#FF0000"&gt;")} Cluster: #{clara_result["&lt;/font&gt;clustering&lt;font color="#FF0000"&gt;"][i]}"&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;A sample output is:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;Data: 0,85,85,0 Cluster: 1&lt;br /&gt;Data: 0,80,90,1 Cluster: 2&lt;br /&gt;Data: 1,83,86,0 Cluster: 1&lt;br /&gt;Data: 2,70,96,0 Cluster: 2&lt;br /&gt;Data: 2,68,80,0 Cluster: 1&lt;br /&gt;Data: 2,65,70,1 Cluster: 1&lt;br /&gt;Data: 1,64,65,1 Cluster: 1&lt;br /&gt;Data: 0,72,95,0 Cluster: 2&lt;br /&gt;Data: 0,69,70,0 Cluster: 1&lt;br /&gt;Data: 2,75,80,0 Cluster: 1&lt;br /&gt;Data: 0,75,70,1 Cluster: 1&lt;br /&gt;Data: 1,72,90,1 Cluster: 2&lt;br /&gt;Data: 1,81,75,0 Cluster: 1&lt;br /&gt;Data: 2,71,91,1 Cluster: 2&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-6166310057372716469?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/6166310057372716469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/simple-clustering-with-rsruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6166310057372716469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6166310057372716469'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/simple-clustering-with-rsruby.html' title='Simple Clustering with RSRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-8840024505564365220</id><published>2009-06-04T09:00:00.004+01:00</published><updated>2009-06-04T18:53:24.455+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Interacting with the Command Line from Ruby</title><content type='html'>&lt;span style="font-family: verdana;"&gt;One of the strengths of Ruby is as a &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;scripting language&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;, that is, a language for managing control of other programs.  A typical setting is to provide our script with some parameters which are then used to set up and run other programs.  For example, we could control the number of times the external program is called, or collect the results and store them in specific files.  T&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;his kind of automation can help speed up our work considerably, and also lets us think of our research at a higher level of abstraction: i.e. just create a pool of training data as big as is needed, rather than having to laboriously construct every item in the pool by hand.  Ruby is also highly suited to this task, as many of the tasks, such as parsing input arguments or formatting strings for output display, are easier in Ruby than in, for example, C.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;To achieve this level of control, we first need some way for our Ruby script to handle command-line arguments provided to it.  Second we need to be able to construct and run commands from within Ruby just as if we had typed them at the command line. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;For example, I am working on the analysis of what are known as k-SAT landscapes: the idea is to construct a boolean function, such as x_1 &amp;amp; x_2 | x_1 &amp;amp; x_3, which contains a given number, m, of clauses, each clause with k terms.  The clauses are constructed from n different variables, and there should be N of the landscapes for any given combination of n, m and k.  I have a C program which will take n, m, and k as input arguments and print the landscape to standard output.  I want to automate the construction of the N landscapes, and capture the output into files named in the format: 'results-n-m-k-i.txt', where i will range from 0 to N-1.  This is ideal for automation, as the construction of any landscape can take up to a day.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Basic Techniques&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;When you start a Ruby program, using: 'ruby program.rb X ...' you can provide command-line arguments as 'X ...'.  These arguments are placed into the array ARGV, as &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;strings&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;.  (Warning for C programmers: &lt;span style="font-family: courier new;"&gt;ARGV[0]&lt;/span&gt; is the first argument, &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;not&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; the name of the program!)  It is a simple matter to read each item out of ARGV, convert to a suitable number format, and place the result into an internal variable: to convert the first parameter to an integer and store in 'x', write: &lt;span style="font-family: courier new;"&gt;x = ARGV[0].to_i&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ruby strings make it easy to interpolate values from variables using the #{} syntax, which interprets anything inside the brackets and puts the result into the string.  For example:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;5.times do |i|&lt;br /&gt;  puts "The value is #{i}"&lt;br /&gt;end&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Will print:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;The value is 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;The value is 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;The value is 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;The value is 3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;The value is 4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Finally, to call an external program, and pass arguments to it, Ruby provides convenient backticks, ` `.  Anything between the backticks will first be interpreted as a string (so variable values can be added in, as above) and then passed to the shell for execution, just as if you had typed the command within the backticks on the command line.  Thus, &lt;span style="font-family: courier new;"&gt;`wc #{filename}`&lt;/span&gt;  will call the word-count program on the file named within the 'filename' variable.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;My final code is below.  Notice the check for the number of input arguments, and output of a help message if there are not enough; this is always useful, as I very quickly forget what those input arguments should be.  The script can be run easily using:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;ruby create-samples.rb 20 50 3 20&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Automate the construction of landscapes&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# ruby create-samples.rb n m k N&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#      where n = number of variables&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#            m = number of clauses&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#            k = number of variables per clause&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#            N = number of formulae&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# Results for formulae constructed with names: results-n-m-k-i.txt&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;#      where i runs from 0 to N-1&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;if&lt;/font&gt;&lt;/b&gt; ARGV&lt;font color="#990000"&gt;.&lt;/font&gt;length &lt;font color="#990000"&gt;!=&lt;/font&gt; &lt;font color="#993399"&gt;4&lt;/font&gt;&lt;br /&gt;  puts &lt;font color="#990000"&gt;&amp;lt;&amp;lt;-&lt;/font&gt;HELPMESSAGE&lt;br /&gt;Automate the construction of landscapes&lt;br /&gt;Copyright &lt;font color="#990000"&gt;(&lt;/font&gt;c&lt;font color="#990000"&gt;)&lt;/font&gt; Peter Lane&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;2008&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;ruby create&lt;font color="#990000"&gt;-&lt;/font&gt;samples&lt;font color="#990000"&gt;.&lt;/font&gt;rb n m k N&lt;br /&gt;&lt;br /&gt;     where n &lt;font color="#990000"&gt;=&lt;/font&gt; number of variables&lt;br /&gt;           m &lt;font color="#990000"&gt;=&lt;/font&gt; number of clauses&lt;br /&gt;           k &lt;font color="#990000"&gt;=&lt;/font&gt; number of variables per clause&lt;br /&gt;           N &lt;font color="#990000"&gt;=&lt;/font&gt; number of formulae&lt;br /&gt;&lt;br /&gt;Results &lt;b&gt;&lt;font color="#0000FF"&gt;for&lt;/font&gt;&lt;/b&gt; formulae constructed with names&lt;font color="#990000"&gt;:&lt;/font&gt; results&lt;font color="#990000"&gt;-&lt;/font&gt;n&lt;font color="#990000"&gt;-&lt;/font&gt;m&lt;font color="#990000"&gt;-&lt;/font&gt;k&lt;font color="#990000"&gt;-&lt;/font&gt;i&lt;font color="#990000"&gt;.&lt;/font&gt;txt&lt;br /&gt;     where i runs from &lt;font color="#993399"&gt;0&lt;/font&gt; to N&lt;font color="#990000"&gt;-&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;br /&gt;HELPMESSAGE&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;else&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  n &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_i&lt;br /&gt;  m &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_i&lt;br /&gt;  k &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_i&lt;br /&gt;  N &lt;font color="#990000"&gt;=&lt;/font&gt; ARGV&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_i&lt;br /&gt;  N&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;    puts &lt;font color="#FF0000"&gt;"Creating file #{i} for n=#{n}, m=#{m}, k=#{k}"&lt;/font&gt;&lt;br /&gt;    `&lt;font color="#990000"&gt;../&lt;/font&gt;makels &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;n&lt;font color="#FF0000"&gt;}&lt;/font&gt; &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;m&lt;font color="#FF0000"&gt;}&lt;/font&gt; &lt;font color="#990000"&gt;#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;k&lt;font color="#FF0000"&gt;}&lt;/font&gt; &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; results&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;n&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;m&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;k&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;-#&lt;/font&gt;&lt;font color="#FF0000"&gt;{&lt;/font&gt;i&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;txt`&lt;br /&gt;    sleep &lt;font color="#993399"&gt;1.0&lt;/font&gt; &lt;i&gt;&lt;font color="#9A1900"&gt;# wait at least a second, to allow for C's randomisation!&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-8840024505564365220?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/8840024505564365220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/interacting-with-command-line-from-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/8840024505564365220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/8840024505564365220'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/interacting-with-command-line-from-ruby.html' title='Interacting with the Command Line from Ruby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-6653110370215089315</id><published>2009-06-03T16:00:00.013+01:00</published><updated>2009-06-03T16:22:33.843+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Control Widgets  in wxRuby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;Ruby's high-level syntax makes it simple to design and write graphical interfaces in code.  In this post, I explore the basic techniques for handling control widgets: how to construct them, retrieve values, and respond to events.  There are two broad classes of control: &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;static&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; controls act as simple display devices, such as a &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;label&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; on the screen; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;non-static&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; controls provide some form of user interaction, such as a &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;button&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;.  There are some common principles for how all these control widgets are constructed and operate.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;span style="font-size:130%;"&gt;General Principles&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Nearly all of the controls are created in a similar way. &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Wx::StaticText.new(self, :label =&gt; "Password", :style =&gt; Wx::ALIGN_RIGHT&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;) &lt;/span&gt;&lt;span style="font-family: courier new;font-family:verdana;" &gt;Wx::TextCtrl.new(self, :style =&gt; Wx::TE_PASSWORD)&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Every control must have a &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;parent&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; window within which it is placed.  This parent window is usually the frame or dialog within which you are placing your controls, &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;self&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; in the above examples.  Each control also has some optional &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;styles&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;.  Finally, there is some specific information for setting up the control, such as the label to display in a &lt;span style="font-family: courier new;"&gt;StaticText&lt;/span&gt; label, or the style for displaying information within the control, such as the 'password' reference in the &lt;span style="font-family: courier new;"&gt;TextCtrl&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;(Things in the documentation which you can usually forget about are the widget's ID identifier, its position, and size.  The ID number is used to identify your widget for the purpose of handling events within C++ code using wxWidgets.  But Ruby provides a better way to register events directly with your widgets.  The widget's position and size are best left to sizers which layout your controls within a window, for which see below.)  &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;A small note about the '&lt;span style="font-family: courier new;"&gt;BoxSizer&lt;/span&gt;' which appears in the examples: this is a way to arrange controls in a vertical or horizontal order.  Without it, all of the controls will appear on top of one another.  I shall cover sizers in more detail in another post.&lt;/span&gt;  &lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Static controls&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;StaticText - a Label&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The simplest control to display is a piece of text, to act as a label.  For this, wxRuby provides the &lt;span style="font-family: courier new;"&gt;StaticText&lt;/span&gt; class.  You must provide two pieces of information, the parent of the control and the text for the label.&lt;/span&gt;  &lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;StaticBitmap&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; - an Image&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Displaying an image is a two stage process.  Assuming your image is stored in a file, you must first create an instance of the &lt;span style="font-family: courier new;"&gt;Bitmap&lt;/span&gt; class from your file: &lt;span style="font-family: courier new;"&gt;Bitmap.new(filename)&lt;/span&gt;  Then display it in a &lt;span style="font-family: courier new;"&gt;StaticBitmap&lt;/span&gt; control.  The syntax for &lt;span style="font-family: courier new;"&gt;StaticBitmap&lt;/span&gt; requires you to fill out the first three arguments: the third is the bitmap to display, the first is the familiar parent panel, and the second is the identifier number.  I said before we are not interested in this number, and wxRuby lets us use &lt;span style="font-family: courier new;"&gt;Wx::ID_ANY&lt;/span&gt; as the parameter so that a new number is assigned internally.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Here is a complete example using both static controls:&lt;/span&gt; &lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; MyFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Controls 1"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;br /&gt;    main_sizer &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;BoxSizer&lt;font color="#990000"&gt;.&lt;/font&gt;new Wx&lt;font color="#990000"&gt;::&lt;/font&gt;VERTICAL&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;StaticText&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;label &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Picture of Mars"&lt;/font&gt;&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;StaticBitmap&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Bitmap&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"planet5.gif"&lt;/font&gt;&lt;font color="#990000"&gt;)))&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_sizer main_sizer&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  MyFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-BL9uSD-L0k/SiaOkVMWYLI/AAAAAAAAAQM/tvXADmYrl54/s1600-h/Screenshot-Controls+1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 222px;" src="http://4.bp.blogspot.com/_-BL9uSD-L0k/SiaOkVMWYLI/AAAAAAAAAQM/tvXADmYrl54/s320/Screenshot-Controls+1.png" alt="" id="BLOGGER_PHOTO_ID_5343114762737049778" border="0" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Non-static controls&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;The setup and display of non-static controls follows the same pattern as the static controls.  However, users can interact with non-static controls, perhaps clicking or selecting displayed items, or entering new information.  So these controls provide a range of events and accessor methods to track what the user is up to.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Buttons&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Buttons are the simplest form of interactive control: they display some text, and react if clicked.  The creation and display part for a button is the same as for a &lt;span style="font-family: courier new;"&gt;StaticText&lt;/span&gt; control:&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-family:verdana;" &gt;@button = Wx::Button.new(self, :label =&gt; "Click me")&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;How do we make the code react to a click?  We associate an action with the button's &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;event&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;.  Every control has one or more events associated with it.  These events can be attached to actions, so that something in the code is called whenever the event is triggered.  In this case, the button has one event, triggered when the button is clicked.  We associate an action, say calling the 'button_clicked' method, with the button as follows:&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;evt_button(@button) {button_clicked}&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;Radio box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;A radio button is a simple button with a usually round bullet which can be selected, on or off.  Unlike checkboxes, radio buttons are organised into groups, and the idea is that one button in the group is always selected, and never more than one.  The &lt;span style="font-family: courier new;"&gt;RadioBox&lt;/span&gt; is constructed using an array of strings which it uses to label up a series of radio buttons and display neatly wrapped in a static line.  It is also possible to add a label to the complete box.  The method &lt;span style="font-family: courier new;"&gt;get_string_selection&lt;/span&gt; is used to retrieve the currently selected string.  Notice how the radio_box is stored in an instance variable, so as to be visible to the 'show_value' method.  &lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; MyFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Controls 4"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@radio_box&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;RadioBox&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;         &lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;label &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Language:"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;         &lt;font color="#990000"&gt;:&lt;/font&gt;choices &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"C"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"C++"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Lisp"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Ruby"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Scheme"&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt; &lt;br /&gt;    button &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Button&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;label &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Show"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_button&lt;font color="#990000"&gt;(&lt;/font&gt;button&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;show_value&lt;font color="#FF0000"&gt;}&lt;/font&gt;    &lt;br /&gt;&lt;br /&gt;    main_sizer &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;BoxSizer&lt;font color="#990000"&gt;.&lt;/font&gt;new Wx&lt;font color="#990000"&gt;::&lt;/font&gt;VERTICAL&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@radio_box&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ALL&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;button&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_sizer main_sizer&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; show_value&lt;br /&gt;    puts &lt;font color="#009900"&gt;@radio_box&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;get_string_selection&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  MyFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-BL9uSD-L0k/SiaOq_985DI/AAAAAAAAAQU/Ivsrw8yLX6A/s1600-h/Screenshot-Controls+4.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 222px;" src="http://4.bp.blogspot.com/_-BL9uSD-L0k/SiaOq_985DI/AAAAAAAAAQU/Ivsrw8yLX6A/s320/Screenshot-Controls+4.png" alt="" id="BLOGGER_PHOTO_ID_5343114877298598962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Listboxes&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A listbox is a scrollable display of a list of strings.  The listbox can be used to select one or more items, and the control can be set up to permit single selection only (the default) or multiple selection (using style LB_MULTIPLE).  The method &lt;span style="font-family: courier new;"&gt;get_selection&lt;/span&gt; returns the index of the current selection, if any, for a single selection listbox, and &lt;span style="font-family: courier new;"&gt;get_selections&lt;/span&gt; returns an array of indices for any selected items in a multiple selection listbox.  The following code constructs a multiple-selection listbox and then prints out selected indices when the 'show' button is clicked.  Notice how the list_box is stored in an instance variable, so as to be visible to the 'show_choices' method.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; MyFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Controls 3"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@list_box&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ListBox&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;br /&gt;          &lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;          &lt;font color="#990000"&gt;:&lt;/font&gt;choices &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"C"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"C++"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Java"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Lisp"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Ruby"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Scheme"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;br /&gt;          &lt;font color="#990000"&gt;:&lt;/font&gt;style &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;LB_MULTIPLE&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    button &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Button&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;label &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Show"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_button&lt;font color="#990000"&gt;(&lt;/font&gt;button&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;show_choices&lt;font color="#FF0000"&gt;}&lt;/font&gt;    &lt;br /&gt;&lt;br /&gt;    main_sizer &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;BoxSizer&lt;font color="#990000"&gt;.&lt;/font&gt;new Wx&lt;font color="#990000"&gt;::&lt;/font&gt;VERTICAL&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#009900"&gt;@list_box&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;button&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_sizer main_sizer&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; show_choices&lt;br /&gt;    puts &lt;font color="#009900"&gt;@list_box&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;get_selections&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  MyFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;Calendar control&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;This control enables the user to select a date.  You can catch different events, such as whether the user clicked on a heading, or changed the day, month or year.  In this example, I just catch the 'double-click on a single day' event, and show how to extract the day, month and year information from the calendar control.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; MyFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Controls:Calendar"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;br /&gt;    cal &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;CalendarCtrl&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_calendar&lt;font color="#990000"&gt;(&lt;/font&gt;cal&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt; &lt;font color="#990000"&gt;|&lt;/font&gt;event&lt;font color="#990000"&gt;|&lt;/font&gt;&lt;br /&gt;      puts &lt;font color="#FF0000"&gt;"Day #{cal.get_date.day}, Month: #{cal.get_date.month}, Year: #{cal.get_date.year}"&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    main_sizer &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;BoxSizer&lt;font color="#990000"&gt;.&lt;/font&gt;new Wx&lt;font color="#990000"&gt;::&lt;/font&gt;VERTICAL&lt;br /&gt;    main_sizer&lt;font color="#990000"&gt;.&lt;/font&gt;add&lt;font color="#990000"&gt;(&lt;/font&gt;cal&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;GROW &lt;font color="#990000"&gt;|&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ALL&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    set_sizer main_sizer&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  MyFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-BL9uSD-L0k/SiaOvC_GOmI/AAAAAAAAAQc/jBwvbsSUbCM/s1600-h/Screenshot-Controls:Calendar.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 222px;" src="http://3.bp.blogspot.com/_-BL9uSD-L0k/SiaOvC_GOmI/AAAAAAAAAQc/jBwvbsSUbCM/s320/Screenshot-Controls:Calendar.png" alt="" id="BLOGGER_PHOTO_ID_5343114946828188258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Finally ... &lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;There are many more controls described in the wxRuby documentation: TextCtrl and RichTextCtrl allow for the display and input of complex formatted text; TreeCtrl enables the display of hierarchical data; and MediaCtrl supports the display of video or sound.  They all follow similar principles to the above, so explore the documentation for details!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-6653110370215089315?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/6653110370215089315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/control-widgets-in-wxruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6653110370215089315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/6653110370215089315'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/06/control-widgets-in-wxruby.html' title='Control Widgets  in wxRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-BL9uSD-L0k/SiaOkVMWYLI/AAAAAAAAAQM/tvXADmYrl54/s72-c/Screenshot-Controls+1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-7433192898906945993</id><published>2009-05-23T18:20:00.005+01:00</published><updated>2009-05-23T19:23:20.351+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Division Pitfall in Ruby</title><content type='html'>&lt;span style="font-family: verdana;"&gt;Today, I want to highlight a pitfall in Ruby which keeps catching me out, and that is with division.  Simple functions are the staple of computing with Ruby, many working out quantities, such as proportions.  In this example, I wanted to compute the proportion of numbers exceeding a particular value in a given list of numbers:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; proportion_exceeding&lt;font color="#990000"&gt;(&lt;/font&gt;numbers&lt;font color="#990000"&gt;,&lt;/font&gt; threshold&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  large_numbers &lt;font color="#990000"&gt;=&lt;/font&gt; numbers&lt;font color="#990000"&gt;.&lt;/font&gt;find_all &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;num&lt;font color="#990000"&gt;|&lt;/font&gt; num &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; threshold&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; large_numbers&lt;font color="#990000"&gt;.&lt;/font&gt;size &lt;font color="#990000"&gt;/&lt;/font&gt; numbers&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The function is very simple.  It takes an array of numbers and a threshold as input, builds a new array by finding all the numbers exceeding the threshold, and then returns the proportion of the large numbers in relation to the original array.  But there is a problem:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; proportion_exceeding([1,2,3,4,5,6], 3.5)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The function returns 0.  What goes wrong is that the division symbol / is being applied to two integers, tries to return the nearest integer to the solution, and so returns 0 for anything less than 1.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 12/3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 5/3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 1/3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Numeric Classes in Ruby&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;To understand what is going on, we should first remind ourselves of the numeric classes available in Ruby.  Numbers come in various forms.  We can ask Ruby to tell us the classes by using the class method on different numbers:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 5.class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Fixnum&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 2.0.class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; (2 ** 1000).class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Bignum&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;These are the basic three.  The Fixnum is your regular integer class, holding numbers up to your machine's word size.  Float is similarly your a floating-point class.  You can find out the range for the latter using Float::MAX and Float::MIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; Float::MAX&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 1.79769313486232e+308&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; Float::MIN&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 2.2250738585072e-308&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Finally, the Bignum is used to hold extremely large integers: try printing 2**n for varying sizes of n to see how large a number Ruby can handle!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Division of Numbers&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The problem Ruby has with basic arithmetic is that it can be asked to add or subtract or multiply or divide any combination of these numbers:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&gt; 2.class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;=&gt; Fixnum&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&gt; 3.5.class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;=&gt; Float&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&gt; 2 + 3.5&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;=&gt; 5.5&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&gt; (2 + 3.5).class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;=&gt; Float&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;When given numbers from two different numbers to add, subtract or multiply together, Ruby will use &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;type conversion&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; to turn all the numbers into their most general form.  In the example above, 2 can be represented either as a Fixnum or a Float, so it is turned into a Float to suit the second number.  The problem comes with division.  Alone of the basic arithmetic operators, division can yield a result of a different type to its arguments: 1 divided by 2 is a half, which is not a Fixnum.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:100%;" &gt;My solution is to get into the habit of &lt;span style="font-style:italic;"&gt;not&lt;/span&gt; using '/'.&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;  In virtually all cases I prefer an accurate result rather than an integer.  Instead, I use the method 'quo', for quotient.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 1.quo(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; (1/2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; (1.quo(2)).class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; Rational&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 1.quo(2) * 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; (1/1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 1/2 * 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&gt; 2.5.quo(7)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;=&gt; 0.357142857142857&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;If you look at the second call above, you will see there is yet another class of number, called Rational.  The rationals are those numbers which can be represented as exact fractions, such as 1/2 or 3/7.  The 'quo' method is quite smart.  Where possible, it will create a Rational class, which is exact.  Where not possible, it will return a Float, as in the last line above.  (Apart from 'quo', the other method to remember is 'fdiv' which always returns a Float.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The revised function looks like:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; proportion_exceeding&lt;font color="#990000"&gt;(&lt;/font&gt;numbers&lt;font color="#990000"&gt;,&lt;/font&gt; threshold&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  large_numbers &lt;font color="#990000"&gt;=&lt;/font&gt; numbers&lt;font color="#990000"&gt;.&lt;/font&gt;find_all &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;num&lt;font color="#990000"&gt;|&lt;/font&gt; num &lt;font color="#990000"&gt;&amp;gt;&lt;/font&gt; threshold&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;return&lt;/font&gt;&lt;/b&gt; large_numbers&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;.&lt;/font&gt;quo&lt;font color="#990000"&gt;(&lt;/font&gt;numbers&lt;font color="#990000"&gt;.&lt;/font&gt;size&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&gt; proportion_exceeding([1,2,3,4,5,6], 3.5)&lt;br /&gt;=&gt; (1/2)&lt;br /&gt;&gt; proportion_exceeding([1,2,3,4,5,6], 4.5)&lt;br /&gt;=&gt; (1/3)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-7433192898906945993?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/7433192898906945993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/division-pitfall-in-ruby.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7433192898906945993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7433192898906945993'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/division-pitfall-in-ruby.html' title='Division Pitfall in Ruby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-5327225432100664574</id><published>2009-05-19T22:29:00.017+01:00</published><updated>2009-05-22T00:17:06.240+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Dialogs in wxRuby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;A dialog is an independent window that your application can use to provide or require some information.  Typical examples are the file dialog, to locate a file, and the printer dialog, to configure a print job.  wxRuby provides a number of standard dialogs to provide platform standard tools to get information from the user or provide information to the user.  This post introduces the simplest dialogs, message dialogs, moves on to ways to retrieve information from the user, and finally considers custom-built dialogs.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;To explore how these dialogs are used, it is convenient to run them within the simplest possible wxRuby program:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;span style="color:#000080;"&gt;require&lt;/span&gt;&lt;/b&gt; &lt;span style="color:#ff0000;"&gt;'wx'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;App&lt;span style="color:#990000;"&gt;.&lt;/span&gt;run &lt;b&gt;&lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; &lt;i&gt;&lt;span style="color:#9a1900;"&gt;#&lt;/span&gt;&lt;/i&gt;&lt;br /&gt; &lt;i&gt;&lt;span style="color:#9a1900;"&gt;# Put dialog code here&lt;/span&gt;&lt;/i&gt;&lt;br /&gt; &lt;i&gt;&lt;span style="color:#9a1900;"&gt;#&lt;/span&gt;&lt;/i&gt;&lt;br /&gt; exit&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Message Dialog&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family:courier new;"&gt;Wx::MessageDialog&lt;/span&gt; class is used to display information to the user.  We can set the title of the dialog box, the text that is displayed, and the icon.  Finally, we can change the buttons on the dialog, to get some feedback from the user.  Let us begin with the simplest application, displaying some information.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;a style="font-family: verdana;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-BL9uSD-L0k/ShMq4HZIhMI/AAAAAAAAAPU/D2V3jEgT7Gk/s1600-h/dialog-1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 222px; height: 154px;" src="http://2.bp.blogspot.com/_-BL9uSD-L0k/ShMq4HZIhMI/AAAAAAAAAPU/D2V3jEgT7Gk/s320/dialog-1.png" alt="" id="BLOGGER_PHOTO_ID_5337657126909674690" border="0" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; md &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;MessageDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;br /&gt;                &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Text within dialog\ncan be on multiple lines"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Title of Dialog"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ICON_INFORMATION&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; md&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;The variable 'md' is set up to hold an instance of the &lt;span style="font-family:courier new;"&gt;MessageDialog&lt;/span&gt; class.  The instance takes four parameters: &lt;ol  style="font-family:verdana;"&gt;&lt;li&gt;the &lt;span style="font-style: italic;"&gt;parent&lt;/span&gt; of the dialog: usually the parent frame, so the dialog is centred on it;&lt;/li&gt;&lt;li&gt;the &lt;span style="font-style: italic;"&gt;text&lt;/span&gt; to display in the body of the dialog;&lt;/li&gt;&lt;li&gt;the &lt;span style="font-style: italic;"&gt;title&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt; of the dialog; and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;the &lt;span style="font-style: italic;"&gt;style&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family:verdana;"&gt;The use of styles is important within wxRuby, as almost every widget within the library can be customised using one or more flags provided within its style parameter.  In the example above, the style is simply &lt;span style="font-family:courier new;"&gt;Wx::ICON_INFORMATION&lt;/span&gt;, which tells the dialog to use an information icon on display.  The choices for the icon include &lt;span style="font-family:courier new;"&gt;Wx::ICON_INFORMATION&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;Wx::ICON_QUESTION&lt;/span&gt;, and &lt;span style="font-family:courier new;"&gt;Wx::ICON_ERROR&lt;/span&gt;.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;The dialog is run by calling its '&lt;span style="font-family:courier new;"&gt;show_modal&lt;/span&gt;' method.  'Modal' means that the dialog will take over interactions with the application whilst it is on the screen.  This is to prevent the user doing something else in the meantime, such as trying to open another file before finishing with the dialog that is currently displayed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Our second example shows how to get information back from a user.  The &lt;span style="font-family:courier new;"&gt;MessageDialog&lt;/span&gt; provides control over which buttons will be displayed in the dialog, and what their labels might be.  I have combined the style for an error icon (&lt;span style="font-family:courier new;"&gt;Wx::ICON_ERROR&lt;/span&gt;) with the style for yes/no buttons (&lt;span style="font-family:courier new;"&gt;Wx::YES_NO&lt;/span&gt;), to get the dialog below.&lt;br /&gt;&lt;br /&gt;How to see which button the user clicked?  The answer is to check the return value from the call to &lt;span style="font-family:courier new;"&gt;md.show_modal&lt;/span&gt; to see if it equals &lt;span style="font-family:courier new;"&gt;Wx::ID_YES&lt;/span&gt;, which is what you get back if you click on the 'yes' button.  The other button styles include &lt;span style="font-family:courier new;"&gt;Wx::ID_CANCEL&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Wx::ID_OK&lt;/span&gt; to use 'ok' and 'cancel' buttons.  Note that styles are joined using bitwise or, '|'.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;a style="font-family: verdana;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-BL9uSD-L0k/ShMuI6f-TZI/AAAAAAAAAPc/VFYBjKBtqr8/s1600-h/dialog-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 154px;" src="http://3.bp.blogspot.com/_-BL9uSD-L0k/ShMuI6f-TZI/AAAAAAAAAPc/VFYBjKBtqr8/s320/dialog-2.png" alt="" id="BLOGGER_PHOTO_ID_5337660714041363858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; md &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;MessageDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;br /&gt;                &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Error in program.  Shall we continue?"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Error Dialog"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;YES_NO &lt;span style="color:#990000;"&gt;|&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ICON_ERROR&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; md&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal &lt;span style="color:#990000;"&gt;==&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_YES&lt;br /&gt;   puts &lt;span style="color:#ff0000;"&gt;"Clicked YES"&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;   puts &lt;span style="color:#ff0000;"&gt;"Clicked NO"&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;File Dialogs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;After the &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;MessageDialog&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;, there is a welcome sense of deja vu with the remaining dialogs.  Let us consider the file dialog, which has a place in most applications as a means to identify the file to work on.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/ShMyuvYlZ2I/AAAAAAAAAPk/2cIayyYATJU/s1600-h/dialog-3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 276px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/ShMyuvYlZ2I/AAAAAAAAAPk/2cIayyYATJU/s320/dialog-3.png" alt="" id="BLOGGER_PHOTO_ID_5337665761939122018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The file dialog can be created just by providing it a parent window and a dialog.  By default, you will get an 'open file' dialog.  If you would like a 'save file' dialog, add the following as the third argument:  '&lt;span style="font-family:courier new;"&gt;:style =&gt; Wx::FD_SAVE | Wx::FD_OVERWRITE_PROMPT&lt;/span&gt;'.  Having created the dialog, we see if the 'Open' or 'Save' button was clicked by checking if the return value is &lt;span style="font-family:courier new;"&gt;Wx::ID_OK&lt;/span&gt;.  The name of the filename is retrieved by accessing the 'filename' attribute of the dialog itself.&lt;/span&gt; &lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; fd &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;FileDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;br /&gt;                &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Title of Dialog"&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; fd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal &lt;span style="color:#990000;"&gt;==&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OK&lt;br /&gt;   puts &lt;span style="color:#ff0000;"&gt;"User selected file: #{fd.filename}"&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;Tip:&lt;/span&gt;&lt;span style="font-family:verdana;"&gt; If you would like your file dialog to open up at the directory you left it in, then store your file dialog in an instance variable of your topmost frame and create it in your frame's &lt;span style="font-family:courier new;"&gt;initialize&lt;/span&gt; method.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Selection Dialogs&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Apart from the file dialog, more general ways to retrieve information from the user include the &lt;span style="font-family:courier new;"&gt;TextEntryDialog&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;PasswordDialog&lt;/span&gt;, and the selection dialogs.  The selection dialogs let the user choose one or more items from a list.  Below is shown the &lt;span style="font-family:courier new;"&gt;MultiSelectionDialog&lt;/span&gt;.  All of these dialogs work in very similar ways, with slightly different methods to retrieve the final information.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/ShM2KZo-M3I/AAAAAAAAAPs/UjfvP-7jahA/s1600-h/dialog-4.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 316px; height: 320px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/ShM2KZo-M3I/AAAAAAAAAPs/UjfvP-7jahA/s320/dialog-4.png" alt="" id="BLOGGER_PHOTO_ID_5337669535673496434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; mcd &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;MultiChoiceDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;br /&gt;                &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Choose one or more languages:"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#ff0000;"&gt;"Example dialog"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span style="color:#990000;"&gt;[&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;"C"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"C++"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Java"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Lisp"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Ruby"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Scheme"&lt;/span&gt;&lt;span style="color:#990000;"&gt;]&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; mcd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal &lt;span style="color:#990000;"&gt;==&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OK&lt;br /&gt;   puts &lt;span style="color:#ff0000;"&gt;"You selected: #{mcd.selections}"&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; exit&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Custom Dialogs&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Missing from the standard wxRuby toolbox is a way to retrieve numeric information from the user.  Also, what happens if you want more than one piece of information at a time? Indeed, can we create our own dialogs within wxRuby?  The answer is yes, we can construct our own dialogs, by subclassing the &lt;span style="font-family:courier new;"&gt;Dialog&lt;/span&gt; class.  We need to fill out the dialog with the widgets of our choosing, catch events when they change to save off the current values, and read the values when the dialog exits.  The code below contains various techniques I have yet to cover in this weblog, but hopefully will still be understandable.&lt;br /&gt;&lt;br /&gt;There is a magic touch: wxRuby provides a very clever method to create and layout buttons for us too.  The method:  &lt;span style="font-family:courier new;"&gt;create_separated_button_sizer&lt;/span&gt;  will generate a Sizer with the horizontal separator line and buttons based on the flags you provide it.  Possible buttons include: OK, CANCEL, YES, NO and HELP.  What is particularly clever about this method is that it will put the buttons in the right order and with the right spacing depending on the operating system you are using!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-BL9uSD-L0k/ShM7Ih18HFI/AAAAAAAAAP0/qb-iF92w0cI/s1600-h/dialog-5.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 222px;" src="http://4.bp.blogspot.com/_-BL9uSD-L0k/ShM7Ih18HFI/AAAAAAAAAP0/qb-iF92w0cI/s320/dialog-5.png" alt="" id="BLOGGER_PHOTO_ID_5337675001073769554" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;span style="color:#000080;"&gt;require&lt;/span&gt;&lt;/b&gt; &lt;span style="color:#ff0000;"&gt;'wx'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;/b&gt; NumberDialog &lt;span style="color:#990000;"&gt;&amp;lt;&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;Dialog&lt;br /&gt; attr_reader &lt;span style="color:#990000;"&gt;:&lt;/span&gt;value&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; initialize&lt;span style="color:#990000;"&gt;(&lt;/span&gt;parent&lt;span style="color:#990000;"&gt;,&lt;/span&gt; title&lt;span style="color:#990000;"&gt;,&lt;/span&gt; label&lt;span style="color:#990000;"&gt;,&lt;/span&gt; min_value&lt;span style="color:#990000;"&gt;=&lt;/span&gt;&lt;span style="color:#993399;"&gt;0&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; max_value&lt;span style="color:#990000;"&gt;=&lt;/span&gt;&lt;span style="color:#993399;"&gt;100&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;super&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;(&lt;/span&gt;parent&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_ANY&lt;span style="color:#990000;"&gt;,&lt;/span&gt; title&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   spin_control &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;SpinCtrl&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_ANY&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;                   &lt;span style="color:#990000;"&gt;:&lt;/span&gt;min &lt;span style="color:#990000;"&gt;=&amp;gt;&lt;/span&gt; min_value&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#990000;"&gt;:&lt;/span&gt;max &lt;span style="color:#990000;"&gt;=&amp;gt;&lt;/span&gt; max_value&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   evt_spinctrl&lt;span style="color:#990000;"&gt;(&lt;/span&gt;spin_control&lt;span style="color:#990000;"&gt;)&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;{&lt;/span&gt;&lt;span style="color:#990000;"&gt;|&lt;/span&gt;e&lt;span style="color:#990000;"&gt;|&lt;/span&gt; &lt;span style="color:#009900;"&gt;@value&lt;/span&gt; &lt;span style="color:#990000;"&gt;=&lt;/span&gt; spin_control&lt;span style="color:#990000;"&gt;.&lt;/span&gt;value&lt;span style="color:#ff0000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   items_sizer &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;BoxSizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;HORIZONTAL&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   items_sizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;add&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;StaticText&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_ANY&lt;span style="color:#990000;"&gt;,&lt;/span&gt; label&lt;span style="color:#990000;"&gt;))&lt;/span&gt;&lt;br /&gt;   items_sizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;add&lt;span style="color:#990000;"&gt;(&lt;/span&gt;spin_control&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;1&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;GROW&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   main_sizer &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;BoxSizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;VERTICAL&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   main_sizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;add&lt;span style="color:#990000;"&gt;(&lt;/span&gt;items_sizer&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;0&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ALL &lt;span style="color:#990000;"&gt;|&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;GROW&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;10&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   main_sizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;add&lt;span style="color:#990000;"&gt;(&lt;/span&gt;create_separated_button_sizer&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;OK &lt;span style="color:#990000;"&gt;|&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;CANCEL&lt;span style="color:#990000;"&gt;),&lt;/span&gt;&lt;br /&gt;                 &lt;span style="color:#993399;"&gt;0&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ALL &lt;span style="color:#990000;"&gt;|&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;GROW&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;5&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   set_sizer main_sizer&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;App&lt;span style="color:#990000;"&gt;.&lt;/span&gt;run &lt;b&gt;&lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; nd &lt;span style="color:#990000;"&gt;=&lt;/span&gt; NumberDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Sample numbers"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Choose:"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;10&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;50&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; nd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal &lt;span style="color:#990000;"&gt;==&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OK&lt;br /&gt;   puts &lt;span style="color:#ff0000;"&gt;"Value is: #{nd.value}"&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; exit&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Finally ... &lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;This post has not touched on all the standard dialogs or methods for using a custom dialog.  There are dialogs to select colours, fonts, and to manage a sequence of tasks through a Wizard.  Nor have I covered all the options that most of these dialogs provide.  But I have tried to cover the more important ones for information input and display.  Once you understand these, you should find the principles for using the remaining dialogs are similar.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-5327225432100664574?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/5327225432100664574/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/dialogs-in-wxruby.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5327225432100664574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5327225432100664574'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/dialogs-in-wxruby.html' title='Dialogs in wxRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-BL9uSD-L0k/ShMq4HZIhMI/AAAAAAAAAPU/D2V3jEgT7Gk/s72-c/dialog-1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-4023743193030402870</id><published>2009-05-16T18:48:00.015+01:00</published><updated>2009-05-18T13:49:52.459+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Displaying Images in wxRuby</title><content type='html'>&lt;span style="font-family:verdana;"&gt;An important area of scientific exploration is the analysis of images.  My favourites are images of planetary surfaces, such as those the Galileo spacecraft took of Ganymede (&lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www2.jpl.nasa.gov/galileo/images/ganymede/ganyimages.html"&gt;http://www2.jpl.nasa.gov/galileo/images/ganymede/ganyimages.html&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;).  I want to take collections of such images, process them a little, and pass them to a classification system for analysis.  But first, it would be nice to view the images.  I will want to do more than a standard image viewer, because there is usually a lot of information that can be taken from an image.  In this post, I look at the elements of wxRuby which let us select and display an image within a frame. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;Starting Point&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;I begin with a simple application, which opens up a frame and displays a menu.  I have added an 'open' menu item, which will be responsible for opening an image and displaying it in the frame.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#000080;"&gt;require&lt;/span&gt;&lt;/b&gt; &lt;span style="color:#ff0000;"&gt;'wx'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;/b&gt; ImageFrame &lt;span style="color:#990000;"&gt;&amp;lt;&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;Frame&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; initialize&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;super&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#990000;"&gt;:&lt;/span&gt;title &lt;span style="color:#990000;"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Image Displayer"&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   set_menu_bar make_menu_bar&lt;br /&gt;   create_status_bar &lt;span style="color:#993399;"&gt;2&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; make_menu_bar&lt;br /&gt;   &lt;i&gt;&lt;span style="color:#9a1900;"&gt;# construct menu&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;   menu_bar &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;MenuBar&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;br /&gt;   &lt;i&gt;&lt;span style="color:#9a1900;"&gt;# -- menu&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;   image_menu &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;Menu&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;br /&gt;   image_menu&lt;span style="color:#990000;"&gt;.&lt;/span&gt;append&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_ABOUT&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   image_menu&lt;span style="color:#990000;"&gt;.&lt;/span&gt;append&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OPEN&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"&amp;amp;Open"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Open an image file"&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   image_menu&lt;span style="color:#990000;"&gt;.&lt;/span&gt;append&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_EXIT&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   evt_menu&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_ABOUT&lt;span style="color:#990000;"&gt;)&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;{&lt;/span&gt;about_program&lt;span style="color:#ff0000;"&gt;}&lt;/span&gt;&lt;br /&gt;   evt_menu&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OPEN&lt;span style="color:#990000;"&gt;)&lt;/span&gt;  &lt;span style="color:#ff0000;"&gt;{&lt;/span&gt;puts "open_image"&lt;span style="color:#ff0000;"&gt;}&lt;/span&gt;&lt;br /&gt;   evt_menu&lt;span style="color:#990000;"&gt;(&lt;/span&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_EXIT&lt;span style="color:#990000;"&gt;)&lt;/span&gt;  &lt;span style="color:#ff0000;"&gt;{&lt;/span&gt;exit_program&lt;span style="color:#ff0000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   menu_bar&lt;span style="color:#990000;"&gt;.&lt;/span&gt;append&lt;span style="color:#990000;"&gt;(&lt;/span&gt;image_menu&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"&amp;amp;Images"&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   menu_bar&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; about_program&lt;br /&gt;   Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;MessageDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;     &lt;span style="color:#ff0000;"&gt;"This program lets you choose an image file\nto display"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;     &lt;span style="color:#ff0000;"&gt;"About Program"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ICON_INFORMATION &lt;span style="color:#990000;"&gt;|&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;OK&lt;span style="color:#990000;"&gt;).&lt;/span&gt;show_modal&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; exit_program&lt;br /&gt;   close&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;App&lt;span style="color:#990000;"&gt;.&lt;/span&gt;run &lt;b&gt;&lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; ImageFrame&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:130%;"  &gt;&lt;span style="font-weight: bold;"&gt;File Dialog&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The standard dialogs within a graphical library make it easy to add functionality to your application in a format your users will expect.  The file dialog is the way to get a filename from the user.  Here, the user must identify an image file to open and display.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The general pattern is first to create an instance of the &lt;span style="font-family:courier new;"&gt;FileDialog&lt;/span&gt; object.  Second, show the dialog, which returns the ID number of the button the user clicked: we will only act if the dialog returns '&lt;span style="font-family:courier new;"&gt;Wx::ID_OK&lt;/span&gt;', to indicate that the user clicked the 'OK' button.  Finally, we ask the dialog instance for the name of the filename.  Here is the code, which should be placed inside the &lt;span style="font-family:courier new;"&gt;open_image&lt;/span&gt; method; for now, it will only display the name of the selected file:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; open_image&lt;br /&gt;   fd &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;FileDialog&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Open an image file"&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt;&lt;br /&gt;              &lt;span style="color:#990000;"&gt;:&lt;/span&gt;style &lt;span style="color:#990000;"&gt;=&amp;gt;&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;FD_FILE_MUST_EXIST&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; fd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;show_modal &lt;span style="color:#990000;"&gt;==&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ID_OK&lt;br /&gt;       puts "Selected #{fd.filename}"&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The 'style' keyword tells the file dialog to only accept existing files, so the user cannot type in an unknown filename.  For this method to be called, we must make a change to the &lt;span style="font-family:courier new;"&gt;make_menu_bar&lt;/span&gt; method:  &lt;span style="font-family:courier new;"&gt;evt_menu(Wx::ID_OPEN) {open_image}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;span style="font-size:130%;"&gt;Displaying an Image&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Once we have the filename of an image, we can open and display the image in the frame.  The image object is known as a &lt;span style="font-family:courier new;"&gt;Bitmap&lt;/span&gt;, and is created from the path of the image to load.  A call to &lt;span style="font-family:courier new;"&gt;is_ok&lt;/span&gt; checks that nothing went wrong, and then the Bitmap can be passed to our display widget.  We replace the puts call above with:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;     &lt;b&gt;&lt;span style="color:#0000ff;"&gt;begin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;       image &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;Bitmap&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new&lt;span style="color:#990000;"&gt;(&lt;/span&gt;fd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;get_path&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;       &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; image&lt;span style="color:#990000;"&gt;.&lt;/span&gt;is_ok&lt;br /&gt;         &lt;span style="color:#009900;"&gt;@display&lt;/span&gt;&lt;span style="color:#990000;"&gt;.&lt;/span&gt;set_image image&lt;br /&gt;         set_status_text&lt;span style="color:#990000;"&gt;(&lt;/span&gt;fd&lt;span style="color:#990000;"&gt;.&lt;/span&gt;get_filename&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;1&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;       &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;     &lt;b&gt;&lt;span style="color:#0000ff;"&gt;rescue&lt;/span&gt;&lt;/b&gt; Exception &lt;i&gt;&lt;span style="color:#9a1900;"&gt;# catch any problems in setting up the bitmap&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;       &lt;b&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;     &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The display widget is responsible for showing the image inside our frame.  As the image may be larger than the frame size, we will need the widget to have scrollbars: we construct a subclass of &lt;span style="font-family:courier new;"&gt;ScrolledWindow&lt;/span&gt;.  Whenever we open an image, we tell the display widget about the new image by calling &lt;span style="font-family:courier new;"&gt;set_image&lt;/span&gt;.  Then, the widget updates its scrollbars to the image's width and height, and refreshes its display.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The last bit of code is to handle the actual drawing of the bitmap.  This is managed through an &lt;span style="font-family:courier new;"&gt;on_draw&lt;/span&gt; method, which is called everytime the widget must update its display.  The &lt;span style="font-family:courier new;"&gt;on_draw&lt;/span&gt; method is called with a pointer to the 'device context' on which it must draw.  Our method is very simple: we clear the device, and then draw the bitmap, if we have one.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;/b&gt; ImageDisplay &lt;span style="color:#990000;"&gt;&amp;lt;&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;ScrolledWindow&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; initialize parent&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;super&lt;/span&gt;&lt;/b&gt; parent&lt;br /&gt;   &lt;span style="color:#009900;"&gt;@image&lt;/span&gt; &lt;span style="color:#990000;"&gt;=&lt;/span&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; set_image image&lt;br /&gt;   &lt;span style="color:#009900;"&gt;@image&lt;/span&gt; &lt;span style="color:#990000;"&gt;=&lt;/span&gt; image&lt;br /&gt;   set_scrollbars&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;span style="color:#993399;"&gt;1&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;1&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#009900;"&gt;@image&lt;/span&gt;&lt;span style="color:#990000;"&gt;.&lt;/span&gt;width&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#009900;"&gt;@image&lt;/span&gt;&lt;span style="color:#990000;"&gt;.&lt;/span&gt;height&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   refresh&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; on_draw dc&lt;br /&gt;   dc&lt;span style="color:#990000;"&gt;.&lt;/span&gt;set_background Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;WHITE_BRUSH&lt;br /&gt;   dc&lt;span style="color:#990000;"&gt;.&lt;/span&gt;clear&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/b&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/b&gt; &lt;span style="color:#009900;"&gt;@image&lt;/span&gt; &lt;span style="color:#990000;"&gt;==&lt;/span&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;   dc&lt;span style="color:#990000;"&gt;.&lt;/span&gt;draw_bitmap&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;span style="color:#009900;"&gt;@image&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;0&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;0&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;span style="font-size:130%;"&gt;Telling the Frame to Display the Widget&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Apart from learning about individual widgets, the user of a GUI library like wxRuby must learn how to display widgets within a frame in the intended places.  The way to do this is with 'Sizers'.  Each widget has a sizer to manage the widgets within it.  The simplest sizers are the BoxSizers, which lay out their children in either a horizontal or a vertical direction.  Widgets are usually constructed and added to sizers in the &lt;span style="font-family:courier new;"&gt;initialize&lt;/span&gt; method of their parent. &lt;br /&gt;&lt;br /&gt;For the program here, we made a vertical sizer.  The widget to display is then added to the sizer.  The call &lt;span style="font-family:courier new;"&gt;sizer.add(@display, 1, Wx::GROW)&lt;/span&gt; tells the sizer which widget to add, that it should expand the widget to fill the space, and that the widget should grow as the frame grows around it.  Finally, the sizer is set as the frame's main sizer.  The final &lt;span style="font-family:courier new;"&gt;initialize&lt;/span&gt; method for &lt;span style="font-family:courier new;"&gt;ImageFrame&lt;/span&gt; is:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt;&lt;/b&gt; initialize&lt;br /&gt;   &lt;b&gt;&lt;span style="color:#0000ff;"&gt;super&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;b&gt;&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#990000;"&gt;:&lt;/span&gt;title &lt;span style="color:#990000;"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;"Image Displayer"&lt;/span&gt;&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   set_menu_bar make_menu_bar&lt;br /&gt;   create_status_bar &lt;span style="color:#993399;"&gt;2&lt;/span&gt;&lt;br /&gt;   sizer &lt;span style="color:#990000;"&gt;=&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;BoxSizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;VERTICAL&lt;br /&gt;   &lt;span style="color:#009900;"&gt;@display&lt;/span&gt; &lt;span style="color:#990000;"&gt;=&lt;/span&gt; ImageDisplay&lt;span style="color:#990000;"&gt;.&lt;/span&gt;new &lt;b&gt;&lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;   sizer&lt;span style="color:#990000;"&gt;.&lt;/span&gt;add&lt;span style="color:#990000;"&gt;(&lt;/span&gt;&lt;span style="color:#009900;"&gt;@display&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; &lt;span style="color:#993399;"&gt;1&lt;/span&gt;&lt;span style="color:#990000;"&gt;,&lt;/span&gt; Wx&lt;span style="color:#990000;"&gt;::&lt;/span&gt;GROW&lt;span style="color:#990000;"&gt;)&lt;/span&gt;&lt;br /&gt;   set_sizer sizer&lt;br /&gt; &lt;b&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/Sg8c1LKHLTI/AAAAAAAAAPI/4DuLifEila8/s1600-h/image-displayer.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 301px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/Sg8c1LKHLTI/AAAAAAAAAPI/4DuLifEila8/s320/image-displayer.png" alt="" id="BLOGGER_PHOTO_ID_5336515783311174962" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-4023743193030402870?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/4023743193030402870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/displaying-images-in-wxruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4023743193030402870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/4023743193030402870'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/displaying-images-in-wxruby.html' title='Displaying Images in wxRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-BL9uSD-L0k/Sg8c1LKHLTI/AAAAAAAAAPI/4DuLifEila8/s72-c/image-displayer.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-5604837380101234636</id><published>2009-05-15T23:55:00.015+01:00</published><updated>2009-05-16T10:15:01.398+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Graphical Interfaces for Your Ruby Programs</title><content type='html'>&lt;span style="font-family: verdana;"&gt;Sometimes, the plain text interface to Ruby is not enough.  A graphical user interface can be convenient, allowing you to, for instance, select the files you want to analyse and see the results directly.  When we create such an interface, our program moves along the dimension from being a &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;tool&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;, which you just use and forget about, to an &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;application&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;, which you use and spend a lot of time with.  My favourite library for graphical interfaces is wxWidgets (&lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.wxwidgets.org/"&gt;http://www.wxwidgets.org/&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;), which is cross platform and easy to use.  Ruby has its own binding to wxWidgets, called &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;wxRuby&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; (&lt;/span&gt;&lt;a style="font-family: verdana;" href="http://wxruby.rubyforge.org/wiki/wiki.pl"&gt;http://wxruby.rubyforge.org/wiki/wiki.pl&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;). &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;wxRuby recently made it to version 2.0, and has become a robust platform for developing software with a graphical user interface, or GUI.  Let us get started with wxRuby, and create a simple program.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Installation&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Installation is covered in &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://wxruby.rubyforge.org/wiki/wiki.pl?Installation"&gt;http://wxruby.rubyforge.org/wiki/wiki.pl?Installation&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;.  You will need wxWidgets installed on your Linux platform: get it from your repository.  On Ubuntu, I used synaptic to search for wxWidgets, and installed &lt;span style="font-family: courier new;"&gt;libwxgtk2.8-0&lt;/span&gt;, which also pulled in &lt;span style="font-family: courier new;"&gt;libwxbase2.8-0&lt;/span&gt;.  Once you have these, rubygems does the rest: &lt;span style="font-family: courier new;"&gt; sudo gem install wxruby&lt;/span&gt;. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Simplest Example&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The simplest example just creates a basic frame.  The code is in three pieces.  The first piece is the &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;loader&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;, which tries to install wxruby; if rubygems is not installed by default (should not happen in newer Ruby distributions) then it will require rubygems before trying to find wxruby.  The second piece defines the SimpleFrame class.  This class is a subclass of the wxWidgets class Frame.  The namespace for all the wxruby material is 'Wx'.  (I like to keep namespaces within my code, but some like to '&lt;span style="font-family: courier new;"&gt;include wx&lt;/span&gt;' at the start, and then the 'Wx::' parts are optional.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The SimpleFrame class has an initialize method which calls its parent class.  The nil tells the parent there is no parent frame for the SimpleFrame to relate to.  The second argument uses a keyword-style format to set the title of the frame.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The third part of the code starts the wx application, and, within the block, creates and shows a SimpleFrame.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# This block ensures that rubygems is present before requiring wx.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; LoadError &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; no_wx_err&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rubygems'&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; LoadError&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;raise&lt;/font&gt;&lt;/b&gt; no_wx_err&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; SimpleFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Simple Frame Title"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  SimpleFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Adding a Menu and Status Bar&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The hardest part in learning about any GUI library is to figure out how the different elements can be placed onto the screen.  Two basic elements are the menu and status bar.  The menu places the commands for your application in an easy to access place, and the status bar provides a method to feed information back to the user. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Adding a menu bar is a three step process.  First, a set of menus must be created, containing any submenus or menuitems.  Second, these menus must be added to a menubar.  And third, the menubar must be added to the frame.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Step 1: creating the menus.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A menu is an instance of &lt;span style="font-family: courier new;"&gt;Wx::Menu&lt;/span&gt;.  Before creating a menu, we must create an instance of &lt;span style="font-family: courier new;"&gt;Wx::Menu&lt;/span&gt; and name it.  Next, we must add the items we want to display to the menu.  Here we meet a useful feature of wxWidgets, which is the &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;standard identifier&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;.  Every widget (instance of a wx class)  within wxWidgets has a unique ID number.  This ID number can be assigned by a user, but there are also several standard ones provided in the library.  Useful ones include: ID_ABOUT, ID_EXIT, ID_OPEN, ID_SAVE.  If you use a standard identifier for a menu item or button, wxWidgets will automatically give it a name, icon and appearance standard for the platform you are using. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;To create a program menu with an About and Quit button, we use:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    program_menu &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Menu&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_EXIT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;How do we make the menu item do something when you click on it?  We associate the menu item widget with a ruby method, so that the method is called every time the menu item is clicked.  When we know the ID number of the widget, we can use that to make the association.  The &lt;span style="font-family: courier new;"&gt;evt_menu&lt;/span&gt; method in the construction of the menu associates the block with the given ID number.  The complete listing below provides some examples of things to do to suit the menu items.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;about_program&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Step 2: Add the menus to a menubar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The menubar is an instance of &lt;span style="font-family: courier new;"&gt;Wx::MenuBar&lt;/span&gt;.  You add menus to the menubar using the append method of menubar.  The append method takes the menu itself and the title of the menu.  Use an ampersand, &amp;amp;, in the title of the menu to provide the little line for a keyboard shortcut to that menu.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Step 3: Add the menubar to the frame&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;The easiest step of the three: just tell the frame to &lt;span style="font-family: courier new;"&gt;set_menu_bar&lt;/span&gt; to your menubar instance.  Below is the full code to initialise the frame with the menubar:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Simple Frame with Menus"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    set_menu_bar make_menu_bar&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_menu_bar&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# construct menu&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    menu_bar &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuBar&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# -- menu 1&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    program_menu &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Menu&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_EXIT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;about_program&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_EXIT&lt;font color="#990000"&gt;)&lt;/font&gt;  &lt;font color="#FF0000"&gt;{&lt;/font&gt;exit_program&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt; &lt;br /&gt;    menu_bar&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;program_menu&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"&amp;amp;Program"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    menu_bar&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Adding a status bar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The status bar is the little strip along the bottom of the screen which contains instructions or information for the user.  The bar can be divided into a number of pieces, so different information can be displayed.  It is very simple to create a status bar: call the &lt;span style="font-family: courier new;"&gt;create_status_bar&lt;/span&gt; method on the frame, provide it with the number of pieces (fields) you want, and it will be set.  Putting text into a field of the status bar is equally easy: call the &lt;span style="font-family: courier new;"&gt;set_status_text&lt;/span&gt; method on the frame, providing it with the string to display and the index (from 0) of the field to display in.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Getting free help&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Something I find very useful about status bars and wxWidgets is that each menu item is given a help string.  This help string gets displayed in field 0 of the status bar, if you have one!  So, include a status bar, and you get free help for your users.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Non-standard menu items&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;You may want to create your own menu item, not one of the standard ones.  To do this, you need to create an instance of MenuItem yourself.  This needs at least three items.  The first is the Menu in which the item will sit.  The second is an ID number - you can write &lt;span style="font-family: courier new;"&gt;Wx::ID_ANY&lt;/span&gt; if you don't care what it is.  The third item is the name of the menu.  The fourth is an optional help string, which will display in any status bar.  The method &lt;span style="font-family: courier new;"&gt;append_item&lt;/span&gt; attaches the item to a menu.  &lt;span style="font-family: courier new;"&gt;evt_menu&lt;/span&gt; is again used to associate a block with the menu, and wxRuby is smart enough to recognise an instance of a menu item as well as a widget ID as its parameter.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;    new_item &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuItem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;program_menu&lt;font color="#990000"&gt;,&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Special"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Special menu"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append_item&lt;font color="#990000"&gt;(&lt;/font&gt;new_item&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;new_item&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;puts &lt;font color="#FF0000"&gt;"Special clicked"&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Put it all together, and you should get something like the following screen shot:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-BL9uSD-L0k/Sg4D4PVDOFI/AAAAAAAAAPA/0QqbXN0tMuQ/s1600-h/simple-menus.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 222px;" src="http://4.bp.blogspot.com/_-BL9uSD-L0k/Sg4D4PVDOFI/AAAAAAAAAPA/0QqbXN0tMuQ/s320/simple-menus.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5336206873202997330" /&gt;&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;Below is the complete program:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# This block ensures that rubygems is present before requiring wx.&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; LoadError &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; no_wx_err&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rubygems'&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'wx'&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; LoadError&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;raise&lt;/font&gt;&lt;/b&gt; no_wx_err&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; SimpleFrame &lt;font color="#990000"&gt;&amp;lt;&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Frame&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;super&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;nil&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;title &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Simple Frame with Menus"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    set_menu_bar make_menu_bar&lt;br /&gt;    create_status_bar &lt;font color="#993399"&gt;2&lt;/font&gt;&lt;br /&gt;    set_status_text&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"Hello"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; make_menu_bar&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# construct menu&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    menu_bar &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuBar&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    &lt;i&gt;&lt;font color="#9A1900"&gt;# -- menu 1&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;    program_menu &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;Menu&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_EXIT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ABOUT&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;about_program&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_EXIT&lt;font color="#990000"&gt;)&lt;/font&gt;  &lt;font color="#FF0000"&gt;{&lt;/font&gt;exit_program&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    new_item &lt;font color="#990000"&gt;=&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MenuItem&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;program_menu&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                                Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ID_ANY&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Special"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"Special menu"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    program_menu&lt;font color="#990000"&gt;.&lt;/font&gt;append_item&lt;font color="#990000"&gt;(&lt;/font&gt;new_item&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    evt_menu&lt;font color="#990000"&gt;(&lt;/font&gt;new_item&lt;font color="#990000"&gt;)&lt;/font&gt; &lt;font color="#FF0000"&gt;{&lt;/font&gt;puts &lt;font color="#FF0000"&gt;"Special clicked"&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt; &lt;br /&gt;    menu_bar&lt;font color="#990000"&gt;.&lt;/font&gt;append&lt;font color="#990000"&gt;(&lt;/font&gt;program_menu&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"&amp;amp;Planet"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    menu_bar&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; about_program&lt;br /&gt;    Wx&lt;font color="#990000"&gt;::&lt;/font&gt;MessageDialog&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;self&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;          &lt;font color="#FF0000"&gt;"Our first wxRuby program"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;          &lt;font color="#FF0000"&gt;"About Program"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;          Wx&lt;font color="#990000"&gt;::&lt;/font&gt;ICON_INFORMATION &lt;font color="#990000"&gt;|&lt;/font&gt; Wx&lt;font color="#990000"&gt;::&lt;/font&gt;OK&lt;font color="#990000"&gt;).&lt;/font&gt;show_modal&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; exit_program&lt;br /&gt;    close&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wx&lt;font color="#990000"&gt;::&lt;/font&gt;App&lt;font color="#990000"&gt;.&lt;/font&gt;run &lt;b&gt;&lt;font color="#0000FF"&gt;do&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  SimpleFrame&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;.&lt;/font&gt;show&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;Tip:&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;  In Ubuntu, associate ruby with your .rb files, and you can run your wxRuby applications by double clicking on the icon!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-5604837380101234636?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/5604837380101234636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/graphical-interfaces-for-your-ruby.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5604837380101234636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/5604837380101234636'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/graphical-interfaces-for-your-ruby.html' title='Graphical Interfaces for Your Ruby Programs'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-BL9uSD-L0k/Sg4D4PVDOFI/AAAAAAAAAPA/0QqbXN0tMuQ/s72-c/simple-menus.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-1920545751097638661</id><published>2009-05-14T20:10:00.010+01:00</published><updated>2009-05-15T01:10:59.776+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RSRuby'/><title type='text'>Constructing a Wrapper around RSRuby</title><content type='html'>&lt;span style="font-family: verdana;"&gt;In my previous post, I looked at creating some graphs and doing other analysis within RSRuby.  The problem with using RSRuby directly is that the syntax can be clunky; there are many things that interfere with simply getting the result.  For example, to save a graph of data, you must start up an instance of R, tell it to create a file of the right type, plot the graph, then tell the device you are finished, etc.  What would be convenient, at least for simple cases, is to have a single function which does all the above in one go.  In this post, I explore how easy it is to create a wrapper around some of the RSRuby calls, and so devise a personal library of functions with just the right level of exposed complexity.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Creating a Wrapper&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I shall give my wrapper library a simple name, 'L', as I don't want long names to type in.  All methods are module methods.  'L' includes an instance of R and the methods in 'L' will do the hard work of interacting with R.  Here is the start of the library:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;module&lt;/font&gt;&lt;/b&gt; L&lt;br /&gt;  R &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance &lt;i&gt;&lt;font color="#9A1900"&gt;# keep a constant R interpreter&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This is very simple, of course.  The instance of R is accessible as 'L::R', and can be called in the usual way.  I think this is important &amp;mdash; the wrapper library does not prevent all the usual ways of interacting with R, but will make some functions simpler.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Accessing Statistical Functions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Let us add some simple statistical functions.  I would like to compute the mean of an array of numbers by calling:  '&lt;span style="font-family: courier new;"&gt;L::mean [1,2,3,4,5,6,7]&lt;/span&gt;', and I can do this by providing functions like:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# --- stats&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;mean items&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;mean items&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;stddev items&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;sd items&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This library is for my own use, so I can use whatever names I like.  I sometimes prefer more verbose forms than R uses, as you can see in the &lt;span style="font-family: courier new;"&gt;stddev&lt;/span&gt; function.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Graphical Functions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The process of creating and saving a graph in RSRuby required a few steps.  We can simplify those steps using our wrapper, creating a function to accept the name of the final graph along with the parameters for constructing the graph.  We use here the usual Ruby trick of combining the hash map arguments into a single Hashmap, so &lt;span style="font-family: courier new;"&gt;save_histogram("sample.png", data, :main =&gt; "Title", :xlab =&gt; "x label")&lt;/span&gt;  will treat the parameters &lt;span style="font-family: courier new;"&gt;:main =&gt; "Title, :xlab =&gt; "x label"&lt;/span&gt; as a single argument, labelled &lt;span style="font-family: courier new;"&gt;params&lt;/span&gt;, which can then be passed to R's own &lt;span style="font-family: courier new;"&gt;hist&lt;/span&gt; function.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;save_histogram&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; data&lt;font color="#990000"&gt;,&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;png filename &lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;hist&lt;font color="#990000"&gt;(&lt;/font&gt;data&lt;font color="#990000"&gt;,&lt;/font&gt; params&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    R&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Reading Data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The machine-learning and data-mining communities have a fairly standard format for representing data instances: comma-separated values, or CSV.  Each line of a text file is taken to represent a single data instance.  The features of the data are separated by commas.  For example, a table of data representing information about cars might hold features about the colour, engine size and whether there was a roofrack:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;white, 1800, no&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;blue, 1200, yes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Many such files contain header information, describing what the column headings are, for instance.  We would like a function that will read such data into a Ruby data structure.  The aims of the function are:&lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: verdana;"&gt;&lt;li&gt;to accept as input the filename of the data to read in;&lt;/li&gt;&lt;li&gt;to optionally accept a number of header lines to ignore;&lt;/li&gt;&lt;li&gt;to optionally accept an alternative separator symbol to the comma;&lt;/li&gt;&lt;li&gt;to return an array in which each element is an array of the features for one instance; and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;to convert the feature values into Integer or Float types, where appropriate.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family: verdana;"&gt;The functions I created are:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# --- reading in data&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# try to convert string item into an Integer or a Float, else return item&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;convert_item item&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;      Integer item&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;begin&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;        Float item&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;rescue&lt;/font&gt;&lt;/b&gt; &lt;br /&gt;        item&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# convert every item in given list of items&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;convert_items items&lt;br /&gt;    items&lt;font color="#990000"&gt;.&lt;/font&gt;collect &lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;convert_item i&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# return a list of the lines from given file&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# -- ignore the top ignore_n lines&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;i&gt;&lt;font color="#9A1900"&gt;# -- convert every item in each line using the above&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;read_data_file&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; ignore_n&lt;font color="#990000"&gt;=&lt;/font&gt;&lt;font color="#993399"&gt;0&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; split_char&lt;font color="#990000"&gt;=&lt;/font&gt;&lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    data &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    file &lt;font color="#990000"&gt;=&lt;/font&gt; File&lt;font color="#990000"&gt;.&lt;/font&gt;open&lt;font color="#990000"&gt;(&lt;/font&gt;filename&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    ignore_n&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;font color="#FF0000"&gt;{&lt;/font&gt; file&lt;font color="#990000"&gt;.&lt;/font&gt;gets &lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;while&lt;/font&gt;&lt;/b&gt; line &lt;font color="#990000"&gt;=&lt;/font&gt; file&lt;font color="#990000"&gt;.&lt;/font&gt;gets&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;unless&lt;/font&gt;&lt;/b&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;strip &lt;font color="#990000"&gt;==&lt;/font&gt; &lt;font color="#FF0000"&gt;""&lt;/font&gt; &lt;i&gt;&lt;font color="#9A1900"&gt;# ignore blank lines&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;        data &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; L&lt;font color="#990000"&gt;.&lt;/font&gt;convert_items&lt;font color="#990000"&gt;(&lt;/font&gt;line&lt;font color="#990000"&gt;.&lt;/font&gt;split&lt;font color="#990000"&gt;(&lt;/font&gt;split_char&lt;font color="#990000"&gt;))&lt;/font&gt;&lt;br /&gt;      &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;    file&lt;font color="#990000"&gt;.&lt;/font&gt;close&lt;br /&gt;    &lt;br /&gt;    data&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Example&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Finally, we can put all these pieces together by simplifying our example from last time.  There, we took an example dataset which had a number of fields in comma-separated format.  That is, each line represents a single data instance, and the information for each instance's features is separated by a comma.  The first five lines of our example dataset are header information, which we do not need.  Reading in these data, extracting the 11th feature from the data, printing the feature's mean and standard deviation, and finally creating a histogram of its values, can now be done quite directly:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;i&gt;&lt;font color="#9A1900"&gt;# -- process the image.txt data&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;image_data &lt;font color="#990000"&gt;=&lt;/font&gt; L&lt;font color="#990000"&gt;::&lt;/font&gt;read_data_file&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"image.txt"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;column_data &lt;font color="#990000"&gt;=&lt;/font&gt; image_data&lt;font color="#990000"&gt;.&lt;/font&gt;collect&lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt; i&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;br /&gt;puts &lt;font color="#FF0000"&gt;"Mean: #{L::mean(column_data)} SD: #{L::stddev(column_data)}"&lt;/font&gt;&lt;br /&gt;L&lt;font color="#990000"&gt;::&lt;/font&gt;save_histogram&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"image.png"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; image_data&lt;font color="#990000"&gt;.&lt;/font&gt;collect&lt;font color="#FF0000"&gt;{&lt;/font&gt;&lt;font color="#990000"&gt;|&lt;/font&gt;i&lt;font color="#990000"&gt;|&lt;/font&gt; i&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;font color="#FF0000"&gt;}&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;br /&gt;                  &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"X from image"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;main&lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt;&lt;font color="#FF0000"&gt;"From image"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Just a Beginning ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Of course, what I've shown above is just the beginning.  It does demonstrate how easy Ruby makes it to provide tailored libraries to simplify daily tasks.  Collect a few dozen of such functions together, and suddenly we have a budding wrapper library.  How far you go to a complete wrapper library really depends on your stamina - the R project comes with a manual of over 1600 pages! &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-1920545751097638661?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/1920545751097638661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/constructing-wrapper-around-rsruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/1920545751097638661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/1920545751097638661'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/constructing-wrapper-around-rsruby.html' title='Constructing a Wrapper around RSRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-7409572782657540464</id><published>2009-05-13T22:44:00.011+01:00</published><updated>2009-05-14T00:52:32.549+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='graphs'/><category scheme='http://www.blogger.com/atom/ns#' term='RSRuby'/><title type='text'>Plotting Simple Graphs with RSRuby</title><content type='html'>R has a powerful set of plotting and graphics tools for visualising data.  I shall look at some of the options for generating graphs,  fitting a line to a graph, and plotting data that is stored in a text file.  If you are familiar with R, the method used here may seem a bit odd, as I call R from Ruby code as a standalone program, generating results with minimal user input.  Working with R is often more of an interactive process, where graphs are built up piece by piece, and shown on the screen.   Instead, I shall immediately save graphs out to file, and then use an image viewer program.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Plotting Points on a Graph&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The simplest graph is obtained by plotting data points and drawing lines between those points.  For instance, the graph below was obtained from the list of x,y coordinates: (1,10) (2,5) (3,2) (4,5) (5,10) using a simple call to RSRuby.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtIxmMJrYI/AAAAAAAAAOY/7c3ijaJvGaQ/s1600-h/sample.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtIxmMJrYI/AAAAAAAAAOY/7c3ijaJvGaQ/s320/sample.png" alt="" id="BLOGGER_PHOTO_ID_5335438200452787586" border="0" /&gt;&lt;/a&gt;The calling code goes through the following steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Creates an instance @@r of the R interpreter.&lt;/li&gt;&lt;li&gt;Instructs the interpreter to use the named PNG file for its graphical output.&lt;/li&gt;&lt;li&gt;Plots the graph.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Tells the interpreter that plotting is over, and the PNG file can be written.&lt;/li&gt;&lt;/ol&gt;The plot command can take a wide range of parameters.  The basic ones are the list of x coordinates, and the list of y coordinates.  The RSRuby bridge is kind to us here, as the lists are Ruby arrays.  The points (1,10) (2,5) (3,2) (4,5) (5,10)  are passed to the interpreter as the two arrays, first of the x-coordinates [1,2,3,4,5] and second of the y-coordinates [10,5,2,5,10].  The rest of the arguments use Ruby's special hashmap notation to give the effect of keyword arguments.  The :xlab and :ylab keywords specify the labels for the x and y axes respectively.  :type specifies how the points and line are plotted: "n" stands for show nothing, "p" for show the points only, "l" for draw lines between the points, "b" for plot both, "c" for  draw lines and leave gaps for the points.  :main sets the title of the graph, and :col lets you colour the points and lines plotted.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;b&gt;&lt;font color="#000080"&gt;require&lt;/font&gt;&lt;/b&gt; &lt;font color="#FF0000"&gt;'rsruby'&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; RSRuby&lt;font color="#990000"&gt;.&lt;/font&gt;instance&lt;br /&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"sample.png"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;plot&lt;font color="#990000"&gt;([&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;3&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;4&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; &lt;br /&gt;    &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"x label"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;ylab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"y label"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    &lt;font color="#990000"&gt;:&lt;/font&gt;type &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"b"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;main &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Simple graph"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt;&lt;br /&gt;    &lt;font color="#990000"&gt;:&lt;/font&gt;col &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"blue"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Fitting a Line to Data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;R provides the 'lm' function for computing linear models.  This function appears very powerful, and relies on the caller to provide it with a formula, or linear model, to fit against.  Consider the following data, which fall around the line y=x:&lt;br /&gt;&lt;br /&gt;(1, 1.2) (1.9, 2.1) (3.1, 2.8) (3.8, 4.1) (4.7, 5.2)&lt;br /&gt;&lt;br /&gt;In order to fit a linear model to these data, we place the x and y coordinates in variables called, perhaps, xs and ys.  Then, in R, we call lm with the argument "xs ~ ys", to define the formula for the linear model.  Below, I give a rather clunky way to do this, which involves assigning variables called xs and ys in the R interpreter - I hope to improve this in later posts.  What is returned is a Ruby object defining the line of fit, and we can print out some summary information about the computed linear model.  By supplying the intercept and y values of our fitted line to the 'abline' method, a line will be added to our graph giving the best fit.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"sample2.png"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;x &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;1.9&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;3.1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;3.8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;4.7&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;y &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#993399"&gt;1.2&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;2.1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;2.8&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;4.1&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#993399"&gt;5.2&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;assign&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'x'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; x&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;assign&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'y'&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; y&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;fit &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;lm&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;'x ~ y'&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;plot&lt;font color="#990000"&gt;(&lt;/font&gt;x&lt;font color="#990000"&gt;,&lt;/font&gt; y&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;abline&lt;font color="#990000"&gt;(&lt;/font&gt;fit&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"coefficients"&lt;/font&gt;&lt;font color="#990000"&gt;][&lt;/font&gt;&lt;font color="#FF0000"&gt;"(Intercept)"&lt;/font&gt;&lt;font color="#990000"&gt;],&lt;/font&gt; fit&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"coefficients"&lt;/font&gt;&lt;font color="#990000"&gt;][&lt;/font&gt;&lt;font color="#FF0000"&gt;"y"&lt;/font&gt;&lt;font color="#990000"&gt;])&lt;/font&gt;&lt;br /&gt;puts fit&lt;font color="#990000"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;"coefficients"&lt;/font&gt;&lt;font color="#990000"&gt;]&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;$ ruby sample-1.rb&lt;br /&gt;{"(Intercept)"=&gt;0.0875346260387804, "y"=&gt;0.913138108428967}&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtTEu4xReI/AAAAAAAAAOg/pMNGuVB5Uo4/s1600-h/sample2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtTEu4xReI/AAAAAAAAAOg/pMNGuVB5Uo4/s320/sample2.png" alt="" id="BLOGGER_PHOTO_ID_5335449524321207778" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Histograms from a Text File&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To finish this post, I want to show how to plot a different kind of graph, using data from a text file.  The text file I shall use is an example from UCI Irvine's Machine Learning Repository (&lt;a href="http://archive.ics.uci.edu/ml/"&gt;http://archive.ics.uci.edu/ml/&lt;/a&gt;), and I grabbed the 'Image Segmentation' dataset for illustration.  The UCI data is usually stored as comma separated data, one instance per row, with some header information at the top.  Let's plot a histogram of the values in the 11th column of data.  (Don't ask why - I just want to see how to do it!)&lt;br /&gt;&lt;br /&gt;First, we store the data in a file, call it "image.txt".  Second, we open the file into Ruby, ignore the first five lines, which contain header information, and then begin working for real.  We read each line, split it up using the comma separator character, and store the 11th item in that array as a floating point number.  The code is:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;data &lt;font color="#990000"&gt;=&lt;/font&gt; &lt;font color="#990000"&gt;[]&lt;/font&gt;&lt;br /&gt;file &lt;font color="#990000"&gt;=&lt;/font&gt; File&lt;font color="#990000"&gt;.&lt;/font&gt;new&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"image.txt"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#FF0000"&gt;"r"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;   &lt;i&gt;&lt;font color="#9A1900"&gt;# open the file for reading&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;font color="#993399"&gt;5&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;times &lt;font color="#FF0000"&gt;{&lt;/font&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;gets&lt;font color="#FF0000"&gt;}&lt;/font&gt;                 &lt;i&gt;&lt;font color="#9A1900"&gt;# ignore the header&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;while&lt;/font&gt;&lt;/b&gt; line &lt;font color="#990000"&gt;=&lt;/font&gt; file&lt;font color="#990000"&gt;.&lt;/font&gt;gets              &lt;i&gt;&lt;font color="#9A1900"&gt;# read all remaining lines&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;  data &lt;font color="#990000"&gt;&amp;lt;&amp;lt;&lt;/font&gt; line&lt;font color="#990000"&gt;.&lt;/font&gt;split&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;","&lt;/font&gt;&lt;font color="#990000"&gt;)[&lt;/font&gt;&lt;font color="#993399"&gt;10&lt;/font&gt;&lt;font color="#990000"&gt;].&lt;/font&gt;to_f  &lt;i&gt;&lt;font color="#9A1900"&gt;# add 11th item to 'data' as a float&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;file&lt;font color="#990000"&gt;.&lt;/font&gt;close                          &lt;i&gt;&lt;font color="#9A1900"&gt;# close the file&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;Finally, generating a histogram from this is fairly simple:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;png&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"sample3.png"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;hist&lt;font color="#990000"&gt;(&lt;/font&gt;data&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;xlab &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Some data"&lt;/font&gt;&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;main &lt;font color="#990000"&gt;=&amp;gt;&lt;/font&gt; &lt;font color="#FF0000"&gt;"Histogram of some data"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#009900"&gt;@@r&lt;/font&gt;&lt;font color="#990000"&gt;.&lt;/font&gt;eval_R&lt;font color="#990000"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;"dev.off()"&lt;/font&gt;&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtaiAoHcFI/AAAAAAAAAOo/ApT8RdFPJ3k/s1600-h/sample3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtaiAoHcFI/AAAAAAAAAOo/ApT8RdFPJ3k/s320/sample3.png" alt="" id="BLOGGER_PHOTO_ID_5335457723880796242" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2153282598923359387-7409572782657540464?l=rubyforscientificresearch.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyforscientificresearch.blogspot.com/feeds/7409572782657540464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/plotting-simple-graphs-with-rsruby.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7409572782657540464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2153282598923359387/posts/default/7409572782657540464'/><link rel='alternate' type='text/html' href='http://rubyforscientificresearch.blogspot.com/2009/05/plotting-simple-graphs-with-rsruby.html' title='Plotting Simple Graphs with RSRuby'/><author><name>Peter Lane</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-BL9uSD-L0k/SgtIxmMJrYI/AAAAAAAAAOY/7c3ijaJvGaQ/s72-c/sample.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2153282598923359387.post-3794987746595046797</id><published>2009-05-12T15:57:00.013+01:00</published><updated>2009-05-12T23:56:17.513+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='RSRuby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Analysing Numeric Data in Text Files with Ruby</title><content type='html'>&lt;span style="font-family: verdana;"&gt;A fairly typical scenario I find myself in is having a program run an experiment, outputting its results into a text file.  I want to automate the data analysis so that large amounts of data are converted into tables, graphs and summarising statistics with as little effort as possible.  This is the kind of work computers &lt;/span&gt;&lt;span style="font-style: italic; font-family: verdana;"&gt;should&lt;/span&gt;&lt;span style="font-family: verdana;"&gt; be doing for us.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;To illustrate a simple case, I have an optimisation program running various experiments, and producing text output, which consists of many lines like:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:95%;"&gt;&lt;span style="font-family: courier new;"&gt;results-14-51-3-0.txt, 26, 7, 128, 18, 0.1, 4.62769, 6.45275e+07, 27.6596, 8, 256, 19, 0.1, 9.25538, 4.79442e+08, 27.6596, 9, 512, 21, 0.1, 18.5108, 3.75805e+09, 27.6596&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;results-14-51-3-1.txt, 21, 7, 128, 16, 0.1, 5.72952, 1.14546e+07, 22.3404, 8, 256, 17, 0.1, 11.459, 6.22772e+07, 22.3404, 9, 512, 18, 0.1, 22.9181, 3.37488e+08, 22.3404&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;results-14-59-3-0.txt, 3, 7, 128, 3, 0.35, 35.84, 53775.3, 3.57143, 8, 256, 3, 0.45, 80.2133, 257532, 3.19149, 9, 512, 3, 0.45, 160.427, 1.03329e+06, 3.19149&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;results-14-59-3-1.txt, 24, 7, 128, 16, 0.1, 5.01333, 2.77391e+07, 25.5319, 8, 256, 20, 0.1, 10.0267, 2.46826e+08, 25.5319, 9, 512, 20, 0.1, 20.0533, 1.39406e+09, 25.5319&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;These provide the following information: &lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: verdana;"&gt;&lt;li&gt;within the name is encoded values for 'n' 'm' 'k', defining the experiment, and the 'instance' number; each experiment has been run 20 times.&lt;/li&gt;&lt;li&gt;next is the actual number of minima located in the file.&lt;/li&gt;&lt;li&gt;finally we have three sets of seven values, encoding: l and "2 to the power of l", the number of samples made, the number of minima located, values for gamma, r_appr and T_gamma_r, and finally N_appr, which is an estimate of the actual number of minima.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-family: verdana;"&gt;I want to collect some aggregate results out of these data and generate the results in a format suitable to use in LaTeX.  (One of the great benefits of using LaTeX for writing articles is that its text format can be created by your programs!)  The first time I tried this, I imported the file into a spreadsheet program as CSV, wrote some cell formulae, and then manually copied all the results over to my text editor - not a process I want to repeat.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Classes for the Data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;As we are using Ruby, we first need some classes to hold the data.  There will be a class for the individual results:&lt;/span&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; Results_l&lt;br /&gt;  attr_reader &lt;font color="#990000"&gt;:&lt;/font&gt;l&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;num_found&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;gamma&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;r_appr&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;t_gamma_r&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;n_appr&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;font color="#990000"&gt;(&lt;/font&gt;l&lt;font color="#990000"&gt;,&lt;/font&gt; pow_l&lt;font color="#990000"&gt;,&lt;/font&gt; num_found&lt;font color="#990000"&gt;,&lt;/font&gt; gamma&lt;font color="#990000"&gt;,&lt;/font&gt; r_appr&lt;font color="#990000"&gt;,&lt;/font&gt; t_gammar_r&lt;font color="#990000"&gt;,&lt;/font&gt; n_appr&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@l&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; l&lt;font color="#990000"&gt;.&lt;/font&gt;to_i&lt;br /&gt;    &lt;font color="#009900"&gt;@num_found&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; num_found&lt;font color="#990000"&gt;.&lt;/font&gt;to_i&lt;br /&gt;    &lt;font color="#009900"&gt;@gamma&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; gamma&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;br /&gt;    &lt;font color="#009900"&gt;@r_appr&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; r_appr&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;br /&gt;    &lt;font color="#009900"&gt;@t_gammar_r&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; t_gammar_r&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;br /&gt;    &lt;font color="#009900"&gt;@n_appr&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; n_appr&lt;font color="#990000"&gt;.&lt;/font&gt;to_f&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;And a class for the complete experiment:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;class&lt;/font&gt;&lt;/b&gt; Results_nmk&lt;br /&gt;  attr_reader &lt;font color="#990000"&gt;:&lt;/font&gt;n&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;m&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;k&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;instance&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;true_N&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;results_1&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;results_2&lt;font color="#990000"&gt;,&lt;/font&gt; &lt;font color="#990000"&gt;:&lt;/font&gt;results_3&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;def&lt;/font&gt;&lt;/b&gt; initialize&lt;font color="#990000"&gt;(&lt;/font&gt;n&lt;font color="#990000"&gt;,&lt;/font&gt; m&lt;font color="#990000"&gt;,&lt;/font&gt; k&lt;font color="#990000"&gt;,&lt;/font&gt; instance&lt;font color="#990000"&gt;,&lt;/font&gt; true_N&lt;font color="#990000"&gt;,&lt;/font&gt; results_1&lt;font color="#990000"&gt;,&lt;/font&gt; results_2&lt;font color="#990000"&gt;,&lt;/font&gt; results_3&lt;font color="#990000"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#009900"&gt;@n&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; n&lt;br /&gt;    &lt;font color="#009900"&gt;@m&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; m&lt;br /&gt;    &lt;font color="#009900"&gt;@k&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; k&lt;br /&gt;    &lt;font color="#009900"&gt;@instance&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; instance&lt;br /&gt;    &lt;font color="#009900"&gt;@true_N&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; true_N&lt;br /&gt;    &lt;font color="#009900"&gt;@results_1&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; results_1&lt;br /&gt;    &lt;font color="#009900"&gt;@results_2&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; results_2&lt;br /&gt;    &lt;font color="#009900"&gt;@results_3&lt;/font&gt; &lt;font color="#990000"&gt;=&lt;/font&gt; results_3&lt;br /&gt;  &lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;font color="#0000FF"&gt;end&lt;/font&gt;&lt;/b&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Reading in the Data&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The data is stored in consecutive lines of a text file.  Our main program will read in each text line, extract the fields that it needs, and construct instances of the above classes with the relevant data.  Each line will be stored as an instance of &lt;span style="font-size:95%;"&gt;&lt;span style="font-family: courier new;"&gt;Result_nmk&lt;/span&gt;&lt;/span&gt;, and these instances will be stored in an array of results.  Ruby provides a number of useful techniques to achieve this.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;First, we need to split a string up into pieces, based on a separator token.  The String.split method is key to making our process here work.  Assume the variable line holds one of th
