noise peak pickup in igor

Dear all,

I am dealing with noise data on the strain curve against time from inverted force torsion pendulum. As the attached image, the noise point (raw data)(top image) is subtracted from the strain curve, with the fixed collecting intervals during experiments. For further noise analysis, I need to pick up the noise event positions, which is the top point of each noise peak, as the image of the noise peak point selected (bottom image). Currently, I am picking up points manually. However, there are thousands points in more than 10 sets of experimental data. Therefore, I wonder whether anyone can help me to write a macro to solve this problem?

I need a macro that can pick up the point only when its value is higher than both of the previous point and the next point in the wave. (or the point, which is higher than both of left and right points in the image, is selected)

thanks a lot for everything and any help for this!
The following code will pick up the local peaks. But it is not clear what you want to do with them, so I've just entered some comments. You will either have to provide some more information on what you want to do with those points, or modify the code in order to get something useful.


Function FindLocalPeaks(data)
    wave data    // wave containing the trace to analyze
   
    variable nPoints = DimSize(data, 0)
   
    variable i
    for (i = 1; i < nPoints - 1; i+=1)
        if ((data[i - 1] < data[i]) && (data[i] > data[i+1]))
            // the point at index i is a local peak
            // here you can take appropriate action with it
        endif
    endfor
End
I was thinking along the same lines, but the loop could be condensed into

noiseout[1,23] = (noisetest[p - 1] < noisetest[p] && noisetest[p] > noisetest[p + 1]) ? 1 : 0

where noisetest is the noise wave and noiseout is a wave that has a value of "1" where a local maximum was found and zero otherwise. It is assumed (and an examination of your example seems to confirm) that endpoints are not considered to be candidates for maxima.

Note:

The values of 1 and 23 for "noiseout[1,23]" were based on noisetest being a 25 element wave. The values of 1 and 23 exclude the initial (point 0) and final (point 24) points from consideration as mixima. (Sorry for not fully explaining this assumption in the initial post.)
Dear 741,
thanks a lot for your help. That's almost what I need. Also, my friend have helped me to modify it based on your commends as below to obtain a new wave from those i as below.

Function FindLocalPeaks(data)
    wave data    // wave containing the trace to analyze
    variable nPoints = DimSize(data, 0)
 
    variable i
    make/n=0/o peakname
    for (i = 1; i < nPoints - 1; i+=1)
        if ((data[i - 1] < data[i]) && (data[i] > data[i+1]))
            // the point at index i is a local peak
          insertpoints numpnts(peakname),1, peakname
          peakname[numpnts(peakname)]=data[i]  
          // here you can take appropriate action with it
        endif
    endfor
End
Thanks jtigor for your suggestions. However, I am not sure how to modify those into the macro contents by myself and just tried 741's methods. Then it works. Thank you vey much for your help again!
syc33 wrote:
Also, my friend have helped me to modify it based on your commends as below to obtain a new wave from those i as below


The additional code is understandable in spirit, but it does have some issues. One of the first issues is performance-wise: by making "peakname" with zero points and then enlarging it by one point for each peak found, you are effectively doing a complete copy of the wave each time. If you only have a low number of peaks (hundreds or a couple of thousands), this might still be acceptably fast.

You can avoid this in two ways: running the peak finding loop twice, the first time just counting how many peaks there are, and then making a wave with the correct number of points and just filling it up. But this requires two loop traversals, which induces a performance penalty just by itself.

Another way is to allocate a wave that you know will have too many points, do the analysis, and then remove all the points that were unnecessary.

Also, this line:
peakname[numpnts(peakname)]=data[i]
is an out-of-bounds error (i.e. you are assigning to a wave element that does not exist). You can see this by realizing that array indices in Igor start from zero and run up to [numpnts(peakname) - 1]. By default Igor stays silent on this, but it is still an error.

Keeping all these points in mind, here's an improved version of the code:


Function FindLocalPeaks(data)
    wave data    // wave containing the trace to analyze
    variable nPoints = DimSize(data, 0)
 
    Make /N=(nPoints) /O PeakName = 0   // PeakName is guaranteed to have too many points
                                        // since there can never be as many peaks as there are points in the data
                                   
    variable i, offset = 0
    for (i = 1; i < nPoints - 1; i+=1)
        if ((data[i - 1] < data[i]) && (data[i] > data[i+1]))
            // the point at index i is a local peak
            PeakName[offset] = data[i]
            offset += 1
        endif
    endfor
   
    // remove all the unused points from PeakName
    Redimension /N=(offset) PeakName
End

741 wrote:
   variable i, offset = 0
    for (i = 1; i < nPoints - 1; i+=1)
        if ((data[i - 1] < data[i]) && (data[i] > data[i+1]))
            // the point at index i is a local peak
            PeakName[offset] = data[i]
            offset += 1
        endif
    endfor


Is the x-axis scaling critical to your work? With the above code you are assembling a collection of peak values, but losing any information on the x-axis location of those values. That is, unless I'm missing a subtle point here.