diff --git a/stable b/stable
index 1d95f3f..8f3f5f0 120000
--- a/stable
+++ b/stable
@@ -1 +1 @@
-v0.71.2
\ No newline at end of file
+v0.71.3
\ No newline at end of file
diff --git a/v0.71 b/v0.71
index 1d95f3f..8f3f5f0 120000
--- a/v0.71
+++ b/v0.71
@@ -1 +1 @@
-v0.71.2
\ No newline at end of file
+v0.71.3
\ No newline at end of file
diff --git a/v0.71.3/.documenter-siteinfo.json b/v0.71.3/.documenter-siteinfo.json
new file mode 100644
index 0000000..5effc96
--- /dev/null
+++ b/v0.71.3/.documenter-siteinfo.json
@@ -0,0 +1 @@
+{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-14T17:17:24","documenter_version":"1.8.0"}}
\ No newline at end of file
diff --git a/v0.71.3/about/citing/index.html b/v0.71.3/about/citing/index.html
new file mode 100644
index 0000000..625db91
--- /dev/null
+++ b/v0.71.3/about/citing/index.html
@@ -0,0 +1,15 @@
+
+
We use the Zulip platform to chat and help the community of users. Consider creating an account and pressing ? on the keyboard there for navigation instructions.
Click on the image to join the channel:
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
The GeoStats.jl project is licensed under the MIT license:
MIT License
+
+Copyright (c) 2015 Júlio Hoffimann <julio.hoffimann@gmail.com> and contributors
+
+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.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
diff --git a/v0.71.3/assets/documenter.js b/v0.71.3/assets/documenter.js
new file mode 100644
index 0000000..0ccf6c8
--- /dev/null
+++ b/v0.71.3/assets/documenter.js
@@ -0,0 +1,1096 @@
+// Generated by Documenter.jl
+requirejs.config({
+ paths: {
+ 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min',
+ 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min',
+ 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min',
+ 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min',
+ 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min',
+ 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min',
+ 'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min',
+ 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min',
+ 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min',
+ },
+ shim: {
+ "highlight-julia": {
+ "deps": [
+ "highlight"
+ ]
+ },
+ "katex-auto-render": {
+ "deps": [
+ "katex"
+ ]
+ },
+ "headroom-jquery": {
+ "deps": [
+ "jquery",
+ "headroom"
+ ]
+ },
+ "highlight-julia-repl": {
+ "deps": [
+ "highlight"
+ ]
+ }
+}
+});
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) {
+$(document).ready(function() {
+ renderMathInElement(
+ document.body,
+ {
+ "delimiters": [
+ {
+ "left": "$",
+ "right": "$",
+ "display": false
+ },
+ {
+ "left": "$$",
+ "right": "$$",
+ "display": true
+ },
+ {
+ "left": "\\[",
+ "right": "\\]",
+ "display": true
+ }
+ ],
+ "macros": {
+ "\\1": "\\mathbb{1}",
+ "\\x": "\\boldsymbol{x}",
+ "\\z": "\\boldsymbol{z}",
+ "\\R": "\\mathbb{R}",
+ "\\g": "\\boldsymbol{g}",
+ "\\cov": "\\text{cov}",
+ "\\l": "\\boldsymbol{\\lambda}",
+ "\\f": "\\boldsymbol{f}",
+ "\\F": "\\boldsymbol{F}",
+ "\\C": "\\boldsymbol{C}",
+ "\\c": "\\boldsymbol{c}",
+ "\\G": "\\boldsymbol{G}"
+ }
+}
+
+ );
+})
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) {
+$(document).ready(function() {
+ hljs.highlightAll();
+})
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery'], function($) {
+
+let timer = 0;
+var isExpanded = true;
+
+$(document).on(
+ "click",
+ ".docstring .docstring-article-toggle-button",
+ function () {
+ let articleToggleTitle = "Expand docstring";
+ const parent = $(this).parent();
+
+ debounce(() => {
+ if (parent.siblings("section").is(":visible")) {
+ parent
+ .find("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-down")
+ .addClass("fa-chevron-right");
+ } else {
+ parent
+ .find("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-right")
+ .addClass("fa-chevron-down");
+
+ articleToggleTitle = "Collapse docstring";
+ }
+
+ parent
+ .children(".docstring-article-toggle-button")
+ .prop("title", articleToggleTitle);
+ parent.siblings("section").slideToggle();
+ });
+ }
+);
+
+$(document).on("click", ".docs-article-toggle-button", function (event) {
+ let articleToggleTitle = "Expand docstring";
+ let navArticleToggleTitle = "Expand all docstrings";
+ let animationSpeed = event.noToggleAnimation ? 0 : 400;
+
+ debounce(() => {
+ if (isExpanded) {
+ $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down");
+ $("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-down")
+ .addClass("fa-chevron-right");
+
+ isExpanded = false;
+
+ $(".docstring section").slideUp(animationSpeed);
+ } else {
+ $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up");
+ $("a.docstring-article-toggle-button")
+ .removeClass("fa-chevron-right")
+ .addClass("fa-chevron-down");
+
+ isExpanded = true;
+ articleToggleTitle = "Collapse docstring";
+ navArticleToggleTitle = "Collapse all docstrings";
+
+ $(".docstring section").slideDown(animationSpeed);
+ }
+
+ $(this).prop("title", navArticleToggleTitle);
+ $(".docstring-article-toggle-button").prop("title", articleToggleTitle);
+ });
+});
+
+function debounce(callback, timeout = 300) {
+ if (Date.now() - timer > timeout) {
+ callback();
+ }
+
+ clearTimeout(timer);
+
+ timer = Date.now();
+}
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require([], function() {
+function addCopyButtonCallbacks() {
+ for (const el of document.getElementsByTagName("pre")) {
+ const button = document.createElement("button");
+ button.classList.add("copy-button", "fa-solid", "fa-copy");
+ button.setAttribute("aria-label", "Copy this code block");
+ button.setAttribute("title", "Copy");
+
+ el.appendChild(button);
+
+ const success = function () {
+ button.classList.add("success", "fa-check");
+ button.classList.remove("fa-copy");
+ };
+
+ const failure = function () {
+ button.classList.add("error", "fa-xmark");
+ button.classList.remove("fa-copy");
+ };
+
+ button.addEventListener("click", function () {
+ copyToClipboard(el.innerText).then(success, failure);
+
+ setTimeout(function () {
+ button.classList.add("fa-copy");
+ button.classList.remove("success", "fa-check", "fa-xmark");
+ }, 5000);
+ });
+ }
+}
+
+function copyToClipboard(text) {
+ // clipboard API is only available in secure contexts
+ if (window.navigator && window.navigator.clipboard) {
+ return window.navigator.clipboard.writeText(text);
+ } else {
+ return new Promise(function (resolve, reject) {
+ try {
+ const el = document.createElement("textarea");
+ el.textContent = text;
+ el.style.position = "fixed";
+ el.style.opacity = 0;
+ document.body.appendChild(el);
+ el.select();
+ document.execCommand("copy");
+
+ resolve();
+ } catch (err) {
+ reject(err);
+ } finally {
+ document.body.removeChild(el);
+ }
+ });
+ }
+}
+
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks);
+} else {
+ addCopyButtonCallbacks();
+}
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) {
+
+// Manages the top navigation bar (hides it when the user starts scrolling down on the
+// mobile).
+window.Headroom = Headroom; // work around buggy module loading?
+$(document).ready(function () {
+ $("#documenter .docs-navbar").headroom({
+ tolerance: { up: 10, down: 10 },
+ });
+});
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery'], function($) {
+
+$(document).ready(function () {
+ let meta = $("div[data-docstringscollapsed]").data();
+
+ if (meta?.docstringscollapsed) {
+ $("#documenter-article-toggle-button").trigger({
+ type: "click",
+ noToggleAnimation: true,
+ });
+ }
+});
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery'], function($) {
+
+/*
+To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc
+
+PSEUDOCODE:
+
+Searching happens automatically as the user types or adjusts the selected filters.
+To preserve responsiveness, as much as possible of the slow parts of the search are done
+in a web worker. Searching and result generation are done in the worker, and filtering and
+DOM updates are done in the main thread. The filters are in the main thread as they should
+be very quick to apply. This lets filters be changed without re-searching with minisearch
+(which is possible even if filtering is on the worker thread) and also lets filters be
+changed _while_ the worker is searching and without message passing (neither of which are
+possible if filtering is on the worker thread)
+
+SEARCH WORKER:
+
+Import minisearch
+
+Build index
+
+On message from main thread
+ run search
+ find the first 200 unique results from each category, and compute their divs for display
+ note that this is necessary and sufficient information for the main thread to find the
+ first 200 unique results from any given filter set
+ post results to main thread
+
+MAIN:
+
+Launch worker
+
+Declare nonconstant globals (worker_is_running, last_search_text, unfiltered_results)
+
+On text update
+ if worker is not running, launch_search()
+
+launch_search
+ set worker_is_running to true, set last_search_text to the search text
+ post the search query to worker
+
+on message from worker
+ if last_search_text is not the same as the text in the search field,
+ the latest search result is not reflective of the latest search query, so update again
+ launch_search()
+ otherwise
+ set worker_is_running to false
+
+ regardless, display the new search results to the user
+ save the unfiltered_results as a global
+ update_search()
+
+on filter click
+ adjust the filter selection
+ update_search()
+
+update_search
+ apply search filters by looping through the unfiltered_results and finding the first 200
+ unique results that match the filters
+
+ Update the DOM
+*/
+
+/////// SEARCH WORKER ///////
+
+function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
+ importScripts(
+ "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js"
+ );
+
+ let data = documenterSearchIndex.map((x, key) => {
+ x["id"] = key; // minisearch requires a unique for each object
+ return x;
+ });
+
+ // list below is the lunr 2.1.3 list minus the intersect with names(Base)
+ // (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with)
+ // ideally we'd just filter the original list but it's not available as a variable
+ const stopWords = new Set([
+ "a",
+ "able",
+ "about",
+ "across",
+ "after",
+ "almost",
+ "also",
+ "am",
+ "among",
+ "an",
+ "and",
+ "are",
+ "as",
+ "at",
+ "be",
+ "because",
+ "been",
+ "but",
+ "by",
+ "can",
+ "cannot",
+ "could",
+ "dear",
+ "did",
+ "does",
+ "either",
+ "ever",
+ "every",
+ "from",
+ "got",
+ "had",
+ "has",
+ "have",
+ "he",
+ "her",
+ "hers",
+ "him",
+ "his",
+ "how",
+ "however",
+ "i",
+ "if",
+ "into",
+ "it",
+ "its",
+ "just",
+ "least",
+ "like",
+ "likely",
+ "may",
+ "me",
+ "might",
+ "most",
+ "must",
+ "my",
+ "neither",
+ "no",
+ "nor",
+ "not",
+ "of",
+ "off",
+ "often",
+ "on",
+ "or",
+ "other",
+ "our",
+ "own",
+ "rather",
+ "said",
+ "say",
+ "says",
+ "she",
+ "should",
+ "since",
+ "so",
+ "some",
+ "than",
+ "that",
+ "the",
+ "their",
+ "them",
+ "then",
+ "there",
+ "these",
+ "they",
+ "this",
+ "tis",
+ "to",
+ "too",
+ "twas",
+ "us",
+ "wants",
+ "was",
+ "we",
+ "were",
+ "what",
+ "when",
+ "who",
+ "whom",
+ "why",
+ "will",
+ "would",
+ "yet",
+ "you",
+ "your",
+ ]);
+
+ let index = new MiniSearch({
+ fields: ["title", "text"], // fields to index for full-text search
+ storeFields: ["location", "title", "text", "category", "page"], // fields to return with results
+ processTerm: (term) => {
+ let word = stopWords.has(term) ? null : term;
+ if (word) {
+ // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names
+ word = word
+ .replace(/^[^a-zA-Z0-9@!]+/, "")
+ .replace(/[^a-zA-Z0-9@!]+$/, "");
+
+ word = word.toLowerCase();
+ }
+
+ return word ?? null;
+ },
+ // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not
+ // find anything if searching for "add!", only for the entire qualification
+ tokenize: (string) => string.split(/[\s\-\.]+/),
+ // options which will be applied during the search
+ searchOptions: {
+ prefix: true,
+ boost: { title: 100 },
+ fuzzy: 2,
+ },
+ });
+
+ index.addAll(data);
+
+ /**
+ * Used to map characters to HTML entities.
+ * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts
+ */
+ const htmlEscapes = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ '"': """,
+ "'": "'",
+ };
+
+ /**
+ * Used to match HTML entities and HTML characters.
+ * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts
+ */
+ const reUnescapedHtml = /[&<>"']/g;
+ const reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+ /**
+ * Escape function from lodash
+ * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts
+ */
+ function escape(string) {
+ return string && reHasUnescapedHtml.test(string)
+ ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr])
+ : string || "";
+ }
+
+ /**
+ * RegX escape function from MDN
+ * Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
+ */
+ function escapeRegExp(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
+ }
+
+ /**
+ * Make the result component given a minisearch result data object and the value
+ * of the search input as queryString. To view the result object structure, refer:
+ * https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult
+ *
+ * @param {object} result
+ * @param {string} querystring
+ * @returns string
+ */
+ function make_search_result(result, querystring) {
+ let search_divider = ``;
+ let display_link =
+ result.location.slice(Math.max(0), Math.min(50, result.location.length)) +
+ (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div
+
+ if (result.page !== "") {
+ display_link += ` (${result.page})`;
+ }
+ searchstring = escapeRegExp(querystring);
+ let textindex = new RegExp(`${searchstring}`, "i").exec(result.text);
+ let text =
+ textindex !== null
+ ? result.text.slice(
+ Math.max(textindex.index - 100, 0),
+ Math.min(
+ textindex.index + querystring.length + 100,
+ result.text.length
+ )
+ )
+ : ""; // cut-off text before and after from the match
+
+ text = text.length ? escape(text) : "";
+
+ let display_result = text.length
+ ? "..." +
+ text.replace(
+ new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence
+ '$&'
+ ) +
+ "..."
+ : ""; // highlights the match
+
+ let in_code = false;
+ if (!["page", "section"].includes(result.category.toLowerCase())) {
+ in_code = true;
+ }
+
+ // We encode the full url to escape some special characters which can lead to broken links
+ let result_div = `
+
+
`;
+ }
+}
+
+function waitUntilSearchIndexAvailable() {
+ // It is possible that the documenter.js script runs before the page
+ // has finished loading and documenterSearchIndex gets defined.
+ // So we need to wait until the search index actually loads before setting
+ // up all the search-related stuff.
+ if (typeof documenterSearchIndex !== "undefined") {
+ runSearchMainCode();
+ } else {
+ console.warn("Search Index not available, waiting");
+ setTimeout(waitUntilSearchIndexAvailable, 1000);
+ }
+}
+
+// The actual entry point to the search code
+waitUntilSearchIndexAvailable();
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery'], function($) {
+
+// Modal settings dialog
+$(document).ready(function () {
+ var settings = $("#documenter-settings");
+ $("#documenter-settings-button").click(function () {
+ settings.toggleClass("is-active");
+ });
+ // Close the dialog if X is clicked
+ $("#documenter-settings button.delete").click(function () {
+ settings.removeClass("is-active");
+ });
+ // Close dialog if ESC is pressed
+ $(document).keyup(function (e) {
+ if (e.keyCode == 27) settings.removeClass("is-active");
+ });
+});
+
+})
+////////////////////////////////////////////////////////////////////////////////
+require(['jquery'], function($) {
+
+$(document).ready(function () {
+ let search_modal_header = `
+
+
First off, thank you for considering contributing to GeoStats.jl. It’s people like you that make this project so much fun. Below are a few suggestions to speed up the collaboration process:
Please be polite, we are here to help and learn from each other.
Try to explain your contribution with simple language.
References to textbooks and papers are always welcome.
Contributing to an open-source project for the very first time can be a very daunting task. To make the process easier and more GitHub-beginner-friendly, the community has written an article about how to start contributing to open-source and overcome the mental and technical barriers that come associated with it. The article will also take you through the steps required to make your first contribution in detail.
If you are experiencing issues or have discovered a bug, please report it on GitHub. To make the resolution process easier, please include the version of Julia and GeoStats.jl in your writeup. These can be found with two commands:
julia> versioninfo()
+julia> using Pkg; Pkg.status()
If you have suggestions of improvement or algorithms that you would like to see implemented, please open an issue on GitHub. Suggestions as well as feature requests are very welcome.
If you have code that you would like to contribute that is awesome! Please open an issue or reach out in our community channel before you create the pull request on GitHub so that we make sure your idea is aligned with the project goals.
After your idea is revised by project maintainers, you implement it online on Github or offline on your machine.
If the changes to the code are minimal, we recommend pressing . on the keyboard on any file in the GitHub repository of interest. This will open the VSCode editor on the web browser where you can implement the changes, commit them and submit a pull request.
If the changes require additional investigation and tests, please get the development version of the project by typing the following in the package manager:
] activate @geo
This will create a fresh environment called @geo where you can edit the project modules without effects on your global user environment. Next, go ahead and ask the package manager to develop the package of interest (e.g. GeoStatsFunctions.jl):
] dev GeoStatsFunctions
You can modify the source code that was cloned in the .julia/dev folder and submit a pull request on GitHub later.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
Given a table or array containing data, we can georeference these objects onto a geospatial domain with the georef function. The result of the georef function is a GeoTable. If you would like to learn this concept in more depth, check out the recording of our JuliaEO 2024 workshop:
Georeference table using coordinates coords of points.
Optionally, specify the coordinate reference system crs, which is set by default based on heuristics, and the lenunit (default to meters for unitless values) that can only be used in CRS types that allow this flexibility. Any CRS or EPSG/ESRI code from CoordRefSystems.jl is supported.
Georeference table using coordinates of points stored in column names.
Optionally, specify the coordinate reference system crs, which is set by default based on heuristics, and the lenunit (default to meters for unitless values) that can only be used in CRS types that allow this flexibility. Any CRS or EPSG/ESRI code from CoordRefSystems.jl is supported.
using GeoStats
+import CairoMakie as Mke
+
+# helper function for plotting two
+# variables named T and P side by side
+function plot(data)
+ fig = Mke.Figure(size = (800, 400))
+ viz(fig[1,1], data.geometry, color = data.T)
+ viz(fig[1,2], data.geometry, color = data.P)
+ fig
+end
Consider a table (e.g. DataFrame) with 25 samples of temperature T and pressure P:
using DataFrames
+
+table = DataFrame(T=rand(25), P=rand(25))
25×2 DataFrame
Row
T
P
Float64
Float64
1
0.477446
0.852434
2
0.944738
0.81652
3
0.704505
0.732916
4
0.936233
0.0320072
5
0.653428
0.393943
6
0.879168
0.694933
7
0.759295
0.601801
8
0.421052
0.155567
9
0.244843
0.782078
10
0.405972
0.767578
11
0.364723
0.750821
12
0.772122
0.362319
13
0.11324
0.625441
14
0.974632
0.373023
15
0.889477
0.15257
16
0.0433758
0.00187064
17
0.938691
0.205616
18
0.345166
0.800411
19
0.401956
0.286133
20
0.150285
0.880893
21
0.0752978
0.780687
22
0.23104
0.541633
23
0.545222
0.338354
24
0.663735
0.621553
25
0.698587
0.608446
We can georeference this table based on a given set of points:
georef(table, rand(Point, 25)) |> plot
or alternatively, georeference it on a 5x5 regular grid (5x5 = 25 samples):
georef(table, CartesianGrid(5, 5)) |> plot
Another common pattern in geospatial data is when the coordinates of the samples are already part of the table as columns. In this case, we can specify the column names:
Consider arrays (e.g. images) with data for various geospatial variables. We can georeference these arrays using a named tuple, and the framework will understand that the shape of the arrays should be preserved in a CartesianGrid:
Load geospatial table from file fname stored in any format.
Various repairs are performed on the stored geometries by default, including fixes of orientation in rings of polygons, removal of zero-area triangles, etc.
Some of the repairs can be expensive on large data sets. In that case, we recommend setting repair=false. Custom repairs can be performed with the Repair transform from Meshes.jl.
Optionally, specify the layer to read within the file, and the length unit lenunit of the coordinates when the format does not include units in its specification. Other kwargs are forwarded to the backend packages.
Please use the formats function to list all supported file formats.
Options
OFF
defaultcolor: default color of the geometries if the file does not have this data (default to RGBA(0.666, 0.666, 0.666, 0.666));
CSV
coords: names of the columns with point coordinates (required option);
Other options are passed to CSV.File, see the CSV.jl documentation for more details;
VTK formats (.vtu, .vtp, .vtr, .vts, .vti)
mask: name of the boolean column that encodes the indices of a grid view (default to :MASK). If the column does not exist in the file, the full grid is returned;
Common Data Model formats (NetCDF, GRIB)
x: name of the column with x coordinates (default to "x", "X", "lon", or "longitude");
y: name of the column with y coordinates (default to "y", "Y", "lat", or "latitude");
z: name of the column with z coordinates (default to "z", "Z", "depth", or "height");
t: name of the column with time measurements (default to "t", "time", or "TIME");
GeoJSON
numbertype: number type of geometry coordinates (default to Float64)
Other options are passed to GeoJSON.read, see the GeoJSON.jl documentation for more details;
GSLIB
Other options are passed to GslibIO.load, see the GslibIO.jl documentation for more details;
Shapefile
Other options are passed to Shapefile.read, see the Shapefile.jl documentation for more details;
GeoParquet
Other options are passed to GeoParquet.read, see the GeoParquet.jl documentation for more details;
GeoTIFF, GeoPackage, KML
Other options are passed to ArchGDAL.read, see the ArchGDAL.jl documentation for more details;
Examples
# load coordinates of geojson file as Float64 (default)
+GeoIO.load("file.geojson")
+# load coordinates of geojson file as Float32
+GeoIO.load("file.geojson", numbertype=Float32)
Displays in io (defaults to stdout if io is not given) a table with all formats supported by GeoIO.jl and the packages used to load and save each of them.
Optionally, sort the table by the :extension, :load or :save columns using the sortby argument.
Spatial histogram of variable var in spatial data sdata. Optionally, specify the block side s and the keyword arguments kwargs for the fit(Histogram, ...) call.
A geospatial domain is a (discretized) region in physical space. For example, a collection of rain gauge stations can be represented as a PointSet in the map. Similarly, a collection of states in a given country can be represented as a GeometrySet of polygons.
We provide flexible domain types for advanced geospatial workflows via the Meshes.jl submodule. The domains can consist of sets (or "soups") of geometries as it is most common in GIS or be actual meshes with topological information.
A domain is an indexable collection of geometries (e.g. mesh) in a given manifold M with point coordinates specified in a coordinate reference system CRS.
A mesh of geometries in a given manifold M with point coordinates specified in a coordinate reference system CRS. Unlike a general domain, a mesh has a well-defined topology TP.
Finally, a Cartesian grid can be constructed by only passing the dimensions dims as a tuple, or by passing each dimension dim1, dim2, ... separately. In this case, the origin and spacing default to (0,0,...) and (1,1,...).
CartesianGrid is an alias to RegularGrid with Cartesian CRS.
Examples
Create a 3D grid with 100x100x50 hexahedrons:
julia> CartesianGrid(100, 100, 50)
Create a 2D grid with 100 x 100 quadrangles and origin at (10.0, 20.0):
GeoStats.jl is an extensible framework for geospatial data science and geostatistical modeling fully written in Julia. It is comprised of several modules for advanced geometric processing, state-of-the-art geostatistical algorithms and sophisticated visualization of geospatial data.
In many fields of science, such as mining engineering, hydrogeology, petroleum engineering, and environmental sciences, traditional statistical methods fail to provide unbiased estimates of resources due to the presence of geospatial correlation. Geostatistics (a.k.a. geospatial statistics) is the branch of statistics developed to overcome this limitation. Particularly, it is the branch that takes geospatial coordinates of data into account. Some major highlights of GeoStats.jl are:
It is simple: has a very short learning curve and requires writing minimal code 😌
It is general: supports all types of geospatial domains, including unstructured meshes 👍
It is native: fully written in Julia for maximum flexibility and performance 🚀
Has an extensive library of algorithms from the geostatistics literature 📚
Our JuliaCon2021 talk provides an overview of geostatistical learning, which is one of the many geostatistical problems addressed by the software:
+
+
Consider reading the Geospatial Data Science with Julia book before reading this documentation. If you have questions, or would like to brainstorm ideas, don't hesitate to start a topic in our community channel.
This section describes the Kriging models used in the Interpolate and InterpolateNeighbors transforms, which provide options for neighborhood search, change of support, etc.
with $Z\colon \R^m \times \Omega \to \R$ a random field.
This package implements the following Kriging variants:
Simple Kriging
Ordinary Kriging
Universal Kriging
External Drift Kriging
All these variants follow the same interface: an object is first created with a given set of parameters, it is then combined with the data to obtain predictions at new geometries.
The fit function takes care of building the Kriging system and factorizing the LHS with an appropriate decomposition (e.g. Cholesky, LU), and the predict (or predictprob) function performs the estimation for a given variable and geometry.
All variants work with general Hilbert spaces, meaning that one can interpolate any data type that implements scalar multiplication, vector addition and inner product.
or in matricial form $\C\l = \c$. We subtract the given mean from the observations $\boldsymbol{y} = \z - \mu \1$ and compute the mean and variance at location $\x_0$:
In External Drift Kriging, the mean of the random field is assumed to be a combination of known smooth functions:
\[\mu(\x) = \sum_k \beta_k m_k(\x)\]
Differently than Universal Kriging, the functions $m_k$ are not necessarily polynomials of the geospatial coordinates. In practice, they represent a list of variables that is strongly correlated (and co-located) with the variable being estimated.
External drifts are known to cause numerical instability. Give preference to other Kriging variants if possible.
Joins geotable₁ with geotable₂ using a certain kind of join and predicate function pred that takes two geometries and returns a boolean ((g1, g2) -> g1 ⊆ g2).
Optionally, add a variable value match to join, in addition to geometric match, by passing a single name or list of variable names (strings or symbols) to the on keyword argument. The variable value match use the isequal function.
Whenever two or more matches are encountered, aggregate varᵢ with aggregation function aggᵢ. If no aggregation function is provided for a variable, then the aggregation function will be selected according to the scientific types: mean for continuous and first otherwise.
Kinds
:left - Returns all rows of geotable₁ filling entries with missing when there is no match in geotable₂.
:inner - Returns the subset of rows of geotable₁ that has a match in geotable₂.
Joins geotable with table using the values of the on variables to match rows with a certain kind of join.
on variables can be a single name or list of variable names (strings or symbols). The variable value match use the isequal function.
Whenever two or more matches are encountered, aggregate varᵢ with aggregation function aggᵢ. If no aggregation function is provided for a variable, then the aggregation function will be selected according to the scientific types: mean for continuous and first otherwise.
Kinds
:left - Returns all rows of geotable filling entries with missing when there is no match in table.
:inner - Returns the subset of rows of geotable that has a match in table.
A geostatistical workflow often consists of four steps:
Definition of geospatial data
Manipulation of geospatial data
Geostatistical modeling
Scientific visualization
In this section, we walk through these steps to illustrate some of the features of the project. In the case of geostatistical modeling, we will specifically explore geostatistical learning models. If you prefer learning from video, check out the recording of our JuliaEO 2023 workshop:
+
+
We assume that the following packages are loaded throughout the code examples:
using GeoStats
+import CairoMakie as Mke
The GeoStats.jl package exports the full stack for geospatial data science and geostatistical modeling. The CairoMakie.jl package is one of the possible visualization backends from the Makie.jl project.
If you are new to Julia and have never heard of Makie.jl before, here are a few tips to help you choose between the different backends:
WGLMakie.jl is the preferred backend for interactive visualization on the web browser. It integrates well with Pluto.jl notebooks and other web-based applications.
GLMakie.jl is the preferred backend for interactive high-performance visualization. It leverages native graphical resources and doesn't require a web browser to function.
CairoMakie.jl is the preferred backend for publication-quality static visualization. It requires less computing power and is therefore recommended for those users with modest laptops.
Note
We recommend importing the Makie.jl backend as Mke to avoid polluting the Julia session with names from the visualization stack.
The Julia ecosystem for loading geospatial data is comprised of several low-level packages such as Shapefile.jl and GeoJSON.jl, which define their own very basic geometry types. Instead of requesting users to learn the so called GeoInterface.jl to handle these types, we provide the high-level GeoIO.jl package to load any file with geospatial data into well-tested geometries from the Meshes.jl submodule:
using GeoIO
+
+zone = GeoIO.load("data/zone.shp")
+
4×6 GeoTable over 4 GeometrySet
+
+
+
PERIMETER
+
ACRES
+
MACROZONA
+
Hectares
+
area_m2
+
geometry
+
+
+
Continuous
+
Continuous
+
Categorical
+
Continuous
+
Continuous
+
MultiPolygon
+
+
+
[NoUnits]
+
[NoUnits]
+
[NoUnits]
+
[NoUnits]
+
[NoUnits]
+
🖈 GeodeticLatLon{SAD69}
+
+
+
+
+
5.8508e6
+
3.23145e7
+
Estuario
+
1.30772e7
+
1.30772e11
+
Multi(21×PolyArea)
+
+
+
9.53947e6
+
2.50594e8
+
Fronteiras Antigas
+
1.01412e8
+
1.01412e12
+
Multi(1×PolyArea)
+
+
+
1.01743e7
+
2.75528e8
+
Fronteiras Intermediarias
+
1.11502e8
+
1.11502e12
+
Multi(1×PolyArea)
+
+
+
7.09612e6
+
1.61293e8
+
Fronteiras Novas
+
6.5273e7
+
6.5273e11
+
Multi(2×PolyArea)
+
+
+
+
Various functions are defined over these geometries, for instance:
sum(area, zone.geometry)
2.9037868929915425e12 m^2
sum(perimeter, zone.geometry)
3.2680213406922124e7 m
Please check the Meshes.jl documentation for more details.
Note
We highly recommend using Meshes.jl geometries in geospatial workflows as they were carefully designed to accomodate advanced features of the GeoStats.jl framework. Any other geometry type will likely fail with our geostatistical algorithms and pipelines.
Geospatial data can be derived from other Julia variables. For example, given a Julia array, which is not attached to any coordinate system, we can georeference the array using the georef function:
Z = [10sin(i/10) + 2j for i in 1:50, j in 1:50]
+
+Ω = georef((Z=Z,))
+
2500×2 GeoTable over 50×50 CartesianGrid
+
+
+
Z
+
geometry
+
+
+
Continuous
+
Quadrangle
+
+
+
[NoUnits]
+
🖈 Cartesian{NoDatum}
+
+
+
+
+
2.99833
+
Quadrangle((x: 0.0 m, y: 0.0 m), ..., (x: 0.0 m, y: 1.0 m))
+
+
+
3.98669
+
Quadrangle((x: 1.0 m, y: 0.0 m), ..., (x: 1.0 m, y: 1.0 m))
+
+
+
4.9552
+
Quadrangle((x: 2.0 m, y: 0.0 m), ..., (x: 2.0 m, y: 1.0 m))
+
+
+
5.89418
+
Quadrangle((x: 3.0 m, y: 0.0 m), ..., (x: 3.0 m, y: 1.0 m))
+
+
+
6.79426
+
Quadrangle((x: 4.0 m, y: 0.0 m), ..., (x: 4.0 m, y: 1.0 m))
+
+
+
7.64642
+
Quadrangle((x: 5.0 m, y: 0.0 m), ..., (x: 5.0 m, y: 1.0 m))
+
+
+
8.44218
+
Quadrangle((x: 6.0 m, y: 0.0 m), ..., (x: 6.0 m, y: 1.0 m))
+
+
+
9.17356
+
Quadrangle((x: 7.0 m, y: 0.0 m), ..., (x: 7.0 m, y: 1.0 m))
+
+
+
9.83327
+
Quadrangle((x: 8.0 m, y: 0.0 m), ..., (x: 8.0 m, y: 1.0 m))
+
+
+
10.4147
+
Quadrangle((x: 9.0 m, y: 0.0 m), ..., (x: 9.0 m, y: 1.0 m))
+
+
+
⋮
+
⋮
+
+
+
+
Default coordinates are assigned based on the size of the array, and different configurations can be obtained with different methods (see Data).
Geospatial data can be visualized with the viz recipe function:
viz(Ω.geometry, color = Ω.Z)
Alternatively, we provide a basic scientific viewer to visualize all viewable variables in the data with a colorbar and other interactive elements (see Visualization):
viewer(Ω)
Note
Julia supports unicode symbols with $\LaTeX$ syntax. We can type \Omega and press TAB to get the symbol Ω in the example above. This autocompletion works in various text editors, including the VSCode editor with the Julia extension.
Our geospatial data implements the Tables.jl interface, which means that they can be accessed as if they were tables with samples in the rows and variables in the columns. In this case, a special column named geometry is created on the fly, row by row, containing Meshes.jl geometries.
For those familiar with the productive DataFrames.jl interface, there is nothing new:
Ω[1,:]
(Z = 2.9983341664682817, geometry = Quadrangle((x: 0.0 m, y: 0.0 m), ..., (x: 0.0 m, y: 1.0 m)))
Ω[1,:geometry]
Quadrangle
+├─ Point(x: 0.0 m, y: 0.0 m)
+├─ Point(x: 1.0 m, y: 0.0 m)
+├─ Point(x: 1.0 m, y: 1.0 m)
+└─ Point(x: 0.0 m, y: 1.0 m)
However, notice that our implementation performs some clever optimizations behind the scenes to avoid expensive creation of geometries:
Ω.geometry
50×50 CartesianGrid
+├─ minimum: Point(x: 0.0 m, y: 0.0 m)
+├─ maximum: Point(x: 50.0 m, y: 50.0 m)
+└─ spacing: (1.0 m, 1.0 m)
We can always retrieve the table of attributes (or features) with the function values and the underlying geospatial domain with the function domain. This can be useful for writing algorithms that are type-stable and depend purely on the feature values:
It is easy to design advanced geospatial pipelines that operate on both the table of features and the underlying geospatial domain:
# pipeline with table transforms
+pipe = Quantile() → StdCoords()
+
+# feed geospatial data to pipeline
+Ω̂ = pipe(Ω)
+
+# plot distribution before and after pipeline
+fig = Mke.Figure(size = (800, 400))
+Mke.hist(fig[1,1], Ω.Z, color = :gray)
+Mke.hist(fig[2,1], Ω̂.Z, color = :gray)
+fig
Coordinates before pipeline:
boundingbox(Ω.geometry)
Box
+├─ min: Point(x: 0.0 m, y: 0.0 m)
+└─ max: Point(x: 50.0 m, y: 50.0 m)
and after pipeline:
boundingbox(Ω̂.geometry)
Box
+├─ min: Point(x: -0.5 m, y: -0.5 m)
+└─ max: Point(x: 0.5 m, y: 0.5 m)
These pipelines are revertible meaning that we can transform the data, perform geostatistical modeling, and revert the pipelines to obtain estimates in the original sample space (see Transforms).
We provide three macros @groupby, @transform and @combine for powerful geospatial split-apply-combine patterns, as well as the function geojoin for advanced geospatial joins.
@transform(Ω, :W = 2 * :Z * area(:geometry))
+
2500×3 GeoTable over 50×50 CartesianGrid
+
+
+
Z
+
W
+
geometry
+
+
+
Continuous
+
Continuous
+
Quadrangle
+
+
+
[NoUnits]
+
[m^2]
+
🖈 Cartesian{NoDatum}
+
+
+
+
+
2.99833
+
5.99667 m^2
+
Quadrangle((x: 0.0 m, y: 0.0 m), ..., (x: 0.0 m, y: 1.0 m))
+
+
+
3.98669
+
7.97339 m^2
+
Quadrangle((x: 1.0 m, y: 0.0 m), ..., (x: 1.0 m, y: 1.0 m))
+
+
+
4.9552
+
9.9104 m^2
+
Quadrangle((x: 2.0 m, y: 0.0 m), ..., (x: 2.0 m, y: 1.0 m))
+
+
+
5.89418
+
11.7884 m^2
+
Quadrangle((x: 3.0 m, y: 0.0 m), ..., (x: 3.0 m, y: 1.0 m))
+
+
+
6.79426
+
13.5885 m^2
+
Quadrangle((x: 4.0 m, y: 0.0 m), ..., (x: 4.0 m, y: 1.0 m))
+
+
+
7.64642
+
15.2928 m^2
+
Quadrangle((x: 5.0 m, y: 0.0 m), ..., (x: 5.0 m, y: 1.0 m))
+
+
+
8.44218
+
16.8844 m^2
+
Quadrangle((x: 6.0 m, y: 0.0 m), ..., (x: 6.0 m, y: 1.0 m))
+
+
+
9.17356
+
18.3471 m^2
+
Quadrangle((x: 7.0 m, y: 0.0 m), ..., (x: 7.0 m, y: 1.0 m))
+
+
+
9.83327
+
19.6665 m^2
+
Quadrangle((x: 8.0 m, y: 0.0 m), ..., (x: 8.0 m, y: 1.0 m))
+
+
+
10.4147
+
20.8294 m^2
+
Quadrangle((x: 9.0 m, y: 0.0 m), ..., (x: 9.0 m, y: 1.0 m))
+
+
+
⋮
+
⋮
+
⋮
+
+
+
+
These are very useful for geospatial data science as they hide the complexity of the geometry column. For more information, check the Queries section of the documentation.
Having defined the geospatial data objects, we proceed and define the geostatistical learning model. Let's assume that we have geopatial data with some variable that we want to predict in a supervised learning setting. We load the data from a CSV file, and inspect the available columns:
Columns band1, band2, ..., band4 represent four satellite bands for different locations (x, y) in this region. The column crop has the crop type for each location that was labeled manually with the purpose of fitting a learning model.
We can now georeference the table and plot some of the variables:
Similar to a generic statistical learning workflow, we split the data into "train" and "test" sets. The main difference here is that our geospatial geosplit function accepts a separating plane specified by its normal direction (1,-1):
We can visualize the domain of the "train" (or source) set Ωs in blue, and the domain of the "test" (or target) set Ωt in gray. We reserved 20% of the samples to Ωs and 80% to Ωt. Internally, this geospatial geosplit function is implemented in terms of efficient geospatial partitions.
Let's define our geostatistical learning model to predict the crop type based on the four satellite bands. We will use the DecisionTreeClassifier model, which is suitable for the task we want to perform. Any model from the StatsLeanModels.jl model is supported, including all models from ScikitLearn.jl:
We will fit the model in Ωs where the features and labels are available and predict in Ωt where the features are available. The Learn transform automatically fits the model to the data:
We note that the prediction of a geostatistical learning model is a geospatial data object, and we can inspect it with the same methods already described above. This also means that we can visualize the prediction directly, side by side with the true label in this synthetic example:
fig = Mke.Figure(size = (800, 400))
+viz(fig[1,1], Ω̂t.geometry, color = Ω̂t.crop)
+viz(fig[1,2], Ωt.geometry, color = Ωt.crop)
+fig
With this example we conclude the basic workflow. To get familiar with other features of the project, please check the the reference guide.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
diff --git a/v0.71.3/random/fields/189114f6.png b/v0.71.3/random/fields/189114f6.png
new file mode 100644
index 0000000..c1f8e76
Binary files /dev/null and b/v0.71.3/random/fields/189114f6.png differ
diff --git a/v0.71.3/random/fields/257f8ad7.png b/v0.71.3/random/fields/257f8ad7.png
new file mode 100644
index 0000000..227a65c
Binary files /dev/null and b/v0.71.3/random/fields/257f8ad7.png differ
diff --git a/v0.71.3/random/fields/2daac4fd.png b/v0.71.3/random/fields/2daac4fd.png
new file mode 100644
index 0000000..8f289c7
Binary files /dev/null and b/v0.71.3/random/fields/2daac4fd.png differ
diff --git a/v0.71.3/random/fields/3bee07fe.png b/v0.71.3/random/fields/3bee07fe.png
new file mode 100644
index 0000000..1ce1309
Binary files /dev/null and b/v0.71.3/random/fields/3bee07fe.png differ
diff --git a/v0.71.3/random/fields/44a84295.png b/v0.71.3/random/fields/44a84295.png
new file mode 100644
index 0000000..f9e6984
Binary files /dev/null and b/v0.71.3/random/fields/44a84295.png differ
diff --git a/v0.71.3/random/fields/44c4a155.png b/v0.71.3/random/fields/44c4a155.png
new file mode 100644
index 0000000..575c786
Binary files /dev/null and b/v0.71.3/random/fields/44c4a155.png differ
diff --git a/v0.71.3/random/fields/4bb8a453.png b/v0.71.3/random/fields/4bb8a453.png
new file mode 100644
index 0000000..5a668b3
Binary files /dev/null and b/v0.71.3/random/fields/4bb8a453.png differ
diff --git a/v0.71.3/random/fields/51cbc270.png b/v0.71.3/random/fields/51cbc270.png
new file mode 100644
index 0000000..125ab69
Binary files /dev/null and b/v0.71.3/random/fields/51cbc270.png differ
diff --git a/v0.71.3/random/fields/59598d51.png b/v0.71.3/random/fields/59598d51.png
new file mode 100644
index 0000000..2ed035e
Binary files /dev/null and b/v0.71.3/random/fields/59598d51.png differ
diff --git a/v0.71.3/random/fields/5a2f311d.png b/v0.71.3/random/fields/5a2f311d.png
new file mode 100644
index 0000000..587a771
Binary files /dev/null and b/v0.71.3/random/fields/5a2f311d.png differ
diff --git a/v0.71.3/random/fields/7d34950b.png b/v0.71.3/random/fields/7d34950b.png
new file mode 100644
index 0000000..60ca653
Binary files /dev/null and b/v0.71.3/random/fields/7d34950b.png differ
diff --git a/v0.71.3/random/fields/812d61d9.png b/v0.71.3/random/fields/812d61d9.png
new file mode 100644
index 0000000..fd60523
Binary files /dev/null and b/v0.71.3/random/fields/812d61d9.png differ
diff --git a/v0.71.3/random/fields/ed2a2407.png b/v0.71.3/random/fields/ed2a2407.png
new file mode 100644
index 0000000..4e5dea3
Binary files /dev/null and b/v0.71.3/random/fields/ed2a2407.png differ
diff --git a/v0.71.3/random/fields/index.html b/v0.71.3/random/fields/index.html
new file mode 100644
index 0000000..55af051
--- /dev/null
+++ b/v0.71.3/random/fields/index.html
@@ -0,0 +1,194 @@
+
+Fields · GeoStats.jl
Generate one or nreals realizations of the field process with method over the domain with data and optional paramaters. Optionally, specify the random number generator rng and global parameters.
The data can be a geotable, a pair, or an iterable of pairs of the form var => T, where var is a symbol or string with the variable name and T is the corresponding data type.
Parameters
workers - Worker processes (default to workers())
threads - Number of threads (default to cpucores())
verbose - Show progress and other information (default to true)
async - Return to master process immediately (default to false)
All field processes can generate realizations in parallel using multiple Julia processes. Doing so requires using the Distributed standard library, like in the following example:
using Distributed
+
+# request additional processes
+addprocs(3)
+
+# load code on every single process
+@everywhere using GeoStats
+
+# setup simulation
+grid = CartesianGrid(100, 100)
+proc = GaussianProcess(GaussianVariogram(range=30.0))
+
+# perform simulation on all worker processes
+real = rand(proc, grid, [:Z => Float64], 3, workers = workers())
The LU Gaussian process method introduced by Alabert 1987. The full covariance matrix is built to include all locations of the process domain, and samples from the multivariate Gaussian are drawn via LU factorization.
Parameters
factorization - Factorization method (default to cholesky)
correlation - Correlation coefficient between two covariates (default to 0)
init - Data initialization method (default to NearestInit())
The method is only adequate for domains with relatively small number of elements (e.g. 100x100 grids) where it is feasible to factorize the full covariance.
For larger domains (e.g. 3D grids), other methods are preferred such as SEQMethod and FFTMethod.
The FFT Gaussian process method introduced by Gutjahr 1997. The covariance function is perturbed in the frequency domain after a fast Fourier transform. White noise is added to the phase of the spectrum, and a realization is produced by an inverse Fourier transform.
Parameters
minneighbors - Minimum number of neighbors (default to 1)
maxneighbors - Maximum number of neighbors (default to 10)
neighborhood - Search neighborhood (default to nothing)
distance - Distance used to find nearest neighbors (default to Euclidean())
The method is limited to simulations on Cartesian grids, and care must be taken to make sure that the correlation length is small enough compared to the grid size.
As a general rule of thumb, avoid correlation lengths greater than 1/3 of the grid.
The method is extremely fast, and can be used to generate large 3D realizations.
The sequential process method introduced by Gomez-Hernandez 1993. It traverses all locations of the geospatial domain according to a path, approximates the conditional Gaussian distribution within a neighborhood using simple Kriging, and assigns a value to the center of the neighborhood by sampling from this distribution.
Parameters
path - Process path (default to LinearPath())
minneighbors - Minimum number of neighbors (default to 1)
maxneighbors - Maximum number of neighbors (default to 36)
neighborhood - Search neighborhood (default to :range)
distance - Distance used to find nearest neighbors (default to Euclidean())
init - Data initialization method (default to NearestInit())
For each location in the process path, a maximum number of neighbors maxneighbors is used to fit the conditional Gaussian distribution. The neighbors are searched according to a neighborhood.
The neighborhood can be a MetricBall, the symbol :range or nothing. The symbol :range is converted to MetricBall(range(γ)) where γ is the variogram of the Gaussian process. If neighborhood is nothing, the nearest neighbors are used without additional constraints.
This method is very sensitive to the various parameters. Care must be taken to make sure that enough neighbors are used in the underlying Kriging model.
Lindgren process with given range (correlation length) and sill (total variance) as described in Lindgren 2011. Optionally, specify the data initialization method init.
The process relies relies on a discretization of the Laplace-Beltrami operator on meshes and is adequate for highly curved domains (e.g. surfaces).
Voxels marked with the special symbol NaN are treated as inactive. The algorithm will skip tiles that only contain inactive voxels to save computation and will generate realizations that are consistent with the mask. This is particularly useful with complex 3D models that have large inactive portions.
# domain of interest
+grid = domain(img)
+
+# skip circle at the center
+nx, ny = size(grid)
+r = 100; circle = []
+for i in 1:nx, j in 1:ny
+ if (i-nx÷2)^2 + (j-ny÷2)^2 < r^2
+ push!(circle, CartesianIndex(i, j))
+ end
+end
+
+# quilting process
+proc = QuiltingProcess(img, (62, 62), inactive = circle)
+
+# unconditional simulation
+real = rand(proc, grid, [:facies => Float64], 2)
+
+fig = Mke.Figure(size = (800, 400))
+viz(fig[1,1], real[1].geometry, color = real[1].facies)
+viz(fig[1,2], real[2].geometry, color = real[2].facies)
+fig
It is possible to incorporate auxiliary variables to guide the selection of patterns from the training image.
using ImageFiltering
+
+# image assumed as ground truth (unknown)
+truth = geostatsimage("WalkerLakeTruth")
+
+# training image with similar patterns
+img = geostatsimage("WalkerLake")
+
+# forward model (blur filter)
+function forward(data)
+ img = asarray(data, :Z)
+ krn = KernelFactors.IIRGaussian([10,10])
+ fwd = imfilter(img, krn)
+ georef((; fwd=vec(fwd)), domain(data))
+end
+
+# apply forward model to both images
+data = forward(truth)
+dataTI = forward(img)
+
+proc = QuiltingProcess(img, (27, 27), soft=(data, dataTI))
+
+real = rand(proc, domain(truth), [:Z => Float64], 2)
+
+fig = Mke.Figure(size = (800, 400))
+viz(fig[1,1], real[1].geometry, color = real[1].Z)
+viz(fig[1,2], real[2].geometry, color = real[2].Z)
+fig
A Poisson process with intensity λ. For a homogeneous process, define λ as a constant real value, while for an inhomogeneous process, define λ as a function or vector of values. If λ is a vector, it is assumed that the process is associated with a Domain with the same number of elements as λ.
A cluster process with parent process proc and offsprings generated with ofun. It is a function that takes a parent point and returns a point pattern from another point process.
ClusterProcess(proc, offs, gfun)
Alternatively, specify the parent process proc, the offspring process offs and the geometry function gfun. It is a function that takes a parent point and returns a geometry or domain for the offspring process.
The Julia ecosystem for geospatial modeling is maturing very quickly as the result of multiple initiatives such as JuliaEarth, JuliaClimate, and JuliaGeo. Each of these initiatives is associated with a different set of challenges that ultimatively determine the types of packages that are being developed in the corresponding GitHub organizations. In this section, we try to clarify what is available to first-time users of the language.
Originally created to host the GeoStats.jl framework, this initiative is primarily concerned with geospatial data science and geostatistical modeling. Due to the various applications in the subsurface of the Earth, most of our Julia packages were developed to work efficiently with both 2D and 3D geometries.
Unlike other initiatives, JuliaEarth is 100% Julia by design. This means that we do not rely on external libraries such as GDAL or Proj4 for geospatial work.
The most recent of the three initiatives, JuliaClimate has been created to address specific challenges in climate modeling. One of these challenges is access to climate data in Julia. Packages such as INMET.jl and CDSAPI.jl serve this purpose and are quite nice to work with.
Focused on bringing well-established external libraries to Julia, JuliaGeo provides packages that are widely used by geospatial communities from other programming languages. GDAL.jl, Proj4.jl and LibGEOS.jl are good examples of such packages.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
Hoffimann, J. 2023.Geospatial Data Science with Julia - A fresh approach to data science with geospatial data and the Julia programming language.
Isaaks, E. and Srivastava, R. 1990.An Introduction to Applied Geostatistics - An introductory book on geostatistics that covers important concepts with very simple language.
GaussianProcesses.jl - Gaussian process regression and Simple Kriging are essentially two names for the same concept. The derivation of Kriging estimators, however; does not require distributional assumptions. It is a beautiful coincidence that for multivariate Gaussian distributions, Simple Kriging gives the conditional expectation.
KernelFunctions.jl - Spatial structure can be represented in many different forms: covariance, variogram, correlogram, etc. Variograms are more general than covariance kernels according to the intrinsic stationary property. This means that there are variogram models with no covariance counterpart. Furthermore, empirical variograms can be easily estimated from the data (in various directions) with an efficient procedure. GeoStats.jl treats variograms as first-class objects.
Interpolations.jl - Kriging and spline interpolation have different purposes, yet these two methods are sometimes listed as competing alternatives. Kriging estimation is about minimizing variance (or estimation error), whereas spline interpolation is about deriving smooth estimators for computer visualization. Kriging is a generalization of splines in which one has the freedom to customize geospatial structure based on data. Besides the estimate itself, Kriging also provides the variance map as a function of point patterns.
ScikitLearn.jl - Traditional statistical learning relies on core assumptions that do not hold in geospatial settings (fixed support, i.i.d. samples, ...). Geostatistical learning has been introduced recently as an attempt to push the frontiers of statistical learning with geospatial data.
Settings
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
This document was generated with Documenter.jl version 1.8.0 on Thursday 14 November 2024. Using Julia version 1.11.1.
diff --git a/v0.71.3/search_index.js b/v0.71.3/search_index.js
new file mode 100644
index 0000000..e0b11f9
--- /dev/null
+++ b/v0.71.3/search_index.js
@@ -0,0 +1,3 @@
+var documenterSearchIndex = {"docs":
+[{"location":"about/community/","page":"Community","title":"Community","text":"We use the Zulip platform to chat and help the community of users. Consider creating an account and pressing ? on the keyboard there for navigation instructions.","category":"page"},{"location":"about/community/","page":"Community","title":"Community","text":"Click on the image to join the channel:","category":"page"},{"location":"about/community/","page":"Community","title":"Community","text":"(Image: Zulip)","category":"page"},{"location":"random/points/#Points","page":"Points","title":"Points","text":"","category":"section"},{"location":"random/points/","page":"Points","title":"Points","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"Base.rand(::GeoStatsProcesses.PointProcess, ::Any)","category":"page"},{"location":"random/points/#Base.rand-Tuple{GeoStatsProcesses.PointProcess, Any}","page":"Points","title":"Base.rand","text":"rand([rng], process::PointProcess, geometry, [nreals])\nrand([rng], process::PointProcess, domain, [nreals])\n\nGenerate one or nreals realizations of the point process inside geometry or domain. Optionally specify the random number generator rng.\n\n\n\n\n\n","category":"method"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nsphere = Sphere((0, 0, 0), 1)\n\n# homogeneous Poisson process\nproc = PoissonProcess(5.0)\n\n# sample two point patterns\npset = rand(proc, sphere, 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], sphere)\nviz!(fig[1,1], pset[1], color = :black)\nviz(fig[1,2], sphere)\nviz!(fig[1,2], pset[2], color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"ishomogeneous","category":"page"},{"location":"random/points/#GeoStatsProcesses.ishomogeneous","page":"Points","title":"GeoStatsProcesses.ishomogeneous","text":"ishomogeneous(process::PointProcess)\n\nTells whether or not the spatial point process process is homogeneous.\n\n\n\n\n\n","category":"function"},{"location":"random/points/#Processes","page":"Points","title":"Processes","text":"","category":"section"},{"location":"random/points/","page":"Points","title":"Points","text":"BinomialProcess","category":"page"},{"location":"random/points/#GeoStatsProcesses.BinomialProcess","page":"Points","title":"GeoStatsProcesses.BinomialProcess","text":"BinomialProcess(n)\n\nA Binomial point process with n points.\n\n\n\n\n\n","category":"type"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# Binomial process\nproc = BinomialProcess(1000)\n\n# sample point patterns\npset = rand(proc, box, 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset[1], color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset[2], color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"PoissonProcess","category":"page"},{"location":"random/points/#GeoStatsProcesses.PoissonProcess","page":"Points","title":"GeoStatsProcesses.PoissonProcess","text":"PoissonProcess(λ)\n\nA Poisson process with intensity λ. For a homogeneous process, define λ as a constant real value, while for an inhomogeneous process, define λ as a function or vector of values. If λ is a vector, it is assumed that the process is associated with a Domain with the same number of elements as λ.\n\n\n\n\n\n","category":"type"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# intensity function\nλ(p) = sum(to(p))^2 / 10000\n\n# homogeneous process\nproc₁ = PoissonProcess(0.5)\n\n# inhomogeneous process\nproc₂ = PoissonProcess(λ)\n\n# sample point patterns\npset₁ = rand(proc₁, box)\npset₂ = rand(proc₂, box)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset₁, color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset₂, color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"InhibitionProcess","category":"page"},{"location":"random/points/#GeoStatsProcesses.InhibitionProcess","page":"Points","title":"GeoStatsProcesses.InhibitionProcess","text":"InhibitionProcess(δ)\n\nAn inhibition point process with minimum distance δ.\n\n\n\n\n\n","category":"type"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# inhibition process\nproc = InhibitionProcess(2.0)\n\n# sample point pattern\npset = rand(proc, box, 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset[1], color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset[2], color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"ClusterProcess","category":"page"},{"location":"random/points/#GeoStatsProcesses.ClusterProcess","page":"Points","title":"GeoStatsProcesses.ClusterProcess","text":"ClusterProcess(proc, ofun)\n\nA cluster process with parent process proc and offsprings generated with ofun. It is a function that takes a parent point and returns a point pattern from another point process.\n\nClusterProcess(proc, offs, gfun)\n\nAlternatively, specify the parent process proc, the offspring process offs and the geometry function gfun. It is a function that takes a parent point and returns a geometry or domain for the offspring process.\n\n\n\n\n\n","category":"type"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (5, 5))\n\n# Matérn process\nproc₁ = ClusterProcess(\n PoissonProcess(1),\n PoissonProcess(1000),\n p -> Ball(p, 0.2)\n)\n\n# inhomogeneous parent and offspring processes\nproc₂ = ClusterProcess(\n PoissonProcess(p -> 0.1 * sum(to(p) .^ 2)),\n p -> rand(PoissonProcess(x -> 5000 * sum((x - p).^2)), Ball(p, 0.5))\n)\n\n# sample point patterns\npset₁ = rand(proc₁, box)\npset₂ = rand(proc₂, box)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset₁, color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset₂, color = :black)\nfig","category":"page"},{"location":"random/points/#Operations","page":"Points","title":"Operations","text":"","category":"section"},{"location":"random/points/","page":"Points","title":"Points","text":"Base.union(::GeoStatsProcesses.PointProcess, ::GeoStatsProcesses.PointProcess)","category":"page"},{"location":"random/points/#Base.union-Tuple{GeoStatsProcesses.PointProcess, GeoStatsProcesses.PointProcess}","page":"Points","title":"Base.union","text":"p₁ ∪ p₂\n\nReturn the union of point processes p₁ and p₂.\n\n\n\n\n\n","category":"method"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# superposition of two Binomial processes\nproc₁ = BinomialProcess(500)\nproc₂ = BinomialProcess(500)\nproc = proc₁ ∪ proc₂ # 1000 points\n\npset = rand(proc, box, 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset[1], color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset[2], color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"thin\nRandomThinning","category":"page"},{"location":"random/points/#GeoStatsProcesses.thin","page":"Points","title":"GeoStatsProcesses.thin","text":"thin(process, method)\n\nThin spatial point process with thinning method.\n\n\n\n\n\n","category":"function"},{"location":"random/points/#GeoStatsProcesses.RandomThinning","page":"Points","title":"GeoStatsProcesses.RandomThinning","text":"RandomThinning(p)\n\nRandom thinning with retention probability p, which can be a constant probability value in [0,1] or a function mapping a point to a probability.\n\nExamples\n\nRandomThinning(0.5)\nRandomThinning(p -> sum(to(p)))\n\n\n\n\n\n","category":"type"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# reduce intensity of Poisson process by half\nproc₁ = PoissonProcess(0.5)\nproc₂ = thin(proc₁, RandomThinning(0.5))\n\n# sample point patterns\npset₁ = rand(proc₁, box)\npset₂ = rand(proc₂, box)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset₁, color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset₂, color = :black)\nfig","category":"page"},{"location":"random/points/","page":"Points","title":"Points","text":"# geometry of interest\nbox = Box((0, 0), (100, 100))\n\n# Binomial process\nproc = BinomialProcess(2000)\n\n# sample point pattern\npset₁ = rand(proc, box)\n\n# thin point pattern with probability 0.5\npset₂ = thin(pset₁, RandomThinning(0.5))\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], box)\nviz!(fig[1,1], pset₁, color = :black)\nviz(fig[1,2], box)\nviz!(fig[1,2], pset₂, color = :black)\nfig","category":"page"},{"location":"variography/empirical/#Empirical-variograms","page":"Empirical variograms","title":"Empirical variograms","text":"","category":"section"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Variograms are widely used in geostatistics due to their intimate connection with (cross-)variance and visual interpretability. The following video explains the concept in detail:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"
\n\n
","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"The Matheron's estimator of the empirical variogram is given by","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"widehatgamma_M(h) = frac12N(h) sum_(ij) in N(h) (z_i - z_j)^2","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"where N(h) = left(ij) mid x_i - x_j = hright is the set of pairs of locations at a distance h and N(h) is the cardinality of the set. Alternatively, the robust Cressie's estimator is given by","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"widehatgamma_C(h) = frac12fracleftfrac1N(h) sum_(ij) in N(h) z_i - z_j^12right^40457 + frac0494N(h) + frac0045N(h)^2","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Both estimators are available and can be used with general distance functions in order to for example:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Model anisotropy (e.g. ellipsoid distance)\nPerform simulation on sphere (e.g. haversine distance)","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Please see Distances.jl for a complete list of distance functions.","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"The high-performance estimation procedure implemented in the framework can consider all pairs of locations regardless of direction (ominidirectional) or a specified partition of the geospatial data (e.g. directional, planar).","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Variograms can plotted with the following options:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"varioplot","category":"page"},{"location":"variography/empirical/#GeoStatsFunctions.varioplot","page":"Empirical variograms","title":"GeoStatsFunctions.varioplot","text":"varioplot(γ; [options])\n\nPlot the variogram γ with given options.\n\nCommon variogram options:\n\ncolor - color of variogram\nsize - size of variogram\nmaxlag - maximum lag of variogram\n\nEmpirical variogram options:\n\npointsize - size of points of variogram\nshowtext - show text counts\ntextsize - size of text counts\nshowhist - show histogram\nhistcolor - color of histogram\n\nNotes\n\nThis function will only work in the presence of a Makie.jl backend via package extensions in Julia v1.9 or later versions of the language.\n\n\n\n\n\n","category":"function"},{"location":"variography/empirical/#(Omini)directional","page":"Empirical variograms","title":"(Omini)directional","text":"","category":"section"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"EmpiricalVariogram\nDirectionalVariogram\nPlanarVariogram","category":"page"},{"location":"variography/empirical/#GeoStatsFunctions.EmpiricalVariogram","page":"Empirical variograms","title":"GeoStatsFunctions.EmpiricalVariogram","text":"EmpiricalVariogram(data, var₁, var₂=var₁; [parameters])\n\nComputes the empirical (a.k.a. experimental) omnidirectional (cross-)variogram for variables var₁ and var₂ stored in geospatial data.\n\nParameters\n\nnlags - number of lags (default to 20)\nmaxlag - maximum lag in length units (default to 1/2 of minimum side of bounding box)\ndistance - custom distance function (default to Euclidean distance)\nestimator - variogram estimator (default to :matheron estimator)\nalgorithm - accumulation algorithm (default to :ball)\n\nAvailable estimators:\n\n:matheron - simple estimator based on squared differences\n:cressie - robust estimator based on 4th power of differences\n\nAvailable algorithms:\n\n:full - loop over all pairs of points in the data\n:ball - loop over all points inside maximum lag ball\n\nAll implemented algorithms produce the exact same result. The :ball algorithm is considerably faster when the maximum lag is much smaller than the bounding box of the domain of the data.\n\nSee also: DirectionalVariogram, PlanarVariogram, EmpiricalVarioplane.\n\nReferences\n\nChilès, JP and Delfiner, P. 2012. Geostatistics: Modeling Spatial Uncertainty\nWebster, R and Oliver, MA. 2007. Geostatistics for Environmental Scientists\nHoffimann, J and Zadrozny, B. 2019. Efficient variography with partition variograms\n\n\n\n\n\n","category":"type"},{"location":"variography/empirical/#GeoStatsFunctions.DirectionalVariogram","page":"Empirical variograms","title":"GeoStatsFunctions.DirectionalVariogram","text":"DirectionalVariogram(direction, data, var₁, var₂=var₁; dtol=1e-6u\"m\", [parameters])\n\nComputes the empirical (cross-)variogram for the variables var₁ and var₂ stored in geospatial data along a given direction with band tolerance dtol in length units.\n\nOptionally, forward parameters for the underlying EmpiricalVariogram.\n\n\n\n\n\n","category":"function"},{"location":"variography/empirical/#GeoStatsFunctions.PlanarVariogram","page":"Empirical variograms","title":"GeoStatsFunctions.PlanarVariogram","text":"PlanarVariogram(normal, data, var₁, var₂=var₁; ntol=1e-6u\"m\", [parameters])\n\nComputes the empirical (cross-)variogram for the variables var₁ and var₂ stored in geospatial data along a plane perpendicular to a normal direction with plane tolerance ntol in length units.\n\nOptionally, forward parameters for the underlying EmpiricalVariogram.\n\n\n\n\n\n","category":"function"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Consider the following example image:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"using GeoStatsImages\n\nimg = geostatsimage(\"Gaussian30x10\")\n\nimg |> viewer","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"We can estimate ominidirectional variograms, which consider pairs of points along all directions:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"γ = EmpiricalVariogram(img, :Z, maxlag = 50.)\n\nvarioplot(γ)","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"directional variograms along a specific direction:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"γₕ = DirectionalVariogram((1.,0.), img, :Z, maxlag = 50.)\nγᵥ = DirectionalVariogram((0.,1.), img, :Z, maxlag = 50.)\n\nvarioplot(γₕ, color = :maroon, histcolor = :maroon)\nvarioplot!(γᵥ)\nMke.current_figure()","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"or planar variograms over a specific plane:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"γᵥ = PlanarVariogram((1.,0.), img, :Z, maxlag = 50.)\nγₕ = PlanarVariogram((0.,1.), img, :Z, maxlag = 50.)\n\nvarioplot(γₕ, color = :maroon, histcolor = :maroon)\nvarioplot!(γᵥ)\nMke.current_figure()","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"note: Note\nThe directional and planar variograms coincide in this example because planes are equal to lines in 2-dimensional space. These concepts are most useful in 3-dimensional space where we may be interested in comparing the horizontal planar range to the vertical directional range.","category":"page"},{"location":"variography/empirical/#Varioplanes","page":"Empirical variograms","title":"Varioplanes","text":"","category":"section"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"Variograms estimated along all directions in a given plane of reference are called varioplanes.","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"EmpiricalVarioplane","category":"page"},{"location":"variography/empirical/#GeoStatsFunctions.EmpiricalVarioplane","page":"Empirical variograms","title":"GeoStatsFunctions.EmpiricalVarioplane","text":"EmpiricalVarioplane(data, var₁, var₂=var₁;\n normal=Vec(0,0,1), nangs=50,\n ptol=0.5u\"m\", dtol=0.5u\"m\",\n [parameters])\n\nGiven a normal direction, estimate the (cross-)variogram of variables var₁ and var₂ along all directions in the corresponding plane of variation.\n\nOptionally, specify the tolerance ptol in length units for the plane partition, the tolerance dtol in length units for the direction partition, the number of angles nangs in the plane, and forward the parameters to the underlying EmpiricalVariogram.\n\n\n\n\n\n","category":"type"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"The varioplane is plotted on a polar axis for all lags and angles:","category":"page"},{"location":"variography/empirical/","page":"Empirical variograms","title":"Empirical variograms","text":"γ = EmpiricalVarioplane(img, :Z, maxlag = 50.)\n\nplaneplot(γ)","category":"page"},{"location":"variography/theoretical/#Theoretical-variograms","page":"Theoretical variograms","title":"Theoretical variograms","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"We provide various theoretical variogram models from the literature, which can can be combined with ellipsoid distances to model geometric anisotropy and nested with scalars or matrix coefficients to express multivariate relations.","category":"page"},{"location":"variography/theoretical/#Models","page":"Theoretical variograms","title":"Models","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"In an intrinsic isotropic model, the variogram is only a function of the distance between any two points x_1x_2 in R^m:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(x_1x_2) = gamma(x_1 - x_2) = gamma(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"Under the additional assumption of 2nd-order stationarity, the well-known covariance is directly related via gamma(h) = cov(0) - cov(h). This package implements a few commonly used as well as other more exotic variogram models. Most of these models share a set of default parameters (e.g. sill=1.0, range=1.0), which can be set with keyword arguments.","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"Functions are provided to query properties of variogram models programmatically:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"isstationary(::Variogram)\nisisotropic(::Variogram)","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.isstationary-Tuple{Variogram}","page":"Theoretical variograms","title":"GeoStatsFunctions.isstationary","text":"isstationary(f)\n\nCheck if geostatistical function f possesses the 2nd-order stationary property.\n\n\n\n\n\n","category":"method"},{"location":"variography/theoretical/#Meshes.isisotropic-Tuple{Variogram}","page":"Theoretical variograms","title":"Meshes.isisotropic","text":"isisotropic(f)\n\nTells whether or not the geostatistical function f is isotropic.\n\n\n\n\n\n","category":"method"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"Corresponding covariance models are available for convenience. For example, the GaussianVariogram and the GaussianCovariance are two alternative representations of the same geostatistical behavior.","category":"page"},{"location":"variography/theoretical/#Gaussian","page":"Theoretical variograms","title":"Gaussian","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) left1 - expleft(-3left(frachrright)^2right)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"GaussianVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.GaussianVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.GaussianVariogram","text":"GaussianVariogram(; range, sill, nugget)\nGaussianVariogram(ball; sill, nugget)\n\nA Gaussian variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(GaussianVariogram())","category":"page"},{"location":"variography/theoretical/#Spherical","page":"Theoretical variograms","title":"Spherical","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) leftleft(frac32left(frachrright) + frac12left(frachrright)^3right) cdot 1_(0r)(h) + 1_rinfty)(h)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"SphericalVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.SphericalVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.SphericalVariogram","text":"SphericalVariogram(; range, sill, nugget)\nSphericalVariogram(ball; sill, nugget)\n\nA spherical variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(SphericalVariogram())","category":"page"},{"location":"variography/theoretical/#Exponential","page":"Theoretical variograms","title":"Exponential","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) left1 - expleft(-3left(frachrright)right)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"ExponentialVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.ExponentialVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.ExponentialVariogram","text":"ExponentialVariogram(; range, sill, nugget)\nExponentialVariogram(ball; sill, nugget)\n\nA exponential variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(ExponentialVariogram())","category":"page"},{"location":"variography/theoretical/#Matern","page":"Theoretical variograms","title":"Matern","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) left1 - frac2^1-nuGamma(nu) left(sqrt2nu 3left(frachrright)right)^nu K_nuleft(sqrt2nu 3left(frachrright)right)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"MaternVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.MaternVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.MaternVariogram","text":"MaternVariogram(; range, sill, nugget, order)\nMaternVariogram(ball; sill, nugget, order)\n\nA Matérn variogram with range, sill and nugget. Optionally, use a custom metric ball and order of the Bessel function.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(MaternVariogram())","category":"page"},{"location":"variography/theoretical/#Cubic","page":"Theoretical variograms","title":"Cubic","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) leftleft(7left(frachrright)^2 - frac354left(frachrright)^3 + frac72left(frachrright)^5 - frac34left(frachrright)^7right) cdot 1_(0r)(h) + 1_rinfty)(h)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"CubicVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.CubicVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.CubicVariogram","text":"CubicVariogram(; range, sill, nugget)\nCubicVariogram(ball; sill, nugget)\n\nA cubic variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(CubicVariogram())","category":"page"},{"location":"variography/theoretical/#Pentaspherical","page":"Theoretical variograms","title":"Pentaspherical","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) leftleft(frac158left(frachrright) - frac54left(frachrright)^3 + frac38left(frachrright)^5right) cdot 1_(0r)(h) + 1_rinfty)(h)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"PentasphericalVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.PentasphericalVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.PentasphericalVariogram","text":"PentasphericalVariogram(; range, sill, nugget)\nPentasphericalVariogram(ball; sill, nugget)\n\nA pentaspherical variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(PentasphericalVariogram())","category":"page"},{"location":"variography/theoretical/#Sine-hole","page":"Theoretical variograms","title":"Sine hole","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) left1 - fracsin(pi h r)pi h rright + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"SineHoleVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.SineHoleVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.SineHoleVariogram","text":"SineHoleVariogram(; range, sill, nugget)\nSineHoleVariogram(ball; sill, nugget)\n\nA sine hole variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(SineHoleVariogram())","category":"page"},{"location":"variography/theoretical/#Circular","page":"Theoretical variograms","title":"Circular","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = (s - n) leftleft(1 - frac2pi cos^-1left(frachrright) + frac2hpi r sqrt1 - frach^2r^2 right) cdot 1_(0r)(h) + 1_rinfty)(h)right + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"CircularVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.CircularVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.CircularVariogram","text":"CircularVariogram(; range, sill, nugget)\nCircularVariogram(ball; sill, nugget)\n\nA circular variogram with range, sill and nugget. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(CircularVariogram())","category":"page"},{"location":"variography/theoretical/#Power","page":"Theoretical variograms","title":"Power","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = sh^a + n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"PowerVariogram","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.PowerVariogram","page":"Theoretical variograms","title":"GeoStatsFunctions.PowerVariogram","text":"PowerVariogram(; scaling, exponent, nugget)\n\nA power variogram with scaling, exponent and nugget.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(PowerVariogram())","category":"page"},{"location":"variography/theoretical/#Nugget","page":"Theoretical variograms","title":"Nugget","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"gamma(h) = n cdot 1_(0infty)(h)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"NuggetEffect","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.NuggetEffect","page":"Theoretical variograms","title":"GeoStatsFunctions.NuggetEffect","text":"NuggetEffect(; nugget)\n\nA pure nugget effect variogram with nugget.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"varioplot(NuggetEffect(1.0))","category":"page"},{"location":"variography/theoretical/#Anisotropy","page":"Theoretical variograms","title":"Anisotropy","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"Anisotropic models are easily obtained by defining an ellipsoid metric in place of the default Euclidean metric as shown in the following example. First, we create an ellipsoid that specifies the ranges and angles of rotation:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"ellipsoid = MetricBall((3.0, 2.0, 1.0), RotZXZ(0.0, 0.0, 0.0))","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"All rotations from Rotations.jl are supported as well as the following additional rotations from commercial geostatistical software:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"MinesightAngles\nDatamineAngles\nVulcanAngles\nGslibAngles","category":"page"},{"location":"variography/theoretical/#GeoStatsBase.MinesightAngles","page":"Theoretical variograms","title":"GeoStatsBase.MinesightAngles","text":"MinesightAngles(θ₁, θ₂, θ₃)\n\nMineSight z-x'-y'' intrinsic rotation convention following the right-hand rule. All angles are in degrees and the sign convention is CW, CCW, CW positive.\n\nThe first rotation θ₁ is a horizontal rotation around the Z-axis, with positive being clockwise. The second rotation θ₂ is a rotation around the new X-axis, which moves the Y-axis into the desired position, with positive direction of rotation is up. The third rotation θ₃ is a rotation around the new Y-axis, which moves the X-axis into the desired position, with positive direction of rotation is up.\n\nReferences\n\nSanchez, J. MINESIGHT® TUTORIALS\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/#GeoStatsBase.DatamineAngles","page":"Theoretical variograms","title":"GeoStatsBase.DatamineAngles","text":"DatamineAngles(θ₁, θ₂, θ₃)\n\nDatamine ZXY rotation convention following the left-hand rule. All angles are in degrees and the signal convention is CW, CW, CW positive. Y is the principal axis.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/#GeoStatsBase.VulcanAngles","page":"Theoretical variograms","title":"GeoStatsBase.VulcanAngles","text":"VulcanAngles(θ₁, θ₂, θ₃)\n\nVulcan ZYX rotation convention following the right-hand rule. All angles are in degrees and the signal convention is CW, CCW, CW positive. X is the principal axis.\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/#GeoStatsBase.GslibAngles","page":"Theoretical variograms","title":"GeoStatsBase.GslibAngles","text":"GslibAngles(θ₁, θ₂, θ₃)\n\nGSLIB z-x'-y'' intrinsic rotation convention following the left-hand rule. All angles are in degrees and the sign convention is CW, CCW, CW positive. Y is the principal axis.\n\nThe first rotation θ₁ is a rotation around the Z-axis, this is also called the azimuth. The second rotation θ₂ is a rotation around the new X-axis, this is also called the dip. The third rotation θ₃ is a rotation around the new Y-axis, this is also called the tilt. \n\nReferences\n\nDeutsch, 2015. The Angle Specification for GSLIB Software\n\n\n\n\n\n","category":"type"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"We pass the ellipsoid as the first argument to the variogram model instead of specifying a single range with a keyword argument:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"GaussianVariogram(ellipsoid, sill = 2.0)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"To illustrate the concept, consider the following 2D data set:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"using Random # hide\nRandom.seed!(2000) # hide\n\npoints = rand(Point, 50, crs=Cartesian2D) |> Scale(100)\ngeotable = georef((Z=rand(50),), points)\n\nviz(geotable.geometry, color = geotable.Z)","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"We interpolate the data with different ellipsoids by varying the angle of rotation from 0 to 2pi clockwise:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"θs = range(0.0, step = π/4, stop = 2π - π/4)\n\n# initialize figure\nfig = Mke.Figure(size = (800, 1600))\n\n# helper function to position subfigures\npos = i -> CartesianIndices((4, 2))[i].I\n\n# Kriging with different angles\nfor (i, θ) in enumerate(θs)\n # ellipsoid rotated clockwise by angle θ\n e = MetricBall((20.,5.), Angle2d(θ))\n\n # anisotropic variogram model\n γ = GaussianVariogram(e)\n\n # domain of interpolation\n grid = CartesianGrid(100, 100)\n\n # perform interpolation\n sol = geotable |> Interpolate(grid, Kriging(γ))\n\n # visualize solution at subplot i\n viz(fig[pos(i)...], sol.geometry, color = sol.Z,\n axis = (title = \"θ = $(rad2deg(θ))ᵒ\",)\n )\nend\n\nfig","category":"page"},{"location":"variography/theoretical/#Nesting","page":"Theoretical variograms","title":"Nesting","text":"","category":"section"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"A nested variogram model gamma(h) = c_1cdotgamma_1(h) + c_2cdotgamma_2(h) + cdots + c_ncdotgamma_n(h) can be constructed from multiple variogram models, including matrix coefficients. The individual structures can be recovered in canonical form with the structures function:","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"structures","category":"page"},{"location":"variography/theoretical/#GeoStatsFunctions.structures","page":"Theoretical variograms","title":"GeoStatsFunctions.structures","text":"structures(γ)\n\nReturn the individual structures of a (possibly nested) variogram as a tuple. The structures are the total nugget cₒ, and the coefficients (or contributions) c[i] for the remaining non-trivial structures g[i] after normalization (i.e. sill=1, nugget=0).\n\nExamples\n\nγ₁ = GaussianVariogram(nugget=1, sill=2)\nγ₂ = SphericalVariogram(nugget=2, sill=3)\n\nγ = 2γ₁ + 3γ₂\n\ncₒ, c, g = structures(γ)\n\n\n\n\n\n","category":"function"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"γ₁ = GaussianVariogram(nugget=1, sill=2)\nγ₂ = ExponentialVariogram(nugget=2, sill=3)\n\n# nested model with matrix coefficients\nγ = [1.0 0.0; 0.0 1.0] * γ₁ + [2.0 0.5; 0.5 3.0] * γ₂\n\n# structures in canonical form\ncₒ, c, g = structures(γ)\n\ncₒ # matrix nugget","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"c # matrix coefficients","category":"page"},{"location":"variography/theoretical/","page":"Theoretical variograms","title":"Theoretical variograms","text":"g # normalized structures","category":"page"},{"location":"contributing/#Contributing","page":"Contributing","title":"Contributing","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"First off, thank you for considering contributing to GeoStats.jl. It’s people like you that make this project so much fun. Below are a few suggestions to speed up the collaboration process:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Please be polite, we are here to help and learn from each other.\nTry to explain your contribution with simple language.\nReferences to textbooks and papers are always welcome.\nFollow the coding standards in the source.","category":"page"},{"location":"contributing/#How-to-start-contributing?","page":"Contributing","title":"How to start contributing?","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Contributing to an open-source project for the very first time can be a very daunting task. To make the process easier and more GitHub-beginner-friendly, the community has written an article about how to start contributing to open-source and overcome the mental and technical barriers that come associated with it. The article will also take you through the steps required to make your first contribution in detail.","category":"page"},{"location":"contributing/#Reporting-issues","page":"Contributing","title":"Reporting issues","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If you are experiencing issues or have discovered a bug, please report it on GitHub. To make the resolution process easier, please include the version of Julia and GeoStats.jl in your writeup. These can be found with two commands:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"julia> versioninfo()\njulia> using Pkg; Pkg.status()","category":"page"},{"location":"contributing/#Feature-requests","page":"Contributing","title":"Feature requests","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If you have suggestions of improvement or algorithms that you would like to see implemented, please open an issue on GitHub. Suggestions as well as feature requests are very welcome.","category":"page"},{"location":"contributing/#Code-contribution","page":"Contributing","title":"Code contribution","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If you have code that you would like to contribute that is awesome! Please open an issue or reach out in our community channel before you create the pull request on GitHub so that we make sure your idea is aligned with the project goals.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"After your idea is revised by project maintainers, you implement it online on Github or offline on your machine.","category":"page"},{"location":"contributing/#Online-changes","page":"Contributing","title":"Online changes","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If the changes to the code are minimal, we recommend pressing . on the keyboard on any file in the GitHub repository of interest. This will open the VSCode editor on the web browser where you can implement the changes, commit them and submit a pull request.","category":"page"},{"location":"contributing/#Offline-changes","page":"Contributing","title":"Offline changes","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If the changes require additional investigation and tests, please get the development version of the project by typing the following in the package manager:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"] activate @geo","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"This will create a fresh environment called @geo where you can edit the project modules without effects on your global user environment. Next, go ahead and ask the package manager to develop the package of interest (e.g. GeoStatsFunctions.jl):","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"] dev GeoStatsFunctions","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"You can modify the source code that was cloned in the .julia/dev folder and submit a pull request on GitHub later.","category":"page"},{"location":"links/#Index","page":"Index","title":"Index","text":"","category":"section"},{"location":"links/","page":"Index","title":"Index","text":"Below is the list of types and functions mentioned in the documentation.","category":"page"},{"location":"links/#Types","page":"Index","title":"Types","text":"","category":"section"},{"location":"links/","page":"Index","title":"Index","text":"Order = [:type]","category":"page"},{"location":"links/#Functions","page":"Index","title":"Functions","text":"","category":"section"},{"location":"links/","page":"Index","title":"Index","text":"Order = [:function]","category":"page"},{"location":"data/#Geospatial-data","page":"Data","title":"Geospatial data","text":"","category":"section"},{"location":"data/#Overview","page":"Data","title":"Overview","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"Given a table or array containing data, we can georeference these objects onto a geospatial domain with the georef function. The result of the georef function is a GeoTable. If you would like to learn this concept in more depth, check out the recording of our JuliaEO 2024 workshop:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"
\n\n
","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"georef","category":"page"},{"location":"data/#GeoTables.georef","page":"Data","title":"GeoTables.georef","text":"georef(table, domain)\n\nGeoreference table on domain from Meshes.jl\n\nExamples\n\njulia> georef((a=rand(100), b=rand(100)), CartesianGrid(10, 10))\n\n\n\n\n\ngeoref(table, geoms)\n\nGeoreference table on vector of geometries geoms from Meshes.jl\n\nExamples\n\njulia> georef((a=rand(10), b=rand(10)), rand(Point, 10))\n\n\n\n\n\ngeoref(table, coords; [crs], [lenunit])\n\nGeoreference table using coordinates coords of points.\n\nOptionally, specify the coordinate reference system crs, which is set by default based on heuristics, and the lenunit (default to meters for unitless values) that can only be used in CRS types that allow this flexibility. Any CRS or EPSG/ESRI code from CoordRefSystems.jl is supported.\n\nExamples\n\njulia> georef((a=[1, 2, 3], b=[4, 5, 6], [(0, 0), (1, 1), (2, 2)])\njulia> georef((a=[1, 2, 3], b=[4, 5, 6], [(0, 0), (1, 1), (2, 2)], crs=LatLon)\njulia> georef((a=[1, 2, 3], b=[4, 5, 6], [(0, 0), (1, 1), (2, 2)], crs=EPSG{4326})\njulia> georef((a=[1, 2, 3], b=[4, 5, 6], [(0, 0), (1, 1), (2, 2)], lenunit=u\"cm\")\n\n\n\n\n\ngeoref(table, names; [crs], [lenunit])\n\nGeoreference table using coordinates of points stored in column names.\n\nOptionally, specify the coordinate reference system crs, which is set by default based on heuristics, and the lenunit (default to meters for unitless values) that can only be used in CRS types that allow this flexibility. Any CRS or EPSG/ESRI code from CoordRefSystems.jl is supported.\n\nExamples\n\ngeoref((a=rand(10), x=rand(10), y=rand(10)), (\"x\", \"y\"))\ngeoref((a=rand(10), x=rand(10), y=rand(10)), (\"x\", \"y\"), crs=LatLon)\ngeoref((a=rand(10), x=rand(10), y=rand(10)), (\"x\", \"y\"), crs=EPSG{4326})\ngeoref((a=rand(10), x=rand(10), y=rand(10)), (\"x\", \"y\"), lenunit=u\"cm\")\n\n\n\n\n\ngeoref(tuple)\n\nGeoreference a named tuple on CartesianGrid(dims), with dims obtained from the arrays stored in the tuple.\n\nExamples\n\njulia> georef((a=rand(10, 10), b=rand(10, 10))) # 2D grid\njulia> georef((a=rand(10, 10, 10), b=rand(10, 10, 10))) # 3D grid\n\n\n\n\n\n","category":"function"},{"location":"data/","page":"Data","title":"Data","text":"The functions values and domain can be used to retrieve the table of attributes and the underlying geospatial domain:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"values\ndomain","category":"page"},{"location":"data/#Base.values","page":"Data","title":"Base.values","text":"values(geotable, [rank])\n\nReturn the values of geotable for a given rank as a table.\n\nThe rank is a non-negative integer that specifies the parametric dimension of the geometries of interest:\n\n0 - points\n1 - segments\n2 - triangles, quadrangles, ...\n3 - tetrahedrons, hexahedrons, ...\n\nIf the rank is not specified, it is assumed to be the rank of the elements of the domain.\n\n\n\n\n\n","category":"function"},{"location":"data/#GeoTables.domain","page":"Data","title":"GeoTables.domain","text":"domain(geotable)\n\nReturn underlying domain of the geotable.\n\n\n\n\n\n","category":"function"},{"location":"data/#Examples","page":"Data","title":"Examples","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"using GeoStats\nimport CairoMakie as Mke\n\n# helper function for plotting two\n# variables named T and P side by side\nfunction plot(data)\n fig = Mke.Figure(size = (800, 400))\n viz(fig[1,1], data.geometry, color = data.T)\n viz(fig[1,2], data.geometry, color = data.P)\n fig\nend","category":"page"},{"location":"data/#Tables","page":"Data","title":"Tables","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"Consider a table (e.g. DataFrame) with 25 samples of temperature T and pressure P:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"using DataFrames\n\ntable = DataFrame(T=rand(25), P=rand(25))","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"We can georeference this table based on a given set of points:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"georef(table, rand(Point, 25)) |> plot","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"or alternatively, georeference it on a 5x5 regular grid (5x5 = 25 samples):","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"georef(table, CartesianGrid(5, 5)) |> plot","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"Another common pattern in geospatial data is when the coordinates of the samples are already part of the table as columns. In this case, we can specify the column names:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"table = DataFrame(T=rand(25), P=rand(25), X=rand(25), Y=rand(25), Z=rand(25))\n\ngeoref(table, (\"X\", \"Y\", \"Z\")) |> plot","category":"page"},{"location":"data/#Arrays","page":"Data","title":"Arrays","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"Consider arrays (e.g. images) with data for various geospatial variables. We can georeference these arrays using a named tuple, and the framework will understand that the shape of the arrays should be preserved in a CartesianGrid:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"T, P = rand(5, 5), rand(5, 5)\n\ngeoref((T=T, P=P)) |> plot","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"Alternatively, we can interpret the entries of the named tuple as columns in a table:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"georef((T=vec(T), P=vec(P)), rand(Point, 25)) |> plot","category":"page"},{"location":"data/#Files","page":"Data","title":"Files","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"The GeoIO.jl package can be used to load/save geospatial data from/to various file formats:","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"GeoIO.load\nGeoIO.save\nGeoIO.formats","category":"page"},{"location":"data/#GeoIO.load","page":"Data","title":"GeoIO.load","text":"load(fname, repair=true, layer=0, lenunit=m, kwargs...)\n\nLoad geospatial table from file fname stored in any format.\n\nVarious repairs are performed on the stored geometries by default, including fixes of orientation in rings of polygons, removal of zero-area triangles, etc.\n\nSome of the repairs can be expensive on large data sets. In that case, we recommend setting repair=false. Custom repairs can be performed with the Repair transform from Meshes.jl.\n\nOptionally, specify the layer to read within the file, and the length unit lenunit of the coordinates when the format does not include units in its specification. Other kwargs are forwarded to the backend packages.\n\nPlease use the formats function to list all supported file formats.\n\nOptions\n\nOFF\n\ndefaultcolor: default color of the geometries if the file does not have this data (default to RGBA(0.666, 0.666, 0.666, 0.666));\n\nCSV\n\ncoords: names of the columns with point coordinates (required option);\nOther options are passed to CSV.File, see the CSV.jl documentation for more details;\n\nVTK formats (.vtu, .vtp, .vtr, .vts, .vti)\n\nmask: name of the boolean column that encodes the indices of a grid view (default to :MASK). If the column does not exist in the file, the full grid is returned;\n\nCommon Data Model formats (NetCDF, GRIB)\n\nx: name of the column with x coordinates (default to \"x\", \"X\", \"lon\", or \"longitude\");\ny: name of the column with y coordinates (default to \"y\", \"Y\", \"lat\", or \"latitude\");\nz: name of the column with z coordinates (default to \"z\", \"Z\", \"depth\", or \"height\");\nt: name of the column with time measurements (default to \"t\", \"time\", or \"TIME\");\n\nGeoJSON\n\nnumbertype: number type of geometry coordinates (default to Float64)\nOther options are passed to GeoJSON.read, see the GeoJSON.jl documentation for more details;\n\nGSLIB\n\nOther options are passed to GslibIO.load, see the GslibIO.jl documentation for more details;\n\nShapefile\n\nOther options are passed to Shapefile.read, see the Shapefile.jl documentation for more details;\n\nGeoParquet\n\nOther options are passed to GeoParquet.read, see the GeoParquet.jl documentation for more details;\n\nGeoTIFF, GeoPackage, KML\n\nOther options are passed to ArchGDAL.read, see the ArchGDAL.jl documentation for more details;\n\nExamples\n\n# load coordinates of geojson file as Float64 (default)\nGeoIO.load(\"file.geojson\")\n# load coordinates of geojson file as Float32\nGeoIO.load(\"file.geojson\", numbertype=Float32)\n\n\n\n\n\n","category":"function"},{"location":"data/#GeoIO.save","page":"Data","title":"GeoIO.save","text":"save(fname, geotable; kwargs...)\n\nSave geotable to file fname of given format based on the file extension.\n\nOther kwargs are forwarded to the backend packages.\n\nPlease use the formats function to list all supported file formats.\n\nOptions\n\nOFF\n\ncolor: name of the column with geometry colors, if nothing the geometries will be saved without colors (default to nothing);\n\nMSH\n\nvcolumn: name of the column in vertex table with node data, if nothing the geometries will be saved without node data (default to nothing);\necolumn: name of the column in element table with element data, if nothing the geometries will be saved without element data (default to nothing);\n\nSTL\n\nascii: defines whether the file will be saved in ASCII format, otherwise Binary format will be used (default to false);\n\nCSV\n\ncoords: names of the columns where the point coordinates will be saved (default to \"x\", \"y\", \"z\");\nfloatformat: C-style format string for float values (default to no formatting);\nOther options are passed to CSV.write, see the CSV.jl documentation for more details;\n\nNetCDF\n\nx: name of the column where the coordinate x will be saved (default to CRS coordinate name);\ny: name of the column where the coordinate y will be saved (default to CRS coordinate name);\nz: name of the column where the coordinate z will be saved (default to CRS coordinate name);\nt: name of the column where the time measurements will be saved (default to \"t\");\n\nGeoTIFF\n\noptions: list with options that will be passed to GDAL;\n\nGeoPackage\n\nlayername: name of the layer where the data will be saved (default to \"data\");\noptions: dictionary with options that will be passed to GDAL;\n\nGSLIB\n\nOther options are passed to GslibIO.save, see the GslibIO.jl documentation for more details;\n\nShapefile\n\nOther options are passed to Shapefile.write, see the Shapefile.jl documentation for more details;\n\nGeoJSON\n\nOther options are passed to GeoJSON.write, see the GeoJSON.jl documentation for more details;\n\nGeoParquet\n\nOther options are passed to GeoParquet.write, see the GeoParquet.jl documentation for more details;\n\nExamples\n\n# overwrite an existing shapefile\nGeoIO.save(\"file.shp\", force = true)\n\n\n\n\n\n","category":"function"},{"location":"data/#GeoIO.formats","page":"Data","title":"GeoIO.formats","text":"formats([io]; sortby=:format)\n\nDisplays in io (defaults to stdout if io is not given) a table with all formats supported by GeoIO.jl and the packages used to load and save each of them. \n\nOptionally, sort the table by the :extension, :load or :save columns using the sortby argument.\n\n\n\n\n\n","category":"function"},{"location":"data/","page":"Data","title":"Data","text":"using GeoIO\n\nzone = GeoIO.load(\"data/zone.shp\")","category":"page"},{"location":"data/#Artifacts","page":"Data","title":"Artifacts","text":"","category":"section"},{"location":"data/","page":"Data","title":"Data","text":"The GeoArtifacts.jl package provides utility functions to automatically download geospatial data from repositories on the internet.","category":"page"},{"location":"data/","page":"Data","title":"Data","text":"using GeoArtifacts\n\n# download artifacts from naturalearthdata.com\nearth = NaturalEarth.naturalearth1(\"water\")\nborders = NaturalEarth.borders()\nairports = NaturalEarth.airports()\nports = NaturalEarth.ports()\n\n# initialize viewer with a coarse \"raster\"\nearth |> Upscale(10, 5) |> viewer\n\n# add other elements to the visualization\nviz!(borders.geometry, color = \"cyan\")\nviz!(airports.geometry, color = \"black\", pointsize=4, pointmarker='✈')\nviz!(ports.geometry, color = \"blue\", pointsize=4, pointmarker='⚓')\n\n# display current figure\nMke.current_figure()","category":"page"},{"location":"visualization/#Visualization","page":"Visualization","title":"Visualization","text":"","category":"section"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"The framework provides powerful visualization recipes for geospatial data science via the Makie.jl project. These recipes were carefully designed to maximize productivity and to protect users from GIS jargon. The main entry point is the viz function:","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"viz\nviz!","category":"page"},{"location":"visualization/#Meshes.viz","page":"Visualization","title":"Meshes.viz","text":"viz(object; [options])\n\nVisualize Meshes.jl object with various options.\n\nAvailable options\n\ncolor - color of geometries\nalpha - transparency in [0,1]\ncolormap - color scheme/map from ColorSchemes.jl\ncolorrange - minimum and maximum color values\nshowsegments - visualize segments\nsegmentcolor - color of segments\nsegmentsize - width of segments\nshowpoints - visualize points\npointmarker - marker of points\npointcolor - color of points\npointsize - size of points\n\nThe option color can be a single scalar or a vector of scalars. For Mesh subtypes, the length of the vector of colors determines if the colors should be assigned to vertices or to elements.\n\nExamples\n\nDifferent coloring methods (vertex vs. element):\n\n# vertex coloring (i.e. linear interpolation)\nviz(mesh, color = 1:nvertices(mesh))\n\n# element coloring (i.e. discrete colors)\nviz(mesh, color = 1:nelements(mesh))\n\nDifferent strategies to show the boundary of geometries (showsegments vs. boundary):\n\n# visualize boundary with showsegments\nviz(polygon, showsegments = true)\n\n# visualize boundary with separate call\nviz(polygon)\nviz!(boundary(polygon))\n\nNotes\n\nThis function will only work in the presence of a Makie.jl backend via package extensions in Julia v1.9 or later versions of the language.\n\n\n\n\n\n","category":"function"},{"location":"visualization/#Meshes.viz!","page":"Visualization","title":"Meshes.viz!","text":"viz!(object; [options])\n\nVisualize Meshes.jl object in an existing scene with options forwarded to viz.\n\n\n\n\n\n","category":"function"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"This function takes a geospatial domain as input and provides a set of aesthetic options to style the elements (i.e. geometries) of the domain.","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"note: Note\nNotice that the geometry column of our geospatial data type is a domain (i.e. data.geometry isa Domain), and that this design enables several optimizations in the visualization itself.","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"Users can also call Makie's plot function in the geometry column as in","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"Mke.plot(data.geometry)","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"and this is equivalent to calling the viz recipe above. The plot function also works with various other objects such as EmpiricalHistogram and EmpiricalVariogram. That is convenient if you don't remember the name of the recipe.","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"Additionaly, we provide a basic scientific viewer to visualize all viewable variables in the data:","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"viewer","category":"page"},{"location":"visualization/#GeoTables.viewer","page":"Visualization","title":"GeoTables.viewer","text":"viewer(geotable; kwargs...)\n\nBasic scientific viewer for geospatial table geotable.\n\nAesthetic options are forwarded via kwargs to the Meshes.viz recipe.\n\n\n\n\n\n","category":"function"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"Other plots are listed below that can be useful for geostatistical analysis.","category":"page"},{"location":"visualization/#Built-in","page":"Visualization","title":"Built-in","text":"","category":"section"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"A hscatter plot between two variables var1 and var2 (possibly with var2 = var1) is a simple scatter plot in which the dots represent all ordered pairs of values of var1 and var2 at a given lag h.","category":"page"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"𝒟 = georef((Z=[10sin(i/10) + j for i in 1:100, j in 1:200],))\n\n𝒮 = sample(𝒟, UniformSampling(500))\n\nfig = Mke.Figure(size = (800, 400))\nhscatter(fig[1,1], 𝒮, :Z, :Z, lag=0)\nhscatter(fig[1,2], 𝒮, :Z, :Z, lag=20)\nhscatter(fig[2,1], 𝒮, :Z, :Z, lag=40)\nhscatter(fig[2,2], 𝒮, :Z, :Z, lag=60)\nfig","category":"page"},{"location":"visualization/#PairPlots.jl","page":"Visualization","title":"PairPlots.jl","text":"","category":"section"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"The PairPlots.jl package provides the pairplot function that can be used with any table, including tables of attributes obtained with the values function.","category":"page"},{"location":"visualization/#Biplots.jl","page":"Visualization","title":"Biplots.jl","text":"","category":"section"},{"location":"visualization/","page":"Visualization","title":"Visualization","text":"The Biplot.jl package provides 2D and 3D statistical biplots.","category":"page"},{"location":"resources/education/#Education","page":"Education","title":"Education","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"We recommend the following educational resources.","category":"page"},{"location":"resources/education/#Learning-resources","page":"Education","title":"Learning resources","text":"","category":"section"},{"location":"resources/education/#Textbooks","page":"Education","title":"Textbooks","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"Hoffimann, J. 2023. Geospatial Data Science with Julia - A fresh approach to data science with geospatial data and the Julia programming language.\nIsaaks, E. and Srivastava, R. 1990. An Introduction to Applied Geostatistics - An introductory book on geostatistics that covers important concepts with very simple language.\nChilès, JP and Delfiner, P. 2012. Geostatistics: Modeling Spatial Uncertainty - An incredible book for those with good mathematical background.\nWebster, R and Oliver, MA. 2007. Geostatistics for Environmental Scientists - A great book with good balance between theory and practice.\nJournel, A. and Huijbregts, Ch. 2003. Mining Geostatistics - A great book with both theoretical and practical developments.","category":"page"},{"location":"resources/education/#Video-lectures","page":"Education","title":"Video lectures","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"Júlio Hoffimann - Video lectures with the GeoStats.jl framework.\nEdward Isaaks - Video lectures on variography, Kriging and related concepts.\nJef Caers - Video lectures on two-point and multiple-point methods.","category":"page"},{"location":"resources/education/#Workshop-material","page":"Education","title":"Workshop material","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"UFMG 2024 [Portuguese] - Geociência de Dados na Mineração, UFMG 2024\nJuliaEO 2024 [English] - Global Workshop on Earth Observation, AIRCentre 2024\nUFMG 2023 [Portuguese] - Geociência de Dados na Mineração, UFMG 2023\nJuliaEO 2023 [English] - Global Workshop on Earth Observation, AIRCentre 2023\nCBMina 2021 [Portuguese] - Introução à Geoestatística, CBMina 2021\nUFMG 2021 [Portuguese] - Introdução à Geoestatística, UFMG 2021","category":"page"},{"location":"resources/education/#Related-concepts","page":"Education","title":"Related concepts","text":"","category":"section"},{"location":"resources/education/#GaussianProcesses.jl","page":"Education","title":"GaussianProcesses.jl","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"GaussianProcesses.jl - Gaussian process regression and Simple Kriging are essentially two names for the same concept. The derivation of Kriging estimators, however; does not require distributional assumptions. It is a beautiful coincidence that for multivariate Gaussian distributions, Simple Kriging gives the conditional expectation.","category":"page"},{"location":"resources/education/#KernelFunctions.jl","page":"Education","title":"KernelFunctions.jl","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"KernelFunctions.jl - Spatial structure can be represented in many different forms: covariance, variogram, correlogram, etc. Variograms are more general than covariance kernels according to the intrinsic stationary property. This means that there are variogram models with no covariance counterpart. Furthermore, empirical variograms can be easily estimated from the data (in various directions) with an efficient procedure. GeoStats.jl treats variograms as first-class objects.","category":"page"},{"location":"resources/education/#Interpolations.jl","page":"Education","title":"Interpolations.jl","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"Interpolations.jl - Kriging and spline interpolation have different purposes, yet these two methods are sometimes listed as competing alternatives. Kriging estimation is about minimizing variance (or estimation error), whereas spline interpolation is about deriving smooth estimators for computer visualization. Kriging is a generalization of splines in which one has the freedom to customize geospatial structure based on data. Besides the estimate itself, Kriging also provides the variance map as a function of point patterns.","category":"page"},{"location":"resources/education/#ScikitLearn.jl","page":"Education","title":"ScikitLearn.jl","text":"","category":"section"},{"location":"resources/education/","page":"Education","title":"Education","text":"ScikitLearn.jl - Traditional statistical learning relies on core assumptions that do not hold in geospatial settings (fixed support, i.i.d. samples, ...). Geostatistical learning has been introduced recently as an attempt to push the frontiers of statistical learning with geospatial data.","category":"page"},{"location":"about/license/","page":"License","title":"License","text":"The GeoStats.jl project is licensed under the MIT license:","category":"page"},{"location":"about/license/","page":"License","title":"License","text":"MIT License\n\nCopyright (c) 2015 Júlio Hoffimann and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","category":"page"},{"location":"domains/#Domains","page":"Domains","title":"Domains","text":"","category":"section"},{"location":"domains/","page":"Domains","title":"Domains","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"domains/#Overview","page":"Domains","title":"Overview","text":"","category":"section"},{"location":"domains/","page":"Domains","title":"Domains","text":"A geospatial domain is a (discretized) region in physical space. For example, a collection of rain gauge stations can be represented as a PointSet in the map. Similarly, a collection of states in a given country can be represented as a GeometrySet of polygons.","category":"page"},{"location":"domains/","page":"Domains","title":"Domains","text":"We provide flexible domain types for advanced geospatial workflows via the Meshes.jl submodule. The domains can consist of sets (or \"soups\") of geometries as it is most common in GIS or be actual meshes with topological information.","category":"page"},{"location":"domains/","page":"Domains","title":"Domains","text":"Domain\nMesh","category":"page"},{"location":"domains/#Meshes.Domain","page":"Domains","title":"Meshes.Domain","text":"Domain{M,CRS}\n\nA domain is an indexable collection of geometries (e.g. mesh) in a given manifold M with point coordinates specified in a coordinate reference system CRS.\n\n\n\n\n\n","category":"type"},{"location":"domains/#Meshes.Mesh","page":"Domains","title":"Meshes.Mesh","text":"Mesh{M,CRS,TP}\n\nA mesh of geometries in a given manifold M with point coordinates specified in a coordinate reference system CRS. Unlike a general domain, a mesh has a well-defined topology TP.\n\n\n\n\n\n","category":"type"},{"location":"domains/#Examples","page":"Domains","title":"Examples","text":"","category":"section"},{"location":"domains/#PointSet","page":"Domains","title":"PointSet","text":"","category":"section"},{"location":"domains/","page":"Domains","title":"Domains","text":"PointSet","category":"page"},{"location":"domains/#Meshes.PointSet","page":"Domains","title":"Meshes.PointSet","text":"PointSet(points)\n\nA set of points (a.k.a. point cloud) representing a Domain.\n\nExamples\n\nAll point sets below are the same and contain two points in R³:\n\njulia> PointSet([Point(1,2,3), Point(4,5,6)])\njulia> PointSet(Point(1,2,3), Point(4,5,6))\njulia> PointSet([(1,2,3), (4,5,6)])\njulia> PointSet((1,2,3), (4,5,6))\n\n\n\n\n\n","category":"type"},{"location":"domains/","page":"Domains","title":"Domains","text":"pset = PointSet(rand(Point, 100))\n\nviz(pset)","category":"page"},{"location":"domains/#GeometrySet","page":"Domains","title":"GeometrySet","text":"","category":"section"},{"location":"domains/","page":"Domains","title":"Domains","text":"GeometrySet","category":"page"},{"location":"domains/#Meshes.GeometrySet","page":"Domains","title":"Meshes.GeometrySet","text":"GeometrySet(geometries)\n\nA set of geometries representing a Domain.\n\nExamples\n\nSet containing two balls centered at (0.0, 0.0) and (1.0, 1.0):\n\njulia> GeometrySet([Ball((0.0, 0.0)), Ball((1.0, 1.0))])\n\nNotes\n\nGeometries with different CRS will be projected to the CRS of the first geometry.\n\n\n\n\n\n","category":"type"},{"location":"domains/","page":"Domains","title":"Domains","text":"tria = Triangle((0.0, 0.0), (1.0, 1.0), (0.0, 1.0))\nquad = Quadrangle((1.0, 1.0), (2.0, 1.0), (2.0, 2.0), (1.0, 2.0))\ngset = GeometrySet([tria, quad])\n\nviz(gset, showsegments = true)","category":"page"},{"location":"domains/#CartesianGrid","page":"Domains","title":"CartesianGrid","text":"","category":"section"},{"location":"domains/","page":"Domains","title":"Domains","text":"RegularGrid\nCartesianGrid","category":"page"},{"location":"domains/#Meshes.RegularGrid","page":"Domains","title":"Meshes.RegularGrid","text":"RegularGrid(dims, origin, spacing)\n\nA regular grid with dimensions dims, lower left corner at origin and cell spacing spacing. The three arguments must have the same length.\n\nRegularGrid(dims, origin, spacing, offset)\n\nA regular grid with dimensions dims, with lower left corner of element offset at origin and cell spacing spacing.\n\nRegularGrid(start, finish, dims=dims)\n\nAlternatively, construct a regular grid from a start point to a finish with dimensions dims.\n\nRegularGrid(start, finish, spacing)\n\nAlternatively, construct a regular grid from a start point to a finish point using a given spacing.\n\nExamples\n\nRegularGrid((10, 20), Point(LatLon(30.0°, 60.0°)), (1.0, 1.0)) # add coordinate units to spacing\nRegularGrid((10, 20), Point(Polar(0.0cm, 0.0rad)), (10.0mm, 1.0rad)) # convert spacing units to coordinate units\nRegularGrid((10, 20), Point(Mercator(0.0, 0.0)), (1.5, 1.5))\nRegularGrid((10, 20, 30), Point(Cylindrical(0.0, 0.0, 0.0)), (3.0, 2.0, 1.0))\n\nSee also CartesianGrid.\n\n\n\n\n\n","category":"type"},{"location":"domains/#Meshes.CartesianGrid","page":"Domains","title":"Meshes.CartesianGrid","text":"CartesianGrid(dims, origin, spacing)\n\nA Cartesian grid with dimensions dims, lower left corner at origin and cell spacing spacing. The three arguments must have the same length.\n\nCartesianGrid(dims, origin, spacing, offset)\n\nA Cartesian grid with dimensions dims, with lower left corner of element offset at origin and cell spacing spacing.\n\nCartesianGrid(start, finish, dims=dims)\n\nAlternatively, construct a Cartesian grid from a start point (lower left) to a finish point (upper right).\n\nCartesianGrid(start, finish, spacing)\n\nAlternatively, construct a Cartesian grid from a start point to a finish point using a given spacing.\n\nCartesianGrid(dims)\nCartesianGrid(dim1, dim2, ...)\n\nFinally, a Cartesian grid can be constructed by only passing the dimensions dims as a tuple, or by passing each dimension dim1, dim2, ... separately. In this case, the origin and spacing default to (0,0,...) and (1,1,...).\n\nCartesianGrid is an alias to RegularGrid with Cartesian CRS.\n\nExamples\n\nCreate a 3D grid with 100x100x50 hexahedrons:\n\njulia> CartesianGrid(100, 100, 50)\n\nCreate a 2D grid with 100 x 100 quadrangles and origin at (10.0, 20.0):\n\njulia> CartesianGrid((100, 100), (10.0, 20.0), (1.0, 1.0))\n\nCreate a 1D grid from -1 to 1 with 100 segments:\n\njulia> CartesianGrid((-1.0,), (1.0,), dims=(100,))\n\nSee also RegularGrid.\n\n\n\n\n\n","category":"type"},{"location":"domains/","page":"Domains","title":"Domains","text":"grid = CartesianGrid(10, 10, 10)\n\nviz(grid, showsegments = true)","category":"page"},{"location":"kriging/#Kriging","page":"Kriging","title":"Kriging","text":"","category":"section"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"note: Note\nThis section describes the Kriging models used in the Interpolate and InterpolateNeighbors transforms, which provide options for neighborhood search, change of support, etc.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"A Kriging model has the form:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"hatZ(x_0) = lambda_1 Z(x_1) + lambda_2 Z(x_2) + cdots + lambda_n Z(x_n)quad x_i in R^m lambda_i in R","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"with Zcolon R^m times Omega to R a random field.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"This package implements the following Kriging variants:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"Simple Kriging\nOrdinary Kriging\nUniversal Kriging\nExternal Drift Kriging","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"All these variants follow the same interface: an object is first created with a given set of parameters, it is then combined with the data to obtain predictions at new geometries.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"The fit function takes care of building the Kriging system and factorizing the LHS with an appropriate decomposition (e.g. Cholesky, LU), and the predict (or predictprob) function performs the estimation for a given variable and geometry.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"All variants work with general Hilbert spaces, meaning that one can interpolate any data type that implements scalar multiplication, vector addition and inner product.","category":"page"},{"location":"kriging/#Simple-Kriging","page":"Kriging","title":"Simple Kriging","text":"","category":"section"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"In Simple Kriging, the mean mu of the random field is assumed to be constant and known. The resulting linear system is:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"beginbmatrix\ncov(x_1x_1) cov(x_1x_2) cdots cov(x_1x_n) \ncov(x_2x_1) cov(x_2x_2) cdots cov(x_2x_n) \nvdots vdots ddots vdots \ncov(x_nx_1) cov(x_nx_2) cdots cov(x_nx_n)\nendbmatrix\nbeginbmatrix\nlambda_1 \nlambda_2 \nvdots \nlambda_n\nendbmatrix\n=\nbeginbmatrix\ncov(x_1x_0) \ncov(x_2x_0) \nvdots \ncov(x_nx_0)\nendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"or in matricial form Cl = c. We subtract the given mean from the observations boldsymboly = z - mu 1 and compute the mean and variance at location x_0:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x_0) = mu + boldsymboly^top l","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"sigma^2(x_0) = cov(0) - c^top l","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"GeoStatsModels.SimpleKriging","category":"page"},{"location":"kriging/#GeoStatsModels.SimpleKriging","page":"Kriging","title":"GeoStatsModels.SimpleKriging","text":"SimpleKriging(γ, μ)\n\nSimple Kriging with variogram model γ and constant mean μ.\n\nNotes\n\nSimple Kriging requires stationary variograms\n\n\n\n\n\n","category":"type"},{"location":"kriging/#Ordinary-Kriging","page":"Kriging","title":"Ordinary Kriging","text":"","category":"section"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"In Ordinary Kriging the mean of the random field is assumed to be constant and unknown. The resulting linear system is:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"beginbmatrix\nG 1 \n1^top 0\nendbmatrix\nbeginbmatrix\nl \nnu\nendbmatrix\n=\nbeginbmatrix\ng \n1\nendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"with nu the Lagrange multiplier associated with the constraint 1^top l = 1. The mean and variance at location x_0 are given by:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x_0) = z^top l","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"sigma^2(x_0) = beginbmatrix g 1 endbmatrix^top beginbmatrix l nu endbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"GeoStatsModels.OrdinaryKriging","category":"page"},{"location":"kriging/#GeoStatsModels.OrdinaryKriging","page":"Kriging","title":"GeoStatsModels.OrdinaryKriging","text":"OrdinaryKriging(γ)\n\nOrdinary Kriging with variogram model γ.\n\n\n\n\n\n","category":"type"},{"location":"kriging/#Universal-Kriging","page":"Kriging","title":"Universal Kriging","text":"","category":"section"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"In Universal Kriging, the mean of the random field is assumed to be a polynomial of the geospatial coordinates:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x) = sum_k=1^N_d beta_k f_k(x)","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"with N_d monomials f_k of degree up to d. For example, in 2D there are 6 monomials of degree up to 2:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x_1x_2) = beta_1 1 + beta_2 x_1 + beta_3 x_2 + beta_4 x_1 x_2 + beta_5 x_1^2 + beta_6 x_2^2","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"The choice of the degree d determines the size of the polynomial matrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"F =\nbeginbmatrix\nf_1(x_1) f_2(x_1) cdots f_N_d(x_1) \nf_1(x_2) f_2(x_2) cdots f_N_d(x_2) \nvdots vdots ddots vdots \nf_1(x_n) f_2(x_n) cdots f_N_d(x_n)\nendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"and polynomial vector f = beginbmatrix f_1(x_0) f_2(x_0) cdots f_N_d(x_0) endbmatrix^top.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"The variogram determines the variogram matrix:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"G =\nbeginbmatrix\ngamma(x_1x_1) gamma(x_1x_2) cdots gamma(x_1x_n) \ngamma(x_2x_1) gamma(x_2x_2) cdots gamma(x_2x_n) \nvdots vdots ddots vdots \ngamma(x_nx_1) gamma(x_nx_2) cdots gamma(x_nx_n)\nendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"and the variogram vector g = beginbmatrix gamma(x_1x_0) gamma(x_2x_0) cdots gamma(x_nx_0) endbmatrix^top.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"The resulting linear system is:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"beginbmatrix\nG F \nF^top boldsymbol0\nendbmatrix\nbeginbmatrix\nl \nboldsymbolnu\nendbmatrix\n=\nbeginbmatrix\ng \nf\nendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"with boldsymbolnu the Lagrange multipliers associated with the universal constraints. The mean and variance at location x_0 are given by:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x_0) = z^top l","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"sigma^2(x_0) = beginbmatrixg fendbmatrix^top beginbmatrixl boldsymbolnuendbmatrix","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"GeoStatsModels.UniversalKriging","category":"page"},{"location":"kriging/#GeoStatsModels.UniversalKriging","page":"Kriging","title":"GeoStatsModels.UniversalKriging","text":"UniversalKriging(γ, degree, dim)\n\nUniversal Kriging with variogram model γ and polynomial of given degree on dim coordinates.\n\nNotes\n\nOrdinaryKriging is recovered for 0th degree polynomial\nFor non-polynomial mean, see ExternalDriftKriging\n\n\n\n\n\n","category":"type"},{"location":"kriging/#External-Drift-Kriging","page":"Kriging","title":"External Drift Kriging","text":"","category":"section"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"In External Drift Kriging, the mean of the random field is assumed to be a combination of known smooth functions:","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"mu(x) = sum_k beta_k m_k(x)","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"Differently than Universal Kriging, the functions m_k are not necessarily polynomials of the geospatial coordinates. In practice, they represent a list of variables that is strongly correlated (and co-located) with the variable being estimated.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"External drifts are known to cause numerical instability. Give preference to other Kriging variants if possible.","category":"page"},{"location":"kriging/","page":"Kriging","title":"Kriging","text":"GeoStatsModels.ExternalDriftKriging","category":"page"},{"location":"kriging/#GeoStatsModels.ExternalDriftKriging","page":"Kriging","title":"GeoStatsModels.ExternalDriftKriging","text":"ExternalDriftKriging(γ, drifts)\n\nExternal Drift Kriging with variogram model γ and external drifts functions. A drift function p -> v maps a point p to a value v.\n\nNotes\n\nExternal drift functions should be smooth\nKriging system with external drift is often unstable\nInclude a constant drift (e.g. p -> 1) for unbiased estimation\nOrdinaryKriging is recovered for drifts = [p -> 1]\nFor polynomial mean, see UniversalKriging\n\n\n\n\n\n","category":"type"},{"location":"random/fields/#Fields","page":"Fields","title":"Fields","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"Base.rand(::GeoStatsProcesses.FieldProcess, ::Domain, ::Any, ::Any)","category":"page"},{"location":"random/fields/#Base.rand-Tuple{GeoStatsProcesses.FieldProcess, Domain, Any, Any}","page":"Fields","title":"Base.rand","text":"rand([rng], process::FieldProcess, domain, data, [nreals], [method]; [parameters])\n\nGenerate one or nreals realizations of the field process with method over the domain with data and optional paramaters. Optionally, specify the random number generator rng and global parameters.\n\nThe data can be a geotable, a pair, or an iterable of pairs of the form var => T, where var is a symbol or string with the variable name and T is the corresponding data type.\n\nParameters\n\nworkers - Worker processes (default to workers())\nthreads - Number of threads (default to cpucores())\nverbose - Show progress and other information (default to true)\nasync - Return to master process immediately (default to false) \n\nExamples\n\njulia> rand(process, domain, geotable, 3)\njulia> rand(process, domain, :z => Float64)\njulia> rand(process, domain, \"z\" => Float64)\njulia> rand(process, domain, [:a => Float64, :b => Float64])\njulia> rand(process, domain, [\"a\" => Float64, \"b\" => Float64])\n\n\n\n\n\n","category":"method"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"Realizations are stored in an Ensemble as illustrated in the following example:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"Ensemble","category":"page"},{"location":"random/fields/#GeoStatsProcesses.Ensemble","page":"Fields","title":"GeoStatsProcesses.Ensemble","text":"Ensemble\n\nAn ensemble of geostatistical realizations from a geostatistical process.\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\ngrid = CartesianGrid(100, 100)\n\n# Gaussian process\nproc = GaussianProcess(GaussianVariogram(range=30.0))\n\n# unconditional simulation\nreal = rand(proc, grid, [:Z => Float64], 100)","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"We can visualize the first two realizations:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"fig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].Z)\nviz(fig[1,2], real[2].geometry, color = real[2].Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"the mean and variance:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"m, v = mean(real), var(real)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], m.geometry, color = m.Z)\nviz(fig[1,2], v.geometry, color = v.Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"or the 25th and 75th percentiles:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"q25 = quantile(real, 0.25)\nq75 = quantile(real, 0.75)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], q25.geometry, color = q25.Z)\nviz(fig[1,2], q75.geometry, color = q75.Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"The cummulative distribution function is obtained likewise:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"p25 = cdf(real, 0.25)\np75 = cdf(real, 0.75)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], p25.geometry, color = p25.Z)\nviz(fig[1,2], p75.geometry, color = p75.Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"All field processes can generate realizations in parallel using multiple Julia processes. Doing so requires using the Distributed standard library, like in the following example:","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using Distributed\n\n# request additional processes\naddprocs(3)\n\n# load code on every single process\n@everywhere using GeoStats\n\n# setup simulation\ngrid = CartesianGrid(100, 100)\nproc = GaussianProcess(GaussianVariogram(range=30.0))\n\n# perform simulation on all worker processes\nreal = rand(proc, grid, [:Z => Float64], 3, workers = workers())","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"Please consult The ultimate guide to distributed computing in Julia.","category":"page"},{"location":"random/fields/#Builtin","page":"Fields","title":"Builtin","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"The following processes are shipped with the framework.","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"GaussianProcess\nLUMethod\nFFTMethod\nSEQMethod","category":"page"},{"location":"random/fields/#GeoStatsProcesses.GaussianProcess","page":"Fields","title":"GeoStatsProcesses.GaussianProcess","text":"GaussianProcess(variogram=GaussianVariogram(), mean=0.0)\n\nGaussian process with given theoretical variogram and global mean.\n\n\n\n\n\n","category":"type"},{"location":"random/fields/#GeoStatsProcesses.LUMethod","page":"Fields","title":"GeoStatsProcesses.LUMethod","text":"LUMethod(; [paramaters])\n\nThe LU Gaussian process method introduced by Alabert 1987. The full covariance matrix is built to include all locations of the process domain, and samples from the multivariate Gaussian are drawn via LU factorization.\n\nParameters\n\nfactorization - Factorization method (default to cholesky)\ncorrelation - Correlation coefficient between two covariates (default to 0)\ninit - Data initialization method (default to NearestInit())\n\nReferences\n\nAlabert 1987. The practice of fast conditional simulations through the LU decomposition of the covariance matrix\nOliver 2003. Gaussian cosimulation: modeling of the cross-covariance\n\nNotes\n\nThe method is only adequate for domains with relatively small number of elements (e.g. 100x100 grids) where it is feasible to factorize the full covariance.\nFor larger domains (e.g. 3D grids), other methods are preferred such as SEQMethod and FFTMethod.\n\n\n\n\n\n","category":"type"},{"location":"random/fields/#GeoStatsProcesses.FFTMethod","page":"Fields","title":"GeoStatsProcesses.FFTMethod","text":"FFTMethod(; [paramaters])\n\nThe FFT Gaussian process method introduced by Gutjahr 1997. The covariance function is perturbed in the frequency domain after a fast Fourier transform. White noise is added to the phase of the spectrum, and a realization is produced by an inverse Fourier transform.\n\nParameters\n\nminneighbors - Minimum number of neighbors (default to 1)\nmaxneighbors - Maximum number of neighbors (default to 10)\nneighborhood - Search neighborhood (default to nothing)\ndistance - Distance used to find nearest neighbors (default to Euclidean())\n\nReferences\n\nGutjahr 1997. General joint conditional simulations using a fast Fourier transform method\nGómez-Hernández, J. & Srivastava, R. 2021. One Step at a Time: The Origins of Sequential Simulation and Beyond\n\nNotes\n\nThe method is limited to simulations on Cartesian grids, and care must be taken to make sure that the correlation length is small enough compared to the grid size.\nAs a general rule of thumb, avoid correlation lengths greater than 1/3 of the grid.\nThe method is extremely fast, and can be used to generate large 3D realizations.\n\n\n\n\n\n","category":"type"},{"location":"random/fields/#GeoStatsProcesses.SEQMethod","page":"Fields","title":"GeoStatsProcesses.SEQMethod","text":"SEQMethod(; [paramaters])\n\nThe sequential process method introduced by Gomez-Hernandez 1993. It traverses all locations of the geospatial domain according to a path, approximates the conditional Gaussian distribution within a neighborhood using simple Kriging, and assigns a value to the center of the neighborhood by sampling from this distribution.\n\nParameters\n\npath - Process path (default to LinearPath())\nminneighbors - Minimum number of neighbors (default to 1)\nmaxneighbors - Maximum number of neighbors (default to 36)\nneighborhood - Search neighborhood (default to :range)\ndistance - Distance used to find nearest neighbors (default to Euclidean())\ninit - Data initialization method (default to NearestInit())\n\nFor each location in the process path, a maximum number of neighbors maxneighbors is used to fit the conditional Gaussian distribution. The neighbors are searched according to a neighborhood.\n\nThe neighborhood can be a MetricBall, the symbol :range or nothing. The symbol :range is converted to MetricBall(range(γ)) where γ is the variogram of the Gaussian process. If neighborhood is nothing, the nearest neighbors are used without additional constraints.\n\nReferences\n\nGomez-Hernandez & Journel 1993. Joint Sequential Simulation of MultiGaussian Fields\n\nNotes\n\nThis method is very sensitive to the various parameters. Care must be taken to make sure that enough neighbors are used in the underlying Kriging model.\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\ngrid = CartesianGrid(100, 100)\n\n# Gaussian process\nproc = GaussianProcess(GaussianVariogram(range=30.0))\n\n# unconditional simulation\nreal = rand(proc, grid, [:Z => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].Z)\nviz(fig[1,2], real[2].geometry, color = real[2].Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"LindgrenProcess","category":"page"},{"location":"random/fields/#GeoStatsProcesses.LindgrenProcess","page":"Fields","title":"GeoStatsProcesses.LindgrenProcess","text":"LindgrenProcess(range=1.0, sill=1.0; init=NearestInit())\n\nLindgren process with given range (correlation length) and sill (total variance) as described in Lindgren 2011. Optionally, specify the data initialization method init.\n\nThe process relies relies on a discretization of the Laplace-Beltrami operator on meshes and is adequate for highly curved domains (e.g. surfaces).\n\nReferences\n\nLindgren et al. 2011. An explicit link between Gaussian fields and Gaussian Markov random fields: the stochastic partial differential equation approach\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\nmesh = simplexify(Sphere((0, 0, 0), 1))\n\n# Lindgren process\nproc = LindgrenProcess()\n\n# unconditional simulation\nreal = rand(proc, mesh, [:Z => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].Z)\nviz(fig[1,2], real[2].geometry, color = real[2].Z)\nfig","category":"page"},{"location":"random/fields/#External","page":"Fields","title":"External","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"The following processes are available in external packages.","category":"page"},{"location":"random/fields/#ImageQuilting.jl","page":"Fields","title":"ImageQuilting.jl","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"QuiltingProcess","category":"page"},{"location":"random/fields/#GeoStatsProcesses.QuiltingProcess","page":"Fields","title":"GeoStatsProcesses.QuiltingProcess","text":"QuiltingProcess(trainimg, tilesize; [paramaters])\n\nImage quilting process with training image trainimg and tile size tilesize as described in Hoffimann et al. 2017.\n\nParameters\n\noverlap - Overlap size (default to (1/6, 1/6, ..., 1/6))\npath - Process path (:raster (default), :dilation, or :random)\ninactive - Vector of inactive voxels (i.e. CartesianIndex) in the grid\nsoft - A pair (data,dataTI) of geospatial data objects (default to nothing)\ntol - Initial relaxation tolerance in (0,1] (default to 0.1)\ninit - Data initialization method (default to NearestInit())\n\nReferences\n\nHoffimann et al 2017. Stochastic simulation by image quilting of process-based geological models\nHoffimann et al 2015. Geostatistical modeling of evolving landscapes by means of image quilting\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using ImageQuilting\nusing GeoStatsImages\n\n# domain of interest\ngrid = CartesianGrid(200, 200)\n\n# quilting process\nimg = geostatsimage(\"Strebelle\")\nproc = QuiltingProcess(img, (62, 62))\n\n# unconditional simulation\nreal = rand(proc, grid, [:facies => Int], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].facies)\nviz(fig[1,2], real[2].geometry, color = real[2].facies)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\ngrid = CartesianGrid(200, 200)\n\n# quilting process\nimg = geostatsimage(\"StoneWall\")\nproc = QuiltingProcess(img, (13, 13))\n\n# unconditional simulation\nreal = rand(proc, grid, [:Z => Int], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].Z)\nviz(fig[1,2], real[2].geometry, color = real[2].Z)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\ngrid = domain(img)\n\n# pre-existing observations\nimg = geostatsimage(\"Strebelle\")\ndata = img |> Sample(20, replace=false)\n\n# quilting process\nproc = QuiltingProcess(img, (30, 30))\n\n# conditional simulation\nreal = rand(proc, grid, data, 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].facies)\nviz(fig[1,2], real[2].geometry, color = real[2].facies)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"Voxels marked with the special symbol NaN are treated as inactive. The algorithm will skip tiles that only contain inactive voxels to save computation and will generate realizations that are consistent with the mask. This is particularly useful with complex 3D models that have large inactive portions.","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"# domain of interest\ngrid = domain(img)\n\n# skip circle at the center\nnx, ny = size(grid)\nr = 100; circle = []\nfor i in 1:nx, j in 1:ny\n if (i-nx÷2)^2 + (j-ny÷2)^2 < r^2\n push!(circle, CartesianIndex(i, j))\n end\nend\n\n# quilting process\nproc = QuiltingProcess(img, (62, 62), inactive = circle)\n\n# unconditional simulation\nreal = rand(proc, grid, [:facies => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].facies)\nviz(fig[1,2], real[2].geometry, color = real[2].facies)\nfig","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"It is possible to incorporate auxiliary variables to guide the selection of patterns from the training image.","category":"page"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using ImageFiltering\n\n# image assumed as ground truth (unknown)\ntruth = geostatsimage(\"WalkerLakeTruth\")\n\n# training image with similar patterns\nimg = geostatsimage(\"WalkerLake\")\n\n# forward model (blur filter)\nfunction forward(data)\n img = asarray(data, :Z)\n krn = KernelFactors.IIRGaussian([10,10])\n fwd = imfilter(img, krn)\n georef((; fwd=vec(fwd)), domain(data))\nend\n\n# apply forward model to both images\ndata = forward(truth)\ndataTI = forward(img)\n\nproc = QuiltingProcess(img, (27, 27), soft=(data, dataTI))\n\nreal = rand(proc, domain(truth), [:Z => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].Z)\nviz(fig[1,2], real[2].geometry, color = real[2].Z)\nfig","category":"page"},{"location":"random/fields/#TuringPatterns.jl","page":"Fields","title":"TuringPatterns.jl","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"TuringProcess","category":"page"},{"location":"random/fields/#GeoStatsProcesses.TuringProcess","page":"Fields","title":"GeoStatsProcesses.TuringProcess","text":"TuringProcess(; [paramaters])\n\nTuring process as described in Turing 1952.\n\nParameters\n\nparams - basic parameters (default to nothing)\nblur - blur algorithm (default to nothing)\nedge - edge condition (default to nothing)\niter - number of iterations (default to 100)\n\nReferences\n\nTuring 1952. The chemical basis of morphogenesis\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using TuringPatterns\n\n# domain of interest\ngrid = CartesianGrid(200, 200)\n\n# unconditional simulation\nreal = rand(TuringProcess(), grid, [:z => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].z)\nviz(fig[1,2], real[2].geometry, color = real[2].z)\nfig","category":"page"},{"location":"random/fields/#StratiGraphics.jl","page":"Fields","title":"StratiGraphics.jl","text":"","category":"section"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"StrataProcess","category":"page"},{"location":"random/fields/#GeoStatsProcesses.StrataProcess","page":"Fields","title":"GeoStatsProcesses.StrataProcess","text":"StrataProcess(environment; [paramaters])\n\nStrata process with given geological environment as described in Hoffimann 2018.\n\nParameters\n\nstate - Initial geological state\nstack - Stacking scheme (:erosional or :depositional)\nnepochs - Number of epochs (default to 10)\n\nReferences\n\nHoffimann 2018. Morphodynamic analysis and statistical synthesis of geormorphic data\n\n\n\n\n\n","category":"type"},{"location":"random/fields/","page":"Fields","title":"Fields","text":"using StratiGraphics\n\n# domain of interest\ngrid = CartesianGrid(50, 50, 20)\n\n# stratigraphic environment\np = SmoothingProcess()\nT = [0.5 0.5; 0.5 0.5]\nΔ = ExponentialDuration(1.0)\nℰ = Environment([p, p], T, Δ)\n\n# strata simulation\nreal = rand(StrataProcess(ℰ), grid, [:z => Float64], 2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], real[1].geometry, color = real[1].z)\nviz(fig[1,2], real[2].geometry, color = real[2].z)\nfig","category":"page"},{"location":"transiography/theoretical/#Theoretical-transiograms","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"We provide various theoretical transiogram models from the literature, which can can be combined with ellipsoid distances to model geometric anisotropy.","category":"page"},{"location":"transiography/theoretical/#Models","page":"Theoretical transiograms","title":"Models","text":"","category":"section"},{"location":"transiography/theoretical/#Linear","page":"Theoretical transiograms","title":"Linear","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"LinearTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.LinearTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.LinearTransiogram","text":"LinearTransiogram(; ranges, proportions)\nLinearTransiogram(ball; proportions)\n\nA linear transiogram with ranges, and proportions. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"transioplot(LinearTransiogram())","category":"page"},{"location":"transiography/theoretical/#Gaussian","page":"Theoretical transiograms","title":"Gaussian","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"GaussianTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.GaussianTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.GaussianTransiogram","text":"GaussianTransiogram(; ranges, proportions)\nGaussianTransiogram(ball; proportions)\n\nA Gaussian transiogram with ranges, and proportions. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"transioplot(GaussianTransiogram())","category":"page"},{"location":"transiography/theoretical/#Spherical","page":"Theoretical transiograms","title":"Spherical","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"SphericalTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.SphericalTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.SphericalTransiogram","text":"SphericalTransiogram(; ranges, proportions)\nSphericalTransiogram(ball; proportions)\n\nA spherical transiogram with ranges, and proportions. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"transioplot(SphericalTransiogram())","category":"page"},{"location":"transiography/theoretical/#Exponential","page":"Theoretical transiograms","title":"Exponential","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"ExponentialTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.ExponentialTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.ExponentialTransiogram","text":"ExponentialTransiogram(; ranges, proportions)\nExponentialTransiogram(ball; proportions)\n\nA exponential transiogram with ranges, and proportions. Optionally, use a custom metric ball.\n\n\n\n\n\n","category":"type"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"transioplot(ExponentialTransiogram())","category":"page"},{"location":"transiography/theoretical/#MatrixExponential","page":"Theoretical transiograms","title":"MatrixExponential","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"MatrixExponentialTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.MatrixExponentialTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.MatrixExponentialTransiogram","text":"MatrixExponentialTransiogram(rate)\nMatrixExponentialTransiogram(ball, rate)\n\nAn exponential transiogram with transition rate matrix. Optionally, specify a metric ball to model anisotropy.\n\nMatrixExponentialTransiogram(lengths, proportions)\nMatrixExponentialTransiogram(ball, lengths, proportions)\n\nAlternatively, build transition rate matrix from mean lengths and relative proportions.\n\nReferences\n\nCarle, S.F. & Fogg, G.E. 1996. Transition probability-based indicator geostatistics\nCarle et al 1998. Conditional Simulation of Hydrofacies Architecture: A Transition Probability/Markov Approach\n\n\n\n\n\n","category":"type"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"transioplot(MatrixExponentialTransiogram((1.0u\"m\", 1.0u\"m\"), (0.5, 0.5)))","category":"page"},{"location":"transiography/theoretical/#PiecewiseLinear","page":"Theoretical transiograms","title":"PiecewiseLinear","text":"","category":"section"},{"location":"transiography/theoretical/","page":"Theoretical transiograms","title":"Theoretical transiograms","text":"PiecewiseLinearTransiogram","category":"page"},{"location":"transiography/theoretical/#GeoStatsFunctions.PiecewiseLinearTransiogram","page":"Theoretical transiograms","title":"GeoStatsFunctions.PiecewiseLinearTransiogram","text":"PiecewiseLinearTransiogram(abscissas, ordinates)\nPiecewiseLinearTransiogram(ball, abscissas, ordinates)\n\nA piecewise-linear transiogram model with abscissas and matrix ordinates obtained from an EmpiricalTransiogram. Optionally, specify a metric ball to model anisotropy.\n\nReferences\n\nLi, W. & Zhang, C. 2005. Application of Transiograms to Markov Chain Simulation and Spatial Uncertainty Assessment of Land-Cover Classes\nLi, W. & Zhang, C. 2010. Linear interpolation and joint model fitting of experimental transiograms for Markov chain simulation of categorical spatial variables\n\n\n\n\n\n","category":"type"},{"location":"resources/publications/#Publications","page":"Publications","title":"Publications","text":"","category":"section"},{"location":"resources/publications/","page":"Publications","title":"Publications","text":"Below is a list of publications made possible with this project:","category":"page"},{"location":"resources/publications/","page":"Publications","title":"Publications","text":"Kim et al. 2024. Coal Thickness Through Compositional Kriging: An Approach Based on Geostatistics\nDoherty et al. 2024 A Method for Quantifying Uncertainty in Spatially Interpolated Meteorological Data with Application to Daily Maximum Air Temperature\nKo et al. 2024. Scaling Hawkes processes to one million COVID-19 cases\nHoffimann, J. 2023. Geospatial Data Science with Julia\nGruchalla et al. 2023. Reevaluating Contour Visualizations for Power Systems Data\nKarsanina, M. & Gerke, K. 2022. Stochastic (re)constructions of non-stationary material structures: Using ensemble averaged correlation functions and non-uniform phase distributions\nSepúlveda et al. 2022. Evaluation of multivariate Gaussian transforms for geostatistical applications\nHoffimann et al. 2022. Modeling Geospatial Uncertainty of Geometallurgical Variables with Bayesian Models and Hilbert-Kriging\nHoffimann et al. 2021. Geostatistical Learning: Challenges and Opportunities\nAsner et al. 2021. Abiotic and Human Drivers of Reef Habitat Complexity Throughout the Main Hawaiian Islands\nAsner et al. 2020. Large-scale mapping of live corals to guide reef conservation\nHoffimann, J. & Zadrozny, B. 2019. Efficient Variography with Partition Variograms\nHoffimann et al. 2019. Morphodynamic Analysis and Statistical Synthesis of Geomorphic Data: Application to a Flume Experiment\nBarfod et al. 2017. Hydrostratigraphic Modeling using Multiple-point Statistics and Airborne Transient Electromagnetic Methods\nHoffimann et al. 2017. Stochastic Simulation by Image Quilting of Process-based Geological Models","category":"page"},{"location":"transforms/#Geospatial-transforms","page":"Transforms","title":"Geospatial transforms","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"We provide a very powerful list of transforms that were designed to work seamlessly with geospatial data. These transforms are implemented in different packages depending on how they interact with geometries.","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"The list of supported transforms is continuously growing. The following code can be used to print an updated list in any project environment:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# packages to print type tree\nusing InteractiveUtils\nusing AbstractTrees\nusing TransformsBase\n\n# packages with transforms\nusing GeoStats\n\n# define the tree of types\nAbstractTrees.children(T::Type) = subtypes(T)\n\n# print all currently available transforms\nAbstractTrees.print_tree(TransformsBase.Transform)","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Transforms at the leaves of the tree above should have a docstring with more information on the available options. For example, the documentation of the Select transform is shown below:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Select","category":"page"},{"location":"transforms/#TableTransforms.Select","page":"Transforms","title":"TableTransforms.Select","text":"Select(col₁, col₂, ..., colₙ)\nSelect([col₁, col₂, ..., colₙ])\nSelect((col₁, col₂, ..., colₙ))\n\nThe transform that selects columns col₁, col₂, ..., colₙ.\n\nSelect(col₁ => newcol₁, col₂ => newcol₂, ..., colₙ => newcolₙ)\n\nSelects the columns col₁, col₂, ..., colₙ and rename them to newcol₁, newcol₂, ..., newcolₙ.\n\nSelect(regex)\n\nSelects the columns that match with regex.\n\nExamples\n\nSelect(1, 3, 5)\nSelect([:a, :c, :e])\nSelect((\"a\", \"c\", \"e\"))\nSelect(1 => :x, 3 => :y)\nSelect(:a => :x, :b => :y)\nSelect(\"a\" => \"x\", \"b\" => \"y\")\nSelect(r\"[ace]\")\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Transforms of type FeatureTransform operate on the attribute table, whereas transforms of type GeometricTransform operate on the underlying geospatial domain:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"TableTransforms.FeatureTransform\nMeshes.GeometricTransform","category":"page"},{"location":"transforms/#TableTransforms.FeatureTransform","page":"Transforms","title":"TableTransforms.FeatureTransform","text":"FeatureTransform\n\nA transform that operates on the columns of the table containing features, i.e., simple attributes such as numbers, strings, etc.\n\n\n\n\n\n","category":"type"},{"location":"transforms/#Meshes.GeometricTransform","page":"Transforms","title":"Meshes.GeometricTransform","text":"GeometricTransform\n\nA method to transform the geometry (e.g. coordinates) of objects. See https://en.wikipedia.org/wiki/Geometric_transformation.\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Other transforms such as Detrend are defined in terms of both the geospatial domain and the attribute table. All transforms and pipelines implement the following functions:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"TransformsBase.isrevertible\nTransformsBase.isinvertible\nTransformsBase.inverse\nTransformsBase.apply\nTransformsBase.revert\nTransformsBase.reapply","category":"page"},{"location":"transforms/#TransformsBase.isrevertible","page":"Transforms","title":"TransformsBase.isrevertible","text":"isrevertible(transform)\n\nTells whether or not the transform is revertible, i.e. supports a revert function. Defaults to false for new transform types.\n\nTransforms can be revertible and yet don't be invertible. Invertibility is a mathematical concept, whereas revertibility is a computational concept.\n\nSee also isinvertible.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#TransformsBase.isinvertible","page":"Transforms","title":"TransformsBase.isinvertible","text":"isinvertible(transform)\n\nTells whether or not the transform is invertible, i.e. whether it implements the inverse function. Defaults to false for new transform types.\n\nTransforms can be invertible in the mathematical sense, i.e., there exists a one-to-one mapping between input and output spaces.\n\nSee also inverse, isrevertible.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#TransformsBase.inverse","page":"Transforms","title":"TransformsBase.inverse","text":"inverse(transform)\n\nReturns the inverse transform of the transform.\n\nSee also isinvertible.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#TransformsBase.apply","page":"Transforms","title":"TransformsBase.apply","text":"newobject, cache = apply(transform, object)\n\nApply transform on the object. Return the newobject and a cache to revert the transform later.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#TransformsBase.revert","page":"Transforms","title":"TransformsBase.revert","text":"object = revert(transform, newobject, cache)\n\nRevert the transform on the newobject using the cache from the corresponding apply call and return the original object. Only defined when the transform isrevertible.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#TransformsBase.reapply","page":"Transforms","title":"TransformsBase.reapply","text":"newobject = reapply(transform, object, cache)\n\nReapply the transform to (a possibly different) object using a cache that was created with a previous apply call. Fallback to apply without using the cache.\n\n\n\n\n\n","category":"function"},{"location":"transforms/#Feature-transforms","page":"Transforms","title":"Feature transforms","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Please check the TableTransforms.jl documentation for an updated list of feature transforms. As an example consider the following features over a Cartesian grid and their statistics:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"using DataFrames\n\n# table of features and domain\ntab = DataFrame(a=rand(1000), b=randn(1000), c=rand(1000))\ndom = CartesianGrid(100, 100)\n\n# georeference table onto domain\nΩ = georef(tab, dom)\n\n# describe features\ndescribe(values(Ω))","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"We can create a pipeline that transforms the features to their normal quantile (or scores):","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"pipe = Quantile()\n\nΩ̄, cache = apply(pipe, Ω)\n\ndescribe(values(Ω̄))","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"We can then revert the transform given any new geospatial data in the transformed sample space:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Ωₒ = revert(pipe, Ω̄, cache)\n\ndescribe(values(Ωₒ))","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"The Learn transform is another important transform from StatsLearnModels.jl:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Learn","category":"page"},{"location":"transforms/#StatsLearnModels.Learn","page":"Transforms","title":"StatsLearnModels.Learn","text":"Learn(train, model, incols => outcols)\n\nFits the statistical learning model using the input columns, selected by incols, and the output columns, selected by outcols, from the train table.\n\nThe column selection can be a single column identifier (index or name), a collection of identifiers or a regular expression (regex).\n\nExamples\n\nLearn(train, model, [1, 2, 3] => \"d\")\nLearn(train, model, [:a, :b, :c] => :d)\nLearn(train, model, [\"a\", \"b\", \"c\"] => 4)\nLearn(train, model, [1, 2, 3] => [:d, :e])\nLearn(train, model, r\"[abc]\" => [\"d\", \"e\"])\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"For more details, consider watching our JuliaCon2021 talk:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"
\n\n
","category":"page"},{"location":"transforms/#Geometric-transforms","page":"Transforms","title":"Geometric transforms","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Please check the Meshes.jl documentation for an updated list of geometric transforms. As an example consider the rotation of geospatial data over a Cartesian grid:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# geospatial domain\nΩ = georef((Z=rand(10, 10),))\n\n# apply geometric transform\nΩr = Ω |> Rotate(Angle2d(π/4))\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], Ω.geometry, color = Ω.Z)\nviz(fig[1,2], Ωr.geometry, color = Ωr.Z)\nfig","category":"page"},{"location":"transforms/#Geostatistical-transforms","page":"Transforms","title":"Geostatistical transforms","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Bellow is the current list of transforms that operate on both the geometries and features of geospatial data. They are implemented in the GeoStatsBase.jl package.","category":"page"},{"location":"transforms/#UniqueCoords","page":"Transforms","title":"UniqueCoords","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"UniqueCoords","category":"page"},{"location":"transforms/#GeoStatsTransforms.UniqueCoords","page":"Transforms","title":"GeoStatsTransforms.UniqueCoords","text":"UniqueCoords(var₁ => agg₁, var₂ => agg₂, ..., varₙ => aggₙ)\n\nRetain locations in data with unique coordinates.\n\nDuplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.\n\nExamples\n\nUniqueCoords(1 => last, 2 => maximum)\nUniqueCoords(:a => first, :b => minimum)\nUniqueCoords(\"a\" => last, \"b\" => maximum)\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# point set with repeated points\np = rand(Point, 50)\nΩ = georef((Z=rand(100),), [p; p])","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# discard repeated points\n𝒰 = Ω |> UniqueCoords()","category":"page"},{"location":"transforms/#Detrend","page":"Transforms","title":"Detrend","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Detrend","category":"page"},{"location":"transforms/#GeoStatsTransforms.Detrend","page":"Transforms","title":"GeoStatsTransforms.Detrend","text":"Detrend(col₁, col₂, ..., colₙ; degree=1)\nDetrend([col₁, col₂, ..., colₙ]; degree=1)\nDetrend((col₁, col₂, ..., colₙ); degree=1)\n\nThe transform that detrends columns col₁, col₂, ..., colₙ with a polynomial of given degree.\n\nDetrend(regex; degree=1)\n\nDetrends the columns that match with regex.\n\nExamples\n\nDetrend(1, 3, 5)\nDetrend([:a, :c, :e])\nDetrend((\"a\", \"c\", \"e\"))\nDetrend(r\"[ace]\", degree=2)\nDetrend(:)\n\nReferences\n\nMenafoglio, A., Secchi, P. 2013. A Universal Kriging predictor for spatially dependent functional data of a Hilbert Space\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# quadratic trend + random noise\nr = range(-1, stop=1, length=100)\nμ = [x^2 + y^2 for x in r, y in r]\nϵ = 0.1rand(100, 100)\nΩ = georef((Z=μ+ϵ,))\n\n# detrend and obtain noise component\n𝒩 = Ω |> Detrend(:Z, degree=2)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], Ω.geometry, color = Ω.Z)\nviz(fig[1,2], 𝒩.geometry, color = 𝒩.Z)\nfig","category":"page"},{"location":"transforms/#Potrace","page":"Transforms","title":"Potrace","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Potrace","category":"page"},{"location":"transforms/#GeoStatsTransforms.Potrace","page":"Transforms","title":"GeoStatsTransforms.Potrace","text":"Potrace(mask; [ϵ])\nPotrace(mask, var₁ => agg₁, ..., varₙ => aggₙ; [ϵ])\n\nTrace polygons on 2D image data with Selinger's Potrace algorithm.\n\nThe categories stored in column mask are converted into binary masks, which are then traced into multi-polygons. When provided, the option ϵ is forwarded to Selinger's simplification algorithm.\n\nDuplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.\n\nExamples\n\nPotrace(:mask, ϵ=0.1)\nPotrace(1, 1 => last, 2 => maximum)\nPotrace(:mask, :a => first, :b => minimum)\nPotrace(\"mask\", \"a\" => last, \"b\" => maximum)\n\nReferences\n\nSelinger, P. 2003. Potrace: A polygon-based tracing algorithm\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"# continuous feature\nZ = [sin(i/10) + sin(j/10) for i in 1:100, j in 1:100]\n\n# binary mask\nM = Z .> 0\n\n# georeference data\nΩ = georef((Z=Z, M=M))\n\n# trace polygons using mask\n𝒯 = Ω |> Potrace(:M)\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], Ω.geometry, color = Ω.Z)\nviz(fig[1,2], 𝒯.geometry, color = 𝒯.Z)\nfig","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"𝒯.geometry","category":"page"},{"location":"transforms/#Rasterize","page":"Transforms","title":"Rasterize","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Rasterize","category":"page"},{"location":"transforms/#GeoStatsTransforms.Rasterize","page":"Transforms","title":"GeoStatsTransforms.Rasterize","text":"Rasterize(grid)\nRasterize(grid, var₁ => agg₁, ..., varₙ => aggₙ)\n\nRasterize geometries within specified grid.\n\nRasterize(nx, ny)\nRasterize(nx, ny, var₁ => agg₁, ..., varₙ => aggₙ)\n\nAlternatively, use the grid with size nx by ny obtained with discretization of the bounding box.\n\nDuplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.\n\nExamples\n\ngrid = CartesianGrid(10, 10)\nRasterize(grid)\nRasterize(10, 10)\nRasterize(grid, 1 => last, 2 => maximum)\nRasterize(10, 10, 1 => last, 2 => maximum)\nRasterize(grid, :a => first, :b => minimum)\nRasterize(10, 10, :a => first, :b => minimum)\nRasterize(grid, \"a\" => last, \"b\" => maximum)\nRasterize(10, 10, \"a\" => last, \"b\" => maximum)\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"A = [1, 2, 3, 4, 5]\nB = [1.1, 2.2, 3.3, 4.4, 5.5]\np1 = PolyArea((2, 0), (6, 2), (2, 2))\np2 = PolyArea((0, 6), (3, 8), (0, 10))\np3 = PolyArea((3, 6), (9, 6), (9, 9), (6, 9))\np4 = PolyArea((7, 0), (10, 0), (10, 4), (7, 4))\np5 = PolyArea((1, 3), (5, 3), (6, 6), (3, 8), (0, 6))\ngt = georef((; A, B), [p1, p2, p3, p4, p5])\n\nnt = gt |> Rasterize(20, 20)\n\nviz(nt.geometry, color = nt.A)","category":"page"},{"location":"transforms/#Clustering","page":"Transforms","title":"Clustering","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Unlike traditional clustering algorithms in machine learning, geostatistical clustering (a.k.a. domaining) algorithms consider both the features and the geospatial coordinates of the data.","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Consider the following data as an example:","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Ω = georef((Z=[10sin(i/10) + j for i in 1:4:100, j in 1:4:100],))\n\nviz(Ω.geometry, color = Ω.Z)","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"GHC","category":"page"},{"location":"transforms/#GeoStatsTransforms.GHC","page":"Transforms","title":"GeoStatsTransforms.GHC","text":"GHC(k, λ; kern=:epanechnikov, link=:ward, as=:cluster)\n\nA transform for partitioning geospatial data into k clusters according to a range λ using Geostatistical Hierarchical Clustering (GHC). The larger the range the more connected are nearby samples.\n\nParameters\n\nk - Approximate number of clusters\nλ - Approximate range of kernel function in length units\nkern - Kernel function (:uniform, :triangular or :epanechnikov)\nlink - Linkage function (:single, :average, :complete, :ward or :ward_presquared)\nas - Variable name used to store clustering results\n\nReferences\n\nFouedjio, F. 2016. A hierarchical clustering method for multivariate geostatistical data\n\nNotes\n\nThe range parameter controls the sparsity pattern of the pairwise distances, which can greatly affect the computational performance of the GHC algorithm. We recommend choosing a range that is small enough to connect nearby samples. For example, clustering data over a 100x100 Cartesian grid with unit spacing is possible with λ=1.0 or λ=2.0 but the problem starts to become computationally unfeasible around λ=10.0 due to the density of points.\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"𝒞 = Ω |> GHC(20, 1.0)\n\nviz(𝒞.geometry, color = 𝒞.cluster)","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"GSC","category":"page"},{"location":"transforms/#GeoStatsTransforms.GSC","page":"Transforms","title":"GeoStatsTransforms.GSC","text":"GSC(k, m; σ=1.0, tol=1e-4, maxiter=10, weights=nothing, as=:cluster)\n\nA transform for partitioning geospatial data into k clusters using Geostatistical Spectral Clustering (GSC).\n\nParameters\n\nk - Desired number of clusters\nm - Multiplicative factor for adjacent weights\nσ - Standard deviation for exponential model (default to 1.0)\ntol - Tolerance of k-means algorithm (default to 1e-4)\nmaxiter - Maximum number of iterations (default to 10)\nweights - Dictionary with weights for each attribute (default to nothing)\nas - Variable name used to store clustering results\n\nReferences\n\nRomary et al. 2015. Unsupervised classification of multivariate geostatistical data: Two algorithms\n\nNotes\n\nThe algorithm implemented here is slightly different than the algorithm\n\ndescribed in Romary et al. 2015. Instead of setting Wᵢⱼ = 0 when i <-/-> j, we simply magnify the weight by a multiplicative factor Wᵢⱼ *= m when i <–> j. This leads to dense matrices but also better results in practice.\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"𝒞 = Ω |> GSC(50, 2.0)\n\nviz(𝒞.geometry, color = 𝒞.cluster)","category":"page"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"SLIC","category":"page"},{"location":"transforms/#GeoStatsTransforms.SLIC","page":"Transforms","title":"GeoStatsTransforms.SLIC","text":"SLIC(k, m; tol=1e-4, maxiter=10, weights=nothing, as=:cluster)\n\nA transform for clustering geospatial data into approximately k clusters using Simple Linear Iterative Clustering (SLIC). The transform produces clusters of samples that are spatially connected based on a distance dₛ and that, at the same time, are similar in terms of vars with distance dᵥ. The tradeoff is controlled with a hyperparameter parameter m in an additive model dₜ = √(dᵥ² + m²(dₛ/s)²).\n\nParameters\n\nk - Approximate number of clusters\nm - Hyperparameter of SLIC model\ntol - Tolerance of k-means algorithm (default to 1e-4)\nmaxiter - Maximum number of iterations (default to 10)\nweights - Dictionary with weights for each attribute (default to nothing)\nas - Variable name used to store clustering results\n\nReferences\n\nAchanta et al. 2011. SLIC superpixels compared to state-of-the-art superpixel methods\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"𝒞 = Ω |> SLIC(50, 0.01)\n\nviz(𝒞.geometry, color = 𝒞.cluster)","category":"page"},{"location":"transforms/#Interpolate","page":"Transforms","title":"Interpolate","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Interpolate\nInterpolateNeighbors\nInterpolateMissing\nInterpolateNaN","category":"page"},{"location":"transforms/#GeoStatsTransforms.Interpolate","page":"Transforms","title":"GeoStatsTransforms.Interpolate","text":"Interpolate(domain, vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\nInterpolate([g₁, g₂, ..., gₙ], vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\n\nInterpolate geospatial data on given domain or vector of geometries [g₁, g₂, ..., gₙ], using geostatistical models model₁, ..., modelₙ for variables vars₁, ..., varsₙ.\n\nInterpolate(domain, model=NN(); [parameters])\nInterpolate([g₁, g₂, ..., gₙ], model=NN(); [parameters])\n\nInterpolate geospatial data on given domain or vector of geometries [g₁, g₂, ..., gₙ], using geostatistical model for all variables.\n\nParameters\n\npoint - Perform interpolation on point support (default to true)\nprob - Perform probabilistic interpolation (default to false)\n\nSee also InterpolateNeighbors, InterpolateMissing, InterpolateNaN.\n\n\n\n\n\n","category":"type"},{"location":"transforms/#GeoStatsTransforms.InterpolateNeighbors","page":"Transforms","title":"GeoStatsTransforms.InterpolateNeighbors","text":"InterpolateNeighbors(domain, vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\nInterpolateNeighbors([g₁, g₂, ..., gₙ], vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\n\nInterpolate geospatial data on given domain or set of geometries g₁, g₂, ..., gₙ, using geostatistical models model₁, ..., modelₙ for variables vars₁, ..., varsₙ.\n\nInterpolateNeighbors(domain, model=NN(); [parameters])\nInterpolateNeighbors([g₁, g₂, ..., gₙ], model=NN(); [parameters])\n\nInterpolate geospatial data on given domain or set of geometries g₁, g₂, ..., gₙ, using geostatistical model for all variables.\n\nUnlike Interpolate, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.\n\nParameters\n\nminneighbors - Minimum number of neighbors (default to 1)\nmaxneighbors - Maximum number of neighbors (default to 10)\nneighborhood - Search neighborhood (default to nothing)\ndistance - A distance defined in Distances.jl (default to Euclidean())\npoint - Perform interpolation on point support (default to true)\nprob - Perform probabilistic interpolation (default to false)\n\nThe maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.\n\nTwo neighborhood search methods are available:\n\nIf a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.\nIf a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.\n\nSee also Interpolate, InterpolateMissing, InterpolateNaN.\n\n\n\n\n\n","category":"type"},{"location":"transforms/#GeoStatsTransforms.InterpolateMissing","page":"Transforms","title":"GeoStatsTransforms.InterpolateMissing","text":"InterpolateMissing(vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\nInterpolateMissing(vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\n\nInterpolate geospatial data on its own domain, using geostatistical models model₁, ..., modelₙ and non-missing values of the variables vars₁, ..., varsₙ.\n\nInterpolateMissing(model=NN(); [parameters])\nInterpolateMissing(model=NN(); [parameters])\n\nInterpolate geospatial data on its own domain, using geostatistical model and non-missing values of all variables.\n\nJust like InterpolateNeighbors, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.\n\nParameters\n\nminneighbors - Minimum number of neighbors (default to 1)\nmaxneighbors - Maximum number of neighbors (default to 10)\nneighborhood - Search neighborhood (default to nothing)\ndistance - A distance defined in Distances.jl (default to Euclidean())\npoint - Perform interpolation on point support (default to true)\nprob - Perform probabilistic interpolation (default to false)\n\nThe maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.\n\nTwo neighborhood search methods are available:\n\nIf a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.\nIf a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.\n\nSee also InterpolateNaN, InterpolateNeighbors, Interpolate.\n\n\n\n\n\n","category":"type"},{"location":"transforms/#GeoStatsTransforms.InterpolateNaN","page":"Transforms","title":"GeoStatsTransforms.InterpolateNaN","text":"InterpolateNaN(vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\nInterpolateNaN(vars₁ => model₁, ..., varsₙ => modelₙ; [parameters])\n\nInterpolate geospatial data on its own domain, using geostatistical models model₁, ..., modelₙ and non-NaN values of the variables vars₁, ..., varsₙ.\n\nInterpolateNaN(model=NN(); [parameters])\nInterpolateNaN(model=NN(); [parameters])\n\nInterpolate geospatial data on its own domain, using geostatistical model and non-NaN values of all variables.\n\nJust like InterpolateNeighbors, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.\n\nParameters\n\nminneighbors - Minimum number of neighbors (default to 1)\nmaxneighbors - Maximum number of neighbors (default to 10)\nneighborhood - Search neighborhood (default to nothing)\ndistance - A distance defined in Distances.jl (default to Euclidean())\npoint - Perform interpolation on point support (default to true)\nprob - Perform probabilistic interpolation (default to false)\n\nThe maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.\n\nTwo neighborhood search methods are available:\n\nIf a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.\nIf a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.\n\nSee also InterpolateMissing, InterpolateNeighbors, Interpolate.\n\n\n\n\n\n","category":"type"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"table = (; Z=[1.,0.,1.])\ncoord = [(25.,25.), (50.,75.), (75.,50.)]\ngeotable = georef(table, coord)\n\ngrid = CartesianGrid(100, 100)\n\nmodel = Kriging(GaussianVariogram(range=35.))\n\ninterp = geotable |> Interpolate(grid, model)\n\nviz(interp.geometry, color = interp.Z)","category":"page"},{"location":"transforms/#Simulate","page":"Transforms","title":"Simulate","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"Simulate","category":"page"},{"location":"transforms/#GeoStatsTransforms.Simulate","page":"Transforms","title":"GeoStatsTransforms.Simulate","text":"Simulate(domain, vars₁ => process₁, ..., varsₙ => processₙ; [parameters])\nSimulate(domain, nreals, vars₁ => process₁, ..., varsₙ => processₙ; [parameters])\nSimulate([g₁, g₂, ..., gₙ], vars₁ => process₁, ..., varsₙ => processₙ; [parameters])\nSimulate([g₁, g₂, ..., gₙ], nreals, vars₁ => process₁, ..., varsₙ => processₙ; [parameters])\n\nSimulate nreals realizations of variables varsᵢ with geostatistical process processᵢ over given domain or vector of geometries [g₁, g₂, ..., gₙ].\n\nThe parameters are forwarded to the rand method of the geostatistical processes.\n\n\n\n\n\n","category":"type"},{"location":"transforms/#CookieCutter","page":"Transforms","title":"CookieCutter","text":"","category":"section"},{"location":"transforms/","page":"Transforms","title":"Transforms","text":"CookieCutter","category":"page"},{"location":"transforms/#GeoStatsTransforms.CookieCutter","page":"Transforms","title":"GeoStatsTransforms.CookieCutter","text":"CookieCutter(domain, parent => process, var₁ => procmap₁, ..., varₙ => procmapₙ; [parameters])\nCookieCutter(domain, nreals, parent => process, var₁ => procmap₁, ..., varₙ => procmapₙ; [parameters])\n\nSimulate nreals realizations of variable parent with geostatistical process process, and each child variable varsᵢ with process map procmapᵢ, over given domain.\n\nThe process map must be an iterable of pairs of the form: value => process. Each process in the map is related to a value of the parent realization, therefore the values of the child variables will be chosen according to the values of the corresponding parent realization.\n\nThe parameters are forwarded to the rand method of the geostatistical processes.\n\nExamples\n\nparent = QuiltingProcess(trainimg, (30, 30))\nchild0 = GaussianProcess(SphericalVariogram(range=20.0, sill=0.2))\nchild1 = GaussianProcess(SphericalVariogram(MetricBall((200.0, 20.0))))\ntransform = CookieCutter(domain, :parent => parent, :child => [0 => child0, 1 => child1])\n\n\n\n\n\n","category":"type"},{"location":"declustering/#Declustering","page":"Declustering","title":"Declustering","text":"","category":"section"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"Declustered statistics are statistics that make use of geospatial coordinates in an attempt to correct potential sampling bias:","category":"page"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"
\n\n
","category":"page"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"The following statistics have geospatial semantics:","category":"page"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"mean(::AbstractGeoTable, ::Any)\nvar(::AbstractGeoTable, ::Any)\nquantile(::AbstractGeoTable, ::Any, ::Any)","category":"page"},{"location":"declustering/#Statistics.mean-Tuple{AbstractGeoTable, Any}","page":"Declustering","title":"Statistics.mean","text":"mean(data, v)\nmean(data, v, s)\n\nDeclustered mean of geospatial data. Optionally, specify the variable v and the block side s.\n\n\n\n\n\n","category":"method"},{"location":"declustering/#Statistics.var-Tuple{AbstractGeoTable, Any}","page":"Declustering","title":"Statistics.var","text":"var(data, v)\nvar(data, v, s)\n\nDeclustered variance of geospatial data. Optionally, specify the variable v and the block side s.\n\n\n\n\n\n","category":"method"},{"location":"declustering/#Statistics.quantile-Tuple{AbstractGeoTable, Any, Any}","page":"Declustering","title":"Statistics.quantile","text":"quantile(data, v, p)\nquantile(data, v, p, s)\n\nDeclustered quantile of geospatial data at probability p. Optionally, specify the variable v and the block side s.\n\n\n\n\n\n","category":"method"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"A histogram with geospatial semantics is also available where the heights of the bins are adjusted based on the coordinates of the samples:","category":"page"},{"location":"declustering/","page":"Declustering","title":"Declustering","text":"EmpiricalHistogram","category":"page"},{"location":"declustering/#GeoStatsBase.EmpiricalHistogram","page":"Declustering","title":"GeoStatsBase.EmpiricalHistogram","text":"EmpiricalHistogram(sdata, var, [s]; kwargs...)\n\nSpatial histogram of variable var in spatial data sdata. Optionally, specify the block side s and the keyword arguments kwargs for the fit(Histogram, ...) call.\n\n\n\n\n\n","category":"type"},{"location":"variography/fitting/#Fitting-variograms","page":"Fitting variograms","title":"Fitting variograms","text":"","category":"section"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"variography/fitting/#Overview","page":"Fitting variograms","title":"Overview","text":"","category":"section"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"Fitting theoretical variograms to empirical observations is an important modeling step to ensure valid mathematical models of geospatial continuity. Given an empirical variogram, the following function can be used to fit models:","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"GeoStatsFunctions.fit","category":"page"},{"location":"variography/fitting/#GeoStatsFunctions.fit","page":"Fitting variograms","title":"GeoStatsFunctions.fit","text":"fit(F, f, algo=WeightedLeastSquares(); kwargs...)\n\nFit theoretical geostatistical function of type F to empirical function f using algorithm algo.\n\nOptionally fix theoretical parameters like range, sill and nugget in the kwargs.\n\nExamples\n\njulia> fit(SphericalVariogram, g)\njulia> fit(ExponentialVariogram, g)\njulia> fit(ExponentialVariogram, g, sill=1.0)\njulia> fit(ExponentialVariogram, g, maxsill=1.0)\njulia> fit(GaussianVariogram, g, WeightedLeastSquares())\n\n\n\n\n\nfit(Fs, f, algo=WeightedLeastSquares(); kwargs...)\n\nFit theoretical geostatistical functions of types Fs to empirical function f using algorithm algo and return the one with minimum error.\n\nExamples\n\njulia> fit([SphericalVariogram, ExponentialVariogram], g)\n\n\n\n\n\nfit(F, f, weightfun; kwargs...)\n\nConvenience method that forwards the weighting function weightfun to the WeightedLeastSquares algorithm.\n\nExamples\n\nfit(SphericalVariogram, g, h -> exp(-h))\nfit(Variogram, g, h -> exp(-h/100))\n\n\n\n\n\nfit(Variogram, g, algo=WeightedLeastSquares(); kwargs...)\n\nFit all stationary Variogram models to empirical variogram g using algorithm algo and return the one with minimum error.\n\nExamples\n\njulia> fit(Variogram, g)\njulia> fit(Variogram, g, WeightedLeastSquares())\n\n\n\n\n\n","category":"function"},{"location":"variography/fitting/#Example","page":"Fitting variograms","title":"Example","text":"","category":"section"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"# sinusoidal data\n𝒟 = georef((Z=[sin(i/2) + sin(j/2) for i in 1:50, j in 1:50],))\n\n# empirical variogram\ng = EmpiricalVariogram(𝒟, :Z, maxlag = 25u\"m\")\n\nvarioplot(g)","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"We can fit specific models to the empirical variogram:","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"γ = GeoStatsFunctions.fit(SineHoleVariogram, g)\n\nvarioplot(g)\nvarioplot!(γ, maxlag = 25u\"m\")\nMke.current_figure()","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"or let the framework find the model with minimum error:","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"γ = GeoStatsFunctions.fit(Variogram, g)\n\nvarioplot(g)\nvarioplot!(γ, maxlag = 25u\"m\")\nMke.current_figure()","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"which should be a SineHoleVariogram given that the synthetic data of this example is sinusoidal.","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"Optionally, we can specify a weighting function to give different weights to the lags:","category":"page"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"γ = GeoStatsFunctions.fit(SineHoleVariogram, g, h -> 1 / h^2)\n\nvarioplot(g)\nvarioplot!(γ, maxlag = 25u\"m\")\nMke.current_figure()","category":"page"},{"location":"variography/fitting/#Methods","page":"Fitting variograms","title":"Methods","text":"","category":"section"},{"location":"variography/fitting/#Weighted-least-squares","page":"Fitting variograms","title":"Weighted least squares","text":"","category":"section"},{"location":"variography/fitting/","page":"Fitting variograms","title":"Fitting variograms","text":"WeightedLeastSquares","category":"page"},{"location":"variography/fitting/#GeoStatsFunctions.WeightedLeastSquares","page":"Fitting variograms","title":"GeoStatsFunctions.WeightedLeastSquares","text":"WeightedLeastSquares()\nWeightedLeastSquares(w)\n\nFit theoretical variogram using weighted least squares with weighting function w (e.g. h -> 1/h). If no weighting function is provided, bin counts of empirical variogram are normalized and used as weights.\n\n\n\n\n\n","category":"type"},{"location":"quickstart/#Quickstart","page":"Quickstart","title":"Quickstart","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"A geostatistical workflow often consists of four steps:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Definition of geospatial data\nManipulation of geospatial data\nGeostatistical modeling\nScientific visualization","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"In this section, we walk through these steps to illustrate some of the features of the project. In the case of geostatistical modeling, we will specifically explore geostatistical learning models. If you prefer learning from video, check out the recording of our JuliaEO 2023 workshop:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"
\n\n
","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We assume that the following packages are loaded throughout the code examples:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"using GeoStats\nimport CairoMakie as Mke","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"The GeoStats.jl package exports the full stack for geospatial data science and geostatistical modeling. The CairoMakie.jl package is one of the possible visualization backends from the Makie.jl project.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"If you are new to Julia and have never heard of Makie.jl before, here are a few tips to help you choose between the different backends:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"WGLMakie.jl is the preferred backend for interactive visualization on the web browser. It integrates well with Pluto.jl notebooks and other web-based applications.\nGLMakie.jl is the preferred backend for interactive high-performance visualization. It leverages native graphical resources and doesn't require a web browser to function.\nCairoMakie.jl is the preferred backend for publication-quality static visualization. It requires less computing power and is therefore recommended for those users with modest laptops.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"note: Note\nWe recommend importing the Makie.jl backend as Mke to avoid polluting the Julia session with names from the visualization stack.","category":"page"},{"location":"quickstart/#Loading/creating-data","page":"Quickstart","title":"Loading/creating data","text":"","category":"section"},{"location":"quickstart/#Loading-data","page":"Quickstart","title":"Loading data","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"The Julia ecosystem for loading geospatial data is comprised of several low-level packages such as Shapefile.jl and GeoJSON.jl, which define their own very basic geometry types. Instead of requesting users to learn the so called GeoInterface.jl to handle these types, we provide the high-level GeoIO.jl package to load any file with geospatial data into well-tested geometries from the Meshes.jl submodule:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"using GeoIO\n\nzone = GeoIO.load(\"data/zone.shp\")","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Various functions are defined over these geometries, for instance:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"sum(area, zone.geometry)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"sum(perimeter, zone.geometry)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Please check the Meshes.jl documentation for more details.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"note: Note\nWe highly recommend using Meshes.jl geometries in geospatial workflows as they were carefully designed to accomodate advanced features of the GeoStats.jl framework. Any other geometry type will likely fail with our geostatistical algorithms and pipelines.","category":"page"},{"location":"quickstart/#Creating-data","page":"Quickstart","title":"Creating data","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Geospatial data can be derived from other Julia variables. For example, given a Julia array, which is not attached to any coordinate system, we can georeference the array using the georef function:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Z = [10sin(i/10) + 2j for i in 1:50, j in 1:50]\n\nΩ = georef((Z=Z,))","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Default coordinates are assigned based on the size of the array, and different configurations can be obtained with different methods (see Data).","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Geospatial data can be visualized with the viz recipe function:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"viz(Ω.geometry, color = Ω.Z)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Alternatively, we provide a basic scientific viewer to visualize all viewable variables in the data with a colorbar and other interactive elements (see Visualization):","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"viewer(Ω)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"note: Note\nJulia supports unicode symbols with LaTeX syntax. We can type \\Omega and press TAB to get the symbol Ω in the example above. This autocompletion works in various text editors, including the VSCode editor with the Julia extension.","category":"page"},{"location":"quickstart/#Manipulating-data","page":"Quickstart","title":"Manipulating data","text":"","category":"section"},{"location":"quickstart/#Table-interface","page":"Quickstart","title":"Table interface","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Our geospatial data implements the Tables.jl interface, which means that they can be accessed as if they were tables with samples in the rows and variables in the columns. In this case, a special column named geometry is created on the fly, row by row, containing Meshes.jl geometries.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"For those familiar with the productive DataFrames.jl interface, there is nothing new:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω[1,:]","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω[1,:geometry]","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω.Z","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"However, notice that our implementation performs some clever optimizations behind the scenes to avoid expensive creation of geometries:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω.geometry","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We can always retrieve the table of attributes (or features) with the function values and the underlying geospatial domain with the function domain. This can be useful for writing algorithms that are type-stable and depend purely on the feature values:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"values(Ω)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"or on the geometries:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"domain(Ω)","category":"page"},{"location":"quickstart/#Geospatial-transforms","page":"Quickstart","title":"Geospatial transforms","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"It is easy to design advanced geospatial pipelines that operate on both the table of features and the underlying geospatial domain:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"# pipeline with table transforms\npipe = Quantile() → StdCoords()\n\n# feed geospatial data to pipeline\nΩ̂ = pipe(Ω)\n\n# plot distribution before and after pipeline\nfig = Mke.Figure(size = (800, 400))\nMke.hist(fig[1,1], Ω.Z, color = :gray)\nMke.hist(fig[2,1], Ω̂.Z, color = :gray)\nfig","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Coordinates before pipeline:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"boundingbox(Ω.geometry)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"and after pipeline:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"boundingbox(Ω̂.geometry)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"These pipelines are revertible meaning that we can transform the data, perform geostatistical modeling, and revert the pipelines to obtain estimates in the original sample space (see Transforms).","category":"page"},{"location":"quickstart/#Geospatial-queries","page":"Quickstart","title":"Geospatial queries","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We provide three macros @groupby, @transform and @combine for powerful geospatial split-apply-combine patterns, as well as the function geojoin for advanced geospatial joins.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"@transform(Ω, :W = 2 * :Z * area(:geometry))","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"These are very useful for geospatial data science as they hide the complexity of the geometry column. For more information, check the Queries section of the documentation.","category":"page"},{"location":"quickstart/#Geostatistical-modeling","page":"Quickstart","title":"Geostatistical modeling","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Having defined the geospatial data objects, we proceed and define the geostatistical learning model. Let's assume that we have geopatial data with some variable that we want to predict in a supervised learning setting. We load the data from a CSV file, and inspect the available columns:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"using CSV\nusing DataFrames\n\ntable = CSV.File(\"data/agriculture.csv\") |> DataFrame\n\nfirst(table, 5)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Columns band1, band2, ..., band4 represent four satellite bands for different locations (x, y) in this region. The column crop has the crop type for each location that was labeled manually with the purpose of fitting a learning model.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We can now georeference the table and plot some of the variables:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω = georef(table, (:x, :y))\n\nfig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], Ω.geometry, color = Ω.band4)\nviz(fig[1,2], Ω.geometry, color = Ω.crop)\nfig","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Similar to a generic statistical learning workflow, we split the data into \"train\" and \"test\" sets. The main difference here is that our geospatial geosplit function accepts a separating plane specified by its normal direction (1,-1):","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ωs, Ωt = geosplit(Ω, 0.2, (1.0, -1.0))\n\nviz(Ωs.geometry)\nviz!(Ωt.geometry, color = :gray90)\nMke.current_figure()","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We can visualize the domain of the \"train\" (or source) set Ωs in blue, and the domain of the \"test\" (or target) set Ωt in gray. We reserved 20% of the samples to Ωs and 80% to Ωt. Internally, this geospatial geosplit function is implemented in terms of efficient geospatial partitions.","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Let's define our geostatistical learning model to predict the crop type based on the four satellite bands. We will use the DecisionTreeClassifier model, which is suitable for the task we want to perform. Any model from the StatsLeanModels.jl model is supported, including all models from ScikitLearn.jl:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"feats = [:band1, :band2, :band3, :band4]\nlabel = :crop\n\nmodel = DecisionTreeClassifier()","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We will fit the model in Ωs where the features and labels are available and predict in Ωt where the features are available. The Learn transform automatically fits the model to the data:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"learn = Learn(Ωs, model, feats => label)","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"The transform can be called with new data to generate predictions:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"Ω̂t = learn(Ωt)","category":"page"},{"location":"quickstart/#Scientific-visualization","page":"Quickstart","title":"Scientific visualization","text":"","category":"section"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"We note that the prediction of a geostatistical learning model is a geospatial data object, and we can inspect it with the same methods already described above. This also means that we can visualize the prediction directly, side by side with the true label in this synthetic example:","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"fig = Mke.Figure(size = (800, 400))\nviz(fig[1,1], Ω̂t.geometry, color = Ω̂t.crop)\nviz(fig[1,2], Ωt.geometry, color = Ωt.crop)\nfig","category":"page"},{"location":"quickstart/","page":"Quickstart","title":"Quickstart","text":"With this example we conclude the basic workflow. To get familiar with other features of the project, please check the the reference guide.","category":"page"},{"location":"resources/ecosystem/#Ecosystem","page":"Ecosystem","title":"Ecosystem","text":"","category":"section"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"The Julia ecosystem for geospatial modeling is maturing very quickly as the result of multiple initiatives such as JuliaEarth, JuliaClimate, and JuliaGeo. Each of these initiatives is associated with a different set of challenges that ultimatively determine the types of packages that are being developed in the corresponding GitHub organizations. In this section, we try to clarify what is available to first-time users of the language.","category":"page"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"\n\n","category":"page"},{"location":"resources/ecosystem/#JuliaEarth","page":"Ecosystem","title":"JuliaEarth","text":"","category":"section"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"Originally created to host the GeoStats.jl framework, this initiative is primarily concerned with geospatial data science and geostatistical modeling. Due to the various applications in the subsurface of the Earth, most of our Julia packages were developed to work efficiently with both 2D and 3D geometries.","category":"page"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"Unlike other initiatives, JuliaEarth is 100% Julia by design. This means that we do not rely on external libraries such as GDAL or Proj4 for geospatial work.","category":"page"},{"location":"resources/ecosystem/#JuliaClimate","page":"Ecosystem","title":"JuliaClimate","text":"","category":"section"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"The most recent of the three initiatives, JuliaClimate has been created to address specific challenges in climate modeling. One of these challenges is access to climate data in Julia. Packages such as INMET.jl and CDSAPI.jl serve this purpose and are quite nice to work with.","category":"page"},{"location":"resources/ecosystem/#JuliaGeo","page":"Ecosystem","title":"JuliaGeo","text":"","category":"section"},{"location":"resources/ecosystem/","page":"Ecosystem","title":"Ecosystem","text":"Focused on bringing well-established external libraries to Julia, JuliaGeo provides packages that are widely used by geospatial communities from other programming languages. GDAL.jl, Proj4.jl and LibGEOS.jl are good examples of such packages.","category":"page"},{"location":"validation/#Validation","page":"Validation","title":"Validation","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"GeoStats.jl was designed to, among other things, facilitate rigorous comparison of different geostatistical models in the literature. As a user of geostatistics, you may be interested in trying various models on a given data set to pick the one with best performance. As a researcher in the field, you may be interested in benchmarking your new model against other established models.","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"Errors of geostatistical solvers can be estimated with the cverror function:","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"cverror","category":"page"},{"location":"validation/#GeoStatsValidation.cverror","page":"Validation","title":"GeoStatsValidation.cverror","text":"cverror(model::GeoStatsModel, geotable, method; kwargs...)\n\nEstimate error of model in a given geotable with error estimation method using Interpolate or InterpolateNeighbors depending on the passed kwargs.\n\ncverror(model::StatsLearnModel, geotable, method)\ncverror((model, invars => outvars), geotable, method)\n\nEstimate error of model in a given geotable with error estimation method using the Learn transform.\n\n\n\n\n\n","category":"function"},{"location":"validation/","page":"Validation","title":"Validation","text":"For example, we can perform block cross-validation on a decision tree model using the following code:","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"using GeoStats\nusing GeoIO\n\n# load geospatial data\nΩ = GeoIO.load(\"data/agriculture.csv\", coords = (\"x\", \"y\"))\n\n# 20%/80% split along the (1, -1) direction\nΩₛ, Ωₜ = geosplit(Ω, 0.2, (1.0, -1.0))\n\n# features and label for supervised learning\nfeats = [:band1,:band2,:band3,:band4]\nlabel = :crop\n\n# learning model\nmodel = DecisionTreeClassifier()\n\n# loss function\nloss = MisclassLoss()\n\n# block cross-validation with r = 30.\nbcv = BlockValidation(30., loss = Dict(:crop => loss))\n\n# estimate of generalization error\nϵ̂ = cverror((model, feats => label), Ωₛ, bcv)","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"We can unhide the labels in the target domain and compute the actual error for comparison:","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"# train in Ωₛ and predict in Ωₜ\nΩ̂ₜ = Ωₜ |> Learn(Ωₛ, model, feats => label)\n\t\n# actual error of the model\nϵ = mean(loss.(Ωₜ.crop, Ω̂ₜ.crop))","category":"page"},{"location":"validation/","page":"Validation","title":"Validation","text":"Below is the list of currently implemented validation methods.","category":"page"},{"location":"validation/#Leave-one-out","page":"Validation","title":"Leave-one-out","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"LeaveOneOut","category":"page"},{"location":"validation/#GeoStatsValidation.LeaveOneOut","page":"Validation","title":"GeoStatsValidation.LeaveOneOut","text":"LeaveOneOut(; loss=Dict())\n\nLeave-one-out validation. Optionally, specify loss function from LossFunctions.jl for some of the variables.\n\nReferences\n\nStone. 1974. Cross-Validatory Choice and Assessment of Statistical Predictions\n\n\n\n\n\n","category":"type"},{"location":"validation/#Leave-ball-out","page":"Validation","title":"Leave-ball-out","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"LeaveBallOut","category":"page"},{"location":"validation/#GeoStatsValidation.LeaveBallOut","page":"Validation","title":"GeoStatsValidation.LeaveBallOut","text":"LeaveBallOut(ball; loss=Dict())\n\nLeave-ball-out (a.k.a. spatial leave-one-out) validation. Optionally, specify loss function from the LossFunctions.jl package for some of the variables.\n\nLeaveBallOut(radius; loss=Dict())\n\nBy default, use Euclidean ball of given radius in space.\n\nReferences\n\nLe Rest et al. 2014. Spatial leave-one-out cross-validation for variable selection in the presence of spatial autocorrelation\n\n\n\n\n\n","category":"type"},{"location":"validation/#K-fold","page":"Validation","title":"K-fold","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"KFoldValidation","category":"page"},{"location":"validation/#GeoStatsValidation.KFoldValidation","page":"Validation","title":"GeoStatsValidation.KFoldValidation","text":"KFoldValidation(k; shuffle=true, loss=Dict())\n\nk-fold cross-validation. Optionally, shuffle the data, and specify loss function from LossFunctions.jl for some of the variables.\n\nReferences\n\nGeisser, S. 1975. The predictive sample reuse method with applications\nBurman, P. 1989. A comparative study of ordinary cross-validation, v-fold cross-validation and the repeated learning-testing methods\n\n\n\n\n\n","category":"type"},{"location":"validation/#Block","page":"Validation","title":"Block","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"BlockValidation","category":"page"},{"location":"validation/#GeoStatsValidation.BlockValidation","page":"Validation","title":"GeoStatsValidation.BlockValidation","text":"BlockValidation(sides; loss=Dict())\n\nCross-validation with blocks of given sides. Optionally, specify loss function from LossFunctions.jl for some of the variables. If only one side is provided, then blocks become cubes.\n\nReferences\n\nRoberts et al. 2017. Cross-validation strategies for data with temporal, spatial, hierarchical, or phylogenetic structure\nPohjankukka et al. 2017. Estimating the prediction performance of spatial models via spatial k-fold cross-validation\n\n\n\n\n\n","category":"type"},{"location":"validation/#Weighted","page":"Validation","title":"Weighted","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"WeightedValidation","category":"page"},{"location":"validation/#GeoStatsValidation.WeightedValidation","page":"Validation","title":"GeoStatsValidation.WeightedValidation","text":"WeightedValidation(weighting, folding; lambda=1.0, loss=Dict())\n\nAn error estimation method which samples are weighted with weighting method and split into folds with folding method. Weights are raised to lambda power in [0,1]. Optionally, specify loss function from LossFunctions.jl for some of the variables.\n\nReferences\n\nSugiyama et al. 2006. Importance-weighted cross-validation for covariate shift\nSugiyama et al. 2007. Covariate shift adaptation by importance weighted cross validation\n\n\n\n\n\n","category":"type"},{"location":"validation/#Density-ratio","page":"Validation","title":"Density-ratio","text":"","category":"section"},{"location":"validation/","page":"Validation","title":"Validation","text":"DensityRatioValidation","category":"page"},{"location":"validation/#GeoStatsValidation.DensityRatioValidation","page":"Validation","title":"GeoStatsValidation.DensityRatioValidation","text":"DensityRatioValidation(k; [parameters])\n\nDensity ratio validation where weights are first obtained with density ratio estimation, and then used in k-fold weighted cross-validation.\n\nParameters\n\nshuffle - Shuffle the data before folding (default to true)\nestimator - Density ratio estimator (default to LSIF())\noptlib - Optimization library (default to default_optlib(estimator))\nlambda - Power of density ratios (default to 1.0)\n\nPlease see DensityRatioEstimation.jl for a list of supported estimators.\n\nReferences\n\nHoffimann et al. 2020. Geostatistical Learning: Challenges and Opportunities\n\n\n\n\n\n","category":"type"},{"location":"queries/#Geospatial-queries","page":"Queries","title":"Geospatial queries","text":"","category":"section"},{"location":"queries/#Split-apply-combine","page":"Queries","title":"Split-apply-combine","text":"","category":"section"},{"location":"queries/","page":"Queries","title":"Queries","text":"We provide a geospatial version of the split-apply-combine pattern:","category":"page"},{"location":"queries/","page":"Queries","title":"Queries","text":"
\n\n
","category":"page"},{"location":"queries/","page":"Queries","title":"Queries","text":"@groupby\n@transform\n@combine","category":"page"},{"location":"queries/#GeoTables.@groupby","page":"Queries","title":"GeoTables.@groupby","text":"@groupby(geotable, col₁, col₂, ..., colₙ)\n@groupby(geotable, [col₁, col₂, ..., colₙ])\n@groupby(geotable, (col₁, col₂, ..., colₙ))\n\nGroup geospatial geotable by columns col₁, col₂, ..., colₙ.\n\n@groupby(geotable, regex)\n\nGroup geospatial geotable by columns that match with regex.\n\nExamples\n\n@groupby(geotable, 1, 3, 5)\n@groupby(geotable, [:a, :c, :e])\n@groupby(geotable, (\"a\", \"c\", \"e\"))\n@groupby(geotable, r\"[ace]\")\n\n\n\n\n\n","category":"macro"},{"location":"queries/#GeoTables.@transform","page":"Queries","title":"GeoTables.@transform","text":"@transform(geotable, :col₁ = expr₁, :col₂ = expr₂, ..., :colₙ = exprₙ)\n\nReturns geospatial geotable with columns col₁, col₂, ..., colₙ computed with expressions expr₁, expr₂, ..., exprₙ.\n\nSee also: @groupby.\n\nExamples\n\n@transform(geotable, :z = :x + 2*:y)\n@transform(geotable, :w = :x^2 - :y^2)\n@transform(geotable, :sinx = sin(:x), :cosy = cos(:y))\n\ngroups = @groupby(geotable, :y)\n@transform(groups, :logx = log(:x))\n@transform(groups, :expz = exp(:z))\n\n@transform(geotable, {\"z\"} = {\"x\"} - 2*{\"y\"})\nxnm, ynm, znm = :x, :y, :z\n@transform(geotable, {znm} = {xnm} - 2*{ynm})\n\n\n\n\n\n","category":"macro"},{"location":"queries/#GeoTables.@combine","page":"Queries","title":"GeoTables.@combine","text":"@combine(geotable, :col₁ = expr₁, :col₂ = expr₂, ..., :colₙ = exprₙ)\n\nReturns geospatial geotable with columns :col₁, :col₂, ..., :colₙ computed with reduction expressions expr₁, expr₂, ..., exprₙ.\n\nIf a reduction expression is not defined for the :geometry column, the geometries will be reduced using Multi.\n\nSee also: @groupby.\n\nExamples\n\n@combine(geotable, :x_sum = sum(:x))\n@combine(geotable, :x_mean = mean(:x))\n@combine(geotable, :x_mean = mean(:x), :geometry = centroid(:geometry))\n\ngroups = @groupby(geotable, :y)\n@combine(groups, :x_prod = prod(:x))\n@combine(groups, :x_median = median(:x))\n@combine(groups, :x_median = median(:x), :geometry = centroid(:geometry))\n\n@combine(geotable, {\"z\"} = sum({\"x\"}) + prod({\"y\"}))\nxnm, ynm, znm = :x, :y, :z\n@combine(geotable, {znm} = sum({xnm}) + prod({ynm}))\n\n\n\n\n\n","category":"macro"},{"location":"queries/#Geospatial-join","page":"Queries","title":"Geospatial join","text":"","category":"section"},{"location":"queries/","page":"Queries","title":"Queries","text":"geojoin\ntablejoin","category":"page"},{"location":"queries/#GeoTables.geojoin","page":"Queries","title":"GeoTables.geojoin","text":"geojoin(geotable₁, geotable₂, var₁ => agg₁, ..., varₙ => aggₙ; kind=:left, pred=intersects, on=nothing)\n\nJoins geotable₁ with geotable₂ using a certain kind of join and predicate function pred that takes two geometries and returns a boolean ((g1, g2) -> g1 ⊆ g2).\n\nOptionally, add a variable value match to join, in addition to geometric match, by passing a single name or list of variable names (strings or symbols) to the on keyword argument. The variable value match use the isequal function.\n\nWhenever two or more matches are encountered, aggregate varᵢ with aggregation function aggᵢ. If no aggregation function is provided for a variable, then the aggregation function will be selected according to the scientific types: mean for continuous and first otherwise.\n\nKinds\n\n:left - Returns all rows of geotable₁ filling entries with missing when there is no match in geotable₂.\n:inner - Returns the subset of rows of geotable₁ that has a match in geotable₂.\n\nExamples\n\ngeojoin(gtb1, gtb2)\ngeojoin(gtb1, gtb2, 1 => mean)\ngeojoin(gtb1, gtb2, :a => mean, :b => std)\ngeojoin(gtb1, gtb2, \"a\" => mean, pred=issubset)\ngeojoin(gtb1, gtb2, on=:a)\ngeojoin(gtb1, gtb2, kind=:inner, on=[\"a\", \"b\"])\n\nSee also tablejoin.\n\n\n\n\n\n","category":"function"},{"location":"queries/#GeoTables.tablejoin","page":"Queries","title":"GeoTables.tablejoin","text":"tablejoin(geotable, table, var₁ => agg₁, ..., varₙ => aggₙ; kind=:left, on)\n\nJoins geotable with table using the values of the on variables to match rows with a certain kind of join.\n\non variables can be a single name or list of variable names (strings or symbols). The variable value match use the isequal function.\n\nWhenever two or more matches are encountered, aggregate varᵢ with aggregation function aggᵢ. If no aggregation function is provided for a variable, then the aggregation function will be selected according to the scientific types: mean for continuous and first otherwise.\n\nKinds\n\n:left - Returns all rows of geotable filling entries with missing when there is no match in table.\n:inner - Returns the subset of rows of geotable that has a match in table.\n\nExamples\n\ntablejoin(gtb, tab, on=:a)\ntablejoin(gtb, tab, 1 => mean, on=:a)\ntablejoin(gtb, tab, :a => mean, :b => std, on=:a)\ntablejoin(gtb, tab, \"a\" => mean, on=[:a, :b])\ntablejoin(gtb, tab, kind=:inner, on=[\"a\", \"b\"])\n\nSee also geojoin.\n\n\n\n\n\n","category":"function"},{"location":"","page":"Home","title":"Home","text":"GeoStats","category":"page"},{"location":"#GeoStats","page":"Home","title":"GeoStats","text":"(Image: GeoStats.jl)\n\n(Image: ) (Image: ) (Image: ) (Image: ) (Image: )\n\n(Image: ) (Image: )\n\nGeoStats.jl is an extensible framework for geospatial data science and geostatistical modeling fully written in Julia. It is comprised of several modules for advanced geometric processing, state-of-the-art geostatistical algorithms and sophisticated visualization of geospatial data.\n\nAll further information is provided in the online documentation.\n\n\n\n\n\n","category":"module"},{"location":"","page":"Home","title":"Home","text":"note: Star us on GitHub!\nIf you have found this software useful, please consider starring it on GitHub. This gives us an accurate lower bound of the (satisfied) user count.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Organizations using the framework:","category":"page"},{"location":"","page":"Home","title":"Home","text":"
","category":"page"},{"location":"","page":"Home","title":"Home","text":"Would like to become a sponsor? Press the sponsor button in our GitHub repository.","category":"page"},{"location":"#Overview","page":"Home","title":"Overview","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"In many fields of science, such as mining engineering, hydrogeology, petroleum engineering, and environmental sciences, traditional statistical methods fail to provide unbiased estimates of resources due to the presence of geospatial correlation. Geostatistics (a.k.a. geospatial statistics) is the branch of statistics developed to overcome this limitation. Particularly, it is the branch that takes geospatial coordinates of data into account. Some major highlights of GeoStats.jl are:","category":"page"},{"location":"","page":"Home","title":"Home","text":"It is simple: has a very short learning curve and requires writing minimal code 😌\nIt is general: supports all types of geospatial domains, including unstructured meshes 👍\nIt is native: fully written in Julia for maximum flexibility and performance 🚀\nHas an extensive library of algorithms from the geostatistics literature 📚","category":"page"},{"location":"","page":"Home","title":"Home","text":"Our JuliaCon2021 talk provides an overview of geostatistical learning, which is one of the many geostatistical problems addressed by the software:","category":"page"},{"location":"","page":"Home","title":"Home","text":"
\n\n
","category":"page"},{"location":"","page":"Home","title":"Home","text":"Consider reading the Geospatial Data Science with Julia book before reading this documentation. If you have questions, or would like to brainstorm ideas, don't hesitate to start a topic in our community channel.","category":"page"},{"location":"","page":"Home","title":"Home","text":"
","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Get the latest stable release with Julia's package manager:","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Pkg\nPkg.add(\"GeoStats\")","category":"page"},{"location":"#Quick-example","page":"Home","title":"Quick example","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Below is an example of geostatistical interpolation of point data over a Cartesian grid with a Kriging model:","category":"page"},{"location":"","page":"Home","title":"Home","text":"# load framework\nusing GeoStats\n\n# load visualization backend\nimport CairoMakie as Mke\n\n# attribute table\ntable = (; Z=[1.,0.,1.])\n\n# coordinates for each row\ncoord = [(25.,25.), (50.,75.), (75.,50.)]\n\n# georeference data\ngeotable = georef(table, coord)\n\n# interpolation domain\ngrid = CartesianGrid(100, 100)\n\n# choose an interpolation model\nmodel = Kriging(GaussianVariogram(range=35.))\n\n# perform interpolation over grid\ninterp = geotable |> Interpolate(grid, model)\n\n# visualize the solution\nviz(interp.geometry, color = interp.Z)","category":"page"},{"location":"#Project-organization","page":"Home","title":"Project organization","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The project is split into various packages:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Package Description\nGeoStats.jl Main package reexporting full stack of packages for geostatistics.\nMeshes.jl Computational geometry and advanced meshing algorithms.\nCoordRefSystems.jl Unitful coordinate reference systems.\nGeoTables.jl Geospatial tables compatible with the framework.\nDataScienceTraits.jl Traits for geospatial data science.\nTableTransforms.jl Transforms and pipelines with tabular data.\nStatsLearnModels.jl Statistical learning models for geospatial prediction.\nGeoStatsBase.jl Base package with core geostatistical definitions.\nGeoStatsFunctions.jl Geostatistical functions and related tools.\nGeoStatsModels.jl Geostatistical models for geospatial interpolation.\nGeoStatsProcesses.jl Geostatistical processes for geospatial simulation.\nGeoStatsTransforms.jl Geostatistical transforms for geospatial data.\nGeoStatsValidation.jl Geostatistical validation methods.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Other packages can be installed separately for additional functionality:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Package Description\nGeoIO.jl Load/save geospatial tables in various formats.\nGeoArtifacts.jl Artifacts for geospatial data science.\nDrillHoles.jl Desurvey/composite drillhole data.","category":"page"},{"location":"#Citing-the-software","page":"Home","title":"Citing the software","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you find this software useful in your work, please consider citing it: ","category":"page"},{"location":"","page":"Home","title":"Home","text":"(Image: JOSS) (Image: DOI)","category":"page"},{"location":"","page":"Home","title":"Home","text":"@ARTICLE{Hoffimann2018,\n title={GeoStats.jl – High-performance geostatistics in Julia},\n author={Hoffimann, Júlio},\n journal={Journal of Open Source Software},\n publisher={The Open Journal},\n volume={3},\n pages={692},\n number={24},\n ISSN={2475-9066},\n DOI={10.21105/joss.00692},\n url={https://dx.doi.org/10.21105/joss.00692},\n year={2018},\n month={Apr}\n}","category":"page"},{"location":"","page":"Home","title":"Home","text":"We ❤ to see our list of publications growing.","category":"page"},{"location":"about/citing/","page":"Citing","title":"Citing","text":"If you find GeoStats.jl useful in your work, please consider citing it:","category":"page"},{"location":"about/citing/","page":"Citing","title":"Citing","text":"(Image: JOSS) (Image: DOI)","category":"page"},{"location":"about/citing/","page":"Citing","title":"Citing","text":"@ARTICLE{Hoffimann2018,\n title={GeoStats.jl – High-performance geostatistics in Julia},\n author={Hoffimann, Júlio},\n journal={Journal of Open Source Software},\n publisher={The Open Journal},\n volume={3},\n pages={692},\n number={24},\n ISSN={2475-9066},\n DOI={10.21105/joss.00692},\n url={https://dx.doi.org/10.21105/joss.00692},\n year={2018},\n month={Apr}\n}","category":"page"},{"location":"transiography/empirical/#Empirical-transiograms","page":"Empirical transiograms","title":"Empirical transiograms","text":"","category":"section"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"using GeoStats # hide\nimport CairoMakie as Mke # hide","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"Transiograms of categorical variables are matrix-valued functions t_ab(h) that measure the transition probability from categorical value a to categorical value b at a given lag h in R. They are often used for the simulation of Markov processes in more than one dimension.","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"The Carle's estimator of the empirical transiogram is given by","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"widehatt_ab(h) = fracsum_(ij) in N(h) I_a_i cdot I_b_jsum_(ij) in N(h) I_a_i","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"where N(h) = left(ij) mid x_i - x_j = hright is the set of pairs of locations at a distance h, and where I_a and I_b are the indicator variables for categorical values (or levels) a and b, respectively.","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"Transiograms can be plotted with the following options:","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"transioplot","category":"page"},{"location":"transiography/empirical/#GeoStatsFunctions.transioplot","page":"Empirical transiograms","title":"GeoStatsFunctions.transioplot","text":"transioplot(t; [options])\n\nPlot the transiogram t with given options.\n\nCommon transiogram options:\n\ncolor - color of transiogram\nsize - size of transiogram\nmaxlag - maximum lag of variogram\nlevels - categorical levels\n\nNotes\n\nThis function will only work in the presence of a Makie.jl backend via package extensions in Julia v1.9 or later versions of the language.\n\n\n\n\n\n","category":"function"},{"location":"transiography/empirical/#(Omini)directional","page":"Empirical transiograms","title":"(Omini)directional","text":"","category":"section"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"EmpiricalTransiogram\nDirectionalTransiogram\nPlanarTransiogram","category":"page"},{"location":"transiography/empirical/#GeoStatsFunctions.EmpiricalTransiogram","page":"Empirical transiograms","title":"GeoStatsFunctions.EmpiricalTransiogram","text":"EmpiricalTransiogram(data, var; [parameters])\n\nComputes the empirical (a.k.a. experimental) omnidirectional transiogram for categorical variable var stored in geospatial data.\n\nParameters\n\nnlags - number of lags (default to 20)\nmaxlag - maximum lag in length units (default to 1/2 of minimum side of bounding box)\ndistance - custom distance function (default to Euclidean distance)\nalgorithm - accumulation algorithm (default to :ball)\n\nAvailable algorithms:\n\n:full - loop over all pairs of points in the data\n:ball - loop over all points inside maximum lag ball\n\nAll implemented algorithms produce the exact same result. The :ball algorithm is considerably faster when the maximum lag is much smaller than the bounding box of the domain of the data.\n\nSee also: DirectionalTransiogram, PlanarTransiogram.\n\nReferences\n\nCarle, S.F. & Fogg, G.E. 1996. Transition probability-based indicator geostatistics\nCarle et al 1998. Conditional Simulation of Hydrofacies Architecture: A Transition Probability/Markov Approach\n\n\n\n\n\n","category":"type"},{"location":"transiography/empirical/#GeoStatsFunctions.DirectionalTransiogram","page":"Empirical transiograms","title":"GeoStatsFunctions.DirectionalTransiogram","text":"DirectionalTransiogram(direction, data, var; dtol=1e-6u\"m\", [parameters])\n\nComputes the empirical transiogram for the categorical variable var stored in geospatial data along a given direction with band tolerance dtol in length units.\n\nOptionally, forward parameters for the underlying EmpiricalTransiogram.\n\n\n\n\n\n","category":"function"},{"location":"transiography/empirical/#GeoStatsFunctions.PlanarTransiogram","page":"Empirical transiograms","title":"GeoStatsFunctions.PlanarTransiogram","text":"PlanarTransiogram(normal, data, var; ntol=1e-6u\"m\", [parameters])\n\nComputes the empirical transiogram for the categorical variable var stored in geospatial data along a plane perpendicular to a normal direction with plane tolerance ntol in length units.\n\nOptionally, forward parameters for the underlying EmpiricalTransiogram.\n\n\n\n\n\n","category":"function"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"Consider the following categorical image:","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"using GeoStatsImages\n\nimg = geostatsimage(\"Gaussian30x10\")\n\nZ = [z < 0 ? 1 : 2 for z in img.Z]\n\ncat = georef((; Z=Z), img.geometry)\n\ncat |> viewer","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"We can estimate the ominidirectional transiogram with","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"t = EmpiricalTransiogram(cat, :Z, maxlag = 50.)\n\ntransioplot(t)","category":"page"},{"location":"transiography/empirical/#Transioplanes","page":"Empirical transiograms","title":"Transioplanes","text":"","category":"section"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"Transiograms estimated along all directions in a given plane of reference are called transioplanes.","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"EmpiricalTransioplane","category":"page"},{"location":"transiography/empirical/#GeoStatsFunctions.EmpiricalTransioplane","page":"Empirical transiograms","title":"GeoStatsFunctions.EmpiricalTransioplane","text":"EmpiricalTransioplane(data, var;\n normal=Vec(0,0,1), nangs=50,\n ptol=0.5u\"m\", dtol=0.5u\"m\",\n [parameters])\n\nGiven a normal direction, estimate the transiogram of variable var along all directions in the corresponding plane of variation.\n\nOptionally, specify the tolerance ptol in length units for the plane partition, the tolerance dtol in length units for the direction partition, the number of angles nangs in the plane, and forward the parameters to the underlying EmpiricalTransiogram.\n\n\n\n\n\n","category":"type"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"The transioplane is plotted on a polar axis for all lags and angles:","category":"page"},{"location":"transiography/empirical/","page":"Empirical transiograms","title":"Empirical transiograms","text":"t = EmpiricalTransioplane(cat, :Z, maxlag = 50.)\n\nplaneplot(t)","category":"page"}]
+}
diff --git a/v0.71.3/siteinfo.js b/v0.71.3/siteinfo.js
new file mode 100644
index 0000000..9b148c2
--- /dev/null
+++ b/v0.71.3/siteinfo.js
@@ -0,0 +1 @@
+var DOCUMENTER_CURRENT_VERSION = "v0.71.3";
diff --git a/v0.71.3/transforms/38245ac8.png b/v0.71.3/transforms/38245ac8.png
new file mode 100644
index 0000000..0232d5a
Binary files /dev/null and b/v0.71.3/transforms/38245ac8.png differ
diff --git a/v0.71.3/transforms/41906f80.png b/v0.71.3/transforms/41906f80.png
new file mode 100644
index 0000000..93b5237
Binary files /dev/null and b/v0.71.3/transforms/41906f80.png differ
diff --git a/v0.71.3/transforms/5b704769.png b/v0.71.3/transforms/5b704769.png
new file mode 100644
index 0000000..17a1c6d
Binary files /dev/null and b/v0.71.3/transforms/5b704769.png differ
diff --git a/v0.71.3/transforms/67465ef7.png b/v0.71.3/transforms/67465ef7.png
new file mode 100644
index 0000000..228409d
Binary files /dev/null and b/v0.71.3/transforms/67465ef7.png differ
diff --git a/v0.71.3/transforms/6e4ebb43.png b/v0.71.3/transforms/6e4ebb43.png
new file mode 100644
index 0000000..38e07d5
Binary files /dev/null and b/v0.71.3/transforms/6e4ebb43.png differ
diff --git a/v0.71.3/transforms/a2ca59ee.png b/v0.71.3/transforms/a2ca59ee.png
new file mode 100644
index 0000000..83bd3ba
Binary files /dev/null and b/v0.71.3/transforms/a2ca59ee.png differ
diff --git a/v0.71.3/transforms/c141b576.png b/v0.71.3/transforms/c141b576.png
new file mode 100644
index 0000000..2c37882
Binary files /dev/null and b/v0.71.3/transforms/c141b576.png differ
diff --git a/v0.71.3/transforms/ea0925ff.png b/v0.71.3/transforms/ea0925ff.png
new file mode 100644
index 0000000..f3130f4
Binary files /dev/null and b/v0.71.3/transforms/ea0925ff.png differ
diff --git a/v0.71.3/transforms/eff9ec66.png b/v0.71.3/transforms/eff9ec66.png
new file mode 100644
index 0000000..b80a2ec
Binary files /dev/null and b/v0.71.3/transforms/eff9ec66.png differ
diff --git a/v0.71.3/transforms/index.html b/v0.71.3/transforms/index.html
new file mode 100644
index 0000000..37c3046
--- /dev/null
+++ b/v0.71.3/transforms/index.html
@@ -0,0 +1,360 @@
+
+Transforms · GeoStats.jl
We provide a very powerful list of transforms that were designed to work seamlessly with geospatial data. These transforms are implemented in different packages depending on how they interact with geometries.
The list of supported transforms is continuously growing. The following code can be used to print an updated list in any project environment:
# packages to print type tree
+using InteractiveUtils
+using AbstractTrees
+using TransformsBase
+
+# packages with transforms
+using GeoStats
+
+# define the tree of types
+AbstractTrees.children(T::Type) = subtypes(T)
+
+# print all currently available transforms
+AbstractTrees.print_tree(TransformsBase.Transform)
Transforms at the leaves of the tree above should have a docstring with more information on the available options. For example, the documentation of the Select transform is shown below:
Transforms of type FeatureTransform operate on the attribute table, whereas transforms of type GeometricTransform operate on the underlying geospatial domain:
Other transforms such as Detrend are defined in terms of both the geospatial domain and the attribute table. All transforms and pipelines implement the following functions:
Revert the transform on the newobject using the cache from the corresponding apply call and return the original object. Only defined when the transformisrevertible.
Reapply the transform to (a possibly different) object using a cache that was created with a previous apply call. Fallback to apply without using the cache.
Please check the TableTransforms.jl documentation for an updated list of feature transforms. As an example consider the following features over a Cartesian grid and their statistics:
using DataFrames
+
+# table of features and domain
+tab = DataFrame(a=rand(1000), b=randn(1000), c=rand(1000))
+dom = CartesianGrid(100, 100)
+
+# georeference table onto domain
+Ω = georef(tab, dom)
+
+# describe features
+describe(values(Ω))
3×7 DataFrame
Row
variable
mean
min
median
max
nmissing
eltype
Symbol
Float64
Float64
Float64
Float64
Int64
DataType
1
a
0.485276
0.00120786
0.484707
0.999245
0
Float64
2
b
0.0176609
-2.95863
0.0136271
3.62072
0
Float64
3
c
0.50863
7.30319e-5
0.511608
0.999331
0
Float64
We can create a pipeline that transforms the features to their normal quantile (or scores):
Please check the Meshes.jl documentation for an updated list of geometric transforms. As an example consider the rotation of geospatial data over a Cartesian grid:
Bellow is the current list of transforms that operate on both the geometries and features of geospatial data. They are implemented in the GeoStatsBase.jl package.
Duplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.
Examples
UniqueCoords(1 => last, 2 => maximum)
+UniqueCoords(:a => first, :b => minimum)
+UniqueCoords("a" => last, "b" => maximum)
Trace polygons on 2D image data with Selinger's Potrace algorithm.
The categories stored in column mask are converted into binary masks, which are then traced into multi-polygons. When provided, the option ϵ is forwarded to Selinger's simplification algorithm.
Duplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.
Examples
Potrace(:mask, ϵ=0.1)
+Potrace(1, 1 => last, 2 => maximum)
+Potrace(:mask, :a => first, :b => minimum)
+Potrace("mask", "a" => last, "b" => maximum)
Alternatively, use the grid with size nx by ny obtained with discretization of the bounding box.
Duplicates of a variable varᵢ are aggregated with aggregation function aggᵢ. If an aggregation function is not defined for variable varᵢ, the default aggregation function will be used. Default aggregation function is mean for continuous variables and first otherwise.
Examples
grid = CartesianGrid(10, 10)
+Rasterize(grid)
+Rasterize(10, 10)
+Rasterize(grid, 1 => last, 2 => maximum)
+Rasterize(10, 10, 1 => last, 2 => maximum)
+Rasterize(grid, :a => first, :b => minimum)
+Rasterize(10, 10, :a => first, :b => minimum)
+Rasterize(grid, "a" => last, "b" => maximum)
+Rasterize(10, 10, "a" => last, "b" => maximum)
Unlike traditional clustering algorithms in machine learning, geostatistical clustering (a.k.a. domaining) algorithms consider both the features and the geospatial coordinates of the data.
Consider the following data as an example:
Ω = georef((Z=[10sin(i/10) + j for i in 1:4:100, j in 1:4:100],))
+
+viz(Ω.geometry, color = Ω.Z)
A transform for partitioning geospatial data into k clusters according to a range λ using Geostatistical Hierarchical Clustering (GHC). The larger the range the more connected are nearby samples.
Parameters
k - Approximate number of clusters
λ - Approximate range of kernel function in length units
kern - Kernel function (:uniform, :triangular or :epanechnikov)
link - Linkage function (:single, :average, :complete, :ward or :ward_presquared)
as - Variable name used to store clustering results
The range parameter controls the sparsity pattern of the pairwise distances, which can greatly affect the computational performance of the GHC algorithm. We recommend choosing a range that is small enough to connect nearby samples. For example, clustering data over a 100x100 Cartesian grid with unit spacing is possible with λ=1.0 or λ=2.0 but the problem starts to become computationally unfeasible around λ=10.0 due to the density of points.
The algorithm implemented here is slightly different than the algorithm
described in Romary et al. 2015. Instead of setting Wᵢⱼ = 0 when i <-/-> j, we simply magnify the weight by a multiplicative factor Wᵢⱼ *= m when i <–> j. This leads to dense matrices but also better results in practice.
SLIC(k, m; tol=1e-4, maxiter=10, weights=nothing, as=:cluster)
A transform for clustering geospatial data into approximately k clusters using Simple Linear Iterative Clustering (SLIC). The transform produces clusters of samples that are spatially connected based on a distance dₛ and that, at the same time, are similar in terms of vars with distance dᵥ. The tradeoff is controlled with a hyperparameter parameter m in an additive model dₜ = √(dᵥ² + m²(dₛ/s)²).
Parameters
k - Approximate number of clusters
m - Hyperparameter of SLIC model
tol - Tolerance of k-means algorithm (default to 1e-4)
maxiter - Maximum number of iterations (default to 10)
weights - Dictionary with weights for each attribute (default to nothing)
as - Variable name used to store clustering results
Interpolate geospatial data on given domain or vector of geometries [g₁, g₂, ..., gₙ], using geostatistical models model₁, ..., modelₙ for variables vars₁, ..., varsₙ.
Interpolate geospatial data on given domain or set of geometries g₁, g₂, ..., gₙ, using geostatistical models model₁, ..., modelₙ for variables vars₁, ..., varsₙ.
Interpolate geospatial data on given domain or set of geometries g₁, g₂, ..., gₙ, using geostatistical model for all variables.
Unlike Interpolate, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.
Parameters
minneighbors - Minimum number of neighbors (default to 1)
maxneighbors - Maximum number of neighbors (default to 10)
neighborhood - Search neighborhood (default to nothing)
distance - A distance defined in Distances.jl (default to Euclidean())
point - Perform interpolation on point support (default to true)
prob - Perform probabilistic interpolation (default to false)
The maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.
Two neighborhood search methods are available:
If a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.
If a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.
Interpolate geospatial data on its own domain, using geostatistical models model₁, ..., modelₙ and non-missing values of the variables vars₁, ..., varsₙ.
Interpolate geospatial data on its own domain, using geostatistical model and non-missing values of all variables.
Just like InterpolateNeighbors, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.
Parameters
minneighbors - Minimum number of neighbors (default to 1)
maxneighbors - Maximum number of neighbors (default to 10)
neighborhood - Search neighborhood (default to nothing)
distance - A distance defined in Distances.jl (default to Euclidean())
point - Perform interpolation on point support (default to true)
prob - Perform probabilistic interpolation (default to false)
The maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.
Two neighborhood search methods are available:
If a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.
If a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.
Interpolate geospatial data on its own domain, using geostatistical model and non-NaN values of all variables.
Just like InterpolateNeighbors, this transform uses neighbor search methods to fit geostatistical models at each interpolation location with a reduced number of measurements.
Parameters
minneighbors - Minimum number of neighbors (default to 1)
maxneighbors - Maximum number of neighbors (default to 10)
neighborhood - Search neighborhood (default to nothing)
distance - A distance defined in Distances.jl (default to Euclidean())
point - Perform interpolation on point support (default to true)
prob - Perform probabilistic interpolation (default to false)
The maxneighbors parameter can be used to perform interpolation with a subset of measurements per prediction location. If maxneighbors is not provided, then all measurements are used.
Two neighborhood search methods are available:
If a neighborhood is provided, local prediction is performed by sliding the neighborhood in the domain.
If a neighborhood is not provided, the prediction is performed using maxneighbors nearest neighbors according to distance.
Simulate nreals realizations of variable parent with geostatistical process process, and each child variable varsᵢ with process map procmapᵢ, over given domain.
The process map must be an iterable of pairs of the form: value => process. Each process in the map is related to a value of the parent realization, therefore the values of the child variables will be chosen according to the values of the corresponding parent realization.
The parameters are forwarded to the rand method of the geostatistical processes.
Transiograms of categorical variables are matrix-valued functions $t_{ab}(h)$ that measure the transition probability from categorical value $a$ to categorical value $b$ at a given lag $h \in \R$. They are often used for the simulation of Markov processes in more than one dimension.
The Carle's estimator of the empirical transiogram is given by
where $N(h) = \left\{(i,j) \mid ||\x_i - \x_j|| = h\right\}$ is the set of pairs of locations at a distance $h$, and where $I_a$ and $I_b$ are the indicator variables for categorical values (or levels) $a$ and $b$, respectively.
Transiograms can be plotted with the following options:
Computes the empirical (a.k.a. experimental) omnidirectional transiogram for categorical variable var stored in geospatial data.
Parameters
nlags - number of lags (default to 20)
maxlag - maximum lag in length units (default to 1/2 of minimum side of bounding box)
distance - custom distance function (default to Euclidean distance)
algorithm - accumulation algorithm (default to :ball)
Available algorithms:
:full - loop over all pairs of points in the data
:ball - loop over all points inside maximum lag ball
All implemented algorithms produce the exact same result. The :ball algorithm is considerably faster when the maximum lag is much smaller than the bounding box of the domain of the data.
Computes the empirical transiogram for the categorical variable var stored in geospatial data along a given direction with band tolerance dtol in length units.
Computes the empirical transiogram for the categorical variable var stored in geospatial data along a plane perpendicular to a normal direction with plane tolerance ntol in length units.
Given a normal direction, estimate the transiogram of variable var along all directions in the corresponding plane of variation.
Optionally, specify the tolerance ptol in length units for the plane partition, the tolerance dtol in length units for the direction partition, the number of angles nangs in the plane, and forward the parameters to the underlying EmpiricalTransiogram.
We provide various theoretical transiogram models from the literature, which can can be combined with ellipsoid distances to model geometric anisotropy.
A piecewise-linear transiogram model with abscissas and matrix ordinates obtained from an EmpiricalTransiogram. Optionally, specify a metric ball to model anisotropy.
GeoStats.jl was designed to, among other things, facilitate rigorous comparison of different geostatistical models in the literature. As a user of geostatistics, you may be interested in trying various models on a given data set to pick the one with best performance. As a researcher in the field, you may be interested in benchmarking your new model against other established models.
Errors of geostatistical solvers can be estimated with the cverror function:
Leave-ball-out (a.k.a. spatial leave-one-out) validation. Optionally, specify loss function from the LossFunctions.jl package for some of the variables.
LeaveBallOut(radius; loss=Dict())
By default, use Euclidean ball of given radius in space.
Cross-validation with blocks of given sides. Optionally, specify loss function from LossFunctions.jl for some of the variables. If only one side is provided, then blocks become cubes.
An error estimation method which samples are weighted with weighting method and split into folds with folding method. Weights are raised to lambda power in [0,1]. Optionally, specify loss function from LossFunctions.jl for some of the variables.
Variograms are widely used in geostatistics due to their intimate connection with (cross-)variance and visual interpretability. The following video explains the concept in detail:
+
+
The Matheron's estimator of the empirical variogram is given by
where $N(h) = \left\{(i,j) \mid ||\x_i - \x_j|| = h\right\}$ is the set of pairs of locations at a distance $h$ and $|N(h)|$ is the cardinality of the set. Alternatively, the robust Cressie's estimator is given by
Both estimators are available and can be used with general distance functions in order to for example:
Model anisotropy (e.g. ellipsoid distance)
Perform simulation on sphere (e.g. haversine distance)
Please see Distances.jl for a complete list of distance functions.
The high-performance estimation procedure implemented in the framework can consider all pairs of locations regardless of direction (ominidirectional) or a specified partition of the geospatial data (e.g. directional, planar).
Variograms can plotted with the following options:
Computes the empirical (a.k.a. experimental) omnidirectional (cross-)variogram for variables var₁ and var₂ stored in geospatial data.
Parameters
nlags - number of lags (default to 20)
maxlag - maximum lag in length units (default to 1/2 of minimum side of bounding box)
distance - custom distance function (default to Euclidean distance)
estimator - variogram estimator (default to :matheron estimator)
algorithm - accumulation algorithm (default to :ball)
Available estimators:
:matheron - simple estimator based on squared differences
:cressie - robust estimator based on 4th power of differences
Available algorithms:
:full - loop over all pairs of points in the data
:ball - loop over all points inside maximum lag ball
All implemented algorithms produce the exact same result. The :ball algorithm is considerably faster when the maximum lag is much smaller than the bounding box of the domain of the data.
Computes the empirical (cross-)variogram for the variables var₁ and var₂ stored in geospatial data along a given direction with band tolerance dtol in length units.
Computes the empirical (cross-)variogram for the variables var₁ and var₂ stored in geospatial data along a plane perpendicular to a normal direction with plane tolerance ntol in length units.
The directional and planar variograms coincide in this example because planes are equal to lines in 2-dimensional space. These concepts are most useful in 3-dimensional space where we may be interested in comparing the horizontal planar range to the vertical directional range.
Given a normal direction, estimate the (cross-)variogram of variables var₁ and var₂ along all directions in the corresponding plane of variation.
Optionally, specify the tolerance ptol in length units for the plane partition, the tolerance dtol in length units for the direction partition, the number of angles nangs in the plane, and forward the parameters to the underlying EmpiricalVariogram.
Fitting theoretical variograms to empirical observations is an important modeling step to ensure valid mathematical models of geospatial continuity. Given an empirical variogram, the following function can be used to fit models:
Fit theoretical variogram using weighted least squares with weighting function w (e.g. h -> 1/h). If no weighting function is provided, bin counts of empirical variogram are normalized and used as weights.
We provide various theoretical variogram models from the literature, which can can be combined with ellipsoid distances to model geometric anisotropy and nested with scalars or matrix coefficients to express multivariate relations.
Under the additional assumption of 2nd-order stationarity, the well-known covariance is directly related via $\gamma(h) = \cov(0) - \cov(h)$. This package implements a few commonly used as well as other more exotic variogram models. Most of these models share a set of default parameters (e.g. sill=1.0, range=1.0), which can be set with keyword arguments.
Functions are provided to query properties of variogram models programmatically:
Corresponding covariance models are available for convenience. For example, the GaussianVariogram and the GaussianCovariance are two alternative representations of the same geostatistical behavior.
Anisotropic models are easily obtained by defining an ellipsoid metric in place of the default Euclidean metric as shown in the following example. First, we create an ellipsoid that specifies the ranges and angles of rotation:
MineSight z-x'-y'' intrinsic rotation convention following the right-hand rule. All angles are in degrees and the sign convention is CW, CCW, CW positive.
The first rotation θ₁ is a horizontal rotation around the Z-axis, with positive being clockwise. The second rotation θ₂ is a rotation around the new X-axis, which moves the Y-axis into the desired position, with positive direction of rotation is up. The third rotation θ₃ is a rotation around the new Y-axis, which moves the X-axis into the desired position, with positive direction of rotation is up.
Datamine ZXY rotation convention following the left-hand rule. All angles are in degrees and the signal convention is CW, CW, CW positive. Y is the principal axis.
Vulcan ZYX rotation convention following the right-hand rule. All angles are in degrees and the signal convention is CW, CCW, CW positive. X is the principal axis.
GSLIB z-x'-y'' intrinsic rotation convention following the left-hand rule. All angles are in degrees and the sign convention is CW, CCW, CW positive. Y is the principal axis.
The first rotation θ₁ is a rotation around the Z-axis, this is also called the azimuth. The second rotation θ₂ is a rotation around the new X-axis, this is also called the dip. The third rotation θ₃ is a rotation around the new Y-axis, this is also called the tilt.
A nested variogram model $\gamma(h) = c_1\cdot\gamma_1(h) + c_2\cdot\gamma_2(h) + \cdots + c_n\cdot\gamma_n(h)$ can be constructed from multiple variogram models, including matrix coefficients. The individual structures can be recovered in canonical form with the structures function:
Return the individual structures of a (possibly nested) variogram as a tuple. The structures are the total nugget cₒ, and the coefficients (or contributions) c[i] for the remaining non-trivial structures g[i] after normalization (i.e. sill=1, nugget=0).
The framework provides powerful visualization recipes for geospatial data science via the Makie.jl project. These recipes were carefully designed to maximize productivity and to protect users from GIS jargon. The main entry point is the viz function:
The option color can be a single scalar or a vector of scalars. For Mesh subtypes, the length of the vector of colors determines if the colors should be assigned to vertices or to elements.
Examples
Different coloring methods (vertex vs. element):
# vertex coloring (i.e. linear interpolation)
+viz(mesh, color = 1:nvertices(mesh))
+
+# element coloring (i.e. discrete colors)
+viz(mesh, color = 1:nelements(mesh))
Different strategies to show the boundary of geometries (showsegments vs. boundary):
# visualize boundary with showsegments
+viz(polygon, showsegments = true)
+
+# visualize boundary with separate call
+viz(polygon)
+viz!(boundary(polygon))
Notes
This function will only work in the presence of a Makie.jl backend via package extensions in Julia v1.9 or later versions of the language.
This function takes a geospatial domain as input and provides a set of aesthetic options to style the elements (i.e. geometries) of the domain.
Note
Notice that the geometry column of our geospatial data type is a domain (i.e. data.geometry isa Domain), and that this design enables several optimizations in the visualization itself.
Users can also call Makie's plot function in the geometry column as in
Mke.plot(data.geometry)
and this is equivalent to calling the viz recipe above. The plot function also works with various other objects such as EmpiricalHistogram and EmpiricalVariogram. That is convenient if you don't remember the name of the recipe.
Additionaly, we provide a basic scientific viewer to visualize all viewable variables in the data:
A hscatter plot between two variables var1 and var2 (possibly with var2 = var1) is a simple scatter plot in which the dots represent all ordered pairs of values of var1 and var2 at a given lag h.
The PairPlots.jl package provides the pairplot function that can be used with any table, including tables of attributes obtained with the values function.