To find a series of Maxima

Hello

I have data for which I would like to determine the width of the pulses from valley to peak, for all pulses in the data. So I need to know X of the minimum and X of the maximum. The pulses are asymmetric, which is why smoothing, differentiating, and finding 0 levels comes with an inaccuracy (please see example).

The valleys are acceptable to me, but the so determined peaks have to much offset. Obviously this is due to the smoothing. And I have tried various smoothing approaches, but non leaves the max where it really is.

Can you think of another approach to determine (mainly) the Xs of the maxima? Maybe an asymmetric peak fit?

Many thanks

 

Remo

 

 

 

example data and min/max from smooth-dif-findlevel0 example.pxp (26.12 KB)

in the mean time I just thought I could do wavestats on a range defined by to valleys. This works well.

Could you smooth the data, differentiate it and look for crossings of zero in positive and negative directions?  Do you have to use the peak and valley positions? You could look for the positions of the maximum positive and negative slopes instead. That might shift less when you smooth the data.

Fourier transforming the data might also be helpful if the pulses are all in registry with each other, meaning there is no phase shift over time.

You could also do some version of highpass and lowpass filtering. Below is an extremely simplified example:

Function TestFunction()

    Wave example
    duplicate/O/R=[0,715] example exampleFFT
    FFT exampleFFT
    Duplicate/C/O exampleFFT exampleInvFFT
    exampleInvFFT[0, x2pnt(exampleInvFFT, 2e7)]=cmplx(0, 0)
    exampleInvFFT[x2pnt(exampleInvFFT, 15e7), *]=cmplx(0, 0)
    IFFT exampleInvFFT
    SetScale/P x, DimOffset(example, 0), DimDelta(example, 0), "",   exampleInvFFT
    Display example, exampleInvFFT
    ModifyGraph rgb(exampleInvFFT)=(29440,0,58880)
   
end

 

Thanks,

currently I am satisfied with the following approach:

 

Function test(w)
    wave w
    Duplicate/O w,w_smth
    Smooth/E=1/S=2 23, w_smth
    Differentiate w_smth/D=w_smth_DIF
    FindLevels /P /D=peaksP  /EDGE=2   w_smth_DIF, 0
    FindLevels /P /D=valleysP  /EDGE=1   w_smth_DIF, 0
    Accurate_test(w,valleysP,peaksP)
End

Function Accurate_test(w,w_valleys,w_peaks)
    wave w,w_valleys    ,w_peaks
    Variable  count
    count=dimsize(w_valleys,0)
   
    make /o/N=(count-1) peaksP_acc
    Variable i
    count=dimsize(w_valleys,0)
   
    for (i=0; i<count; i+=1)
        wavestats/q /R=[w_valleys[i],w_valleys[i+1]] w
        peaksP_acc[i]= V_maxRowLoc     
        endfor
   
   
    make /o/N=(count-1) valleysP_Acc
    Variable j
   
    for (j=0; j<count; j+=1)
        wavestats/q /R=[w_peaks[j],w_peaks[j+1]] w
        valleysP_Acc[j]= V_minRowLoc       
        endfor
   
    duplicate /o peaksP_acc peaksX_acc
    duplicate /o valleysP_acc valleysX_acc
    duplicate /o w wX
    wX=x   
    peaksX_acc=wX[peaksX_acc]
    valleysX_acc=wX[valleysX_acc]
End

 

Presuming the period is constant, you could fit a sin or cosine wave equation to the data.

y = A*sin(2*Pi*w*(x - xo))

This approach will give you an average period w and its uncertainty.

Here is another approach to consider that is based on template matching:

Choose a "typical" pulse and match it against the full wave.  Here is what I did:

duplicate/r=[334,360] example,onePeak
Duplicate/O example,W_Correlation
Correlate onePeak, W_Correlation
Display W_Correlation

The last wave is pretty easy to analyze.

 

AG

Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More