Skip to content

Commit 0854357

Browse files
committed
add tests, fix a few small errors
1 parent 5e81c0e commit 0854357

File tree

6 files changed

+143
-7
lines changed

6 files changed

+143
-7
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ before_install:
1515
script:
1616
- julia -e 'Pkg.init(); run(`ln -s $(pwd()) $(Pkg.dir("KDE"))`); Pkg.pin("KDE"); Pkg.resolve()'
1717
- julia -e 'using KDE; @assert isdefined(:KDE); @assert typeof(KDE) === Module'
18+
- julia ./runtests.jl

runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
tests = [
2+
"univariate",
3+
"bivariate",
4+
]
5+
6+
println("Running tests:")
7+
8+
for t in tests
9+
test_fn = joinpath("test", "$t.jl")
10+
println(" * $test_fn")
11+
include(test_fn)
12+
end

src/bivariate.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,19 @@ function conv(k::BivariateKDE, dist::(UnivariateDistribution,UnivariateDistribut
5858
# Convolve fft with characteristic function of kernel
5959
cx = -twoπ/(step(k.x)*Kx)
6060
cy = -twoπ/(step(k.y)*Ky)
61-
for j = 1:size(ft,2)
62-
for i = 1:size(ft,1)
63-
ft[i,j] *= cf(distx,(i-1)*cx)*cf(disty,min(j-1,Ky-j+1)*cy)
61+
for j = 0:size(ft,2)-1
62+
for i = 0:size(ft,1)-1
63+
ft[i+1,j+1] *= cf(distx,i*cx)*cf(disty,min(j,Ky-j)*cy)
6464
end
6565
end
66+
dens = irfft(ft, Kx)
67+
68+
for i = 1:length(dens)
69+
dens[i] = max(0.0,dens[i])
70+
end
6671

6772
# Invert the Fourier transform to get the KDE
68-
BivariateKDE(k.x, k.y, irfft(ft, Kx))
73+
BivariateKDE(k.x, k.y, dens)
6974
end
7075

7176
typealias BivariateDistribution Union(MultivariateDistribution,(UnivariateDistribution,UnivariateDistribution))

src/univariate.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ kernel_dist{D}(::Type{D},w::Real) = (s = w/std(D(0.0,1.0)); D(0.0,s))
1616
function default_bandwidth(data::Vector{Float64}, alpha::Float64 = 0.9)
1717
# Determine length of data
1818
ndata = length(data)
19+
ndata <= 1 && return alpha
1920

2021
# Calculate width using variance and IQR
2122
var_width = std(data)
@@ -103,12 +104,18 @@ function conv(k::UnivariateKDE, dist::UnivariateDistribution)
103104
# = e^{i*t*a} \sum_{k=0}^K e^{-2pi*i*k*(-t*s*K/2pi)/K} N_k / N
104105
# = A * fft(N_k/N)[-t*s*K/2pi + 1]
105106
c = -twoπ/(step(k.x)*K)
106-
for j = 1:length(ft)
107-
ft[j] *= cf(dist,(j-1)*c)
107+
for j = 0:length(ft)-1
108+
ft[j+1] *= cf(dist,j*c)
109+
end
110+
111+
dens = irfft(ft, K)
112+
# fix rounding error.
113+
for i = 1:K
114+
dens[i] = max(0.0,dens[i])
108115
end
109116

110117
# Invert the Fourier transform to get the KDE
111-
UnivariateKDE(k.x, irfft(ft, K))
118+
UnivariateKDE(k.x, dens)
112119
end
113120

114121
# main kde interface methods

test/bivariate.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Base.Test
2+
using Distributions
3+
using KDE
4+
5+
import KDE: kernel_dist, default_bandwidth, kde_boundary, kde_range, tabulate
6+
7+
for D in [(Normal,Normal),(Uniform,Uniform),(Logistic,Logistic)]
8+
d = kernel_dist(D,(0.5,0.5))
9+
@test isa(d,D)
10+
dx,dy = d
11+
@test mean(dx) == 0.0
12+
@test mean(dy) == 0.0
13+
@test_approx_eq std(dx) 0.5
14+
@test_approx_eq std(dy) 0.5
15+
end
16+
17+
r = kde_range((-2.0,2.0), 128)
18+
@test step(r) > 0
19+
20+
for X in ([0.0], [0.0,0.0], [0.0,0.5], [-0.5:0.1:0.5])
21+
w = default_bandwidth(X)
22+
@test w > 0
23+
lo, hi = kde_boundary(X,w)
24+
@test lo < hi
25+
kr = kde_range((lo,hi), 10)
26+
@test step(kr) > 0
27+
28+
for D in (Normal, )
29+
k1 = tabulate((X,X),(r,r))
30+
@test isa(k1,BivariateKDE)
31+
@test size(k1.density) == (length(k1.x), length(k1.y))
32+
@test all(k1.density .>= 0.0)
33+
@test_approx_eq sum(k1.density)*step(k1.x)*step(k1.y) 1.0
34+
35+
k2 = conv(k1,kernel_dist((D,D),(0.1,0.1)))
36+
@test isa(k2,BivariateKDE)
37+
@test size(k2.density) == (length(k2.x), length(k2.y))
38+
@test all(k2.density .>= 0.0)
39+
@test_approx_eq sum(k2.density)*step(k2.x)*step(k2.y) 1.0
40+
41+
k3 = kde((X,X);kernel=D)
42+
@test isa(k3,BivariateKDE)
43+
@test size(k3.density) == (length(k3.x), length(k3.y))
44+
@test all(k3.density .>= 0.0)
45+
@test_approx_eq sum(k3.density)*step(k3.x)*step(k3.y) 1.0
46+
47+
k4 = kde((X,X),(r,r);kernel=D)
48+
@test isa(k4,BivariateKDE)
49+
@test size(k4.density) == (length(k4.x), length(k4.y))
50+
@test all(k4.density .>= 0.0)
51+
@test_approx_eq sum(k4.density)*step(k4.x)*step(k4.y) 1.0
52+
53+
k5 = kde([X X];kernel=D)
54+
@test isa(k5,BivariateKDE)
55+
@test size(k5.density) == (length(k5.x), length(k5.y))
56+
@test all(k5.density .>= 0.0)
57+
@test_approx_eq sum(k5.density)*step(k5.x)*step(k5.y) 1.0
58+
59+
end
60+
end

test/univariate.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Base.Test
2+
using Distributions
3+
using KDE
4+
5+
import KDE: kernel_dist, default_bandwidth, kde_boundary, kde_range, tabulate
6+
7+
for D in [Normal,Uniform,Logistic]
8+
d = kernel_dist(D,0.5)
9+
@test isa(d,D)
10+
@test mean(d) == 0.0
11+
@test_approx_eq std(d) 0.5
12+
end
13+
14+
r = kde_range((-2.0,2.0), 128)
15+
@test step(r) > 0
16+
17+
for X in ([0.0], [0.0,0.0], [0.0,0.5], [-0.5:0.1:0.5])
18+
w = default_bandwidth(X)
19+
@test w > 0
20+
lo, hi = kde_boundary(X,w)
21+
@test lo < hi
22+
kr = kde_range((lo,hi), 10)
23+
@test step(kr) > 0
24+
25+
for D in (Normal, )
26+
k1 = tabulate(X,r)
27+
@test isa(k1,UnivariateKDE)
28+
@test length(k1.density) == length(k1.x)
29+
@test all(k1.density .>= 0.0)
30+
@test_approx_eq sum(k1.density)*step(k1.x) 1.0
31+
32+
k2 = conv(k1,kernel_dist(D,0.1))
33+
@test isa(k2,UnivariateKDE)
34+
@test length(k2.density) == length(k2.x)
35+
@test all(k2.density .>= 0.0)
36+
@test_approx_eq sum(k2.density)*step(k2.x) 1.0
37+
38+
k3 = kde(X;kernel=D)
39+
@test isa(k3,UnivariateKDE)
40+
@test length(k3.density) == length(k3.x)
41+
@test all(k3.density .>= 0.0)
42+
@test_approx_eq sum(k3.density)*step(k3.x) 1.0
43+
44+
k4 = kde(X,r;kernel=D)
45+
@test isa(k4,UnivariateKDE)
46+
@test length(k4.density) == length(k4.x)
47+
@test all(k4.density .>= 0.0)
48+
@test_approx_eq sum(k4.density)*step(k4.x) 1.0
49+
50+
end
51+
end

0 commit comments

Comments
 (0)