|
| 1 | +<html> |
| 2 | + <head> |
| 3 | + <title> Ruby Gnuplot - How To </title> |
| 4 | + <style TYPE="text/css"> |
| 5 | + BODY { background: lightyellow; foreground: black; link: #000099; |
| 6 | + vlink: #000066 } |
| 7 | + |
| 8 | + H1 { color: green; text-align: center } |
| 9 | + H2 { color: green; text-align: left } |
| 10 | + H3 { color: green; text-align: left } |
| 11 | + </style> |
| 12 | + </head> |
| 13 | + |
| 14 | + <body> |
| 15 | + <h1> Ruby Gnuplot - How To </h1> |
| 16 | + |
| 17 | + <p align="center"> |
| 18 | + [<a href="http://rubyforge.org/projects/rgplot">Rubyforge Project |
| 19 | + page</a>] |
| 20 | + [<a href="ChangeLog">ChangeLog</a>] |
| 21 | + [<a href="AUTHORS.txt">Authors</a>] |
| 22 | + [<a href="LICENSE.txt">License</a>] |
| 23 | + </p> |
| 24 | + |
| 25 | + <h2> History and Background </h2> |
| 26 | + |
| 27 | + <p> |
| 28 | + Gnuplot is a program that has a rich language for the generation of |
| 29 | + plots. It has a unique place in academia as it was one of the first |
| 30 | + freely available programs for plot generation. I started using gnuplot |
| 31 | + over 10 years ago while pursuing my Master's degree in Physics and have |
| 32 | + been using it actively ever since. |
| 33 | + </p> |
| 34 | + |
| 35 | + <h3>Version 0.9 </h3> |
| 36 | + <blockquote> |
| 37 | + My first attempt at a Ruby interface to gnuplot was an object interface |
| 38 | + encapsulating gnuplot language. This was taken directly from the Python |
| 39 | + gnuplot interface. In spite of my being very familiar with Gnuplot and |
| 40 | + Ruby and being the author of the RGnuplot package, I found it |
| 41 | + non-intuitive to use the RGnuplot package. I found myself constantly |
| 42 | + looking at the code to figure out what I needed to do. |
| 43 | + |
| 44 | + This was not sufficient and did not sit well. |
| 45 | + </blockquote> |
| 46 | + |
| 47 | + <h3>Version 1.0</h3> |
| 48 | + <blockquote> |
| 49 | + The second attempt at a Ruby interface was to do absolutely nothing but |
| 50 | + use Ruby's built in string manipulation methods. This meant that I |
| 51 | + could simply use my knowledge of Gnuplot without having to worry about |
| 52 | + objects. |
| 53 | + |
| 54 | + While in some ways an improvement over Version 0.9, it still did not sit |
| 55 | + well with me. |
| 56 | + </blockquote> |
| 57 | + |
| 58 | + <h3> Version 2.0 </h3> |
| 59 | + <blockquote> |
| 60 | + After attending RubyConf 2004 I was inspired by Rich Kilmer's use of |
| 61 | + Ruby to implement domain specific languages. That is the current |
| 62 | + implementation of Gnuplot and quite probably the one that I'll stick |
| 63 | + with for some time. This version combines the direct mapping of the |
| 64 | + gnuplot language without wrapping with the ruby syntax and mechanism of |
| 65 | + adding methods to existing classes to interface Ruby objects with |
| 66 | + gnuplot. |
| 67 | + </blockquote> |
| 68 | + |
| 69 | + <h2>Setup </h2> |
| 70 | + |
| 71 | + <h3>Version 2.2</h3> |
| 72 | + |
| 73 | + <p> If the 'gnuplot' command is in your path then there is no required |
| 74 | + setup. If the gnuplot executable for your system is called something other |
| 75 | + than simply 'gnuplot' then set the RB_GNUPLOT environment variable to the |
| 76 | + name of the executable. This must either be a full path to the gnuplot |
| 77 | + command or an executable filename that exists in your PATH environment |
| 78 | + variable. |
| 79 | + </p> |
| 80 | + |
| 81 | + |
| 82 | + <h2> Ruby Gnuplot Concepts </h2> |
| 83 | + |
| 84 | + <p> |
| 85 | + Gnuplot has a very simple conceptual model. Calls to <em>Set</em> are |
| 86 | + made to set parameters and either <em>Plot</em> or <em>Splot</em> is |
| 87 | + called to generate the actual plot. The <em>dataset</em> to be |
| 88 | + plotted can be specified in a number of ways, contained in a seperate |
| 89 | + file, generated from a function, read from standard input, or read |
| 90 | + immediately after the plot command. |
| 91 | + </p> |
| 92 | + |
| 93 | + <p> |
| 94 | + The object model for the Ruby gnuplot wrapper directly mimics this |
| 95 | + layout and flow. The following are the standard steps for generating a |
| 96 | + plot: |
| 97 | + </p> |
| 98 | + |
| 99 | + <ol> |
| 100 | + <li> <p> Instantiate a Plot or Splot object and set parameters by gnuplot |
| 101 | + variable name.</p> </li> |
| 102 | + |
| 103 | + <li> <p>Instantiate DataSet objects and attach Ruby objects containing |
| 104 | + the data to be plotted to the DataSet. Attach properties that modify |
| 105 | + the plot command using the modifier name.</p> |
| 106 | + </li> |
| 107 | + |
| 108 | + <li> <p>Send the Plot/Splot object to a Gnuplot instance for |
| 109 | + plotting.</p> </li> |
| 110 | + </ol> |
| 111 | + |
| 112 | + <p> |
| 113 | + The Version 2.0 interface makes very heavy use of blocks leading to very |
| 114 | + readable code. |
| 115 | + </p> |
| 116 | + |
| 117 | + <p>Gnuplot.open </p> |
| 118 | + <blockquote> |
| 119 | + Instantiates a new Gnuplot process. The path to the executable is |
| 120 | + determined on a Unix or MacOSX system using the which command. Windows |
| 121 | + users, I have no idea what to do. |
| 122 | + |
| 123 | + If a block is given to the function the opened process is passed into |
| 124 | + the block. This mimics the most common usage of the File.open method. |
| 125 | + </blockquote> |
| 126 | + |
| 127 | + <p>Plot.new </p> |
| 128 | + <p>SPlot.new </p> |
| 129 | + <blockquote> |
| 130 | + Create a new Plot or Splot object. DataSets are attached to the object |
| 131 | + to specify the data and its properties. |
| 132 | + |
| 133 | + If a block is given to the function, the plot object is passed into the |
| 134 | + block. |
| 135 | + </blockquote> |
| 136 | + |
| 137 | + <p>DataSet.new</p> |
| 138 | + <blockquote> |
| 139 | + Associates a Ruby object containing the data to plot with the properties |
| 140 | + that will be passed to the plot command for that dataset. Any Ruby |
| 141 | + object can be associated with a DataSet as long as it understands the |
| 142 | + to_gplot method. |
| 143 | + </blockquote> |
| 144 | + |
| 145 | + <p> to_gplot </p> |
| 146 | + <blockquote> |
| 147 | + Within Gnuplot, plot data is read in very simple formats. The |
| 148 | + to_gplot method is expected to write the data of the object in a format |
| 149 | + that is understandable by Gnuplot. One of the many great things about |
| 150 | + Ruby is that methods can be added after the original declaration. The |
| 151 | + gnuplot module defines the to_gplot method on the following classes: |
| 152 | + |
| 153 | + Array, String, and Matrix. |
| 154 | + |
| 155 | + Simply define a to_gplot method on your own class to tie the class into |
| 156 | + gnuplot. |
| 157 | + </blockquote> |
| 158 | + |
| 159 | + <h2> Examples </h2> |
| 160 | + |
| 161 | + <h3> Simple sin wave </h3> |
| 162 | + |
| 163 | + <p> The following example simply plots the value of sin(x) between the |
| 164 | + ranges of -10 and 10. A few points to notice: |
| 165 | + </p> |
| 166 | + |
| 167 | + <ul> |
| 168 | + <li><p> The code uses nested blocks to construct the plot. The newly |
| 169 | + created object is passed to the block so it can be modified in |
| 170 | + place. |
| 171 | + </p> |
| 172 | + </li> |
| 173 | + |
| 174 | + <li><p> Each of the gnuplot plot variables are modified using the |
| 175 | + variable name as a method name on the plot object or on the dataset |
| 176 | + object. The wrapper also takes care of the single quoting that is |
| 177 | + required on some of the variables like title, ylabel, and xlabel. |
| 178 | + </p> |
| 179 | + </li> |
| 180 | + |
| 181 | + <li><p> The plot object simply has an array of DataSets. The |
| 182 | + constructor initializes this empty array before yielding to the |
| 183 | + block. This method uses the << operator to add the DataSet to |
| 184 | + the plot. |
| 185 | + </p> |
| 186 | + </li> |
| 187 | + |
| 188 | + <li><p> When the plot block ends, if an IO object is given to the Plot |
| 189 | + constructor, the plot commands will be written to the IO object. |
| 190 | + Any object can be passed to the constructor as long as it |
| 191 | + understands the << operator. |
| 192 | + </p> |
| 193 | + </li> |
| 194 | + </ul> |
| 195 | + |
| 196 | + <pre class='code'> |
| 197 | +Gnuplot.open do |gp| |
| 198 | + Gnuplot::Plot.new( gp ) do |plot| |
| 199 | + |
| 200 | + plot.xrange "[-10:10]" |
| 201 | + plot.title "Sin Wave Example" |
| 202 | + plot.ylabel "x" |
| 203 | + plot.xlabel "sin(x)" |
| 204 | + |
| 205 | + plot.data << Gnuplot::DataSet.new( "sin(x)" ) do |ds| |
| 206 | + ds.with = "lines" |
| 207 | + ds.linewidth = 4 |
| 208 | + end |
| 209 | + |
| 210 | + end |
| 211 | + |
| 212 | +end |
| 213 | + </pre> |
| 214 | + |
| 215 | + <h3> Plotting discrete points </h3> |
| 216 | + |
| 217 | + <p> |
| 218 | + Array data can be plotted quite easily since Arrays have a defined |
| 219 | + to_gplot method. |
| 220 | + </p> |
| 221 | + |
| 222 | + <ul> |
| 223 | + <li><p>Simply pass an array of data to the constructor of the DataSet |
| 224 | + object or set the data property of the DataSet. In this example, |
| 225 | + because there are two arrays, each array will be a single column of |
| 226 | + data to the gnuplot process. |
| 227 | + </p> |
| 228 | + </li> |
| 229 | + </ul> |
| 230 | + |
| 231 | + <pre class='code'> |
| 232 | +Gnuplot.open do |gp| |
| 233 | + Gnuplot::Plot.new( gp ) do |plot| |
| 234 | + |
| 235 | + plot.title "Array Plot Example" |
| 236 | + plot.ylabel "x" |
| 237 | + plot.xlabel "x^2" |
| 238 | + |
| 239 | + x = (0..50).collect { |v| v.to_f } |
| 240 | + y = x.collect { |v| v ** 2 } |
| 241 | + |
| 242 | + plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds| |
| 243 | + ds.with = "linespoints" |
| 244 | + ds.notitle |
| 245 | + end |
| 246 | + end |
| 247 | +end |
| 248 | + </pre> |
| 249 | + |
| 250 | + <h3> Multiple Data Sets </h3> |
| 251 | + |
| 252 | + <p> As many data sets as are desired can be attached to a plot. Each of |
| 253 | + these can have their own plot modifiers. Notice in this example how the |
| 254 | + data array is explicitly set instead of using the << operator. |
| 255 | + </p> |
| 256 | + |
| 257 | + <p> Also in this example, the commands are not written to the Gnuplot |
| 258 | + process but are instead written to a File called gnuplot.dat. This file |
| 259 | + can later be run directly by a gnuplot process as it contains only the |
| 260 | + gnuplot commands. |
| 261 | + </p> |
| 262 | + |
| 263 | + <pre class='code'> |
| 264 | +File.open( "gnuplot.dat", "w") do |gp| |
| 265 | + Gnuplot::Plot.new( gp ) do |plot| |
| 266 | + |
| 267 | + plot.xrange "[-10:10]" |
| 268 | + plot.title "Sin Wave Example" |
| 269 | + plot.ylabel "x" |
| 270 | + plot.xlabel "sin(x)" |
| 271 | + |
| 272 | + x = (0..50).collect { |v| v.to_f } |
| 273 | + y = x.collect { |v| v ** 2 } |
| 274 | + |
| 275 | + plot.data = [ |
| 276 | + Gnuplot::DataSet.new( "sin(x)" ) { |ds| |
| 277 | + ds.with = "lines" |
| 278 | + ds.title = "String function" |
| 279 | + ds.linewidth = 4 |
| 280 | + }, |
| 281 | + |
| 282 | + Gnuplot::DataSet.new( [x, y] ) { |ds| |
| 283 | + ds.with = "linespoints" |
| 284 | + ds.title = "Array data" |
| 285 | + } |
| 286 | + ] |
| 287 | + |
| 288 | + end |
| 289 | + |
| 290 | +end |
| 291 | + |
| 292 | + </pre> |
| 293 | + |
| 294 | + </body> |
| 295 | +</html> |
0 commit comments