Simple? contour plot question from new user

I have a 2D array of point corrdinates in the x,y plane. I would like to produce a contour plot which displays the density of the point distribution in the plane. Is this possible? How? I have been playing with Igor for about two hours so I'll need pretty simple instructions. Thanks

DN
Go to "Windows" -> "New"-> "Contour Plot" -> "Contour Plot..."

A dialog box will come up. The Z-wave should be your array and the x and y should be calculated from your point scaling.

Click "Do It". Right click on the plot to modify the graph.

Andy
I had tried that route, but in the New Contour Plot window, the z-wave entry is blank and I can't get it to show or load anything. What I had previously done was to load the two column csv file as a wave. The two column headers do appear in the x wave an y wave boxes but the z wave entry is empty.
[ UPDATE: This rest of this post is wrong. The one-extra-point business is for an image plot, not a contour plot. ]

When you create a contour of a matrix of Z values using explicit X and Y waves, the X and Y waves must have one extra point. This is because, for example, the X wave specifies the X coordinate of the left edge of each pixel in the matrix and Igor needs to know the X coordinate of the right edge of the last pixel. Use explicit X and Y waves only if your data is unevenly spaced.

If your data is evenly-spaced, choose _calculated_ for X wave and Y wave and set the X and Y scaling of the matrix of Z values to indicate what the spacing is. To set the X and Y scaling, choose Data->Change Wave Scaling.

If you do have unevenly-spaced Z data then you must add an extra point to your X and Y waves. The extra point should specify the X or Y coordinate of the right edge of the last pixel in the matrix of Z values. You can add the extra point using a table.

OK, I think I'm starting to follow. At present, the array consists of 3400 pairs of numbers, corresponding to random points on the x,y plain. These are not sorted in any partoicular order (though obviously they could be). For example, the last entry in the array is: -21.87,9.12 which is typical of the values of the other array rows.

Each value in the array is specified to two decimals (only). So, do I need to sort the array, and how do I work out the value of the additional point you mention?

Thanks
dcnicholls wrote:
OK, I think I'm starting to follow. At present, the array consists of 3400 pairs of numbers, corresponding to random points on the x,y plain. These are not sorted in any partoicular order (though obviously they could be). For example, the last entry in the array is: -21.87,9.12 which is typical of the values of the other array rows.

Each value in the array is specified to two decimals (only). So, do I need to sort the array, and how do I work out the value of the additional point you mention?


I'm not tracking.

To create a contour plot in Igor you need either a matrix (2D wave) of Z values or a series of XYZ triplets. Your latest post does not mention a matrix and does not mention a Z wave. Do you have a matrix of Z values or a series of XYZ triplets?

If you just have XY data, create an XY plot in marker mode, like this:

Display yData vs xData
ModifyGraph mode=3 // Markers mode


If you have XYZ data, whether in the form of a matrix of Z values or XYZ triplets, try checking out the Contour Demo experiment by choosing File->Example Experiments->Contour Demo. This may help you understand what Igor is looking for.

Here is another simple example using a matrix of Z values:

Make/N=(50,50) mat
SetScale x -1, 1, mat
SetScale y -1, 1, mat
mat = x * y
Edit mat
NewImage mat
Display;AppendMatrixContour mat
AppendImage mat

Let me clarify. The values in the array specify points on an x-y pane the bounds of which are determined by the data set itself. They are just a collection of x,y values. When you plot them on an x,y graph the points tend to clump towards the middle of the graph and thin out towards the edges. I wanted to plot contours corresponding to how dense the clump is at any point on the x,y plain. If you look at any specific point on the x,y plain, there is either something present or (usually) nothing present. There is nothing regular about the value distribution. Think of it as a 2D projection of a swarm of bees (actually, galaxies) that you want to plot contours of swarm density for on the projected plain.

When I tried the command:

Display yData vs xData

Igor replied "expected Wave name".

Algorithmically, I can think of one way of doing it, namely for a regularly spaced set of cells of width dx,dy, spanning the same x,y range as the original data set, for each cell in the array, how many objects in the original data set are there within each cell, and set that value as the 'z' value for the x,y cell, then use that as the basis for contour drawing. But I was hoping Igor might have something like that built in.

dcnicholls wrote:
Let me clarify. The values in the array specify points on an x-y pane the bounds of which are determined by the data set itself. They are just a collection of x,y values.


In this case you can not do a contour plot. A contour plot requires X, Y and Z values and you have only X and Y values.

dcnicholls wrote:
When you plot them on an x,y graph the points tend to clump towards the middle of the graph and thin out towards the edges. I wanted to plot contours corresponding to how dense the clump is at any point on the x,y plain. If you look at any specific point on the x,y plain, there is either something present or (usually) nothing present. There is nothing regular about the value distribution. Think of it as a 2D projection of a swarm of bees (actually, galaxies) that you want to plot contours of swarm density for on the projected plain.


