Index out of range for customized indices

 

 

Hello,

I am trying to write a function that chooses the index of the most often occurring value in a wave. In context, I'm trying to find the most common voltage in a voltage trace in a wave's time window from 3 to 3.5 seconds. Thing is, I chose to change the indices using SetScale/I, to go from -.070 to -.010, incrementing by .00025. I've added some comments in all caps so help clarify how it works. When I run it, the debugger gives an error saying "Index out of range for wave "yVarCandidates."

Here is the code:

 

 

Function/D findMode(w)
    wave w
       
        variable ic
    variable yvar
   
    variable minVolt = -0.070//mV
    variable maxVolt = -0.010//mV
    variable increment = .00025//mV
    variable mostCommonY = minVolt //WILL BE USED AS THE STARTING POINT FOR FINDING THE MAX, SEEN IN THIRD FOR LOOP
   
    Make/D/O/N = ((maxVolt - minVolt) / increment) yvarCandidates
    //sets the range of indices for above wave
    SetScale/I y, minVolt, maxVolt, "mV", yVarCandidates//THIS IS THE PART THAT MAY BE GIVING ME PROBLEMS
   
        //IF A GIVEN INDEX IS CROSSED BY VOLTAGE TRACE, A "TALLY" IS ADDED TO IT.
    for(yvar = minVolt; yvar < maxVolt; yvar += increment)//goes from -70mv to -10 mv just to be safe
        for(ic = x2pnt(w, 3); ic < x2pnt(w, 3.5); ic += 1) //3 and 3.5 is the X value and not the pnt (index, rather),
                                            // it is not always a round integer; its in seconds
            if((w[ic - 1] < yvar && w[ic] > yvar) || (w[ic - 1] > yvar && w[ic] < yvar))//if it crosses the thing
                yvarCandidates[yvar] += 1
            endif
        endfor
    endfor

    //GO THROUGH THE WAVE AND FIND THE MAX, RETURN ITS INDEX, WHICH ACTUALLY CORRESPONDS TO THE MODE VOLTAGE .
    variable i
    for(i = minVolt; i < maxVolt; i += increment)//goes from -70mv to -10 mv just to be safe
        if(yVarCandidates[i] > yVarCandidates[mostCommonY])//if it crosses the thing
            mostCommonY = i//equals idnex, which sould also be the index
        endif
    endfor//DEBUGGER POINTS HERE, BUT OF COURSE IT IS REALLY ERRORING OUT INSIDE LOOP
   

    KillWaves /Z yvarCandidates//save memory
    //RETURN A DOUBLE REPRESENTING THE MOST COMMON VOLTAGE
        return mostCommonY
end

 


I'm new to Igor so I'd appreciate any input you can offer about my question, and if anything else bothers you, it would be very helpful if you pointed that out too.

Thanks!

DJackson

 

Quote:

for(i = minVolt; i < maxVolt; i += increment)//goes from -70mv to -10 mv just to be safe
    if(yVarCandidates[i] > yVarCandidates[mostCommonY])//if it crosses the thing



When you use square brackets to index a wave, the index must be in terms of point number.

If you want to index the wave in terms of X value, you need to use parentheses, not square brackets.

For details, execute:
DisplayHelpTopic "Waveform Arithmetic and Assignment"

and read through the next subtopic, "Indexing and Subranges".

Also, anytime you have code that marches through waves point-by-point, you should look for another way to do it. I'm not sure what you are attempting but something like WaveStats or FindAPeak might allow you to eliminate the loop.

Finally, when using X indices, you need to be aware of roundoff, because floating point numbers often do not exactly represent a value. For that reason, if you do have to write a loop, it is usually better to do it in terms of point number.


Thanks, hrodstein.

I tried replacing the brackets with parentheses but the same error occurred. I'm going to make the way I go through this wave more efficient, less redundant thanks to your ideas. Unfortunately, there does not seem to be a function in Igor that automatically finds the mode. If you know of a way let me know. Also, wouldn't many if not all of these preprogrammed methods just march through waves too?
Wavestats returns the location of the min and max over the range you give it. See the /R flag, and pay attention to the fact that /R=[] uses point numbers (array indexes) and /R=() uses scaling values (volts in your case, I think).

--Jim Prouty
Software Engineer, WaveMetrics, Inc.
Quote:
Unfortunately, there does not seem to be a function in Igor that automatically finds the mode.


I misunderstood what you are attempting to do because your original post started with:

Quote:
I am trying to write a function that chooses the index of the highest value in a wave.


which is not finding the mode.

Quote:
If you know of a way let me know.


I think doing a histogram, using the Histogram operation, followed by finding the X location of the maximum value of the histogram, using WaveStats, might do it.

Quote:
Also, wouldn't many if not all of these preprogrammed methods just march through waves too?


If by preprogrammed you mean built-in, yes, they would march through waves. But marching through waves in C code, which is what Igor does internally, is much faster than doing it in Igor code.
Yep, that was my fault- I was misleading. I changed it. Thanks for everyone's help.