Skip to content

Commit

Permalink
Merge ea58691 into b74f5b0
Browse files Browse the repository at this point in the history
  • Loading branch information
richardreeve committed Jul 9, 2018
2 parents b74f5b0 + ea58691 commit aa85646
Show file tree
Hide file tree
Showing 22 changed files with 439 additions and 138 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ meta = Metacommunity(pop)
```

#### Calculating diversity
First we need to calculate the low-level diversity component seperately, by passing a `metacommunity` object to the appropriate function; `RawAlpha()`, `NormalisedAlpha()`, `RawBeta()`, `NormalisedBeta()`, `RawRho()`, `NormalisedRho()`, or `Gamma()`.
First we need to calculate the low-level diversity component seperately, by passing a `metacommunity` object to the appropriate function; `RawAlpha()`, `NormalisedAlpha()`, `RawBeta()`, `NormalisedBeta()`, `RawRho()`, `NormalisedRho()`, or `Gamma()`.

```julia
# First, calculate the normalised alpha component
Expand Down Expand Up @@ -153,10 +153,13 @@ included in the Diversity.Phylogenetics submodule. Documentation for
these diversity measures can be found
[here](http://richardreeve.github.io/Diversity.jl/latest/phylogenetics/).
The phylogenetics code relies on the [Phylo][phylo-url] package to
generate trees to incorporate into the diversity code:
generate trees to incorporate into the diversity code, and the
`Diversity.Phylogenetics` sub-package will be created when both
main packages are loaded:

```julia-repl
julia> using Diversity, Phylo, Diversity.Phylogenetics
Creating Diversity to Phylo interface...
julia> communities = [4 1; 3 2; 1 0; 0 1] / 12;
Expand Down
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
julia 0.6
DataFrames 0.9.0
Phylo 0.2.0
Missings
Compat 0.59.0
Requires
RecipesBase
1 change: 1 addition & 0 deletions ext/EcoBase/.codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
comment: false
35 changes: 35 additions & 0 deletions ext/EcoBase/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Documentation: http://docs.travis-ci.com/user/languages/julia/
language: julia
os:
- linux
- osx
julia:
- 0.6
- nightly
notifications:
email: false
git:
depth: 99999999

## uncomment the following lines to allow failures on nightly julia
## (tests will run but not make your overall status red)
#matrix:
# allow_failures:
# - julia: nightly

## uncomment and modify the following lines to manually install system packages
#addons:
# apt: # apt-get for linux
# packages:
# - gfortran
#before_script: # homebrew for mac
# - if [ $TRAVIS_OS_NAME = osx ]; then brew install gcc; fi

## uncomment the following lines to override the default test script
#script:
# - julia -e 'Pkg.clone(pwd()); Pkg.build("EcoBase"); Pkg.test("EcoBase"; coverage=true)'
after_success:
# push coverage results to Coveralls
- julia -e 'cd(Pkg.dir("EcoBase")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
# push coverage results to Codecov
- julia -e 'cd(Pkg.dir("EcoBase")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
22 changes: 22 additions & 0 deletions ext/EcoBase/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The EcoBase.jl package is licensed under the MIT "Expat" License:

> Copyright (c) 2018: Michael K. Borregaard.
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
>
3 changes: 3 additions & 0 deletions ext/EcoBase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# EcoBase

A package implementing an abstract interface to data types used in ecological analyses
3 changes: 3 additions & 0 deletions ext/EcoBase/REQUIRE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
julia 0.6

RecipesBase
47 changes: 47 additions & 0 deletions ext/EcoBase/appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"

## uncomment the following lines to allow failures on nightly julia
## (tests will run but not make your overall status red)
#matrix:
# allow_failures:
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"

branches:
only:
- master
- /release-.*/

notifications:
- provider: Email
on_build_success: false
on_build_failure: false
on_build_status_changed: false

install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# If there's a newer build queued for the same PR, cancel this one
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile(
$env:JULIA_URL,
"C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia

build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
- C:\projects\julia\bin\julia -e "versioninfo();
Pkg.clone(pwd(), \"EcoBase\"); Pkg.build(\"EcoBase\")"

test_script:
- C:\projects\julia\bin\julia -e "Pkg.test(\"EcoBase\")"
62 changes: 62 additions & 0 deletions ext/EcoBase/src/DataTypes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
AbstractThings
Supertype for container of objects being observed, whether these are
species, sequences, tips of a phylogeny (which could be either), or
some other type of thing. This will contain the names of the things
being observed, and (optionally) metadata about them, such as a
phylogeny that connects them, taxonomic information, their sequences,
trait information, information on similarity between the different
things, etc.
"""
abstract type AbstractThings end

"""
AbstractPlaces
Supertype for container of places where things are found (see
AbstractThings). This will contain names or a reference for the
places, and (optionally) metadata such as what kind of place these
are, e.g. geographic locations (see subtype AbstractLocations), where
additional metadata will includes location data, animal ids for where
the samples of things where retrieved from, etc.
"""
abstract type AbstractPlaces end

"""
AbstractLocations <: AbstractPlaces
Subtype of AbstractPlaces that refers to locations with some
geographical component. This may be a series of arbitrarily arranged
points, a series of areas, or even grid of of regularly spaced
quadrats (see AbstractGrid).
"""
abstract type AbstractLocations <: AbstractPlaces end

"""
AbstractGrid <: AbstractLocations <: AbstractPlaces
Subtype of AbstractLocations that refers to a grid of regularly
spaced, identically shaped, locations.
"""
abstract type AbstractGrid <: AbstractLocations end

"""
AbstractAssemblage{D <: Real (e.g. Int, Float64, Bool),
T <: AbstractThings,
P <: AbstractPlaces}
An assemblage of things recorded as being present in one or more
places. These may, for instance, be species counts in quadrats over a
regular grid, relative abundance of viral sequences in a group of
individuals, or presence-absence of genera over multiple islands.
"""
abstract type AbstractAssemblage{D <: Real,
T <: AbstractThings,
P <: AbstractPlaces} end

# depend explicitly on AxisArrays (and/or sparse) in some implementation?
15 changes: 15 additions & 0 deletions ext/EcoBase/src/EcoBase.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module EcoBase

import Base: show
import RecipesBase

include("DataTypes.jl")

include("Interface.jl")
export nthings, nplaces, occupancy, richness, records, placenames, thingnames
export occurring, noccurring, occupied, noccupied, occurrences
export indices, coordinates, xcells, ycells, cells, xmin, xmax, ymin, ymax
export xrange, yrange, xcellsize, ycellsize, cellsize

include("PlotRecipes.jl")
end # module
97 changes: 97 additions & 0 deletions ext/EcoBase/src/Interface.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Functions - most have to be implemented with the concrete type
occurrences(com::AbstractAssemblage) = error("function not defined for this type")
view(com::AbstractAssemblage) = error("function not defined for this type")
places(asm::AbstractAssemblage) = error("function not defined for this type")
things(asm::AbstractAssemblage) = error("function not defined for this type")

nplaces(com::AbstractPlaces) = error("function not defined for this type")
placenames(com::AbstractPlaces) = error("function not defined for this type")

nthings(com::AbstractThings) = error("function not defined for this type")
thingnames(com::AbstractThings) = error("function not defined for this type")

nzrows(a::AbstractMatrix) = find(sum(a .> 0, 2) .> 0)
nzcols(a::AbstractMatrix) = find(sum(a .> 0, 1) .> 0)
nnz(a::AbstractArray) = sum(a .> 0)

occurring(com::AbstractAssemblage) = nzrows(occurrences(com))
occupied(com::AbstractAssemblage) = nzcols(occurrences(com))
occupied(com::AbstractAssemblage, idx) = findn(occurrences(com)[idx, :])
occurring(com::AbstractAssemblage, idx) = findn(occurrences(com)[:, idx])

noccurring(x) = length(occurring(x))
noccupied(x) = length(occupied(x))
noccurring(x, idx) = length(occurring(x, idx))
noccupied(x, idx) = length(occupied(x, idx))

thingoccurrences(com::AbstractAssemblage, idx) = view(occurrences(com), idx, :)
placeoccurrences(com::AbstractAssemblage, idx) = view(occurrences(com), :, idx) # make certain that the view implementation also takes thing or place names

richness(com::AbstractAssemblage{Bool, T, P}) where {T, P} = vec(sum(occurrences(com), 1))
richness(com::AbstractAssemblage) = vec(mapslices(nnz, occurrences(com), 1))

occupancy(com::AbstractAssemblage{Bool, T, P}) where {T, P} = vec(sum(occurrences(com), 2))
occupancy(com::AbstractAssemblage) = vec(mapslices(nnz, occurrences(com), 2))

records(com::AbstractAssemblage) = nnz(occurrences(com))

cooccurring(com::AbstractAssemblage, inds...) = cooccurring(com, [inds...])
function cooccurring(com::AbstractAssemblage, inds::AbstractVector)
sub = view(com, species = inds)
richness(sub) .== nthings(sub)
end

function createsummaryline(vec::AbstractVector{<:AbstractString})
linefunc(vec) = mapreduce(x -> x * ", ", *, vec[1:(end-1)]) * vec[end]
length(vec) == 1 && return vec[1]
length(vec) < 6 && return linefunc(vec)
linefunc(vec[1:3]) * "..." * linefunc(vec[(end-1):end])
end


function show(io::IO, com::T) where T <: AbstractAssemblage
sp = createsummaryline(thingnames(com))
si = createsummaryline(placenames(com))
println(io,
"""$T with $(nthings(com)) things in $(nplaces(com)) places
Thing names:
$(sp)
Place names:
$(si)
""")
end


macro forward_func(ex, fs)
T, field = ex.args[1], ex.args[2].args[1]
T = esc(T)
fs = Meta.isexpr(fs, :tuple) ? map(esc, fs.args) : [esc(fs)]
:($([:($f(x::$T, args...) = (Base.@_inline_meta; $f($(field)(x), args...)))
for f in fs]...);
nothing)
end

@forward_func AbstractAssemblage.places nplaces, placenames
@forward_func AbstractAssemblage.things nthings, thingnames

# TODO:
# accessing cache

xmin(g::AbstractGrid) = error("function not defined for this type")
ymin(g::AbstractGrid) = error("function not defined for this type")
xcellsize(g::AbstractGrid) = error("function not defined for this type")
ycellsize(g::AbstractGrid) = error("function not defined for this type")
xcells(g::AbstractGrid) = error("function not defined for this type")
ycells(g::AbstractGrid) = error("function not defined for this type")
cellsize(g::AbstractGrid) = xcellsize(g), ycellsize(g)
cells(g::AbstractGrid) = xcells(g), ycells(g)
xrange(g::AbstractGrid) = xmin(g):xcellsize(g):xmax(g) #includes intermediary points
yrange(g::AbstractGrid) = ymin(g):ycellsize(g):ymax(g)
xmax(g::AbstractGrid) = xmin(g) + xcellsize(g) * (xcells(g) - 1)
ymax(g::AbstractGrid) = ymin(g) + ycellsize(g) * (ycells(g) - 1)


indices(grd::AbstractGrid, idx) = error("function not defined for this type") #Implement this in SpatialEcology!
coordinates(grd::AbstractGrid) = error("function not defined for this type")
54 changes: 54 additions & 0 deletions ext/EcoBase/src/PlotRecipes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@


function convert_to_image(var::AbstractVector, grd::AbstractGrid)
x = Matrix{Float64}(reverse(cells(grd))...)
fill!(x, NaN)
xind, yind = indices(grd, 1), indices(grd,2) #since matrices are drawn from upper left corner
[x[yind[i], xind[i]] = val for (i, val) in enumerate(var)]
x
end

RecipesBase.@recipe function f(var::AbstractVector, grd::AbstractGrid)
registercolors()
seriestype := :heatmap
aspect_ratio --> :equal
grid --> false
xrange(grd), yrange(grd), convert_to_image(var, grd)
end

# RecipesBase.@recipe function f(sit::SiteFields) # not sure what SiteFields are
# ones(nsites(sit)), sit
# end

RecipesBase.@recipe function f(var::AbstractVector, pnt::AbstractLocations)
registercolors()
seriestype := :scatter
aspect_ratio --> :equal
grid --> false
marker_z := var
legend --> false
cd = coordinates(pnt)
cd[:,1], cd[:,2]
end

RecipesBase.@recipe function f(asm::AbstractAssemblage; occupied = true)
var = richness(asm)
if occupied
var = [Float64(v) for v in var]
(var[var.==0] .= NaN)
end
var, asm.site
end


RecipesBase.@recipe function f(var::AbstractVector, asm::AbstractAssemblage)
var, asm.site
end

RecipesBase.@recipe function f(var::Symbol, asm::AbstractAssemblage)
asm.site.sitestats[var], asm.site
end

RecipesBase.@recipe function f(g::Function, asm::AbstractAssemblage)
g(asm), asm.site
end
5 changes: 5 additions & 0 deletions ext/EcoBase/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using EcoBase
using Base.Test

# write your own tests here
@test 1 == 2

0 comments on commit aa85646

Please sign in to comment.