Thursday, January 16, 2014

My First Script: Plotting Data

This post is the first in a series designed to show you how to use OT/JSvg to analyze data.  There's a whole lot to JSvg, so rather than attempt to cover everything at once, we'll take it piecemeal.  Perhaps the simplest analysis used in many science classes the plotting of data.  OT/JSvg makes this relatively easy to do using regular JavaScript, the linga franca of the internet.  But to get started, you will need to get the Analysis Console open first.  In Firefox, go to the Tools option in the Menu Bar, and select "Start Analysis Console".  If you don't see it, you don't have OT/JSvg properly installed, and I'll refer you to the previous post.   At this point, you will see the console pop up.


Figure 1: A blank console after it has first popped up.

The purpose of the console is to allow users to easily make use of the JSvg libraries and see results in an organized manner.  The console also allows you to open up both the Web Console, a command line interface that allows you to type commands and do calculations using the scope of the window, and ScratchPad, a simple JavaScript programming editor with syntax highlighting.  Today, we're going to use ScratchPad to write the code.  The results will be displayed in the Analysis Console.

Let's start with the data.  In one particular physics lab, students measure resistance of various lengths of wire.   Of course, as wire is conductive, it takes a whole lot of wire to provide a measurable resistance with most multimeters.  So we use coils of wire rather than linear lengths.  Then the students make their measurements of resistance every so many coils and calculate the length based on the number.  If we know the radius of the coil, and the number of coils, it is pretty straight forward to calculate the total length.

    var R = 0.02275;   // m
    var Ncoils = 100;  // Number of coils
    var pi = Math.PI;  // Use pi as a short hand for the JavaScript 
                       // constant Math.PI
    var L = 2*pi*R*Ncoils;   // This is the total length;
 
But wait! We can do better than this. Let's say that we make six measurements at increments of 100 coils. We could write out each calculation, OR, we could do one better and use a loop and arrays. Loops allow you to repeat calculations an arbitrary number of times without having to type out each one. In short, they are time savers. Arrays allow you to store results. While in general, they are of a related type (for example lengths of wire), in JavaScript arrays can consist of all kinds of unrelated objects. More on that later. Let's change the code to this.

    var R = 0.02275;   // m
    var Ncoils = 100;  // Number of coils
    var Ntrials = 6;   // Number of trials 
                       //   (presume we sample resistance every 100 coils)
    var pi = Math.PI;  // Use pi as a short hand for the JavaScript constant Math.PI
    var L = new Array();   // Define the array.  It's empty now.  
    for (var i=0; i< Ntrials; i++) {
         var Ntot = (i+1)*Ncoils;  // Total number of coils this sample.
         L[i] = 2*pi*R*Ntot;   // This is the ith value of length in the array
    }

The loop is called a for loop and it works like this. Starting with an index (i) of 0, do this loop while i is less than Ntrials (6 times), incrementing i by 1 each time (i++). The result is that the array L will contain six values based on a formula that was executed six times, once per loop. The formula
    Ntot = (i+1)*Ncoils

calculates the total number of coils in that iteration. The first time, since the loop index i is zero, the result will be:
    Ntot = (0+1)*100 = 100 coils.

The second time, when the index is one, the result will be:
    Ntot = (1+1)*100 = 200 coils.

And so on. We will use the L array as our x values. For y values we have our measured resistances.
   resist = [0.6,1.1,1.6,2.1,2.7,3.5];   // Ohms

Note that there are six values in this array and that they are separated by commas. To this point, one could run the ScratchPad code without the help of JSvg since it's pure JavaScript. However to plot these data, we need to use JSvg graphics functions. The simplest scatterplot function available (without going low-level) is
    drawSeriesPlot([2D xarray], [2D yarray], 0,0, filename)
where the first argument is your x data, and the second is your y data. These are 2D arrays rather than 1D arrays by default so that if you have multiple series of data, you can plot them in a single command. The third and fourth arguments of the function are deprecated. For now, just use zeroes every time you call the command. The final argument is the filename in string form. This means that there should be quotes around the name. It is important that you specify the ".svg" extension to ensure that the graph displays properly. So here's the plotting command.
    drawSeriesPlot([L],[resist], 0,0, 'resistivityPlot.svg');

The 1D arrays L and resist are each enclosed in brackets to make them into 2D arrays. If you are starting with 2D arrays, you will not need to do this. When you run this command your graph will appear in the upper left-hand pane of the console (current graph), and when you mouse-over it, its background will turn orange. Clicking on the orange will make it appear in the main frame.

Figure 2: Results thus far
 You will notice a couple of things at this point: first, that there are no labels on the axes, and second, that there is a legend with a series called "unnamed0" displayed.  Let's add the titles via code (and later we'll see how to add them post-coding). The following commands create titles for your graph.
    optsGraphTitles[0].name = 'Length (m)';    // x-axis title
    optsGraphTitles[1].name = 'Resistance (\\Omega )';  // y-axis title
    optsGraphTitles[2].name = 'Resistance vs Length';   // main title
    optsGraphTitles[3].name = 'for a coil of wire';     // sub title

Figure 3: The graph after titles have been added.
If you're sharp, you'll notice that the \\Omega turned into an upper case omega in the y-axis title.  Generally, you can create Greek letters in this manner.  However, you will also need to remember to leave a space after the letter for the parser to work correctly.

We still have the issue of the legend.  One generally doesn't use the legend for single series plots.  So let's remove it.  Set the variable optsLegend to false to suppress its appearance.
    
    optsLegend = false;

The final graph (for today) will look as follows:

Figure 4: The final graph, no legend and with titles.
It is, of course, possible to change things around without dropping to ScratchPad. When your graph is displayed within the Analysis Console, you can click to change most items. Clicking on a title allows you to change its font or position. Clicking on an axis allows you to set the color of the grid lines, the number of divisions on the axis, the use of minor ticks, the precision of the displayed numbers, and so on. The font of the axis matches the font of the axis title. Should you forget to add titles, mouse over the upper left hand side of the graph, and after a couple of seconds, a title dialog will appear. In the meantime, here's the code for the day.
    
    var R = 0.02275;   // m
    var Ncoils = 100;  // Number of coils
    var Ntrials = 6;   // Number of trials 
                   //   (presume we sample resistance every 100 coils)
    var pi = Math.PI;  // Use pi as a short hand for the JavaScript constant Math.PI
    var L = new Array();   // Define the array.  It's empty now.  
    for (var i=0; i< Ntrials; i++) {
         var Ntot = (i+1)*Ncoils;  // Total number of coils this sample.
         L[i] = 2*pi*R*Ntot;   // This is the ith value of length in the array
    }

    var resist = [0.6,1.1,1.6,2.1,2.7,3.5];   // Ohms

    // Graphics commands
    optsGraphTitles[0].name = 'Length (m)';    // x-axis title
    optsGraphTitles[1].name = 'Resistance (\\Omega )';  // y-axis title
    optsGraphTitles[2].name = 'Resistance vs Length';   // main title
    optsGraphTitles[3].name = 'for a coil of wire';     // sub title

    optsLegend = false;

    drawSeriesPlot([L],[resist], 0,0, 'resistivityPlot.svg');

In the next post, we'll talk about how to fit a line to these data. Cheers!

1 comment:

  1. Sadly, I've not had the time to keep this updated. Perhaps this semester? I have more activities planned...

    ReplyDelete