I don't know how to do that. Perhaps someone else will have an idea.

dcnicholls wrote:
When I tried the command:

Display yData vs xData

Igor replied "expected Wave name".


You need to replace yData and xData with the names of your Y and X waves.

dcnicholls wrote:
Algorithmically, I can think of one way of doing it, namely for a regularly spaced set of cells of width dx,dy, spanning the same x,y range as the original data set, for each cell in the array, how many objects in the original data set are there within each cell, and set that value as the 'z' value for the x,y cell, then use that as the basis for contour drawing. But I was hoping Igor might have something like that built in.


Yes, that would work. I don't believe Igor has anything built-in.

I have attempted to write a function that does this. It is not thoroughly tested. You can find it here. Copy and paste it to the procedure window of a new experiment and try the example commands in the comments. Then read the function to get a sense of how it works.
Beaten by WM!
I just coded this little function, looks quite similar to what Howard did. In my case, you can only specify a square grid and the name of the output matrix is hardcoded. But the result is a little different...so I post it anyway.
Wolfgang Harneit
function pntDensity(xWave, yWave, nIntervals)
wave xWave, yWave
variable nIntervals
    variable nPnts = min(numpnts(xWave), numpnts(yWave))
    variable xMin = WaveMin(xWave), yMin = WaveMin(yWave)
    variable xMax = WaveMax(xWave), yMax = WaveMax(yWave)
    Make/O/N=(nIntervals, nIntervals) mat
    SetScale/I x, xMin, xMax, mat
    SetScale/I y, yMin, yMax, mat
    Duplicate/FREE/O xWave, xSorted
    Duplicate/FREE/O yWave, ySorted
    Redimension/N=(nPnts) xSorted, ySorted
    xSorted = round((xSorted - xMin) * nIntervals / (xMax-xMin))
    ySorted = round((ySorted - yMin) * nIntervals / (yMax-yMin))
    Sort {xSorted, ySorted} xSorted, ySorted
    variable n, nx = 0, ny = 0
    for( n = 0; n < nPnts; n += 1)
        if( (ySorted[n] > ny) || (xSorted[n] > nx) )
            nx = xSorted[n]
            ny = ySorted[n]
        endif
        mat[nx][ny] += 1
    endfor
end


A sample call is
Make/O/N=10000 xData=sin(pi*enoise(1)), yData=sin(pi*enoise(1))
Display yData vs xData
ModifyGraph mode(yData)=2
•pntDensity(xData, yData, 10)
AppendMatrixContour mat
Thanks, those functions look very helpful. Now I have to go back to do my homework on where to locate the user function(s) (../Documents/WaveMetrics/Igor Pro 6 User Files/User Procedures/ ?), what to name them (*.ipf?), and how to invoke them from the command line. I don't know where my mistakes are being made yet. "I may be gone for a while".
OK, got the CreateDensityMatrix function working. Curious result, not what I was expecting, as it still retains a "grid" structure with internal contours within each cell, rather than global contours. Maybe a consequence of the data itself. See screenshots. (axes rotated).
orig_data.png (20.65 KB) Graph1.png (47.14 KB)
Problem solved, I think. I found a routine called 2D Joint Histogram on the Igor exchange which does the job. I made a 2d image from the columns of the original data, binning it 5x5, ran the 2D histogram on it, MatrixFiltered the result, then did the Windows > New > Contour Plot. Nice.

I've just begun to appreciate the power of Igor!

Thanks to all for guidance.
dcnicholls wrote:
Problem solved, I think. I found a routine called 2D Joint Histogram on the Igor exchange which does the job. I made a 2d image from the columns of the original data, binning it 5x5, ran the 2D histogram on it, MatrixFiltered the result, then did the Windows > New > Contour Plot. Nice.

I've just begun to appreciate the power of Igor!

Thanks to all for guidance.


And I think that 2D Joint Histogram is faster and cleverer than my own code that ships with Igor. For mine, add this line to your Procedure window:

#include <Bivariate Histogram 2>


There are comments describing the file at the top; select Windows->Procedure Windows->Bivariate Histogram 2.ipf. My procedure adds a bit of GUI to the problem.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Quote:
For mine, add this line to your Procedure window:

#include


Curious Browser or bulletin board quirk: I cannot see the <Bivariate Histogram 2> term in Safari that follows the "#include"

I only saw it when I quoted the original to ask what was included! (So question answered itself!)

I used the HTML codes &gt; and &lt; to show it in my post

DN
dcnicholls wrote:

Curious Browser or bulletin board quirk: I cannot see the <Bivariate Histogram 2> term in Safari that follows the "#include"
DN


This is because John forgot to surround his Igor code with <igor></igor> tags. I just fixed his original post so it looks right again.