⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 allan.m

📁 这个Matlab程序用于计算时域信号的阿伦Allan方差。
💻 M
字号:
function [retval, s, errorb] = allan(data,tau,name)% Compute the Allan deviation for a set of time-domain frequency data% [RETVAL, S, ERRORB] = ALLAN(DATA,TAU,NAME)% DATA should be a struct and have the following fields:%  DATA.freq    The frequency measurements in Hz%  DATA.rate or DATA.time%               The sampling rate in Hertz (DATA.rate) or a timestamp for%               each measurement in seconds (DATA.time). Computation is%               shorter when the rate is known, but if the rate is%               inaccurate, then the Allan plot will be skewed.%               DATA.rate is used if both fields are present.%               If DATA.rate == 0, then the timestamps are used.% TAU is an array of tau values for computing Allan deviation.% NAME is a label that is added to the plot titles.%% RETVAL is the array of Allan deviation values at each TAU.% S is an optional output of other statistical measures of the data (mean, std, etc).% ERRORB is an optional output containing the error estimates for a 1-sigma%   confidence interval. Error bars are plotted as vertical lines at each point%   (MATLAB-style error bars cannot be used due to a known bug in MATLAB R14SP3).%% Example:%% To compute the Allan deviation for the data in the variable "lt":% >> lt% lt = %     freq: [1x86400 double]%     rate: 0.50%% Use:%% >> ad = allan(lt,[1 10 100],'lt data');%% The Allan deviation will be computed and plotted at tau = 1,10,100 seconds.%  1-sigma confidence intervals will be indicated by vertical lines.%% Notes:%  No pre-processing of the data is performed. %  For rate-based data, AD is computed only for tau values greater than the%   minimum time between samples and less than the half the total time. For%   time-stamped data, only tau values greater than the maximum gap between%   samples and less than half the total time are used.%  The calculation for rate-based data is *much* faster than for time-stamp%   data. You may wish to run the rate-based calculation first, then%   compare with time-stamp-based. Often the differences are insignificant.%  To plot the "tau bins", uncomment the code at the beginning of the%   "plot" section (last section of code, search for "TAUBIN").%  This function has been validated using the test data from NBS Monograph%   140 and the 1000-point test data set given by Riley [1].%   If you have other validation results, please let me know!%% For more information, see:% [1] W. J. Riley, "Addendum to a test suite for the calculation of time domain%  frequency stability," presented at IEEE Frequency Control Symposium,%  1996.% Available on the web:%  http://www.ieee-uffc.org/freqcontrol/paper1ht.html%%% M.A. Hopcroft%      hopcroft at mems stanford edu%%% MH APR2008% v1.61  improve error handling, plotting%        fix bug in regular data calc for high-rate data%        fix bug in timestamp data calc for large starting gap%         (thanks to C. B. Ruiz for identifying these bugs)%        uses timestamps for DATA.rate=0%        progress indicator for large timestamp data processingversionstr = 'allan v1.71';% FCz OCT2008% v1.71 'lookfor' gives now useful comments; script and sample data are%       availabie on www.nbi.dk/~czerwin/files/allan.zip% v1.7  Improve program performance by mainly predefining matrices outside%       of loops (avoiding memory allocation within loops); no changes to manual%% MH JUN2007% v1.54 Improve data plotting and optional bin plotting% MH FEB2007% v1.5  use difference from median for plotting%       added MAD calculation for outlier detection% MH JAN2007% v1.48 plotting typos fixes% MH DEC2006% v1.46 hack to plot error bars% v1.44 further validation (Riley 1000-pt)%       plot mean and std% MH NOV2006% v1.42 typo fix comments% v1.4  fix irregular rate algorithm%       irregular algorithm rejects tau less than max gap in time data%       validate both algorithms using test data from NBS Monograph 140% v1.3  fix time calc if data.time not present%       add error bars (not possible due to bug in MATLAB R14SP3)%       remove offset calculation% v1.24 improve feedback% MH SEP2006% v1.22 updated comments% v1.2  errors and warnings% v1.1  handle irregular interval data% Suggestion for further improvement: The limiting performance factor for the timestamp% case is the slow performance of 'find()'. Here might logical indexing be% an appropriate solution.% Pre-allocation of f, fa and fs does not improve performance% significantly.% defaultsif nargin < 3, name=''; endif nargin < 2, tau=[1 10]; end %one could in principle construct a nice TAU matrix which incorporates knowledge about rate, halftime, etc.fprintf(1,'allan: %s\n\n',versionstr);%% Basic statistical tests on the data sets.numpoints=length(data.freq);s.max=max(data.freq);s.min=min(data.freq);s.mean=mean(data.freq);s.median=median(data.freq);if isfield(data,'time')    s.linear=polyfit(data.time,data.freq,1);elseif isfield(data,'rate')    s.linear=polyfit(1/data.rate:1/data.rate:length(data.freq)/data.rate,data.freq,1);else    error('Either "time" or "rate" must be present in DATA. See "help allan" for details. [err1]');ends.std=std(data.freq);if nargout < 2, disp(s); enddfreq=data.freq;% scale to median for plottingmfreq=dfreq-s.median;%pre-defining sm and sme here to prevent pre-allocation within loopsm=zeros(1, length(tau)); sme=zeros(1, length(tau));% Screen for outliers using 5x Median Absolute deviation (MAD) criteriaMAD = median(abs(dfreq-s.median)/0.6745);%%%%% Two cases - regular or irregular data%% Regular - Is there a regular interval between measurements?if isfield(data,'rate') && data.rate > 0 % if there is a regular interval    fprintf(1, 'allan: regular data (rate = %g Hz)\n',data.rate);        tmstep = 1/data.rate;        if isfield(data,'time')        % adjust time to remove any starting gap        dtime=data.time-data.time(1)+mean(diff(data.time));                if (data.rate - 1/mean(diff(dtime))) > 1e-6            fprintf(1,'allan: WARNING: data.rate (%f Hz) does not match recorded data rate (%f Hz)\n',data.rate,1/mean(diff(dtime)));        end        fprintf(1,'allan: Length of time record: %f sec\n',dtime(end)-dtime(1));        % find halfway point        halftime = fix((dtime(end)-dtime(1))/2);    else        halftime = fix(tmstep*length(data.freq)/2);    end    fprintf(1, 'allan: max. tau value: %g sec. (time/2)\n',halftime);    % time axis data    dtime=tmstep:tmstep:length(dfreq)*tmstep;            % truncate tau to appropriate values    tau = tau(find(tau >= tmstep & tau <= halftime));    % size(tau)    fac = round(tau/tmstep);        fprintf(1,'allan: calculating Allan deviation...\n');        % calculate the Allan deviation for each value of tau    k=0; tic;    for i = tau        k=k+1;        %% Instead of defining a matrix which allocated lateron, it is        %% pre-allocated here and used at #2#        %f=[];        f= zeros( fac(k), floor(length(data.freq)/fac(k)) );                % truncate frequency set to an even multiple of this tau value        freq=dfreq(1:end-rem(length(dfreq),fac(k)));        length(freq);        % group the measurements into columns by tau         for j=1:fac(k)            f(j,:)=freq(j:fac(k):end);  % #2#        end        % save the binning points for plotting        fs(k,1:length(freq)/fac(k))=fac(k):fac(k):length(freq); fval{k}=mean(f,1);        % average in each "tau group"        fa=mean(f,1);        % first finite difference        fd=diff(fa);        % calculate Allan deviation for this tau        m=length(fa);        sm(k)=sqrt(0.5/(m-1)*(sum(fd.^2)));        % estimate error bars        sme(k)=sm(k)/sqrt(m);                fprintf(1,'%d ',i);            end    fprintf(1,'\n'); toc    % plot the frequency results    %figure    %plot(dtime,mfreq,'.b');    % string for plot title    name=[name ' (' num2str(data.rate) ' Hz)'];            %% Irregular data, no fixed interval    elseif isfield(data,'time')    % the interval between measurements is irregular    %  so we must group the data by time        %the two following matrices don't have to be generated, +2 because of    %beginning and end bin    time=zeros(1, 2*(length(data.time)+2)); freq=zeros(1, 2*(length(data.freq)+2));        % adjust time to remove any starting gap or zero    dtime=data.time-data.time(1)+mean(diff(data.time));        fprintf(1, 'allan: irregular data (no rate).\n');    fprintf(1,'allan: Length of time record: %f sec\n',dtime(end)-dtime(1));    fprintf(1, '       Average rate: %g Hz (%g sec/measurement); Max. gap: %g sec at position %d\n',...        1/mean(diff(dtime)),mean(diff(dtime)),max(diff(dtime)),find(diff(dtime)==max(diff(dtime))));        % truncate tau to appropriate values    % find halfway point    halftime = fix((dtime(end)-dtime(1))/2);    tau = tau(find(tau >= max(diff(dtime)) & tau <= halftime));    if isempty(tau)        error('allan: ERROR: no appropriate tau values (> %g s, < %g s)\n',max(diff(dtime)),fix(dtime(end)/2));    end                fprintf(1,'allan: calculating Allan deviation...');    k=0; tic;    for i = tau        fprintf(1,'\n%d ',i);                k=k+1; fa=[];         f=[];        jk=0; km=0;                % truncate data set to an even multiple of this tau value        freq=dfreq(find(dtime <= dtime(end)-rem(dtime(end),i)));        time=dtime(find(dtime <= dtime(end)-rem(dtime(end),i)));                % break up the data into groups of tau length        while i*km < time(end)            km=km+1;                                    % progress bar            if rem(km,100)==0, fprintf(1,'.'); end            if rem(km,1000)==0, fprintf(1,'%g/%g\n',km,round(time(end)/i)); end            f = freq(find(i*(km-1) < time & time <= i*km));            if ~isnan(any(f)) && any(f) ~= 0                fa(km)=mean(f);            else                fa(km)=0;            end                        % save the binning points for plotting            if find(time <= i*km) > 0                fs(k,km)=max(time(find(time <= i*km)));            else                fs(k,km)=0;            end            fval{k}=fa;                    end        % first finite difference of the averaged results        fd=diff(fa);        % calculate Allan deviation for this tau        m=length(fa);        sm(k)=sqrt(0.5/(m-1)*(sum(fd.^2)));                % estimate error bars        sme(k)=sm(k)/sqrt(m);            end    fprintf(1,'\n'); toc        % string for plot title    name=[name ' (timestamp)'];%     % plot the frequency results%     if ~isempty(time) && ~isempty(freq)%         figure%         plot(dtime,mfreq,'.b');%         name=['(time) ' name];%     else%         fprintf(1,'allan: ERROR: no appropriate tau values (> %g s)\n',max(diff(data.time)));%     endelse    error('allan: WARNING: no DATA.rate or DATA.time! Type "help allan" for more information. [err2]');end%%%%%%%%%% plotting% plot the frequency data, centered on medianfigureplot(dtime,mfreq,'.b');hold on;    %% Optional plot    TAUBIN    % plot the time divisions%     [rfs,cfs]=size(fs);%     colororder=get(gca,'ColorOrder');%     axis tight; ap=axis; kc=2;%     for j=1:rfs%         kc=kc+1; if rem(kc,length(colororder))==1, kc=2; end%         plot the tau division boundaries%         for b=1:max(find(fs(j,:)));%             plot([fs(j,b) fs(j,b)],[ap(3)*1.1 ap(4)*1.1],'-','Color',colororder(kc,:));%             if b == 1%                 plot([dtime(1) fs(j,b)],[fval{j}(b)-s.median fval{j}(b)-s.median],'-','Color',colororder(kc,:),'LineWidth',4);%             else%                 plot([fs(j,b-1) fs(j,b)],[fval{j}(b)-s.median fval{j}(b)-s.median],'-','Color',colororder(kc,:),'LineWidth',4);%             end%         end%     end%     axis auto    %% End optional plot    fx = xlim;% plot([fx(1) fx(2)],[s.median s.median],'-k');plot([fx(1) fx(2)],[0 0],':k');% plot([fx(1) fx(2)],[s.mean+s.std s.mean+s.std],'-r');% plot([fx(1) fx(2)],[s.mean-s.std s.mean-s.std],'-r');% plot([fx(1) fx(2)],[3*MAD 3*MAD],'--r');% plot([fx(1) fx(2)],[-3*MAD -3*MAD],'--r');plot([fx(1) fx(2)],[5*MAD 5*MAD],'-r');plot([fx(1) fx(2)],[-5*MAD -5*MAD],'-r');title(['Data: ' name],'FontSize',16,'FontName','Arial');%set(get(gca,'Title'),'Interpreter','none');xlabel('time (sec)','FontSize',14,'FontName','Arial');ylabel('Data - Median [frequency]','FontSize',14,'FontName','Arial');set(gca,'FontSize',14,'FontName','Arial');if ne(isempty(sm), 1)    figure    plotlinewidth=2;            % plot with loglog scale    loglog(tau, sm, '.-b', 'LineWidth', plotlinewidth, 'MarkerSize', 24);    errorbar(tau,sm,sme,'.-b', 'Markersize', 18); set(gca,'XScale','log'); set(gca,'YScale','log');    % plot with y log scale    % semilogy(tau, sm, '.-b', 'LineWidth', plotlinewidth, 'MarkerSize', 24);    % errorbar(tau,sm,sme,'.-b', 'Markersize', 18); set(gca,'YScale','log');    % plot with x log scale    % semilogx(tau,sm,'.-b','LineWidth',plotlinewidth,'MarkerSize',24);    % errorbar(tau,sm,sme,'.-b', 'Markersize', 18); set(gca,'XScale','log');        % There's still a bug that screws up the error bars on a loglog and semilog plots.    % When this is fixed, set(...) becomes unnecessary         grid on;    title(['Allan Deviation: ' name],'FontSize',16,'FontName','Arial');    %set(get(gca,'Title'),'Interpreter','none');    xlabel('\tau (sec)','FontSize',14,'FontName','Arial');    ylabel('\sigma_y(\tau) (Hz)','FontSize',14,'FontName','Arial');    set(gca,'FontSize',14,'FontName','Arial');    % expand the x axis a little bit so that the errors bars look nice    adax = axis;    axis([adax(1)*0.9 adax(2)*1.1 adax(3) adax(4)]);else    fprintf(1,'allan: WARNING: no values calculated. Check that TAU > 1/DATA.rate\n');    fprintf(1,'Type "help allan" for more information.\n\n');end        retval = sm;errorb = sme;return

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -