In the last post, I went through (in some detail) the details around how to do fits to data. In doing so, I included a fairly detailed discussion of the JavaScript array object. In this post, I'm going to be a bit less detailed and give a few examples of the use of the doFit() function. This is not, by any means, the only way to do fitting in JSvg, but it does provide a simple wrapper that hides the more complicated fitting methods from the user. Once the Analysis Console is up, if one types:
doFit.toSource()
the following code will appear. In fact, much more will appear, but I've shown the headers of the code here.
"function doFit(xArr,yArr,fitN,prec) {
// This should return a fit array and the equations of fit, and coefficients
// pass 1d xArr and 1d yArr
// fitN = 1 - linear
// 2 - quadratic
// 3 - cubic
// 4 - sinusoidal"
In much of the JSvg codebase, the code is commented so as to provide the user with additional help as to how to use the various functions. In its current state, doFit() supports linear, quadratic, cubic, and sinusoidal fitting. (Note that in the next release of OT/JSvg, it will also support logarithmic, exponential, and power law fitting, but more on that in another post). So to use the function one needs a vector of x-data, a vector of y-data, a number specifying which fit to do, and a precision. If precision isn't specified, all output numbers will be shown to the third digit past the decimal place.
So, without further ado, here are a couple of examples. Presume that I have x-data and y-data as follows:
var xdata = [1.3333,1.3381,1.3429,1.3476,1.3524,1.3571,1.3619,1.3667,1.3714,1.3762,1.3810,1.3857,1.3905,1.3952,1.4000,1.4048,
1.4095,1.4143,1.4190,1.4238,1.4286,1.4333,1.4381,1.4429,1.4476,1.4524,1.4571,1.4619,1.4667,1.4714,1.4762,1.4810,
1.4857,1.4905,1.4952,1.5000,1.5048,1.5095,1.5143,1.5190,1.5238,1.5286,1.5333,1.5381,1.5429,1.5476,1.5524,1.5571,
1.5619,1.5667,1.5714,1.5762,1.5810,1.5857,1.5905,1.5952,1.6000,1.6048,1.6095,1.6143,1.6190,1.6238,1.6286,1.6333,
1.6381,1.6429,1.6476,1.6524,1.6571,1.6619,1.6667,1.6714,1.6762,1.6810,1.6857,1.6905,1.6952,1.7000,1.7048,1.7095,
1.7143,1.7190,1.7238,1.7286,1.7333,1.7381,1.7429,1.7476,1.7524,1.7571,1.7619,1.7667,1.7714,1.7762,1.7810,1.7857,
1.7905,1.7952,1.8000,1.8048,1.8095,1.8143,1.8190,1.8238,1.8286,1.8333,1.8381,1.8429,1.8476,1.8524,1.8571,1.8619,
1.8667,1.8714,1.8762,1.8810,1.8857,1.8905,1.8952,1.9000,1.9048,1.9095,1.9143,1.9190,1.9238,1.9286,1.9333,1.9381,
1.9429,1.9476,1.9524,1.9571,1.9619,1.9667,1.9714,1.9762,1.9810];
var ydata = [0.986,1.003,1.015,1.027,1.04,1.052,1.06,1.073,1.085,1.093,1.105,1.114,1.126,1.134,1.142,1.155,1.163,1.167,1.175,
1.184,1.192,1.2,1.208,1.216,1.225,1.229,1.237,1.245,1.249,1.253,1.262,1.266,1.27,1.278,1.282,1.286,1.29,1.295,1.299,
1.303,1.307,1.307,1.311,1.315,1.315,1.315,1.319,1.323,1.323,1.323,1.323,1.327,1.327,1.327,1.327,1.327,1.327,1.327,
1.327,1.327,1.323,1.323,1.323,1.319,1.315,1.315,1.315,1.311,1.307,1.307,1.303,1.299,1.295,1.29,1.286,1.282,1.278,
1.27,1.266,1.262,1.253,1.249,1.245,1.237,1.229,1.225,1.216,1.212,1.204,1.196,1.188,1.179,1.171,1.163,1.155,1.147,
1.138,1.13,1.118,1.11,1.097,1.089,1.077,1.064,1.044,1.044,1.036,1.023,1.011,0.999,0.986,0.974,0.962,0.949,0.933,
0.921,0.908,0.892,0.879,0.867,0.851,0.838,0.822,0.81,0.793,0.777,0.76,0.744,0.727,0.711,0.695,0.678,0.662,0.645,
0.625,0.608,0.592];
To plot the data with a fit, we must first construct a fit. We do it as follows (blindly assuming that these data follow a linear trend:
var fitOrder = 1;
var fitPrec = 3;
fitObj1 = doFit(xdata,ydata,fitOrder,fitPrec);
Just because, at this point, we don't know that the data *are* actually linear, let's try fitting a quadratic as well:
var fitOrder = 2;
var fitPrec = 3;
fitObj2 = doFit(xdata,ydata,fitOrder,fitPrec);
So now there are two "fitObjs" which contain fit data. What do they contain? Recall that doFit() returns the following values.
// fitObj[0] = 1D array containing the predicted y values for each x data point
// fitObj[1] = equation of fit (t is default variable) (String)
// fitObj[2] = 1D array containing the coefficients of fit starting with highest order term
So let's put the rest of our script together and plot.
// Put x and y data and fits into output plotting variables:
var xout = [xdata, xdata, xdata]; // xdata are the coordinate pairs for the fit data from doFit();
var yout = [ydata, fitObj1[0], fitObj2[0]]; // matching y data
// Now for graphics parameters:
optsSeries[0].name = 'data'; // Call it what you will, but this is our original data
optsSeries[1].name = fitObj1[1]; // Label for the first fit
optsSeries[2].name = fitObj2[1]; // Label for the second fit
// Fits look better with a line rather than points
optsSeries[1].itype = 1;
optsSeries[2].itype = 1;
// And sometimes it's nice to adjust the colors
optsSeries[1].stroke = 'blue';
optsSeries[2].stroke = 'black';
// How about some labels?
optsGraphTitles[0].name = 'Time (s)';
optsGraphTitles[1].name = 'y position (m)';
optsGraphTitles[2].name = 'y vs t';
optsGraphTitles[3].name = 'for a tossed ball';
// Name the file, don't forget .svg Windows users!
var fn = 'fallingMotion.svg';
// Now plot it!
drawSeriesPlot(xout,yout, 0,0, fn);
The resultant graph looks like this (after clicking the legend and title to adjust the positioning).
For the physics crowd, you will clearly see that these data originated from a ball drop and, as such, the quadratic fits much better. In fact these data result from the "Falling Motion" lab included in OpenTrack's tracking portion of the program.
A new release of OT/JSvg is due out shortly, and when it comes I will go over some of the new features.
Cheers!