From 498c80c02aef7ef6696689375fc57750ade55475 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Thu, 11 Jul 2024 13:06:00 +0200 Subject: [PATCH 01/15] print to io --- src/data_utils.jl | 18 +++++++++--------- src/ensemble.jl | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/data_utils.jl b/src/data_utils.jl index 02d2da0..c495182 100644 --- a/src/data_utils.jl +++ b/src/data_utils.jl @@ -20,28 +20,28 @@ end function Base.show(io::IO, mime::MIME"text/plain", data::SDMdata{K}) where K y = response(data) - print("SDMdata object with ") + print(io, "SDMdata object with ") printstyled(sum(y), bold = true) - print(" presence points and ") + print(io, " presence points and ") printstyled(length(y) - sum(y), bold = true) - print(" absence points. \n \n") + print(io, " absence points. \n \n") - printstyled("Resampling: \n", bold = true) - println("Data is divided into $(nfolds(data)) folds using resampling strategy $(resampler(data)).") + printstyled(io, "Resampling: \n", bold = true) + println(io, "Data is divided into $(nfolds(data)) folds using resampling strategy $(resampler(data)).") n_presences = length.(getindex.(traintestpairs(data), 1)) n_absences = length.(getindex.(traintestpairs(data), 2)) table_cols = hcat(1:nfolds(data), n_presences, n_absences) - header = (["fold", "presences", "absences"]) + header = (["fold", "# train", "# test"]) PrettyTables.pretty_table(io, table_cols; header = header) - printstyled("Predictor variables: \n", bold = true) + printstyled(io, "Predictor variables: \n", bold = true) Base.show(io, mime, MLJBase.schema(predictor(data))) if isnothing(geometry(data)) - print("Does not contain geometry data") + print(io, "Does not contain geometry data") else - print("Also contains geometry data") + print(io, "Also contains geometry data") end end diff --git a/src/ensemble.jl b/src/ensemble.jl index cad7f26..e96a7d3 100644 --- a/src/ensemble.jl +++ b/src/ensemble.jl @@ -114,7 +114,7 @@ function Base.show(io::IO, mime::MIME"text/plain", ensemble::SDMensemble{K}) whe println(io, "trained SDMensemble, containing $(n_machines(ensemble)) SDMmachines across $(Base.length(ensemble)) SDMgroups \n") - println("Uses the following models:") + println(io, "Uses the following models:") for k in K modeltype = MLJBase.name(model(ensemble[k])) printstyled(io, k, color = :blue) From 47520291ad78c6ed20f27a8e8660ca939c19779c Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 6 Sep 2024 15:00:31 +0200 Subject: [PATCH 02/15] fix thin, move rng --- Project.toml | 3 ++- src/SpeciesDistributionModels.jl | 1 + src/thin.jl | 28 ++++++++++++++++------------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Project.toml b/Project.toml index 9e238a6..b470ebf 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0" Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" EvoTrees = "f6006082-12f8-11e9-0c9c-0d5d367ab1e5" GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a" +GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" Lasso = "b4fcebef-c861-5a0f-a7e2-ba9dc32b180a" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Loess = "4345ca2d-374a-55d4-8d30-97f9976e7612" @@ -49,8 +50,8 @@ julia = "1.9" [extras] Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" MLJModels = "d491faf4-2d78-11e9-2867-c94bc002c0b7" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/SpeciesDistributionModels.jl b/src/SpeciesDistributionModels.jl index 92b3e6d..5622321 100644 --- a/src/SpeciesDistributionModels.jl +++ b/src/SpeciesDistributionModels.jl @@ -3,6 +3,7 @@ module SpeciesDistributionModels import Tables, StatsBase, Statistics, StatsAPI, StatsModels, LinearAlgebra, Random, ThreadsX import MLJBase, StatisticalMeasures, StatisticalMeasuresBase, ScientificTypesBase, CategoricalArrays import GLM, PrettyTables, Rasters, EvoTrees, DecisionTree, Shapley, Loess, Distances +import GeoInterface as GI using MLJBase: pdf using Rasters: Raster, RasterStack, Band diff --git a/src/thin.jl b/src/thin.jl index 6d85ae3..9068276 100644 --- a/src/thin.jl +++ b/src/thin.jl @@ -1,16 +1,17 @@ """ - thin(x, cutoff; distance = Haversine(), [rng]) + thin([rng], x, cutoff; distance = Haversine(), [geometrycolumn]) Thin spatial data by removing points that are closer than `cutoff` distance to the nearest other point in the dataset. ## Arguments + - `rng`: a random number generator. The default is `Random.GLOBAL_RNG()`. - `x`: an `AbstractVector` that iterates points, or a table with a `:geometry` column. - `cutoff`: the distance threshold in units of `distance`. ## Keywords - `distance`: the distance metric used to calculate distances between points. The default is `Haversine()`, which uses the Haversine formula to calculate the distance between coordinates in meter units. - - `rng`: a random number generator. The default is `Random.GLOBAL_RNG()`. + - `geometrycolumn`: the name of the column in the table that contains the points, if `x` is a table. Usually defaults to `:geometry`. ## Example ```jldoctest @@ -20,7 +21,7 @@ # thin to 1000 meters thin(geometries, 1000) # thin to 1 degree - thin(geometries, 1; distance = Euclidean(), rng = Xoshiro(123)) + thin(Xoshiro(123), geometries, 1; distance = Euclidean()) # output 2-element Vector{Tuple{Int64, Real}}: @@ -28,21 +29,24 @@ (1, 0) ``` """ -function thin(x, cutoff; distance = Distances.Haversine(), rng = Random.GLOBAL_RNG) - if Tables.istable(x) - geoms = Tables.getcolumn(x, :geometry) - indices = _thin(geoms, cutoff, distance, rng) +thin(x, cutoff; kw...) = thin(Random.GLOBAL_RNG, x, cutoff; kw...) + +function thin(rng::Random.AbstractRNG, x, cutoff; distance = Distances.Haversine(), geometrycolumn = nothing) # = first(GI.geometrycolumn(x)) + if !(x isa AbstractVector{<:GI.NamedTuplePoint}) && Tables.istable(x) + geomcol = isnothing(geometrycolumn) ? first(GI.geometrycolumns(data)) : geometrycolumn + geoms = Tables.getcolumn(Tables.Columns(x), geomcol) + indices = _thin(rng, geoms, cutoff, distance) return Tables.subset(x, indices) elseif x isa AbstractVector - _geoms = unique(x) - indices = _thin(_geoms, cutoff, distance, rng) - return _geoms[indices] + geoms = unique(x) + indices = _thin(rng, geoms, cutoff, distance) + return geoms[indices] else - throw(ArgumentError("x must be an AbstractVector or a Table with a :geometry column.")) + throw(ArgumentError("x must be an AbstractVector or a Table with a :$geometrycolumn column.")) end end -function _thin(geoms::AbstractVector, cutoff::Real, distance::Distances.Metric, rng::Random.AbstractRNG) +function _thin(rng::Random.AbstractRNG, geoms::AbstractVector, cutoff::Real, distance::Distances.Metric) dist_matrix = Distances.pairwise(distance, geoms) dist_mask = dist_matrix .< cutoff From e254b2261863244ff013bca53e8fb1ff23472e75 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Mon, 9 Sep 2024 13:03:25 +0200 Subject: [PATCH 03/15] printstyled to io --- src/data_utils.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_utils.jl b/src/data_utils.jl index c495182..0379ecb 100644 --- a/src/data_utils.jl +++ b/src/data_utils.jl @@ -21,9 +21,9 @@ end function Base.show(io::IO, mime::MIME"text/plain", data::SDMdata{K}) where K y = response(data) print(io, "SDMdata object with ") - printstyled(sum(y), bold = true) + printstyled(io, sum(y), bold = true) print(io, " presence points and ") - printstyled(length(y) - sum(y), bold = true) + printstyled(io, length(y) - sum(y), bold = true) print(io, " absence points. \n \n") printstyled(io, "Resampling: \n", bold = true) From 166c0edce49cf714b4440f4a05fad5eddcfa0b22 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 27 Sep 2024 15:01:00 +0200 Subject: [PATCH 04/15] vitepress docs --- docs/.gitignore | 4 + docs/Project.toml | 2 + docs/make.jl | 32 ++-- docs/package.json | 16 ++ docs/src/.vitepress/config.mts | 53 ++++++ docs/src/.vitepress/theme/index.ts | 19 ++ docs/src/.vitepress/theme/style.css | 266 ++++++++++++++++++++++++++++ docs/src/api.md | 21 +++ docs/src/example.md | 85 +++++++++ docs/src/index.md | 16 +- 10 files changed, 490 insertions(+), 24 deletions(-) create mode 100644 docs/.gitignore create mode 100644 docs/package.json create mode 100644 docs/src/.vitepress/config.mts create mode 100644 docs/src/.vitepress/theme/index.ts create mode 100644 docs/src/.vitepress/theme/style.css create mode 100644 docs/src/api.md create mode 100644 docs/src/example.md diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..0587d74 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,4 @@ +build/ +node_modules/ +package-lock.json +Manifest.toml \ No newline at end of file diff --git a/docs/Project.toml b/docs/Project.toml index 7d24093..00b9e02 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,5 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365" +LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" SpeciesDistributionModels = "3ef73bbf-0321-4d3b-9a2e-5fbebc8e35da" diff --git a/docs/make.jl b/docs/make.jl index 6bdcf9e..474475d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,25 +1,25 @@ +using Documenter, DocumenterVitepress using SpeciesDistributionModels -using Documenter - -DocMeta.setdocmeta!(SpeciesDistributionModels, :DocTestSetup, :(using SpeciesDistributionModels); recursive=true) makedocs(; modules=[SpeciesDistributionModels], - authors="Tiem van der Deure , Rafael Schouten ", - repo="https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl/blob/{commit}{path}#{line}", + authors= "Tiem van der Deure , Rafael Schouten ", + repo="https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl", sitename="SpeciesDistributionModels.jl", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://tiemvanderdeure.github.io/SpeciesDistributionModels.jl", - edit_link="master", - assets=String[], + format=DocumenterVitepress.MarkdownVitepress( + repo = "https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl", + devurl = "dev", + devbranch = "master", + push_preview = true, + deploy_url = "tiemvanderdeure.github.io/SpeciesDistributionModels.jl", ), - pages=[ - "Home" => "index.md", - ], + warnonly = true, ) -deploydocs(; +deploydocs(; repo="github.com/tiemvanderdeure/SpeciesDistributionModels.jl", - devbranch="master", -) + target = "build", # this is where Vitepress stores its output + branch = "gh-pages", + devbranch = "master", + push_preview = true +) \ No newline at end of file diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..eb992db --- /dev/null +++ b/docs/package.json @@ -0,0 +1,16 @@ +{ + "scripts": { + "docs:dev": "vitepress dev build/.documenter", + "docs:build": "vitepress build build/.documenter", + "docs:preview": "vitepress preview build/.documenter" + }, + "devDependencies": { + "markdown-it-mathjax3": "^4.3.2", + "vitepress": "^1.2.3", + "vitepress-plugin-tabs": "^0.5.0" + }, + "dependencies": { + "markdown-it": "^14.0.0", + "markdown-it-footnote": "^4.0.0" + } +} diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts new file mode 100644 index 0000000..5abf5aa --- /dev/null +++ b/docs/src/.vitepress/config.mts @@ -0,0 +1,53 @@ +import { defineConfig } from 'vitepress' +import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' +import mathjax3 from "markdown-it-mathjax3"; +import footnote from "markdown-it-footnote"; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! + title: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + description: 'Species distirbution modelling in Julia', + lastUpdated: true, + cleanUrls: true, + outDir: 'REPLACE_ME_DOCUMENTER_VITEPRESS', // This is required for MarkdownVitepress to work correctly... + head: [['link', { rel: 'icon', href: 'REPLACE_ME_DOCUMENTER_VITEPRESS_FAVICON' }]], + ignoreDeadLinks: true, + + markdown: { + math: true, + config(md) { + md.use(tabsMarkdownPlugin), + md.use(mathjax3), + md.use(footnote) + }, + theme: { + light: "github-light", + dark: "github-dark"} + }, + themeConfig: { + outline: 'deep', + logo: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + search: { + provider: 'local', + options: { + detailedView: true + } + }, + nav: [ + { text: 'Example', link: '/example' }, + { text: 'API', link: '/api' }, + ], + editLink: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + socialLinks: [ + { icon: 'github', link: 'REPLACE_ME_DOCUMENTER_VITEPRESS' } + ], + footer: { + message: 'Made with DocumenterVitepress.jl
', + copyright: `© Copyright ${new Date().getUTCFullYear()}.` + } + } +}) + + + diff --git a/docs/src/.vitepress/theme/index.ts b/docs/src/.vitepress/theme/index.ts new file mode 100644 index 0000000..463b5d8 --- /dev/null +++ b/docs/src/.vitepress/theme/index.ts @@ -0,0 +1,19 @@ +// .vitepress/theme/index.ts +import { h } from 'vue' +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client' +import './style.css' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + // https://vitepress.dev/guide/extending-default-theme#layout-slots + }) + }, + enhanceApp({ app, router, siteData }) { + enhanceAppWithTabs(app) + } +} satisfies Theme \ No newline at end of file diff --git a/docs/src/.vitepress/theme/style.css b/docs/src/.vitepress/theme/style.css new file mode 100644 index 0000000..09d5c4a --- /dev/null +++ b/docs/src/.vitepress/theme/style.css @@ -0,0 +1,266 @@ +/* Customize default theme styling by overriding CSS variables: +https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css + */ + + /* Layouts */ + +/* + :root { + --vp-layout-max-width: 1440px; +} */ + +.VPHero .clip { + white-space: pre; + max-width: 500px; +} + +/* Fonts */ + +@font-face { + font-family: JuliaMono-Regular; + src: url("https://cdn.jsdelivr.net/gh/cormullion/juliamono/webfonts/JuliaMono-Regular.woff2"); +} + + :root { + /* Typography */ + --vp-font-family-base: "Barlow", "Inter var experimental", "Inter var", + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + + /* Code Snippet font */ + --vp-font-family-mono: JuliaMono-Regular, monospace; + +} + +/* +Disable contextual alternates (kind of like ligatures but different) in monospace, +which turns `/>` to an up arrow and `|>` (the Julia pipe symbol) to an up arrow as well. +This is pretty bad for Julia folks reading even though copy+paste retains the same text. +*/ +/* Target elements with class 'mono' */ +.mono-no-substitutions { + font-family: "JuliaMono-Light", monospace; + font-feature-settings: "calt" off; +} + +/* Alternatively, you can use the following if you prefer: */ +.mono-no-substitutions-alt { + font-family: "JuliaMono-Light", monospace; + font-variant-ligatures: none; +} + +/* If you want to apply this globally to all monospace text: */ +pre, code { + font-family: "JuliaMono-Light", monospace; + font-feature-settings: "calt" off; +} + +/* Colors */ + +:root { + --julia-blue: #4063D8; + --julia-purple: #9558B2; + --julia-red: #CB3C33; + --julia-green: #389826; + + --vp-c-brand: #389826; + --vp-c-brand-light: #3dd027; + --vp-c-brand-lighter: #9499ff; + --vp-c-brand-lightest: #bcc0ff; + --vp-c-brand-dark: #535bf2; + --vp-c-brand-darker: #454ce1; + --vp-c-brand-dimm: #212425; +} + + /* Component: Button */ + +:root { + --vp-button-brand-border: var(--vp-c-brand-light); + --vp-button-brand-text: var(--vp-c-white); + --vp-button-brand-bg: var(--vp-c-brand); + --vp-button-brand-hover-border: var(--vp-c-brand-light); + --vp-button-brand-hover-text: var(--vp-c-white); + --vp-button-brand-hover-bg: var(--vp-c-brand-light); + --vp-button-brand-active-border: var(--vp-c-brand-light); + --vp-button-brand-active-text: var(--vp-c-white); + --vp-button-brand-active-bg: var(--vp-button-brand-bg); +} + +/* Component: Home */ + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #9558B2 30%, + #CB3C33 + ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #9558B2 30%, + #389826 30%, + #CB3C33 + ); + --vp-home-hero-image-filter: blur(40px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(72px); + } +} + +/* Component: Custom Block */ + +:root.dark { + --vp-custom-block-tip-border: var(--vp-c-brand); + --vp-custom-block-tip-text: var(--vp-c-brand-lightest); + --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); + + /* // Tweak the color palette for blacks and dark grays */ + --vp-c-black: hsl(220 20% 9%); + --vp-c-black-pure: hsl(220, 24%, 4%); + --vp-c-black-soft: hsl(220 16% 13%); + --vp-c-black-mute: hsl(220 14% 17%); + --vp-c-gray: hsl(220 8% 56%); + --vp-c-gray-dark-1: hsl(220 10% 39%); + --vp-c-gray-dark-2: hsl(220 12% 28%); + --vp-c-gray-dark-3: hsl(220 12% 23%); + --vp-c-gray-dark-4: hsl(220 14% 17%); + --vp-c-gray-dark-5: hsl(220 16% 13%); + + /* // Backgrounds */ + /* --vp-c-bg: hsl(240, 2%, 11%); */ + --vp-custom-block-info-bg: hsl(220 14% 17%); + /* --vp-c-gutter: hsl(220 20% 9%); + + --vp-c-bg-alt: hsl(220 20% 9%); + --vp-c-bg-soft: hsl(220 14% 17%); + --vp-c-bg-mute: hsl(220 12% 23%); + */ +} + + /* Component: Algolia */ + +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand) !important; +} + +/* Component: MathJax */ + +mjx-container > svg { + display: block; + margin: auto; +} + +mjx-container { + padding: 0.5rem 0; +} + +mjx-container { + display: inline; + margin: auto 2px -2px; +} + +mjx-container > svg { + margin: auto; + display: inline-block; +} + +/** + * Colors links + * -------------------------------------------------------------------------- */ + + :root { + --vp-c-brand-1: #CB3C33; + --vp-c-brand-2: #CB3C33; + --vp-c-brand-3: #CB3C33; + --vp-c-sponsor: #ca2971; + --vitest-c-sponsor-hover: #c13071; +} + +.dark { + --vp-c-brand-1: #91dd33; + --vp-c-brand-2: #91dd33; + --vp-c-brand-3: #91dd33; + --vp-c-sponsor: #91dd33; + --vitest-c-sponsor-hover: #e51370; +} + +/** + * Change images from light to dark theme + * -------------------------------------------------------------------------- */ + + :root:not(.dark) .dark-only { + display: none; +} + +:root:is(.dark) .light-only { + display: none; +} + +/* https://bddxg.top/article/note/vitepress优化/一些细节上的优化.html#文档页面调整-加宽 */ + +.VPDoc.has-aside .content-container { + max-width: 100% !important; +} +.aside { + max-width: 200px !important; + padding-left: 0 !important; +} +.VPDoc { + padding-top: 15px !important; + padding-left: 5px !important; + +} +/* This one does the right menu */ + +.VPDocOutlineItem li { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + max-width: 200px; +} + +.VPNavBar .title { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +@media (max-width: 960px) { + .VPDoc { + padding-left: 25px !important; + } +} + +/* This one does the left menu */ + +/* .VPSidebarItem .VPLink p { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + max-width: 200px; +} */ + + +/* Component: Docstring Custom Block */ + +.jldocstring.custom-block { + border: 1px solid var(--vp-c-gray-2); + color: var(--vp-c-text-1) +} + +.jldocstring.custom-block summary { + font-weight: 700; + cursor: pointer; + user-select: none; + margin: 0 0 8px; +} diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..349baba --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,21 @@ +```@meta +DocTestSetup= quote +using SpeciesDistributionModels +end +``` +## Index +```@index +Modules = [SpeciesDistributionModels] +``` + +## Reference - Exported functions +```@autodocs +Modules = [SpeciesDistributionModels] +Private = false +``` + +## Reference - Internal functions +```@autodocs +Modules = [SpeciesDistributionModels] +Public = false +``` diff --git a/docs/src/example.md b/docs/src/example.md new file mode 100644 index 0000000..66b864d --- /dev/null +++ b/docs/src/example.md @@ -0,0 +1,85 @@ +# Example of a full species distribution modelling workflow + +## Environmental data + +```{julia} +#| echo: false +if !haskey(ENV, "RASTERDATASOURCES_PATH") + ENV["RASTERDATASOURCES_PATH"] = "."; +end +using CairoMakie +CairoMakie.activate!(type = "png") +``` +\ +```{julia} +using Rasters, RasterDataSources, ArchGDAL, NaturalEarth, DataFrames +bio = RasterStack(WorldClim{BioClim}, (1,12)) +countries = naturalearth("ne_10m_admin_0_countries") |> DataFrame +australia = subset(countries, :NAME => ByRow(==("Australia"))).geometry +bio_aus = Rasters.trim(mask(bio; with = australia)[X = 110 .. 156, Y = -45 .. -10]) +``` + +## Environmental data +```{julia} +using CairoMakie +Rasters.rplot(bio_aus) +``` + +## Occurrence data +```{julia} +using GBIF2, SpeciesDistributionModels +sp = species_match("Eucalyptus regnans") +occurrences_raw = occurrence_search(sp; year = (1970,2000), country = "AU", hasCoordinate = true, limit = 2000) +occurrences = thin(occurrences_raw.geometry, 5000) + +``` +## Background points +```{julia} +using StatsBase +bg_indices = sample(findall(boolmask(bio_aus)), 500) +bg_points = DimPoints(bio_aus)[bg_indices] +fig, ax, pl = plot(bio_aus.bio1) +scatter!(ax, occurrences; color = :red) +scatter!(ax, bg_points; color = :grey) +fig +``` + +## Handling data +```{julia} +using SpeciesDistributionModels +p_data = extract(bio_aus, occurrences; skipmissing = true) +bg_data = bio_aus[bg_indices] +data = sdmdata(p_data, bg_data; resampler = CV(nfolds = 3)) +``` + +## Fitting an ensemble +```{julia} +using Maxnet: MaxnetBinaryClassifier +using EvoTrees: EvoTreeClassifier +using MLJGLMInterface: LinearBinaryClassifier +models = ( + maxnet = MaxnetBinaryClassifier(), + brt = EvoTreeClassifier(), + glm = LinearBinaryClassifier() +) + +ensemble = sdm(data, models) +``` + +## Evaluating an ensemble +```{julia} +import SpeciesDistributionModels as SDM +ev = SDM.evaluate(ensemble; measures = (; auc, accuracy)) +``` + +## Predicting +```{julia} +pred = SDM.predict(ensemble, bio_aus; reducer = mean) +plot(pred; colorrange = (0,1)) +``` + +## Understanding the model +```{julia} +expl = SDM.explain(ensemble; method = ShapleyValues(8)) +interactive_response_curves(expl) +``` \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 31fcaf7..1368cb4 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,14 +1,14 @@ -```@meta -CurrentModule = SpeciesDistributionModels -``` +--- +layout: home +--- # SpeciesDistributionModels Documentation for [SpeciesDistributionModels](https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl). -```@index -``` -```@autodocs -Modules = [SpeciesDistributionModels] -``` +## Installation + +````julia +] add github.com/tiemvanderdeure/SpeciesDistributionModels.jl +```` From 68519dd02703319227a3291f4105cd43b6764a25 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 27 Sep 2024 16:38:30 +0200 Subject: [PATCH 05/15] remove LiveServer from project --- docs/Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/Project.toml b/docs/Project.toml index 00b9e02..20f39bf 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,4 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365" -LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" SpeciesDistributionModels = "3ef73bbf-0321-4d3b-9a2e-5fbebc8e35da" From e1a974d02698c4985f6140799b3c79f819be68c7 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 27 Sep 2024 16:39:12 +0200 Subject: [PATCH 06/15] drop push_preview argument --- docs/make.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 474475d..515cf48 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -10,7 +10,6 @@ makedocs(; repo = "https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl", devurl = "dev", devbranch = "master", - push_preview = true, deploy_url = "tiemvanderdeure.github.io/SpeciesDistributionModels.jl", ), warnonly = true, From 6017052437ff3489e54d0d0438f16385b69e14da Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Fri, 27 Sep 2024 19:54:32 +0100 Subject: [PATCH 07/15] fix docs (#13) --- .gitignore | 4 ++++ docs/.gitignore | 4 ---- docs/Project.toml | 11 +++++++++++ docs/make.jl | 9 ++++++--- docs/src/example.md | 22 +++++++++++----------- docs/src/index.md | 2 ++ 6 files changed, 34 insertions(+), 18 deletions(-) delete mode 100644 docs/.gitignore diff --git a/.gitignore b/.gitignore index 95731a5..c275a8e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ /Manifest.toml /docs/Manifest.toml /docs/build/ +node_modules/ +package-lock.json +Manifest.toml +.vscode \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 0587d74..0000000 --- a/docs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build/ -node_modules/ -package-lock.json -Manifest.toml \ No newline at end of file diff --git a/docs/Project.toml b/docs/Project.toml index 20f39bf..c746249 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,15 @@ [deps] +ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3" +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365" +EvoTrees = "f6006082-12f8-11e9-0c9c-0d5d367ab1e5" +GBIF2 = "dedd4f52-e074-43bf-924d-d6bce14ad628" +MLJGLMInterface = "caf8df21-4939-456d-ac9c-5fefbfb04c0c" +Maxnet = "81f79f80-22f2-4e41-ab86-00c11cf0f26f" +NaturalEarth = "436b0209-26ab-4e65-94a9-6526d86fea76" +RasterDataSources = "3cb90ccd-e1b6-4867-9617-4276c8b2ca36" +Rasters = "a3a2b9e3-a471-40c9-b274-f788e487c689" SpeciesDistributionModels = "3ef73bbf-0321-4d3b-9a2e-5fbebc8e35da" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" diff --git a/docs/make.jl b/docs/make.jl index 515cf48..a6ac79f 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,15 +4,18 @@ using SpeciesDistributionModels makedocs(; modules=[SpeciesDistributionModels], authors= "Tiem van der Deure , Rafael Schouten ", - repo="https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl", sitename="SpeciesDistributionModels.jl", format=DocumenterVitepress.MarkdownVitepress( - repo = "https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl", + repo = "github.com/tiemvanderdeure/SpeciesDistributionModels.jl", devurl = "dev", devbranch = "master", - deploy_url = "tiemvanderdeure.github.io/SpeciesDistributionModels.jl", ), warnonly = true, + pages = [ + "Home" => "index.md", + "Getting started" => "example.md", + "API" => "api.md" + ] ) deploydocs(; diff --git a/docs/src/example.md b/docs/src/example.md index 66b864d..00abc30 100644 --- a/docs/src/example.md +++ b/docs/src/example.md @@ -2,7 +2,7 @@ ## Environmental data -```{julia} +```@example test #| echo: false if !haskey(ENV, "RASTERDATASOURCES_PATH") ENV["RASTERDATASOURCES_PATH"] = "."; @@ -10,8 +10,8 @@ end using CairoMakie CairoMakie.activate!(type = "png") ``` -\ -```{julia} + +```@example test using Rasters, RasterDataSources, ArchGDAL, NaturalEarth, DataFrames bio = RasterStack(WorldClim{BioClim}, (1,12)) countries = naturalearth("ne_10m_admin_0_countries") |> DataFrame @@ -20,13 +20,13 @@ bio_aus = Rasters.trim(mask(bio; with = australia)[X = 110 .. 156, Y = -45 .. -1 ``` ## Environmental data -```{julia} +```@example test using CairoMakie Rasters.rplot(bio_aus) ``` ## Occurrence data -```{julia} +```@example test using GBIF2, SpeciesDistributionModels sp = species_match("Eucalyptus regnans") occurrences_raw = occurrence_search(sp; year = (1970,2000), country = "AU", hasCoordinate = true, limit = 2000) @@ -34,7 +34,7 @@ occurrences = thin(occurrences_raw.geometry, 5000) ``` ## Background points -```{julia} +```@example test using StatsBase bg_indices = sample(findall(boolmask(bio_aus)), 500) bg_points = DimPoints(bio_aus)[bg_indices] @@ -45,7 +45,7 @@ fig ``` ## Handling data -```{julia} +```@example test using SpeciesDistributionModels p_data = extract(bio_aus, occurrences; skipmissing = true) bg_data = bio_aus[bg_indices] @@ -53,7 +53,7 @@ data = sdmdata(p_data, bg_data; resampler = CV(nfolds = 3)) ``` ## Fitting an ensemble -```{julia} +```@example test using Maxnet: MaxnetBinaryClassifier using EvoTrees: EvoTreeClassifier using MLJGLMInterface: LinearBinaryClassifier @@ -67,19 +67,19 @@ ensemble = sdm(data, models) ``` ## Evaluating an ensemble -```{julia} +```@example test import SpeciesDistributionModels as SDM ev = SDM.evaluate(ensemble; measures = (; auc, accuracy)) ``` ## Predicting -```{julia} +```@example test pred = SDM.predict(ensemble, bio_aus; reducer = mean) plot(pred; colorrange = (0,1)) ``` ## Understanding the model -```{julia} +```@example test expl = SDM.explain(ensemble; method = ShapleyValues(8)) interactive_response_curves(expl) ``` \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 1368cb4..6ba202a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,6 +1,8 @@ +```@raw html --- layout: home --- +``` # SpeciesDistributionModels From 05c42a8a154367a002d325156e0b609f73288b7a Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Mon, 21 Oct 2024 13:32:14 +0200 Subject: [PATCH 08/15] add text to example --- Project.toml | 2 +- docs/src/example.md | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index b470ebf..71fe333 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,7 @@ SpeciesDistributionModelsMakieExt = "Makie" CategoricalDistributions = "0.1.14" Distances = "0.10" MLJGLMInterface = "0.3.7" -Rasters = "0.10.1, 0.11" +Rasters = "0.10.1-0.12" StatisticalMeasures = "0.1.5" StatsModels = "0.7.3" julia = "1.9" diff --git a/docs/src/example.md b/docs/src/example.md index 00abc30..aea9cc8 100644 --- a/docs/src/example.md +++ b/docs/src/example.md @@ -1,6 +1,5 @@ # Example of a full species distribution modelling workflow - -## Environmental data +This example fits and projects species distribution models for the tree species _Eucaplytus regnans_ from scratch. ```@example test #| echo: false @@ -11,6 +10,11 @@ using CairoMakie CairoMakie.activate!(type = "png") ``` +## Environmental data +We start by downloading environmental data. We use the [Rasters](www.github.com/rafaqz/Rasters.jl) package to handle raster data, and RasterDataSources.jl to automatically download Worldclim data. + +In this example, we just download bioclimatic variables 1 and 12 (annual mean temperature and annual mean precipitation). We then mask to the country borders of Australia. + ```@example test using Rasters, RasterDataSources, ArchGDAL, NaturalEarth, DataFrames bio = RasterStack(WorldClim{BioClim}, (1,12)) @@ -19,21 +23,30 @@ australia = subset(countries, :NAME => ByRow(==("Australia"))).geometry bio_aus = Rasters.trim(mask(bio; with = australia)[X = 110 .. 156, Y = -45 .. -10]) ``` -## Environmental data +Let's plot this data to see what it looks like. + ```@example test using CairoMakie Rasters.rplot(bio_aus) ``` ## Occurrence data +Next, we use [GBIF2.jl](www.github.com/rafaqz/GBIF2.jl) to download occurrence records for this species. We use the [thin](@ref) function in this package to weed out occurrences that are very close to each other, using a cut-off of 5km. + ```@example test using GBIF2, SpeciesDistributionModels sp = species_match("Eucalyptus regnans") occurrences_raw = occurrence_search(sp; year = (1970,2000), country = "AU", hasCoordinate = true, limit = 2000) occurrences = thin(occurrences_raw.geometry, 5000) - ``` + ## Background points +Next, we sample random points to use as background points. + +From Rasters 0.12.1 on, this will be easier with Rasters.sample! + +Let's plot both the occurrence and background points to see where _Eucalyptus regnans_ is found. + ```@example test using StatsBase bg_indices = sample(findall(boolmask(bio_aus)), 500) @@ -45,6 +58,8 @@ fig ``` ## Handling data +SpeciesDistributionModels.jl has a [sdmdata](@ref) function to handle input data. It takes tabular presence and background data as inputs, such as what is returned by `Rasters.extract` and `Rasters.sample`. + ```@example test using SpeciesDistributionModels p_data = extract(bio_aus, occurrences; skipmissing = true) @@ -53,6 +68,8 @@ data = sdmdata(p_data, bg_data; resampler = CV(nfolds = 3)) ``` ## Fitting an ensemble +Now that we have our `data` object with presence and background data, we can fit our ensemble. The `sdm` function fits a whole ensemble, taking two arguments: a data object and a `NamedTuple` with models the ensemble should have. This can be any MLJ-compatible model. In this case, we use Maxnet, boosted regression trees (from the EvoTrees.jl package), and a GLM. + ```@example test using Maxnet: MaxnetBinaryClassifier using EvoTrees: EvoTreeClassifier @@ -67,19 +84,30 @@ ensemble = sdm(data, models) ``` ## Evaluating an ensemble +We can evaluate the entire ensemble using any metric from [StatisticalMeasures.jl](https://github.com/JuliaAI/StatisticalMeasures.jl). + ```@example test import SpeciesDistributionModels as SDM ev = SDM.evaluate(ensemble; measures = (; auc, accuracy)) ``` ## Predicting +Next, we the climatic suitability of the species throughout Australia using `SpeciesDistributionModels.predict`. We can specify a `reducer` argument to get a single value, instead of a prediction for each member in the ensemble. + ```@example test pred = SDM.predict(ensemble, bio_aus; reducer = mean) plot(pred; colorrange = (0,1)) ``` ## Understanding the model +[SDM.explain](@ref) offers tools to estimate the contribution and response curves for each variable. Currently, the only implemented method is Shapley values from the [Shapley.jl](www.gitlab.com/ExpandingMan/Shapley.jl) package. + ```@example test expl = SDM.explain(ensemble; method = ShapleyValues(8)) +variable_importance(expl) +``` + +We can also interactively plot the model explanation to get response curves. +```@example test interactive_response_curves(expl) ``` \ No newline at end of file From b4cfd5eef37afddd0a91ed7ad3b0d2b081ccb99a Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Mon, 21 Oct 2024 13:42:58 +0200 Subject: [PATCH 09/15] fix Rasters compat --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 71fe333..9e19cf1 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,7 @@ SpeciesDistributionModelsMakieExt = "Makie" CategoricalDistributions = "0.1.14" Distances = "0.10" MLJGLMInterface = "0.3.7" -Rasters = "0.10.1-0.12" +Rasters = "0.10.1, 0.11-0.12" StatisticalMeasures = "0.1.5" StatsModels = "0.7.3" julia = "1.9" From e1bdd228b0c224cf91d0b15b60315896ce9c0179 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Mon, 21 Oct 2024 13:46:37 +0200 Subject: [PATCH 10/15] fix Rasters compat for real --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9e19cf1..e4318b6 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,7 @@ SpeciesDistributionModelsMakieExt = "Makie" CategoricalDistributions = "0.1.14" Distances = "0.10" MLJGLMInterface = "0.3.7" -Rasters = "0.10.1, 0.11-0.12" +Rasters = "0.10.1, 0.11, 0.12" StatisticalMeasures = "0.1.5" StatsModels = "0.7.3" julia = "1.9" From 01d028722e2750f77ee3acdab69b9e1d77ed4df8 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Tue, 22 Oct 2024 14:51:13 +0200 Subject: [PATCH 11/15] make thin type stable --- src/thin.jl | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/thin.jl b/src/thin.jl index 9068276..cbfd7ce 100644 --- a/src/thin.jl +++ b/src/thin.jl @@ -48,26 +48,30 @@ end function _thin(rng::Random.AbstractRNG, geoms::AbstractVector, cutoff::Real, distance::Distances.Metric) dist_matrix = Distances.pairwise(distance, geoms) - dist_mask = dist_matrix .< cutoff dist_sum = vec(sum(dist_mask; dims = 1)) - s = size(dist_sum, 1) - - indices = collect(1:s) + l = length(dist_sum) + keep_mask = trues(l) - for i in 1:s - m = maximum(dist_sum) + for _ in 1:l + m = 1 + for i in 1:l + if keep_mask[i] + m = max(m, dist_sum[i]) + end + end if m == 1 break else drop = rand(rng, findall(dist_sum .== m)) - dist_sum .-= @view dist_mask[drop, :] - drop_indices = 1:s .!= drop - dist_mask = @view dist_mask[drop_indices, drop_indices] - dist_sum = @view dist_sum[drop_indices] - s -= 1 - indices = @view indices[drop_indices] + keep_mask[drop] = false + for j in 1:l + if keep_mask[j] && dist_mask[j, drop] + dist_sum[j] -= 1 + end + end end end - return indices + + return keep_mask end From 3acaa8e8570db8de6a711fb4a706e83f27c8c6ed Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Tue, 22 Oct 2024 16:32:58 +0200 Subject: [PATCH 12/15] specify rasterdatasources_path in ci.yml --- .github/workflows/CI.yml | 1 + docs/src/example.md | 9 --------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3013acd..1010a68 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -58,6 +58,7 @@ jobs: - uses: julia-actions/julia-docdeploy@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RASTERDATASOURCES_PATH: "." - name: Run doctests shell: julia --project=docs --color=yes {0} run: | diff --git a/docs/src/example.md b/docs/src/example.md index aea9cc8..0d3986d 100644 --- a/docs/src/example.md +++ b/docs/src/example.md @@ -1,15 +1,6 @@ # Example of a full species distribution modelling workflow This example fits and projects species distribution models for the tree species _Eucaplytus regnans_ from scratch. -```@example test -#| echo: false -if !haskey(ENV, "RASTERDATASOURCES_PATH") - ENV["RASTERDATASOURCES_PATH"] = "."; -end -using CairoMakie -CairoMakie.activate!(type = "png") -``` - ## Environmental data We start by downloading environmental data. We use the [Rasters](www.github.com/rafaqz/Rasters.jl) package to handle raster data, and RasterDataSources.jl to automatically download Worldclim data. From 70a33c22186a9411a93e1514709a4c20b4e10945 Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Thu, 21 Nov 2024 17:32:09 +0100 Subject: [PATCH 13/15] add some more documentation --- docs/src/.vitepress/config.mts | 15 +++++++++++- .../src/{example.md => eucalyptus_regnans.md} | 0 docs/src/getting_started.md | 24 +++++++++++++++++++ docs/src/index.md | 13 +++++++--- 4 files changed, 48 insertions(+), 4 deletions(-) rename docs/src/{example.md => eucalyptus_regnans.md} (100%) create mode 100644 docs/src/getting_started.md diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts index 5abf5aa..e7e002f 100644 --- a/docs/src/.vitepress/config.mts +++ b/docs/src/.vitepress/config.mts @@ -35,8 +35,21 @@ export default defineConfig({ } }, nav: [ - { text: 'Example', link: '/example' }, + { text: 'Getting started', link: '/getting_started' }, + { text: 'Examples', items: + [ + text: 'Distribution of Eucalyptus regnans', link: '/eucalyptus_regnans' + ] + }, { text: 'API', link: '/api' }, + { text: 'Ecosystem', + items: [ + { text: 'Rasters.jl', link: 'https://rafaqz.github.io/Rasters.jl/dev/' }, + { text: 'MLJ.jl', link: 'https://juliaai.github.io/MLJ.jl/dev/' }, + { text: 'GBIF2.jl', link: 'https://rafaqz.github.io/GBIF2.jl/dev/' }, + { text: 'HDF5.jl', link: 'https://juliaio.github.io/HDF5.jl/stable/'}, + ] + }, ], editLink: 'REPLACE_ME_DOCUMENTER_VITEPRESS', socialLinks: [ diff --git a/docs/src/example.md b/docs/src/eucalyptus_regnans.md similarity index 100% rename from docs/src/example.md rename to docs/src/eucalyptus_regnans.md diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md new file mode 100644 index 0000000..6601e7e --- /dev/null +++ b/docs/src/getting_started.md @@ -0,0 +1,24 @@ +# Getting started with SpeciesDistributionModels.jl +This package is under active development. Be advised that it may change at any time. + +## Installation +This package is not registered yet, but can easily be installed directly from GitHub. +```julia +] add github.com/tiemvanderdeure/SpeciesDistributionModels.jl +``` + +## Core functionality +A species distribution modelling workflow would typically consist of some data handling, then fitting a model, then evaluating it, and finally projecting to spatial data. + +In this package, the main data handling tool is the [sdmdata](@ref) function, which takes two Tables.jl-compatible data objects (e.g. DataFrames) as input and returns an `SDMdata` object. You can also specify a resampling strategy or select a subset of variables in this step. + +Next, this object and a `NamedTuple` of models is passed to the [sdm](@ref) function to fit the models. The models can be any object that implements the MLJ interface and is compatible with binary categorical data. See the [MLJ model registry](https://juliaai.github.io/MLJ.jl/dev/model_browser/#Classification) for a list of available models. + +A fit ensemble can then be passed to functions like `SDM.evaluate` and `SDM.predict`. + +## Types +Most types in this package are named acoording to the same nested structure with three levels; machine, group, and ensemble. This does for fitted models ([SDMmachine](@ref), [SDMgroup](@ref), and [SDMensemble](@ref)), evaluations of those models ([SDMmachineEvaluation](@ref) etc.), and mdoel explanations ([SDMmachineExplanation](@ref) etc.). The meaning of machine, group, and ensemble in this package is as follows: +- machine: a single instance of one particular model fit using one particular set of data. +- group: one or more machines, which are instances of the same model, but may be fit on different sets of data (e.g. resampling folds) +- ensemble: one or more groups, which each use different models. + diff --git a/docs/src/index.md b/docs/src/index.md index 6ba202a..459f282 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -8,9 +8,16 @@ layout: home Documentation for [SpeciesDistributionModels](https://github.com/tiemvanderdeure/SpeciesDistributionModels.jl). +This package is under active development. Be advised that it may change at any time. ## Installation - -````julia +This package is not registered yet, but can easily be installed directly from GitHub. +```julia ] add github.com/tiemvanderdeure/SpeciesDistributionModels.jl -```` +``` + +## About this package +The goal of `SpeciesDistributionModels.jl` is to combine the convenience of species distribution modelling packages in R with the speed and intuitive syntax of Julia. + +This package allows you to fit, evaluate, and project ensemble SDMs with just a few commands. It relies on [Rasters.jl](https://github.com/rafaqz/Rasters.jl/) and the [MLJ](https://github.com/juliaai/mlj.jl) ecosystem, bringing together Julia's geospatial and machine learning ecosystems. + From e7174b60f07196fe2e97cc043f84a1c1ace0d45a Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 22 Nov 2024 10:28:35 +0100 Subject: [PATCH 14/15] drop pages from make.jl --- docs/make.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index a6ac79f..8f86f36 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -10,12 +10,7 @@ makedocs(; devurl = "dev", devbranch = "master", ), - warnonly = true, - pages = [ - "Home" => "index.md", - "Getting started" => "example.md", - "API" => "api.md" - ] + warnonly = true ) deploydocs(; From 09e8c18650ef076454127dfe8740aa22d90b019b Mon Sep 17 00:00:00 2001 From: tiemvanderdeure Date: Fri, 22 Nov 2024 10:57:02 +0100 Subject: [PATCH 15/15] config fix --- docs/src/.vitepress/config.mts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts index e7e002f..02185a2 100644 --- a/docs/src/.vitepress/config.mts +++ b/docs/src/.vitepress/config.mts @@ -38,7 +38,7 @@ export default defineConfig({ { text: 'Getting started', link: '/getting_started' }, { text: 'Examples', items: [ - text: 'Distribution of Eucalyptus regnans', link: '/eucalyptus_regnans' + { text: 'Distribution of Eucalyptus regnans', link: '/eucalyptus_regnans' }, ] }, { text: 'API', link: '/api' }, @@ -47,7 +47,7 @@ export default defineConfig({ { text: 'Rasters.jl', link: 'https://rafaqz.github.io/Rasters.jl/dev/' }, { text: 'MLJ.jl', link: 'https://juliaai.github.io/MLJ.jl/dev/' }, { text: 'GBIF2.jl', link: 'https://rafaqz.github.io/GBIF2.jl/dev/' }, - { text: 'HDF5.jl', link: 'https://juliaio.github.io/HDF5.jl/stable/'}, + { text: 'RasterDataSources.jl', link: 'http://docs.ecojulia.org/RasterDataSources.jl/dev/' }, ] }, ],