From 7a41ea5afa6c227589322ec44265c2e6feb87d9b Mon Sep 17 00:00:00 2001 From: Jago Date: Tue, 14 Sep 2021 22:52:38 +0100 Subject: [PATCH 1/4] Added varfinite, variance equivilant to meanfinite I can't seem to find anything that has similar functionality to meanfinite but for standard deviations and so have written up what I've been using here. --- src/ImageBase.jl | 3 ++- src/statistics.jl | 14 ++++++++++++++ test/statistics.jl | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ImageBase.jl b/src/ImageBase.jl index d466214..c8884e1 100644 --- a/src/ImageBase.jl +++ b/src/ImageBase.jl @@ -14,7 +14,8 @@ export minfinite, maxfinite, maxabsfinite, - meanfinite + meanfinite, + varfinite using Reexport diff --git a/src/statistics.jl b/src/statistics.jl index 83289f0..284ff83 100644 --- a/src/statistics.jl +++ b/src/statistics.jl @@ -64,3 +64,17 @@ else return s./n end end + +""" + varfinite(A; kwargs...) + +Compute the variance of `A`, ignoring any non-finite values. + +The supported `kwargs` are those of `sum(f, A; kwargs...)`. +""" +function varfinite(A; kwargs...) + m = meanfinite(A; kwargs...) + n = sum(Map12(isfinite, x->true, x->false), A; kwargs...) # TODO: replace with `Returns` + s = sum(Map12(isfinite, identity, zero), (A .- m).^2; kwargs...) + return s ./ (n .- 1) +end \ No newline at end of file diff --git a/test/statistics.jl b/test/statistics.jl index 2c051b8..52a1592 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -11,13 +11,18 @@ using Test @test eltype(s12) <: RGB A = [NaN, 1, 2, 3] @test meanfinite(A, 1) ≈ [2] + @test varfinite(A, dims=1) ≈ [1] A = [NaN 1 2 3; NaN 6 5 4] mf = meanfinite(A, 1) + vf = varfinite(A, dims=1) @test isnan(mf[1]) @test mf[1,2:end] ≈ [3.5,3.5,3.5] + @test vf[1,:] ≈ [0,12.5,4.5,0.5] @test meanfinite(A, 2) ≈ reshape([2, 5], 2, 1) + @test varfinite(A, dims=2) ≈ reshape([1, 1], 2, 1) @test meanfinite(A, (1,2)) ≈ [3.5] + @test varfinite(A, dims=(1,2)) ≈ [3.5] @test minfinite(A) == 1 @test maxfinite(A) == 6 @test maxabsfinite(A) == 6 From 4dc499dd1365cbfe92456a2e015ad9c6d6f6614a Mon Sep 17 00:00:00 2001 From: Jago Date: Tue, 14 Sep 2021 23:03:49 +0100 Subject: [PATCH 2/4] Updated meanfinite tests for depreciated behaviour Changed instances of `meanfinite(A, region)` to `meanfinite(A, dims=region)` to stop the depreciation warnings during tests. --- test/statistics.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/statistics.jl b/test/statistics.jl index 52a1592..e683ee8 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -9,20 +9,25 @@ using Test img = colorview(RGB, PermutedDimsArray(A, (3,1,2))) s12 = sum(img, dims=(1,2)) @test eltype(s12) <: RGB + A = [NaN, 1, 2, 3] - @test meanfinite(A, 1) ≈ [2] + @test meanfinite(A, dims=1) ≈ [2] @test varfinite(A, dims=1) ≈ [1] + A = [NaN 1 2 3; NaN 6 5 4] - mf = meanfinite(A, 1) + mf = meanfinite(A, dims=1) vf = varfinite(A, dims=1) @test isnan(mf[1]) @test mf[1,2:end] ≈ [3.5,3.5,3.5] @test vf[1,:] ≈ [0,12.5,4.5,0.5] - @test meanfinite(A, 2) ≈ reshape([2, 5], 2, 1) + + @test meanfinite(A, dims=2) ≈ reshape([2, 5], 2, 1) @test varfinite(A, dims=2) ≈ reshape([1, 1], 2, 1) - @test meanfinite(A, (1,2)) ≈ [3.5] + + @test meanfinite(A, dims=(1,2)) ≈ [3.5] @test varfinite(A, dims=(1,2)) ≈ [3.5] + @test minfinite(A) == 1 @test maxfinite(A) == 6 @test maxabsfinite(A) == 6 @@ -34,7 +39,7 @@ using Test @test maxfinite(A) == maximum(A) A = rand(Float32,3,5,5) img = colorview(RGB, A) - dc = meanfinite(img, 1)-reshape(reinterpretc(RGB{Float32}, mean(A, dims=2)), (1,5)) + dc = meanfinite(img, dims=1)-reshape(reinterpretc(RGB{Float32}, mean(A, dims=2)), (1,5)) @test maximum(map(_abs, dc)) < 1e-6 dc = minfinite(img)-RGB{Float32}(minimum(A, dims=(2,3))...) @test _abs(dc) < 1e-6 From e3ea376cf015d6dde6e9a388e3c7292683e412ea Mon Sep 17 00:00:00 2001 From: Jago Date: Tue, 14 Sep 2021 23:34:50 +0100 Subject: [PATCH 3/4] Changed varfinite to support Julia true, x->false), A; kwargs...) # TODO: replace with `Returns` - s = sum(Map12(isfinite, identity, zero), (A .- m).^2; kwargs...) - return s ./ (n .- 1) -end \ No newline at end of file +function varfinite end + +if Base.VERSION >= v"1.1" + function varfinite(A; kwargs...) + m = meanfinite(A; kwargs...) + n = sum(Map12(isfinite, x->true, x->false), A; kwargs...) # TODO: replace with `Returns` + s = sum(Map12(isfinite, identity, zero), (A .- m).^2; kwargs...) + return s ./ (n .- 1) + end +else + function varfinite(A; kwargs...) + m = meanfinite(A; kwargs...) + n = sum(Map12(isfinite, x->true, x->false).(A); kwargs...) + s = sum(Map12(isfinite, identity, zero).((A .- m).^2); kwargs...) + return s ./ (n .- 1) + end +end + \ No newline at end of file From 2cdb62d6e1fb1313a51cf52893c07734c0322a04 Mon Sep 17 00:00:00 2001 From: Jago Date: Wed, 15 Sep 2021 11:43:06 +0100 Subject: [PATCH 4/4] Changed all behaviour when there are no finite values and updated tests Test now checks for only one valid value (->\sigma=NaN). --- src/statistics.jl | 4 ++-- test/statistics.jl | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/statistics.jl b/src/statistics.jl index d52d8fb..9c2a730 100644 --- a/src/statistics.jl +++ b/src/statistics.jl @@ -79,14 +79,14 @@ if Base.VERSION >= v"1.1" m = meanfinite(A; kwargs...) n = sum(Map12(isfinite, x->true, x->false), A; kwargs...) # TODO: replace with `Returns` s = sum(Map12(isfinite, identity, zero), (A .- m).^2; kwargs...) - return s ./ (n .- 1) + return s ./ max.(0, (n .- 1)) end else function varfinite(A; kwargs...) m = meanfinite(A; kwargs...) n = sum(Map12(isfinite, x->true, x->false).(A); kwargs...) s = sum(Map12(isfinite, identity, zero).((A .- m).^2); kwargs...) - return s ./ (n .- 1) + return s ./ max.(0, (n .- 1)) end end \ No newline at end of file diff --git a/test/statistics.jl b/test/statistics.jl index e683ee8..abdbc56 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -14,13 +14,19 @@ using Test @test meanfinite(A, dims=1) ≈ [2] @test varfinite(A, dims=1) ≈ [1] + A = [NaN NaN 1; + 1 2 3] + vf = varfinite(A, dims=2) + @test isnan(vf[1]) + A = [NaN 1 2 3; NaN 6 5 4] mf = meanfinite(A, dims=1) vf = varfinite(A, dims=1) @test isnan(mf[1]) - @test mf[1,2:end] ≈ [3.5,3.5,3.5] - @test vf[1,:] ≈ [0,12.5,4.5,0.5] + @test mf[2:end] ≈ [3.5,3.5,3.5] + @test isnan(vf[1]) + @test vf[2:end] ≈ [12.5,4.5,0.5] @test meanfinite(A, dims=2) ≈ reshape([2, 5], 2, 1) @test varfinite(A, dims=2) ≈ reshape([1, 1], 2, 1)