Allan Variance by Mike Johnson
jcor
and I started making minor usability changes to it. I created this project so that others can benefit and collaborate on this code.
Usage: save as an .ipf, load into Igor, plot the data you will analyze, continue through the AllanVariance menu.
#pragma rtGlobals=1 // Use modern global access method.
//Allan variance function for 1-D wave
//9/13/12 maj
//2017-09-08 jcc, a few usability tweaks
// originally posted at http://www.igorexchange.com/node/2757
// original file http://www.igorexchange.com/files/AllanVariance.ipf
// original author, Mike Johnson http://www.igorexchange.com/user/3700
//*********************************************** //
// from Wikipedia "Allan variance"-- //
// "Allan variance is defined as one half of the time average of the //
// squares of the differences between successive readings of the //
// signal deviation sampled over the sampling period. The Allan //
// variance depends on the time period used between samples: //
// therefore it is a function of the sample period, commonly //
// denoted as tau, likewise the distribution being measured, and is //
// displayed as a graph rather than a single number. " //
//*********************************************** //
Menu "Allan variance"
"Plot Allan Variance of a wave plotted on the top graph",AllanVariance()
"Add lines for white noise", AllanWhite()
End
// creates two new waves containing allan variance and averaging window
Function AllanVariance([wName,nMax,p0,p1])
String wName // wave to use
Variable nMax // maximum npnts to average for Allan variance
variable p0,p1 // optionally use only wName[p0,p1] for the calculation[jcc]
// variable getDev // optionally return the deviation instead of variance (sqrt(var)) [future feature]
If (ParamIsDefault(nMax) || ParamIsDefault(wName))
nMax = 50
Prompt wName, "Plot Allan variance of",popup, WaveList("*", ";","WIN:")
Prompt nMax, "Maximum number of variances:"
DoPrompt "Allan variance",wName, nMax
if(V_flag) //user canceled
Abort "User canceled Allan variance."
endif
endif
WAVE w = $wName
Variable wd
wd = WaveDims(w)
If(wd !=1)
Abort "Allan variance is available for 1-D waves only."
endif
if (!ParamIsDefault(p0) || !ParamIsDefault(p1))
make /free/d/n=(p1-p0+1) wtrimmed
wtrimmed= w[p+p0]
wave w= wtrimmed
endif
String aaxis,avar,alertStr
aaxis = wName + "_avx" // x-axis for output wave
avar = wName + "_avar" // output wave
If((Exists(aaxis) == 1) %| (Exists(avar)==1))
alertStr = "Wave(s) for Allan variance of \'"+wName
alertStr += "\' already exist, overwrite them?"
DoAlert 1, alertStr
If(V_flag == 2)
Abort "User aborted AllanVariance."
endif
endif
Variable npt,dX,n2,n3,n4
npt = numpnts(w)
dX = deltax(w)
n2 = 2*floor(sqrt(npt)) // later limit n2 to nMax points
Make/O/N=(n2) $aaxis
WAVE aaxisW = $aaxis
aaxisW = (p+1)*dX
aaxisW[(n2/2+1),(n2-1)] = dX*round(npt/(n2-p+1))
If(n2 > nMax) // replace middle point by exp spaced pts
n3 = floor(nMax/3)
n4 = n2-2*n3
DeletePoints n3,n4,aaxisW
InsertPoints n3,n3,aaxisW
Variable j=0
Variable h = (aaxisW[(2*n3)]/aaxisW[(n3-1)])^(1/(n3+1))
Variable hh = h
Do
aaxisW[j+n3] = aaxisW[(n3-1)]*hh
hh *=h
j += 1
While(j <= n3)
endif
Make/O/N=(numpnts(aaxisW)) $avar
WAVE avarW = $avar
avarW = FAllanVar(w, aaxisW[p])
Display/K=1 avarW vs aaxisW
AllanVarianceStyle()
// get also white noise
AllanWhite(wName=aaxis)
// // convert to deviation? [future feature]
// if (getDev)
// avarW= sqrt(avarW)
// Label/Z left "Allan deviation" // AllanVarianceStyle() had labelled it before
// endif
return 0
End
// this function actually performs the Allan variance analysis
Function FAllanVar(inWave, xInt)
WAVE inWave
Variable xInt // x interval for averaging
Variable npt = numpnts(inWave)
Variable dX = deltax(inWave) // x-spacing for inWave
Variable numInt, ptsInt
numInt = ceil(npt*dX/xInt) // number of intervals
ptsInt = ceil(npt/numInt) // number of pts per interval
Make/FREE/N=(numInt) tempAllan
tempAllan = 0
Variable i = 0,p1,p2
Do
p1 = pnt2x(inWave,i*ptsInt)
p2 = pnt2x(inWave,(i+1)*ptsInt-1)
tempAllan[i] = mean(inWave,p1,p2)
i += 1
While(i < numInt)
tempAllan = tempAllan[p+1] - tempAllan[p]
DeletePoints (numInt-1),1,tempAllan
tempAllan = tempAllan*tempAllan/2
If(numInt >2)
WaveStats/Q tempAllan
return V_avg
else
return tempAllan[0]
endif
end
// Draw lines for white noise
Function AllanWhite([wName])
String wName // wave to use
if (ParamisDefault(wname))
Prompt wName, "Add white noise lines for",popup, WaveList("*", ";","WIN:")
DoPrompt "Add white noise lines", wName
endif
if(V_flag) //user canceled
Abort "User canceled white noise lines."
endif
String line1,line2,line3, aaxis,avar,alertStr,wn
Variable uchar= 0,start = 0, dX
Do // find last "_" in wave name
start = uchar+1
uchar = strsearch(wName, "_",start)
While(uchar != -1)
If(start==1)
alertStr = "Cannot find Allan variance wave(s). "
Abort alertStr
endif
If(cmpstr(wName[(start),(start+1)],"av") !=0)
alertStr = "Cannot find Allan variance wave(s). "
Abort alertStr
endif
wn = wName[0,(start-2)]
WAVE w = $wn
If(WaveExists(w) != 1)
alertStr = "Cannot find \'"+wn+"\'"
Abort alertStr
endif
dX = deltax(w)
line1 = wn+"_l1"
line2 = wn+"_l2"
line3 = wn+"_l3"
aaxis = wn+"_avx"
avar = wn+"_avar"
If((Exists(line1) == 1) %| (Exists(line2)==1) %| (Exists(line3)==1))
alertStr = "White noise wave(s) for \'"+wName
alertStr += "\' already exist, overwrite them?"
DoAlert 1, alertStr
If(V_flag == 2)
Abort "User aborted AllanWhite"
endif
endif
If((Exists(aaxis) != 1) %| Exists(avar) != 1)
alertStr = "Cannot find \'"+aaxis+"\' (or \'"+avar+"\')"
Abort alertStr
endif
Make/O/N=(numpnts($aaxis)) $line1,$line2,$line3
WAVE lineW1 = $line1
WAVE lineW2 = $line2
WAVE lineW3 = $line3
WAVE aaxisW = $aaxis
WAVE avarW = $avar
lineW2 = avarW[0]/aaxisW[p]*dX
Variable npt = numpnts($wn)
lineW1 = avarW[0]* dX*sqrt(2/npt/aaxisW[p]) + lineW2[p]
lineW3 = -avarW[0]* dX*sqrt(2/npt/aaxisW[p]) + lineW2[p]
// GetAxis/Q left //gets left axis limits
AppendToGraph lineW1,lineW2,lineW3 vs aaxisW
ModifyGraph lstyle($line1)=7,lstyle($line2)=1,lstyle($line3)=7
ModifyGraph lsize($line1)=1,lsize($line2)=1,lsize($line3)=1
// SetAxis left,V_min,V_max
return 0
End
Function AllanVarianceStyle()
ModifyGraph/Z grid=2
ModifyGraph/Z log=1
ModifyGraph/Z mirror=1
Label/Z left "Allan variance"
Label/Z bottom "Averaging time"
End
//Allan variance function for 1-D wave
//9/13/12 maj
//2017-09-08 jcc, a few usability tweaks
// originally posted at http://www.igorexchange.com/node/2757
// original file http://www.igorexchange.com/files/AllanVariance.ipf
// original author, Mike Johnson http://www.igorexchange.com/user/3700
//*********************************************** //
// from Wikipedia "Allan variance"-- //
// "Allan variance is defined as one half of the time average of the //
// squares of the differences between successive readings of the //
// signal deviation sampled over the sampling period. The Allan //
// variance depends on the time period used between samples: //
// therefore it is a function of the sample period, commonly //
// denoted as tau, likewise the distribution being measured, and is //
// displayed as a graph rather than a single number. " //
//*********************************************** //
Menu "Allan variance"
"Plot Allan Variance of a wave plotted on the top graph",AllanVariance()
"Add lines for white noise", AllanWhite()
End
// creates two new waves containing allan variance and averaging window
Function AllanVariance([wName,nMax,p0,p1])
String wName // wave to use
Variable nMax // maximum npnts to average for Allan variance
variable p0,p1 // optionally use only wName[p0,p1] for the calculation[jcc]
// variable getDev // optionally return the deviation instead of variance (sqrt(var)) [future feature]
If (ParamIsDefault(nMax) || ParamIsDefault(wName))
nMax = 50
Prompt wName, "Plot Allan variance of",popup, WaveList("*", ";","WIN:")
Prompt nMax, "Maximum number of variances:"
DoPrompt "Allan variance",wName, nMax
if(V_flag) //user canceled
Abort "User canceled Allan variance."
endif
endif
WAVE w = $wName
Variable wd
wd = WaveDims(w)
If(wd !=1)
Abort "Allan variance is available for 1-D waves only."
endif
if (!ParamIsDefault(p0) || !ParamIsDefault(p1))
make /free/d/n=(p1-p0+1) wtrimmed
wtrimmed= w[p+p0]
wave w= wtrimmed
endif
String aaxis,avar,alertStr
aaxis = wName + "_avx" // x-axis for output wave
avar = wName + "_avar" // output wave
If((Exists(aaxis) == 1) %| (Exists(avar)==1))
alertStr = "Wave(s) for Allan variance of \'"+wName
alertStr += "\' already exist, overwrite them?"
DoAlert 1, alertStr
If(V_flag == 2)
Abort "User aborted AllanVariance."
endif
endif
Variable npt,dX,n2,n3,n4
npt = numpnts(w)
dX = deltax(w)
n2 = 2*floor(sqrt(npt)) // later limit n2 to nMax points
Make/O/N=(n2) $aaxis
WAVE aaxisW = $aaxis
aaxisW = (p+1)*dX
aaxisW[(n2/2+1),(n2-1)] = dX*round(npt/(n2-p+1))
If(n2 > nMax) // replace middle point by exp spaced pts
n3 = floor(nMax/3)
n4 = n2-2*n3
DeletePoints n3,n4,aaxisW
InsertPoints n3,n3,aaxisW
Variable j=0
Variable h = (aaxisW[(2*n3)]/aaxisW[(n3-1)])^(1/(n3+1))
Variable hh = h
Do
aaxisW[j+n3] = aaxisW[(n3-1)]*hh
hh *=h
j += 1
While(j <= n3)
endif
Make/O/N=(numpnts(aaxisW)) $avar
WAVE avarW = $avar
avarW = FAllanVar(w, aaxisW[p])
Display/K=1 avarW vs aaxisW
AllanVarianceStyle()
// get also white noise
AllanWhite(wName=aaxis)
// // convert to deviation? [future feature]
// if (getDev)
// avarW= sqrt(avarW)
// Label/Z left "Allan deviation" // AllanVarianceStyle() had labelled it before
// endif
return 0
End
// this function actually performs the Allan variance analysis
Function FAllanVar(inWave, xInt)
WAVE inWave
Variable xInt // x interval for averaging
Variable npt = numpnts(inWave)
Variable dX = deltax(inWave) // x-spacing for inWave
Variable numInt, ptsInt
numInt = ceil(npt*dX/xInt) // number of intervals
ptsInt = ceil(npt/numInt) // number of pts per interval
Make/FREE/N=(numInt) tempAllan
tempAllan = 0
Variable i = 0,p1,p2
Do
p1 = pnt2x(inWave,i*ptsInt)
p2 = pnt2x(inWave,(i+1)*ptsInt-1)
tempAllan[i] = mean(inWave,p1,p2)
i += 1
While(i < numInt)
tempAllan = tempAllan[p+1] - tempAllan[p]
DeletePoints (numInt-1),1,tempAllan
tempAllan = tempAllan*tempAllan/2
If(numInt >2)
WaveStats/Q tempAllan
return V_avg
else
return tempAllan[0]
endif
end
// Draw lines for white noise
Function AllanWhite([wName])
String wName // wave to use
if (ParamisDefault(wname))
Prompt wName, "Add white noise lines for",popup, WaveList("*", ";","WIN:")
DoPrompt "Add white noise lines", wName
endif
if(V_flag) //user canceled
Abort "User canceled white noise lines."
endif
String line1,line2,line3, aaxis,avar,alertStr,wn
Variable uchar= 0,start = 0, dX
Do // find last "_" in wave name
start = uchar+1
uchar = strsearch(wName, "_",start)
While(uchar != -1)
If(start==1)
alertStr = "Cannot find Allan variance wave(s). "
Abort alertStr
endif
If(cmpstr(wName[(start),(start+1)],"av") !=0)
alertStr = "Cannot find Allan variance wave(s). "
Abort alertStr
endif
wn = wName[0,(start-2)]
WAVE w = $wn
If(WaveExists(w) != 1)
alertStr = "Cannot find \'"+wn+"\'"
Abort alertStr
endif
dX = deltax(w)
line1 = wn+"_l1"
line2 = wn+"_l2"
line3 = wn+"_l3"
aaxis = wn+"_avx"
avar = wn+"_avar"
If((Exists(line1) == 1) %| (Exists(line2)==1) %| (Exists(line3)==1))
alertStr = "White noise wave(s) for \'"+wName
alertStr += "\' already exist, overwrite them?"
DoAlert 1, alertStr
If(V_flag == 2)
Abort "User aborted AllanWhite"
endif
endif
If((Exists(aaxis) != 1) %| Exists(avar) != 1)
alertStr = "Cannot find \'"+aaxis+"\' (or \'"+avar+"\')"
Abort alertStr
endif
Make/O/N=(numpnts($aaxis)) $line1,$line2,$line3
WAVE lineW1 = $line1
WAVE lineW2 = $line2
WAVE lineW3 = $line3
WAVE aaxisW = $aaxis
WAVE avarW = $avar
lineW2 = avarW[0]/aaxisW[p]*dX
Variable npt = numpnts($wn)
lineW1 = avarW[0]* dX*sqrt(2/npt/aaxisW[p]) + lineW2[p]
lineW3 = -avarW[0]* dX*sqrt(2/npt/aaxisW[p]) + lineW2[p]
// GetAxis/Q left //gets left axis limits
AppendToGraph lineW1,lineW2,lineW3 vs aaxisW
ModifyGraph lstyle($line1)=7,lstyle($line2)=1,lstyle($line3)=7
ModifyGraph lsize($line1)=1,lsize($line2)=1,lsize($line3)=1
// SetAxis left,V_min,V_max
return 0
End
Function AllanVarianceStyle()
ModifyGraph/Z grid=2
ModifyGraph/Z log=1
ModifyGraph/Z mirror=1
Label/Z left "Allan variance"
Label/Z bottom "Averaging time"
End
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More