circ_kuipertest.m 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. function [pval, k, K] = circ_kuipertest(alpha1, alpha2, res, vis_on)
  2. % [pval, k, K] = circ_kuipertest(sample1, sample2, res, vis_on)
  3. %
  4. % The Kuiper two-sample test tests whether the two samples differ
  5. % significantly.The difference can be in any property, such as mean
  6. % location and dispersion. It is a circular analogue of the
  7. % Kolmogorov-Smirnov test.
  8. %
  9. % H0: The two distributions are identical.
  10. % HA: The two distributions are different.
  11. %
  12. % Input:
  13. % alpha1 fist sample (in radians)
  14. % alpha2 second sample (in radians)
  15. % res resolution at which the cdf is evaluated
  16. % vis_on display graph
  17. %
  18. % Output:
  19. % pval p-value; the smallest of .10, .05, .02, .01, .005, .002,
  20. % .001, for which the test statistic is still higher
  21. % than the respective critical value. this is due to
  22. % the use of tabulated values. if p>.1, pval is set to 1.
  23. % k test statistic
  24. % K critical value
  25. %
  26. % References:
  27. % Batschelet, 1980, p. 112
  28. %
  29. % Circular Statistics Toolbox for Matlab
  30. % By Marc J. Velasco and Philipp Berens, 2009
  31. % velasco@ccs.fau.edu
  32. if nargin < 3
  33. res = 100;
  34. end
  35. if nargin < 4
  36. vis_on = 0;
  37. end
  38. n = length(alpha1(:));
  39. m = length(alpha2(:));
  40. % create cdfs of both samples
  41. [phis1 cdf1 phiplot1 cdfplot1] = circ_samplecdf(alpha1, res);
  42. [phis2 cdf2 phiplot2 cdfplot2] = circ_samplecdf(alpha2, res);
  43. % maximal difference between sample cdfs
  44. [dplus, gdpi] = max([0 cdf1-cdf2]);
  45. [dminus, gdmi] = max([0 cdf2-cdf1]);
  46. % calculate k-statistic
  47. k = n * m * (dplus + dminus);
  48. % find p-value
  49. [pval K] = kuiperlookup(min(n,m),k/sqrt(n*m*(n+m)));
  50. K = K * sqrt(n*m*(n+m));
  51. % visualize
  52. if vis_on
  53. figure
  54. plot(phiplot1, cdfplot1, 'b', phiplot2, cdfplot2, 'r');
  55. hold on
  56. plot([phis1(gdpi-1), phis1(gdpi-1)], [cdf1(gdpi-1) cdf2(gdpi-1)], 'o:g');
  57. plot([phis1(gdmi-1), phis1(gdmi-1)], [cdf1(gdmi-1) cdf2(gdmi-1)], 'o:g');
  58. hold off
  59. set(gca, 'XLim', [0, 2*pi]);
  60. set(gca, 'YLim', [0, 1.1]);
  61. xlabel('Circular Location')
  62. ylabel('Sample CDF')
  63. title('CircStat: Kuiper test')
  64. h = legend('Sample 1', 'Sample 2', 'Location', 'Southeast');
  65. set(h,'box','off')
  66. set(gca, 'XTick', pi*0:.25:2)
  67. set(gca, 'XTickLabel', {'0', '', '', '', 'pi', '', '', '', '2pi'})
  68. end
  69. end
  70. function [p K] = kuiperlookup(n, k)
  71. load kuipertable.mat;
  72. alpha = [.10, .05, .02, .01, .005, .002, .001];
  73. nn = ktable(:,1); %#ok<NODEF>
  74. % find correct row of the table
  75. [easy row] = ismember(n, nn);
  76. if ~easy
  77. % find closest value if no entry is present)
  78. row = length(nn) - sum(n<nn);
  79. if row == 0
  80. error('N too small.');
  81. else
  82. warning('N=%d not found in table, using closest N=%d present.',n,nn(row)) %#ok<WNTAG>
  83. end
  84. end
  85. % find minimal p-value and test-statistic
  86. idx = find(ktable(row,2:end)<k,1,'last');
  87. if ~isempty(idx)
  88. p = alpha(idx);
  89. else
  90. p = 1;
  91. end
  92. K = ktable(row,idx+1);
  93. end