Index out of range

Hello,

I am getting the error that "index is out of range" but I can't see what the problem is. My procedure is below. It takes a 2D wave corresponding to xy coordinates and rotates them about the origin. To do this it takes the last coordinate, calculates the angle to move this point to lie at y=0 and X>0, i.e. due east from the origin. Then goes through each row in the wave and rotates each coordinate by this angle.

I added a print statement for debugging. It sails through my wavelist and calculates the angle for all waves. It then throws the index out of range error (the wave in question is the first one in my wavelist). The bizarre thing is that my graph gets updated with maybe half of the waves rotated correctly. I checked numpnts for the wave that throws the error and what the last point is, both are correct.

Any help would be appreciated. If there is a better flow control method than a for-endfor within a for-endfor, it would be great if someone can tell me what it is. Does this explain why the graph gets partially updated?

Thanks
sjr51

Function Rotator(wavenames) //rotates a set of 2D coordinates about the origin
    String wavenames
    Variable theta, xprime, yprime, xcd, ycd
    variable i=0
    Variable j=0 // i will count through the waves, j will be row index
    Variable ABx, CDx, ABy, CDy
    For (i = 0; i < ItemsInList(wavenames); i += 1)
        String name = StringFromList(i,wavenames)
        Wave/z w1= $name
        variable last = NumPnts(w1)/2
            ABx=1 //calculate theta. ABx and ABy are set at 1,0. This will give a 1 unit long line at 90°
            CDx=w1[last][0]
            ABy=0
            CDy=w1[last][1]
            theta=acos(((ABx*CDx)+(ABy*CDy))/(sqrt((ABx^2)+(ABy^2))*sqrt((CDx^2)+(CDy^2)))) //answer in radians
            print name, " is ",theta
            For (j = 0; j < last; j+=1)
                xcd = w1[j][0]
                ycd = w1[j][1]
                xprime = (xcd*(cos(theta)))-(ycd*(sin(theta)))
                yprime = (xcd*(sin(theta)))+(ycd*(cos(theta)))
                w1[j][0] = xprime
                w1[j][1] = yprime
            endfor
    endfor
End
This error occurs if your index number is referencing a point outside the waves range (i.e. point 13 of a 10 point wave). The lines of code where this could happen are statements like 'w1[last][0]' or 'w1[j][0]'. You might want to inspect the values for 'last' and 'j' (e.g., using the debugger) and look if they are within the waves boundaries at all times. For example it would be problematic to fetch the number of points of a wave (e.g. 10) and use them directly in an assignment. Since the point counting starts from zero, this would throw an error (i.e., using 10 where the points go from 0...9). In your code NumPnts(w1)/2 might be problematic. What if the wave has 11 points (=> NumPnts/2 = 5.5 ~ 6)?

Edit: Ok, that was maybe not very helpful since you seem to have checked various things already. There are however some statements in your post which are contradicting. For example, how can the first wave in your list be the problem, when the data is handled correctly until a certain point? Anyway, it might help if you could post a simple example experiment with some data where the error is present.
Thank you for your reply, Chozo.

The waves are 2D sets of coordinates so I *think* that last = Numpnts(w1)2 will be OK, because Numpnts should be 2* row number (I wasn't sure how to do this). I'm sure you are right about last or j being the problem.

I have posted a simplified version of the experiment. When you execute this command on Graph0:

rotator(wavelist("*",";","WIN:"))


It replicates the problem that I described for the full experiment. Error for the first wave in the wavelist, printing all angles and rotating some of them in the graph.

Again - any help would be appreciated!
Steve
RotatorSample.pxp (64.03 KB)
Thanks for the example experiment. I see now what the error is. As suspected, the pitfall of point counting vs. number of points has worked once again (I found myself in this one several times). ;)
By calculating NumPnts(w1)/2 you get the full number of points in the row dimension of your wave. So for so good. But since counting starts from zero, you have the number of points minus one as the last index. Using this directly as assignment will lead to the error.
Just change the following and the error will go away:
...
    variable last = NumPnts(w1)/2
    ABx=1 //calculate theta. ABx and ABy are set at 1,0. This will give a 1 unit long line at 90°
    CDx=w1[last-1][0]
    ABy=0
    CDy=w1[last-1][1]
...
For multi-dimensional waves like yours, use DimSize rather than numpnts:
variable last = DimSize(w1,0) // number of rows


--Jim Prouty
Software Engineer, WaveMetrics, Inc.
And, as suggested earlier- use the debugger! Right-click in any procedure window and select Enable Debugger. Then right-click again and select Debug on Error. That will stop your function and break into the debugger at the point where the error occurred, allowing you to see exactly what caused the error.

The debugger regularly saves my life (or at least my sanity).

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Also, there may certain cases where that type of error is benign. For example, I have just had the need to draw several rows of circles which are colored in adjacent pairs. Some rows had an even number of circles, and some an odd number. Without testing for evenness and altering the for loop for two cases, an "index out of range" error occured for odd rows. The simplest solution I thought of was to revert to the earlier
#pragma rtGlobals=2
which did not generate this error. Attempting to draw a circle at a non-existing point no longer caused a problem.

However, you should be clear whether your particular range error is harmless before using this fix.
Thank you all for the comments. I'll use dimsize in future - and the debugger. The point about it being benign is a good one, the waves were processed correctly (it turns out that there was a bug in the rotation calculation which meant that some waves didn't get rotated correctly, rather than it failing on some). It also explains the mystery of why the procedure ran through to that point. Obviously, running it correctly is the way to go. Thanks for the help with this - I might put the procedure in code snippets, now it runs correctly, it might be useful to somebody.