Looping over this loop
rhjpires
Maybe you guys can help me to troubleshoot this. I have written a For loop to creates a window that runs over a waveform to generate an FFT, and from that FFT obtain information over the first peak which in my data usually appears between 0.2 and 1 Hz. I want to track frequency changes overtime by monitoring the peak position and eventually dispersion as well by checking the width of the FFT peak. I also use an IF statement to run all values down to 0 in case no peak above a given threshold is not observed.
To avoid detecting other adjoining peaks that may be more intense, I have implemented the search method in the FFTs as a two step process: first using
FindLevels
followed by FindPeak
.My problem is the following: every time I run this code my first value is always 0, all the remaining values seem to be OK, but the very first one is always zero.
If you can detect something wrong in the code below, your input would be greatly appreciated.
Many thanks in advance,
R.
//walk over a time-series using a window of defined size to:
// (1) make an FFT
// (2) collect peak data from the FFT over the specified frequency range
//Window advances by sliding a fraction of the window size
For (i=0; i<Numbsteps; i+=1)
wleft = StepSize_P*i //Left side pf the window starts ate 0 and is a function of the window step size
Wright = WinSize_P+wleft-1 //Right side of the window is a function of the left side and of the windows size
WinTime=pnt2x(TempWave, wright-WinSize_P/2) //window time is a middle value
Temp_Time1[i]=WinTime
Print "window borders: ", wleft, wright, "and the average is", WinTime
//Do the FFTs and correct for the sampling number
FFT /OUT=3 /WINF=Hanning /RP=[wleft,wright] /DEST=TempFFT TempWave;
TempFFT/=WinSize_P
//Use FindLevels to detect the occurance shoulder of a peak
wave W_FindLevels
FindLevels /R=(StartSearch, EndSearch) /N=1 /EDGE=1 TempFFT, PeakThreshold
//if no levels are crossed
if (V_Flag!=0)
Temp_Amp[i] = 0
Temp_Pos[i] = 0
Temp_Width[i] = 0
Else
//should levels be crossed then do FindPeak
Variable StartHz = W_FindLevels[0]-0.2
Variable EndHz = W_FindLevels[0]+0.2
Variable V_PeakLoc
Variable V_PeakWidth
Variable V_PeakVal
FindPeak /R=(StartHz, EndHz) /M=(PeakThreshold) TempFFT
Temp_Pos[i] = V_PeakLoc
Temp_Width [i] = V_PeakWidth
Temp_Amp[i] = V_PeakVal
EndIf
//Give FFT a name and store in own folder
FinalFFTName="FFT_"+MaskName+"_"+num2str(i)
print FinalFFTName
Duplicate TempFFT $FinalFFTName
Movewave $FinalFFTName, root:Dynamic_FFT:$(MaskName):FFTs:
EndFor
// (1) make an FFT
// (2) collect peak data from the FFT over the specified frequency range
//Window advances by sliding a fraction of the window size
For (i=0; i<Numbsteps; i+=1)
wleft = StepSize_P*i //Left side pf the window starts ate 0 and is a function of the window step size
Wright = WinSize_P+wleft-1 //Right side of the window is a function of the left side and of the windows size
WinTime=pnt2x(TempWave, wright-WinSize_P/2) //window time is a middle value
Temp_Time1[i]=WinTime
Print "window borders: ", wleft, wright, "and the average is", WinTime
//Do the FFTs and correct for the sampling number
FFT /OUT=3 /WINF=Hanning /RP=[wleft,wright] /DEST=TempFFT TempWave;
TempFFT/=WinSize_P
//Use FindLevels to detect the occurance shoulder of a peak
wave W_FindLevels
FindLevels /R=(StartSearch, EndSearch) /N=1 /EDGE=1 TempFFT, PeakThreshold
//if no levels are crossed
if (V_Flag!=0)
Temp_Amp[i] = 0
Temp_Pos[i] = 0
Temp_Width[i] = 0
Else
//should levels be crossed then do FindPeak
Variable StartHz = W_FindLevels[0]-0.2
Variable EndHz = W_FindLevels[0]+0.2
Variable V_PeakLoc
Variable V_PeakWidth
Variable V_PeakVal
FindPeak /R=(StartHz, EndHz) /M=(PeakThreshold) TempFFT
Temp_Pos[i] = V_PeakLoc
Temp_Width [i] = V_PeakWidth
Temp_Amp[i] = V_PeakVal
EndIf
//Give FFT a name and store in own folder
FinalFFTName="FFT_"+MaskName+"_"+num2str(i)
print FinalFFTName
Duplicate TempFFT $FinalFFTName
Movewave $FinalFFTName, root:Dynamic_FFT:$(MaskName):FFTs:
EndFor
I'd recommend to use the built-in debugger (right click on the code: Enable Debugger and set a break point (left click on the grey are left of the code, a red circle shows up, click again to undo) within
Temp_Amp[i] = 0
Temp_Pos[i] = 0
Temp_Width[i] = 0
Else...
If it stops here and i is zero, just no peaks are found for the first frame.
Alternatively, use 42 instead of 0 in this part of code and see if 'the answer' (42) shows up in the results.
HJ
April 10, 2017 at 05:06 am - Permalink
It appears that W_FindLevels only appears to populate on the second turn of the cycle, when i =1 and above, for i = 0 the value of W_FindLevels is . This means that when i=0, StartHz and EndHz variables return NaN.
Any ideas of what could be going wrong here?
Many thanks.
R.
April 10, 2017 at 06:01 am - Permalink
if (V_Flag!=0) //<----- Shouln't this be == 2
From the description of v_flag in Findlevels
HJ
April 10, 2017 at 07:07 am - Permalink
A.G.
April 10, 2017 at 08:40 am - Permalink
However, that did not resolve the problem. In fact, removing the IF statement all together, had no change in the process.
What appears to matter is where in the code W_FindLevels is declared.
Originally W_FindLevels was declared right before the FindLevels operation.
Declaring it outside the For loop, results in an empty wave throughout the several For loop cycles, not just when i=0
The problem was resolved by declaring the wave W_FindLevels after the Find_Levels operation.
This is interesting because I did not
MAKE
a wave that cannot be overwritten, I simply declared it.And so, is it then the general rule that every time one needs to call a wave generated by an igor function - say, as part of an expression - one should declare it after its creation, not before?
Many thanks,
R.
April 10, 2017 at 09:26 am - Permalink
April 10, 2017 at 09:27 am - Permalink
It is best to think of a WAVE w=something statement as a runtime assignment, not only a compile-time declaration.
So where the statement occurs matters, just like other assignments.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
April 10, 2017 at 11:12 am - Permalink
Yes- DisplayHelpTopic "Accessing Global Variables And Waves"
At runtime, a WAVE statement triggers the actual look-up of the wave, so it must happen only after the wave actually exists.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
April 10, 2017 at 11:15 am - Permalink
Cheers,
R.
April 10, 2017 at 11:01 pm - Permalink