diff --git a/.github/workflows/CompatHelper.yaml b/.github/workflows/CompatHelper.yaml index 5bd2e49..c0854d5 100644 --- a/.github/workflows/CompatHelper.yaml +++ b/.github/workflows/CompatHelper.yaml @@ -19,7 +19,7 @@ jobs: os: - ubuntu-latest steps: - - uses: julia-actions/setup-julia@latest + - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.julia-version }} arch: ${{ matrix.arch }} @@ -28,7 +28,7 @@ jobs: import Pkg name = "CompatHelper" uuid = "aa819f21-2bde-4658-8897-bab36330d9b7" - version = "2" + version = "3" Pkg.add(; name, uuid, version) shell: julia --color=yes {0} - name: "Run CompatHelper" diff --git a/.github/workflows/doc-cleanup.yaml b/.github/workflows/doc-cleanup.yaml new file mode 100644 index 0000000..5945be8 --- /dev/null +++ b/.github/workflows/doc-cleanup.yaml @@ -0,0 +1,26 @@ +name: Doc Preview Cleanup + +on: + pull_request: + types: [closed] + +jobs: + doc-preview-cleanup: + runs-on: ubuntu-latest + steps: + - name: Checkout gh-pages branch + uses: actions/checkout@v2 + with: + ref: gh-pages + - name: Delete preview and history + push changes + run: | + if [ -d "previews/PR$PRNUM" ]; then + git config user.name "richardreeve" + git config user.email "git@richardreeve.net" + git rm -rf "previews/PR$PRNUM" + git commit -m "delete preview" + git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree}) + git push --force origin gh-pages-new:gh-pages + fi + env: + PRNUM: ${{ github.event.number }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 42fe1a8..9a3cafa 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -6,10 +6,13 @@ on: - dev tags: - 'v*' + pull_request: workflow_dispatch: jobs: build: + permissions: + contents: write runs-on: ubuntu-latest steps: - name: Checkout code @@ -24,7 +27,7 @@ jobs: import Pkg Pkg.develop(Pkg.PackageSpec(path=pwd())) Pkg.instantiate() - Pkg.add("Phylo") + Pkg.add("Diversity") Pkg.add("Documenter") shell: julia --project=docs/ --color=yes {0} - name: Build and deploy diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 43c6d15..af6ee40 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -22,6 +22,6 @@ jobs: version: nightly arch: x64 - name: Build package - uses: julia-actions/julia-buildpkg@latest + uses: julia-actions/julia-buildpkg@v1 - name: Run tests - uses: julia-actions/julia-runtest@latest + uses: julia-actions/julia-runtest@v1 diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index d6e7433..3f8a5a5 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -15,7 +15,7 @@ jobs: strategy: matrix: julia-version: - - '1.4' + - '1.6' - '1' os: - ubuntu-latest @@ -38,25 +38,27 @@ jobs: arch: ${{ matrix.arch }} - name: Install R if: matrix.os == 'macOS-latest' - uses: r-lib/actions/setup-r@master + uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.R-version }} - - name: Install R packages + - name: Install ape and rdiversity if: matrix.os == 'macOS-latest' run: | install.packages("ape", repos="http://cran.r-project.org") install.packages("rdiversity", repos="http://cran.r-project.org") shell: R --vanilla --file={0} - name: Build package - uses: julia-actions/julia-buildpkg@master + uses: julia-actions/julia-buildpkg@v1 - name: Running - uses: julia-actions/julia-runtest@master + uses: julia-actions/julia-runtest@v1 - name: Process coverage uses: julia-actions/julia-processcoverage@v1 - name: Coveralls - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./lcov.info + file: ./lcov.info - name: Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 + with: + files: lcov.info diff --git a/.gitignore b/.gitignore index 717fcea..8b1c033 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.cov +/Manifest.toml +.vscode diff --git a/README.md b/README.md index 385d200..c751578 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ The package is registered in the `General` registry on v1.x and so can be instal ## Project Status -The package is confirmed to work against the current LTS Julia v1.4 release +The package is confirmed to work against the current LTS Julia v1.6 release and the latest release on Linux, macOS, and Windows. It is also tested against nightly. diff --git a/docs/src/ecology.md b/docs/src/ecology.md index 113676d..312d0e8 100644 --- a/docs/src/ecology.md +++ b/docs/src/ecology.md @@ -1,6 +1,6 @@ # Diversity.Ecology -n the **Diversity.Ecology** submodule, we replicate old ecological +In the **Diversity.Ecology** submodule, we replicate old ecological diversity measures and generalised versions of them that relate to our general measures of alpha, beta and gamma diversity at subcommunity and ecosystem measures. The generalisations of the richness, Shannon @@ -18,7 +18,7 @@ julia> using Diversity.Ecology, LinearAlgebra julia> community = [10, 20, 20]; -julia> community /= sum(community); +julia> community /= sum(community); #Convert counts to proportions julia> diversity = simpson(community) 1×7 DataFrame @@ -55,6 +55,41 @@ julia> generalisedjaccard(ecosystem, [0, 1, 2], Matrix(1.0I, 3, 3)) │ 1 │ Arbitrary Z │ Jaccard │ 0 │ types │ │ metacommunity │ │ 0.333333 │ │ 2 │ Arbitrary Z │ Jaccard │ 1 │ types │ │ metacommunity │ │ 0.414214 │ │ 3 │ Arbitrary Z │ Jaccard │ 2 │ types │ │ metacommunity │ │ 0.5 │ + +julia> community = [0.7, 0.2, 0.1] + +julia> pielou(community) +1×7 DataFrame + Row │ div_type measure type_level type_name partition_level partition_name diversity + │ String String String String String String Float64 +─────┼────────────────────────────────────────────────────────────────────────────────────── + 1 │ Unique Pielou types subcommunity 1 0.729847 + +julia> communitymat = [10 20 30 20 0; #5 sites/subcommunities (columns) and 6 species (rows) + 10 0 50 80 10; + 60 10 90 0 0; + 10 10 10 10 10; + 70 70 70 70 70; + 10 0 0 90 0] + +julia> generalisedpielou(subcommunityDiversity, communitymat) +5×7 DataFrame + Row │ div_type measure type_level type_name partition_level partition_name diversity + │ String String String String String String Float64 +─────┼───────────────────────────────────────────────────────────────────────────────────────── + 1 │ Arbitrary Z Pielou types subcommunity 1 0.781115 + 2 │ Arbitrary Z Pielou types subcommunity 2 0.745557 + 3 │ Arbitrary Z Pielou types subcommunity 3 0.888073 + 4 │ Arbitrary Z Pielou types subcommunity 4 0.864562 + 5 │ Arbitrary Z Pielou types subcommunity 5 0.622366 + +julia> generalisedpielou(metacommunityDiversity, communitymat) +1×7 DataFrame + Row │ div_type measure type_level type_name partition_level partition_name diversity + │ String String String String String String Float64 +─────┼───────────────────────────────────────────────────────────────────────────────────────── + 1 │ Arbitrary Z Pielou types metacommunity 0.510146 + ``` ```@contents diff --git a/src/Diversity.jl b/src/Diversity.jl index 90202a7..2c10bba 100644 --- a/src/Diversity.jl +++ b/src/Diversity.jl @@ -157,7 +157,7 @@ export generalisedrichness, richness export generalisedshannon, shannon export generalisedsimpson, simpson export generalisedjaccard, jaccard - +export generalisedpielou, pielou end # sub-module Ecology """ diff --git a/src/DiversityMeasure.jl b/src/DiversityMeasure.jl index 9f36c08..78a3c04 100644 --- a/src/DiversityMeasure.jl +++ b/src/DiversityMeasure.jl @@ -193,10 +193,9 @@ function inddiv end df = reduce(append!, dfs) cols = addedoutputcols(_getmeta(measure)) if length(cols) > 0 - len = length(df) data = getaddedoutput(_getmeta(measure)) for col in keys(cols) - insert!(df, length(df) + 1, data[col], col) + insertcols!(df, ncol(df) + 1, col => data[col]) end end return df @@ -249,10 +248,9 @@ function subdiv end df = reduce(append!, dfs) cols = addedoutputcols(_getmeta(measure)) if length(cols) > 0 - len = length(df) data = getaddedoutput(_getmeta(measure)) for col in keys(cols) - insert!(df, length(df) + 1, data[col], col) + insertcols!(df, ncol(df) + 1, col => data[col]) end end return df @@ -307,10 +305,9 @@ function metadiv end diversity=raw) cols = addedoutputcols(_getmeta(measure)) if length(cols) > 0 - len = length(df) data = getaddedoutput(_getmeta(measure)) for col in keys(cols) - insert!(df, length(df) + 1, data[col], col) + insertcols!(df, ncol(df) + 1, col => data[col]) end end return df diff --git a/src/Ecology.jl b/src/Ecology.jl index 5edfa7c..7a90f3f 100644 --- a/src/Ecology.jl +++ b/src/Ecology.jl @@ -184,11 +184,11 @@ end Calculates Simpson's index (1 / diversity at q = 2) of a series of columns representing independent subcommunity counts. -# Arguments: +#### Arguments: - `proportions`: population proportions -# Returns: +#### Returns: - concentrations of subcommunities """ @@ -212,7 +212,7 @@ for the species. This gives a measure of the distinctness of the subcommunities, though we believe that beta and normalised beta have better properties. -# Arguments: +#### Arguments: - `proportions`: population proportions @@ -221,7 +221,7 @@ better properties. - `Z`: similarity matrix or - `sim`: instance of AbstractTypes -# Returns: +#### Returns: - Jaccard-related distinctivess measures """ @@ -256,11 +256,11 @@ Calculates Jaccard index (Jaccard similarity coefficient) of two columns representing independent subcommunity counts, which is normmetaalpha(proportions, 0) / metagamma(proportions, 0) - 1 -# Arguments: +#### Arguments: - `proportions`: population proportions -# Returns: +#### Returns: - the Jaccard index """ @@ -271,3 +271,85 @@ function jaccard(asm::EcoBase.AbstractAssemblage) hassimilarity(asm) && error("function cannot run with $(typeof(gettypes(asm))) types as contains similarity") return jaccard(occurrences(asm)) end + +""" +generalisedpielou::DiversityLevel, proportions::AbstractArray, + Z::AbstractMatrix) +generalisedpielou(level::DiversityLevel, proportions::AbstractArray, + sim::AbstractTypes) + +Calculates a generalisation of Pielou's evenness for columns +representing the counts or proportions of subcommunities. Values range from +zero to one, with one representing complete evenness within the +community. Since this is calculated as H / Hmax, and is just a proportion, +values remain unchanged regardless of the value(s) of q supplied. + +#### Arguments: +- `level`: DiversityLevel to calculate at (e.g. subcommunityDiversity) + +- `proportions`: population proportions + +- `Z`: similarity matrix or +- `sim`: instance of AbstractTypes + +#### Returns: +- Pielou's evenness metric (at metacommunity level) or metrics (of subcommunities) +""" +function generalisedpielou end +generalisedpielou(level::DiversityLevel, + proportions::AbstractArray, + Z::AbstractMatrix = Matrix(1.0I, size(proportions, 1), size(proportions, 1))) = + generalisedpielou(level, proportions, GeneralTypes(Z)) + +function generalisedpielou(level::DiversityLevel, + proportions::AbstractArray, + sim::AbstractTypes) + if (level == subcommunityDiversity) + dm = ᾱ + ns = vec(sum(x->x>0, proportions, dims=1)) + elseif (level == metacommunityDiversity) + dm = Gamma + ns = sum(x->x>0, proportions) + else + error("Can't calculate richness for $level") + end + gp = level(dm(Metacommunity(proportions, sim)), 1) + gp[!,:diversity] .= log.(gp[!,:diversity])./log.(ns) + gp[!,:measure] .= "Pielou" + select!(gp, Not(:q)) + return gp +end + +""" + pielou(proportions::AbstractMatrix) + +Calculates Pielou's evenness of a series of +columns representing independent subcommunity counts. + +#### Arguments: + +- `proportions`: population proportions + +#### Returns: + +- evenness of subcommunities + +#### Example: +``` +communitymat = [10 20 30 20 0; #5 sites/subcommunities (columns) and 6 species (rows) + 10 0 50 80 10; + 60 10 90 0 0; + 10 10 10 10 10; + 70 70 70 70 70; + 10 0 0 90 0] + +pielou(communitymat) +``` +""" +pielou(proportions::AbstractVecOrMat) = + generalisedpielou(subcommunityDiversity, proportions, + UniqueTypes(size(proportions, 1))) +function pielou(asm::EcoBase.AbstractAssemblage) + hassimilarity(asm) && error("function cannot run with $(typeof(gettypes(asm))) types as contains similarity") + return pielou(occurrences(asm)) +end diff --git a/src/Metacommunity.jl b/src/Metacommunity.jl index 2a9f836..c65075d 100644 --- a/src/Metacommunity.jl +++ b/src/Metacommunity.jl @@ -33,7 +33,6 @@ Metacommunity(abundances::AbstractArray, Partition. Should only be accessed through getordinariness!(::Metacommunity), which will populate the cache if it has not yet been calculated. - """ mutable struct Metacommunity{FP, ARaw, AProcessed, Sim, Part} <: Diversity.API.AbstractMetacommunity{FP, ARaw, AProcessed, Sim, Part} diff --git a/test/run_rcall.jl b/test/run_rcall.jl index 582e327..eece8b7 100644 --- a/test/run_rcall.jl +++ b/test/run_rcall.jl @@ -58,7 +58,7 @@ if !skipR qs = sort([rand(7)*10..., 0, 1, Inf]) names = ["symmetric", "asymmetric"] Zs = [Zsym, Zasym] - @testset "Z matrix - $(names[k])" for k in 1:length(Zs) + @testset "Z matrix - $(names[k])" for k in axes(Zs, 1) Z = Zs[k] meta = Metacommunity(pops, Z) diversities = Dict(:raw_alpha => α(meta), diff --git a/test/test_DiversityMeasure.jl b/test/test_DiversityMeasure.jl index a967e71..2178aee 100644 --- a/test/test_DiversityMeasure.jl +++ b/test/test_DiversityMeasure.jl @@ -32,7 +32,7 @@ nab = NormalisedAlpha(meta2) fulls = ["raw alpha diversity", "normalised alpha diversity", "distinctiveness", "effective number of subcommunities", "redundancy", "representativeness", "gamma diversity"] - for i in 1:length(diversities) + for i in axes(diversities, 1) @test diversities[i] == shortds[i] @test getName(diversities[i](meta)) == chars[i] @test getASCIIName(diversities[i](meta2)) == asciis[i] diff --git a/test/test_EffectiveNumbers.jl b/test/test_EffectiveNumbers.jl index 5bae549..dd30b9e 100644 --- a/test/test_EffectiveNumbers.jl +++ b/test/test_EffectiveNumbers.jl @@ -59,7 +59,7 @@ end @test typeof(qD(manyweights[:,1], 0)) <: AbstractFloat @test typeof(qD(manyweights[:,1], [0])) <: Vector - for i in 1:size(manyweights, 2) + for i in axes(manyweights, 2) @test qD(manyweights[:,i], [0]) ≈ numspecies * ones((1, size(manyweights[:,i], 2))) end end @@ -70,7 +70,7 @@ end @test qDZ(weights, [0, 1, 2, 3, Inf], Z1) ≈ [1, 1, 1, 1, 1] - for i in 1:size(manyweights, 2) + for i in axes(manyweights, 2) @test qDZ(manyweights[:,i], [0, 1, 2, Inf], ones((size(manyweights[:,i], 1), size(manyweights[:,i], 1)))) ≈ ones((4, size(manyweights[:,i], 2))) diff --git a/test/test_Hill.jl b/test/test_Hill.jl index a5dd97e..5907a08 100644 --- a/test/test_Hill.jl +++ b/test/test_Hill.jl @@ -13,7 +13,7 @@ manyweights *= Diagonal(reshape(mapslices(v -> 1. / sum(v), manyweights, dims=1) (numcommunities))); @testset "Hill numbers" begin - for i in 1:size(manyweights, 2) + for i in axes(manyweights, 2) @test hillnumber(manyweights[:,i], [0])[!,:diversity] ≈ [numspecies] end end