diff --git a/README.md b/README.md index ccea9ff..d9f868f 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ SpectralIndices.jl is a Julia package for working with spectral indices commonly ## Features - Compute a wide range of spectral indices. -- Support for various data types, including but not limited to +- Support for various data types, including but not limited to (see this [issue](https://github.com/awesome-spectral-indices/SpectralIndices.jl/issues/8) for an updated list and WIP) - [x] Arrays - [x] DataFrames - [x] YAXArrays diff --git a/test/compute_index.jl b/test/compute_index.jl index 6396a65..1e2367e 100644 --- a/test/compute_index.jl +++ b/test/compute_index.jl @@ -1,3 +1,4 @@ +using Test using SpectralIndices using DataFrames using YAXArrays @@ -5,73 +6,79 @@ using YAXArrays expected_ndvi_value_f64 = 0.5721271393643031 expected_savi_value_f64 = 0.5326251896813354 -# Basics -@test compute_index("NDVI"; N=0.643, R=0.175) == expected_ndvi_value_f64 -# Type handling -@test compute_index("NDVI"; N=fill(0.643, 5), R=fill(0.175, 5)) isa Array -# Corner cases -#@test compute_index("NDVI"; N=0.0, R=0.0) == NaN -#Input validation -@test_throws AssertionError compute_index("InvalidIndex"; N=0.5, R=0.5) -# Multiple indices -results = compute_index(["NDVI", "SAVI"]; N=0.643, R=0.175, L=0.5) -@test length(results) == 2 -@test results[1] == expected_ndvi_value_f64 -@test results[2] == expected_savi_value_f64 +@testset "Basic Functionality" begin + @test compute_index("NDVI"; N=0.643, R=0.175) == expected_ndvi_value_f64 +end -# test dataframes -# single index as params -df_single = DataFrame(; N=[0.643, 0.56], R=[0.175, 0.22]) -result_single = compute_index("NDVI", df_single) -@test size(result_single, 1) == 2 -@test size(result_single, 2) == 1 -@test names(result_single) == ["NDVI"] +@testset "Type Handling" begin + @test compute_index("NDVI"; N=fill(0.643, 5), R=fill(0.175, 5)) isa Array +end + +# @testset "Corner Cases" begin +# @test compute_index("NDVI"; N=0.0, R=0.0) == NaN +# end + +@testset "Input Validation" begin + @test_throws AssertionError compute_index("InvalidIndex"; N=0.5, R=0.5) +end + +@testset "Multiple Indices" begin + results = compute_index(["NDVI", "SAVI"]; N=0.643, R=0.175, L=0.5) + @test length(results) == 2 + @test results[1] == expected_ndvi_value_f64 + @test results[2] == expected_savi_value_f64 +end -# single index as kwargs dfn_single = DataFrame(; N=[0.643, 0.56]) dfr_single = DataFrame(; R=[0.175, 0.22]) dfl_single = DataFrame(; L=[0.5, 0.4]) -result_single2 = compute_index("NDVI"; N=dfn_single, R=dfr_single) -@test size(result_single2, 1) == 2 -@test size(result_single2, 2) == 1 -@test names(result_single2) == ["NDVI"] -@test result_single2 == result_single -# multiple indices as params -df_multiple = DataFrame(; N=[0.643, 0.56], R=[0.175, 0.22], L=[0.5, 0.4]) -result_multiple = compute_index(["NDVI", "SAVI"], df_multiple) -@test size(result_multiple, 1) == 2 -@test size(result_multiple, 2) == 2 -@test names(result_multiple) == ["NDVI", "SAVI"] +@testset "DataFrame Tests" begin + @testset "Single Index as Params" begin + df_single = DataFrame(; N=[0.643, 0.56], R=[0.175, 0.22]) + result_single = compute_index("NDVI", df_single) + @test size(result_single, 1) == 2 + @test size(result_single, 2) == 1 + @test names(result_single) == ["NDVI"] + end -# multiple indices as kwargs -result_multiple2 = compute_index(["NDVI", "SAVI"]; N=dfn_single, R=dfr_single, L=dfl_single) -@test size(result_multiple2, 1) == 2 -@test size(result_multiple2, 2) == 2 -@test names(result_multiple2) == ["NDVI", "SAVI"] -@test result_multiple2 == result_multiple + @testset "Single Index as kwargs" begin + result_single2 = compute_index("NDVI"; N=dfn_single, R=dfr_single) + @test size(result_single2, 1) == 2 + @test size(result_single2, 2) == 1 + @test names(result_single2) == ["NDVI"] + end -# test Yaxarrays -axes = (Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)) -N_data = fill(0.643, (5, 5, 10)) -R_data = fill(0.175, (5, 5, 10)) -L_data = fill(0.5, (5, 5, 10)) + @testset "Multiple Indices as Params" begin + df_multiple = DataFrame(; N=[0.643, 0.56], R=[0.175, 0.22], L=[0.5, 0.4]) + result_multiple = compute_index(["NDVI", "SAVI"], df_multiple) + @test size(result_multiple, 1) == 2 + @test size(result_multiple, 2) == 2 + @test names(result_multiple) == ["NDVI", "SAVI"] + end -nds = YAXArray((Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)), N_data) -rds = YAXArray((Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)), R_data) -lds = YAXArray((Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)), L_data) + @testset "Multiple Indices as kwargs" begin + result_multiple2 = compute_index( + ["NDVI", "SAVI"]; N=dfn_single, R=dfr_single, L=dfl_single + ) + @test size(result_multiple2, 1) == 2 + @test size(result_multiple2, 2) == 2 + @test names(result_multiple2) == ["NDVI", "SAVI"] + end +end -nr_ds = concatenatecubes([nds, rds], Dim{:Variables}(["N", "R"])) -nrl_ds = concatenatecubes([nds, rds, lds], Dim{:Variables}(["N", "R", "L"])) +@testset "YAXArray Tests" begin + # Setup YAXArrays + axes = (Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)) + nds = YAXArray(axes, fill(0.643, (5, 5, 10))) + rds = YAXArray(axes, fill(0.175, (5, 5, 10))) -# single index -# as params -result_yaxa_single = compute_index("NDVI", nr_ds) -@test size(result_yaxa_single) == size(rds) == size(nds) -# as kwargs -result_yaxa_single2 = compute_index("NDVI"; N=nds, R=rds) -@test size(result_yaxa_single2) == size(rds) == size(nds) -@test result_yaxa_single == result_yaxa_single2 + @testset "Single Index Tests" begin + nr_ds = concatenatecubes([nds, rds], Dim{:Variables}(["N", "R"])) + result_yaxa_single = compute_index("NDVI", nr_ds) + @test size(result_yaxa_single) == size(rds) == size(nds) + end +end # multiple indices # TODO # as params diff --git a/test/compute_kernel.jl b/test/compute_kernel.jl index 70925c3..55a5cb7 100644 --- a/test/compute_kernel.jl +++ b/test/compute_kernel.jl @@ -2,31 +2,84 @@ using SpectralIndices using DataFrames using YAXArrays +# define data structures +# Number +a, b, c, p, sigma = 2, 3, 1, 2, 5 + +# Array +a_v, b_v, c_v, p_v, sigma_v = [1, 2, 3], [4, 5, 6], [1, 1, 1], [2, 2, 2], [5, 5, 5] + +# Dataframe +df = DataFrame(; a=[1, 2], b=[3, 4], c=[1, 1], p=[2, 2], sigma=[5, 5]) + +# YAXArray +axes = (Dim{:Lon}(1:5), Dim{:Lat}(1:5), Dim{:Time}(1:10)) +a_yaxa = fill(0.643, (5, 5, 10)) +b_yaxa = fill(0.175, (5, 5, 10)) +c_yaxa = fill(0.5, (5, 5, 10)) +p_yaxa = fill(0.5, (5, 5, 10)) +sigma_yaxa = fill(0.5, (5, 5, 10)) + +ads = YAXArray(axes, a_yaxa) +bds = YAXArray(axes, b_yaxa) +cds = YAXArray(axes, c_yaxa) +pds = YAXArray(axes, p_yaxa) +sigmads = YAXArray(axes, sigma_yaxa) + +yaxa = concatenatecubes( + [ads, bds, cds, pds, sigmads], Dim{:Variables}(["a", "b", "c", "p", "sigma"]) +) + +# testing @testset "Tests for linear function" begin # Test with numbers - @test linear(2, 3) == 6 + @test linear(a, b) == 6 # Test with arrays - @test all(linear([1, 2, 3], [4, 5, 6]) .== [4, 10, 18]) + @test all(linear(a_v, b_v) .== [4, 10, 18]) + + # test with dataframes + @test eachcol(linear(df)) == eachcol(DataFrame(; linear=[3, 8])) + + # test with yaxarrays + @test all(linear(yaxa) .== YAXArray(axes, fill(0.112525, 5, 5, 10))) end @testset "Tests for poly function" begin # Test with numbers - @test poly(2, 3, 1, 2) == 49 + @test poly(a, b, c, p) == 49 # Test with arrays - a, b, c, p = [1, 2, 3], [4, 5, 6], [1, 1, 1], [2, 2, 2] expected_result = [(1 * 4 + 1)^2, (2 * 5 + 1)^2, (3 * 6 + 1)^2] - @test all(poly(a, b, c, p) .== expected_result) + @test all(poly(a_v, b_v, c_v, p_v) .== expected_result) + + # test with dataframes + df_expected = DataFrame(; poly=[(1 * 3 + 1)^2, (2 * 4 + 1)^2]) + @test eachcol(poly(df)) == eachcol(df_expected) + + # Test with yaxarrays + yaxa_expected = fill((0.643 * 0.175 + 0.5)^0.5, (5, 5, 10)) + @test all(poly(yaxa) .== YAXArray(axes, yaxa_expected)) end @testset "Tests for RBF function" begin # Test with numbers - @test RBF(1, 2, 5) ≈ 0.9801986733067553 + expected_number_result = exp((-1.0 * (a - b)^2.0) / (2.0 * sigma^2.0)) + @test RBF(a, b, sigma) ≈ expected_number_result # Test with arrays - #a, b, sigma = [1, 2, 3], [4, 5, 6], [0.5, 0.5, 0.5] ## TODO extend function to hadle different types - a, b, sigma = [1, 2, 3], [4, 5, 6], [5, 5, 5] - expected_result = exp.((-1.0 .* ((a .- b) .^ 2.0)) ./ (2.0 .* (sigma .^ 2.0))) - @test all(RBF(a, b, sigma) .≈ expected_result) + expected_array_result = + exp.((-1.0 .* ((a_v .- b_v) .^ 2.0)) ./ (2.0 .* (sigma_v .^ 2.0))) + @test all(RBF(a_v, b_v, sigma_v) .≈ expected_array_result) + + # Test with dataframes + df_expected = DataFrame(; + RBF=exp.((-1.0 .* ((df.a .- df.b) .^ 2.0)) ./ (2.0 .* (df.sigma .^ 2.0))) + ) + @test eachcol(RBF(df)) == eachcol(df_expected) + + # Test with yaxarrays + yaxa_expected = + exp.((-1.0 .* ((a_yaxa .- b_yaxa) .^ 2.0)) ./ (2.0 .* (sigma_yaxa .^ 2.0))) + @test all(RBF(yaxa) .== YAXArray(axes, yaxa_expected)) end diff --git a/test/runtests.jl b/test/runtests.jl index 8e9255e..11347ef 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,15 +1,15 @@ using SafeTestsets using Test -@testset "Axioms" begin - @safetestset "Axioms" begin - include("axioms.jl") - end - @safetestset "Compute" begin - include("compute_index.jl") - include("compute_kernel.jl") - end - @safetestset "Utils" begin - include("utils.jl") - end +@safetestset "Axioms" begin + include("axioms.jl") +end + +@safetestset "Compute" begin + include("compute_index.jl") + include("compute_kernel.jl") +end + +@safetestset "Utils" begin + include("utils.jl") end