Simple? surface plot question
dcnicholls
I have variable A plotted against variable B. Variable A's values (independent) are stored in one column. Variable B's values are the dependant ones. They are stored in a dozen columns, each column calculated from variable A for a particular value of (independent) variable C.
The simple 2D plot consists of a series of plots of A vs B, each curve corresponding to a value of C.
How can I fit a surface to these curves?
The help file says this:
2D Waves: Sometimes called "matrix of z-values", these are M rows by N columns waves where each entry represents a scalar z-value. You can apply wave scaling (see SetScale) to associate an X value with every row and a Y value with each column.
I can concatnate the columns of B data into a Z-wave, but I don't know how to use wave scaling to associate an X value with rows (from variable A?) and a Y value with the columns (from variable C?). If that's what I should be doing?
Thanks
DN
I'm not a big fan of the "dependent" terminology and before we start building surfaces we need to make sure that there is some significance to connecting between point i in column j and point i in column (j+1). If that is not the case then your options are to use a waterfall plot or a set of path plots in 3D.
If your data should be plotted as a surface and if each column represents samples that are taken at equal intervals along each one of the axes you can apply wave scaling to the concatenated wave. You can do that programmatically using the SetScale operation or by going to Data Menu->Change Wave Scaling. Once you applied wave scaling you can simply select the concatenated wave in the Data Browser and choose Gizmo Plot from the contextual menu (right-click on Windows or Ctrl-click on Macintosh).
If you are having difficulty understanding these concepts feel free to contact me directly.
A.G.
WaveMetrics, Inc.
April 2, 2010 at 09:45 am - Permalink
An image plot is the simplest, but usually requires that your X and Y data be evenly spaced. You say that you have a dozen columns, which I take to mean you already have a 2D wave (matrix) of the data (the B values), which I will assume is called "B". In that case, you want to scale the B wave to match the scaling of the A and C data. This means that if the A values are {3,5,7,9,10} and the C values are {1.0,1.1,1.2,1.3,1.4,1.5}, you would do:
SetScale /p y,1,0.1,B // Ditto for the columns of B.
NewImage B // Makes an image plot of B. The colors correspond to the B data, and the axis values correspond to the scaling you just applied.
A contour plot can be done even if your X and Y data are not evenly spaced:
AppendMatrixContour B vs {A,C}
If they are evenly spaced, you can also just do something similar to what we did with the Image Plot:
SetScale /p y,1,0.1,B // Ditto for the columns of B.
Display
AppendMatrixContour B
Surface plots are the trickiest. If the Gizmo and Surface Plot XOPs are already installed (they should be in a recent version of Igor), you can use a graphical interface to make your surface plot, which will help you learn the commands:
SetScale /p y,1,0.1,B // Ditto for the columns of B.
CreateSurfer
// Then click source, "Matrix of Z-values" and pick your wave B. Click "Do It", and check "Always Update".
You can then export a surface plot to Gizmo, which uses OpenGL to give your an incredibly versatile graphics engine, at the expense of being tricky to use.
Update:
It may be easier and better to use Gizmo directly:
SetScale /p y,1,0.1,B // Ditto for the columns of B.
NewGizmo
AppendToGizmo defaultSurface=B
Rick
April 2, 2010 at 01:48 pm - Permalink
Each 1D wave has an internal x0 and dx properties. These properties are set using the SetScale operation and are used to map a point number to a computed X value: x = x0 + dx*pointNumber. Choose File->Example Experiments->Tutorial->X Scaling Tutorial for a demonstration or see "Waves - The Key Igor Concept" at the start of the Getting Started help file.
Each 2D wave has internal x0, dx, y0 and dy properties from which Igor computes X values and Y values.
If your X and Y values are evenly-spaced then you can use wave scaling. Choose Data->Change Wave Scaling to generate the required SetScale commands.
If your X and Y values are not evenly-spaced then you can not use wave scaling.
If you select a multi-variate curve-fitting function and a 2D wave as your data, Curve Fitting dialog allows you to choose _calculated_ or an explicit wave for both your X and Y values. _calculated_ means "use the X or Y values calculated from the wave scaling properties".
Given a 5x5 2D wave named mat, a 5-point 1D wave named xData and a 5-point 2D wave named yData, I am able to generate the following command using the Curve Fitting dialog:
If you are still stuck, send an experiment with your data to support@wavemetrics.com.
April 2, 2010 at 10:13 am - Permalink
Yes, that is the case. The values in row i in consecutive columns differ only in the value of C used to calculate them.
The data are calculated, not observed, so the spacing is even.
Actually the equation is:
B = log(InverseErf(C)/k1 - k2) + k3 + 2*log(A)
with B plotted against A for a range of C values (the k's are constants).
I tried the process and I think I'm getting somewhere. Certainly this has opened a few more doors, although I'm still blundering around a bit :-)
That's the best way to learn!
Thanks.
April 2, 2010 at 05:09 pm - Permalink
B = log(InverseErf(C)/k1 - k2) + k3 + 2*log(A)
A and C are equal size column vectors.
How do I calculate a 2D matrix B such that
B(i,j) = log(InverseErf(C(j))/k1 - k2) + k3 + 2*log(A(i))
for all i, j?
Do I need to do that in a loop? Along the lines of
for j= 0 to jmax
for i= 0 to imax
B(i,j) = log(InverseErf(C(j))/k1 - k2) + k3 + 2*log(A(i))
next i
next j
DN
April 3, 2010 at 03:40 am - Permalink
Function mH(m1, c1, d1)
Wave m1, c1, d1
Variable i, j
for(j=0;j<128;j+=1)
for(i=0;i<128;i+=1)
m1[i][j] = log(InverseErf(c1[j])/0.12 -6.4) + 5.371 +2*log(d1[i])
endfor
endfor
End
but is there a more elegant way to do it?
April 3, 2010 at 04:56 am - Permalink
Yes:
Wave m1, c1, d1
m1 = log(InverseErf(c1[q])/0.12 -6.4) + 5.371 +2*log(d1[p]) // Here I assume you want to iterate over all rows and column of m1. If you only want to go to [0,127] (and there are more than 128 rows and columns), do m1[0,127][0,127]=...
End
"p" and "q" are a shortcut for accessing the row and column indices of the left-hand side. This allows you to do wave assignments that would otherwise require a loop.
Rick
April 3, 2010 at 08:12 am - Permalink
Splendid! Thanks.
DN
April 3, 2010 at 08:38 am - Permalink
For an explanation of this feature:
April 3, 2010 at 08:15 pm - Permalink
Thanks. I used the command line version of the equation rather than as a function and it worked perfectly (in fact I have now inverted the equation with c as the calculated matrix).
It is certainly a lot neater than writing a set of for loops. I knew Igor had to have a clean way to do the calculation, but didn't know what to look for.
DN
April 3, 2010 at 08:56 pm - Permalink