Creating a wave reference to one column of a matrix

I am trying to create a 1D wave reference to a single column of 1 2D (matrix) wave. To create a reference w to column 3 of a 2D wave, the syntax I hoped would work is

Wave w = wave2d[][3]

but this is not syntactically correct. What is the correct way to do this?

To avoid any confusion: Above code does NOT create a wave reference to the column, but instead creates a new wave w in the folder, which contains only the column in question and can be used instead. The original wave wave2D is not altered at all with wave assignments to w. Thus, to modify the column, you would need to write the contents of w back into wave2D. If you are using this inside code I would recommend to use at least MatrixOp/FREE to free up the memory afterwards. To be honest, I am not sure why you want to refer to a single column. What is the use case here?

It's not possible to do what you asked in your original question.

Splitting a 2D wave into one or more 1D waves is the correct approach, but since you are copying the data when you do that it comes with the caveats that @chozo mentioned.

In reply to by chozo

chozo wrote:

... To be honest, I am not sure why you want to refer to a single column. What is the use case here?

Obviously I don't know what the case is here, but I do this all the time. I often use labelled 2D waves to store information of n samples, e.g. chemical analyses and other parameters, rather than clutter up folders with multiple 1D waves. Data analysis typically involves functions working on the entire matrix as well as on single columns/rows. 

Sure, but wouldn't you assign the column outright instead of extracting it out? I do this as well, for example, when working with functions specifically designed for 1D data, such as FindLevel, Extract etc.

I personally never assign new values to original columns/rows, but whether I extract them to create output depends on the complexity of the arithmetic expression, which can become quite clumsy with column/row/dimlabel aware syntax. 

What I am really trying to do is to extract the value of a given column wave at a particular value of its scaled x-value. I would like this process to properly interpolate as needed. For an ordinary 1D wave this can be done easily:

value = wave1D(3.5)

If wave1D looks like (wave1d.x, wave1D.d) = (...{3, 9},{4, 10}...) then value will be assigned to 9.5.

However, for a 2D wave the same kind of syntax (while legal) does not result in a properly interpolated result. If we write

value = wave2D(3.5)[0]

and column 1 of wave2D is identical to wave1D (including scaling), then value is equal to 10; the scaled x-value of 3.5 is evidently rounded to the closest x-value that is actually associated with a point (here, 4.0).

This may more easily be seen by graphing these various quantities. I have created a 2D wave, wave2D, whose column values are linearly increasing. When we plot, e.g., wave2D[*][0] we see this smooth increase in red. When I interpolate this column directly into a 1D wave, we get the staircase appearance shown in blue, because the x-values are rounded.  Finally, if I copy the 2D column into a 1D wave (same number of points and scaling), then interpolate into another 1D wave, the result is the smooth curve shown in green (the curves are vertically offset for clarity).

So right now my code consists of copying a column into a 1D wave, then using the "value = wave1D(3.5)" notation.

Graph1.png (130.8 KB)

Yes, that is a limitation of Igor's wave assignment, see here:

DisplayHelpTopic "Interpolation in Wave Assignments"

In this case, extracting the column is a good choice, but you could also use interp2D.

I found this discussion that may be relevant. It sounds like maybe this behavior is corrected in Igor 9? (I have Igor 8.) Also, Chozo's suggestion of using interp2D works without creating a temporary 1D wave:

value = Interp2D (wave2D,  3.5, 0)

gives the expected interpolated value of 9.5.

 

The linked discussion was about the use of assignments using square brackets []. And yes, this interpolation issue for 1D waves has indeed been resolved in Igor 9. This does not help in your case, since automatic 2D interpolation is still not supported. interp2D is the way to go if you just need a simple interpolated value from a 2D wave. Interestingly, you can get an interpolated result from a 2D wave of the first column by leaving out the column index. Try:

print wave2D(3.5)
print wave2D(3.5)(0)

To interpolate in the row dimension, use something like

wave2D(xvalue + ncol * (IndexToScale(wave2D, dimsize(wave2D, 0), 0) - DimOffset(wave2D, 0)))

where xvalue is the row x value and ncol is the column number.

Note that I used a point number of  (last row + 1)  for IndexToScale.

Igor doesn't do this automatically for 2D waves because there is no way to know whether you expect 2D bilinear interpolation, 1D row, or 1D column interpolation. Better not try extrapolating the input x values.

 

Interp2d() is probably the most efficient method but you have to be careful that your second coordinate is a precise match for the column (if wave scaling is involved).  If you rely on wave scaling you should refrain from using MatrixOP.