diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml new file mode 100644 index 000000000..a482cfaf2 --- /dev/null +++ b/.github/workflows/Documenter.yml @@ -0,0 +1,35 @@ +name: Documenter +on: + push: + branches: [main] + tags: [v*] + pull_request: + branches: [main] +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +jobs: + build: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/cache@v1 + with: + cache-registries: "true" + - name: Install documentation dependencies + run: julia --project=docs -e 'using Pkg; pkg"dev ."; Pkg.instantiate()' + - name: Build and deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key + GKSwstype: "100" # https://discourse.julialang.org/t/generation-of-documentation-fails-qt-qpa-xcb-could-not-connect-to-display/60988 + JULIA_DEBUG: "Documenter" + DATADEPS_ALWAYS_ACCEPT: true + run: | + julia --code-coverage=user --project=docs/ --color=yes docs/genfiles.jl + julia --code-coverage=user --project=docs/ --color=yes docs/make.jl \ No newline at end of file diff --git a/.gitignore b/.gitignore index a4a1ec11b..03d3e0a82 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,18 @@ *.jl.cov *.jl.mem .DS_Store -Manifest.toml -/dev/ + +/Manifest.toml +/.vscode/ +tmp +generated +build +.vscode +.DS_Store + +docs/docs +docs/site docs/build +docs/var +deps/build.jl +Manifest.toml \ No newline at end of file diff --git a/docs/Project.toml b/docs/Project.toml index 10e1dcdf0..90a9739e9 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,7 +1,9 @@ [deps] +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +DocumenterMarkdown = "997ab1e6-3595-5248-9280-8efb232c3433" +Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" diff --git a/docs/_overrides/partials/source.html b/docs/_overrides/partials/source.html new file mode 100644 index 000000000..413044452 --- /dev/null +++ b/docs/_overrides/partials/source.html @@ -0,0 +1,30 @@ +{% import "partials/language.html" as lang with context %} + +
+ {% set icon = config.theme.icon.repo or "fontawesome/brands/git-alt" %} + {% include ".icons/" ~ icon ~ ".svg" %} +
+
+ {{ config.repo_name }} +
+
+{% if config.theme.twitter_url %} + +
+ {% include ".icons/fontawesome/brands/twitter.svg" %} +
+
+ {{ config.theme.twitter_name }} +
+
+{% endif %} +{% if config.theme.sponsor_url %} + +
+ {% include ".icons/fontawesome/regular/heart.svg" %} +
+
+ {{ config.theme.sponsor_name }} +
+
+{% endif %} \ No newline at end of file diff --git a/docs/crash/course/course.jl b/docs/crash/course/course.jl new file mode 100644 index 000000000..0a4ab715f --- /dev/null +++ b/docs/crash/course/course.jl @@ -0,0 +1,283 @@ +using DimensionalData + +# ## Dimensions and DimArrays + +# The core type of DimensionalData.jl is the [`Dimension`](@ref) and the types +# that inherit from it, such as `Ti`, `X`, `Y`, `Z`, the generic `Dim{:x}`, or +# others that you define manually using the [`@dim`](@ref) macro. + +# `Dimension`s are primarily used in [`DimArray`](@ref), other +# [`AbstractDimArray`](@ref). + +# We can use dimensions without a value index - these simply label the axis. +# A `DimArray` with labelled dimensions is constructed by: + +using DimensionalData +A = rand(X(5), Y(5)) + +# get value + +A[Y(1), X(2)] + +# As shown above, `Dimension`s can be used to construct arrays in `rand`, `ones`, +# `zeros` and `fill` with either a range for a lookup index or a number for the +# dimension length. + +# Or we can use the `Dim{X}` dims by using `Symbol`s, and indexing with keywords: + +A = DimArray(rand(5, 5), (:a, :b)) + +# get value + +A[a=3, b=5] + +# Often, we want to provide a lookup index for the dimension: + +using Dates +t = DateTime(2001):Month(1):DateTime(2001,12) +x = 10:10:100 +A = rand(X(x), Ti(t)) + +# Here both `X` and `Ti` are dimensions from `DimensionalData`. The currently +# exported dimensions are `X, Y, Z, Ti` (`Ti` is shortening of `Time`). + +# The length of each dimension index has to match the size of the corresponding +# array axis. + +# This can also be done with `Symbol`, using `Dim{X}`: + +A2 = DimArray(rand(12, 10), (time=t, distance=x)) + +# Symbols can be more convenient to use than defining custom dims with `@dim`, but +# have some downsides. They don't inherit from a specific `Dimension` type, so +# plots will not know what axis to put them on. They also cannot use the basic +# constructor methods like `rand` or `zeros`, as we cannot dispatch on `Symbol` +# for Base methods without "type-piracy". + + +# ## Indexing the array by name and index + +# Dimensions can be used to index the array by name, without having to worry +# about the order of the dimensions. + +# The simplest case is to select a dimension by index. Let's say every 2nd point +# of the `Ti` dimension and every 3rd point of the `X` dimension. This is done +# with the simple `Ti(range)` syntax like so: + +A[X(1:3:11), Ti(1:2:11)] + +# When specifying only one dimension, all elements of the other +# dimensions are assumed to be included: + +A[X(1:3:10)] + +# !!! info "Indexing" +# Indexing `AbstractDimArray`s works with `getindex`, `setindex!` and +# `view`. The result is still an `AbstracDimArray`, unless using all single +# `Int` or `Selector`s that resolve to `Int`. + + +# `Dimension`s can be used to construct arrays in `rand`, `ones`, `zeros` and +# `fill` with either a range for a lookup index or a number for the dimension +# length. + +using DimensionalData +A1 = ones(X(1:40), Y(50)) + +# We can also use dim wrappers for indexing, so that the dimension order in the underlying array +# does not need to be known: + +A1[Y(1), X(1:10)] + + +# ## Indexing Performance + +# Indexing with `Dimension` has no runtime cost: + +A2 = ones(X(3), Y(3)) + +# time ? +using BenchmarkTools + +println(@btime $A2[X(1), Y(2)]) + +# and + +println(@btime parent($A2)[1, 2]) + +# ## Specifying `dims` keyword arguments with `Dimension` + +# In many Julia functions like `size` or `sum`, you can specify the dimension +# along which to perform the operation as an `Int`. It is also possible to do this +# using [`Dimension`](@ref) types with `AbstractDimArray`: + +A3 = rand(X(3), Y(4), Ti(5)); +sum(A3; dims=Ti) + +# This also works in methods from `Statistics`: + +using Statistics +mean(A3; dims=Ti) + +# ## Methods where dims, dim types, or `Symbol`s can be used to indicate the array dimension: + +# - `size`, `axes`, `firstindex`, `lastindex` +# - `cat`, `reverse`, `dropdims` +# - `reduce`, `mapreduce` +# - `sum`, `prod`, `maximum`, `minimum`, +# - `mean`, `median`, `extrema`, `std`, `var`, `cor`, `cov` +# - `permutedims`, `adjoint`, `transpose`, `Transpose` +# - `mapslices`, `eachslice` + +# ## LookupArrays and Selectors + +# Indexing by value in `DimensionalData` is done with [Selectors](@ref). +# IntervalSets.jl is now used for selecting ranges of values (formerly `Between`). + +# | Selector | Description | +# | :---------------------- | :------------------------------------------------------------------ | +# | [`At(x)`](@ref) | get the index exactly matching the passed in value(s) | +# | [`Near(x)`](@ref) | get the closest index to the passed in value(s) | +# | [`Contains(x)`](@ref) | get indices where the value x falls within an interval | +# | [`Where(f)`](@ref) | filter the array axis by a function of the dimension index values. | +# | [`a..b`] | get all indices between two values, inclusively. | +# | [`OpenInterval(a, b)`] | get all indices between `a` and `b`, exclusively. | +# | [`Interval{A,B}(a, b)`] | get all indices between `a` and `b`, as `:closed` or `:open`. | + + +# Selectors find indices in the `LookupArray`, for each dimension. +# Here we use an `Interval` to select a range between integers and `DateTime`: + +A[X(12..35), Ti(Date(2001, 5)..Date(2001, 7))] + + +# Selectors can be used in `getindex`, `setindex!` and +# `view` to select indices matching the passed in value(s) + +# We can use selectors inside dim wrappers, here selecting values from `DateTime` and `Int`: + +using Dates +timespan = DateTime(2001,1):Month(1):DateTime(2001,12) +A4 = rand(Ti(timespan), X(10:10:100)) +A4[X(Near(35)), Ti(At(DateTime(2001,5)))] + +# Without dim wrappers selectors must be in the right order, and specify all axes: + +using Unitful +A5 = rand(Y((1:10:100)u"m"), Ti((1:5:100)u"s")); +A5[10.5u"m" .. 50.5u"m", Near(23u"s")] + + +# We can also use Linear indices as in standard `Array`: + +A5[1:5] + +# But unless the `DimArray` is one dimensional, this will return a regular +# `Array`. It is not possible to keep the `LookupArray` or even `Dimension`s after +# linear indexing is used. + +# ## LookupArrays and traits + +# Using a regular range or `Vector` as a lookup index has a number of downsides. +# We cannot use `searchsorted` for fast searches without knowing the order of the +# array, and this is slow to compute at runtime. It also means `reverse` or +# rotations cannot be used while keeping the `DimArray` wrapper. + +# Step sizes are also a problem. Some ranges like `LinRange` lose their step size +# with a length of `1`. Often, instead of a range, multi-dimensional data formats +# provide a `Vector` of evenly spaced values for a lookup, with a step size +# specified separately. Converting to a range introduces floating point errors +# that means points may not be selected with `At` without setting tolerances. + +# This means using a lookup wrapper with traits is more generally robust and +# versatile than simply using a range or vector. DimensionalData provides types +# for specifying details about the dimension index, in the [`LookupArrays`](@ref) +# sub-module: + +using DimensionalData +using .LookupArrays + +# The main [`LookupArray`](@ref) are : + +# - [`Sampled`](@ref) +# - [`Categorical`](@ref), +# - [`NoLookup`](@ref) + +# Each comes with specific traits that are either fixed or variable, depending +# on the contained index. These enable optimisations with `Selector`s, and modified +# behaviours, such as: + +# 1. Selection of [`Intervals`](@ref) or [`Points`](@ref), which will give slightly +# different results for selectors like `..` - as whole intervals are +# selected, and have different `bounds` values. + +# 2. Tracking of lookup order. A reverse order is labelled `ReverseOrdered` and +# will still work with `searchsorted`, and for plots to always be the right way +# up when either the index or the array is backwards. Reversing a `DimArray` +# will reverse the `LookupArray` for that dimension, swapping `ReverseOrdered` +# to `ForwardOrdered`. + +# 3. `Sampled` [`Intervals`](@ref) can have index located at a [`Locus`](@ref) of: + +# - [`Start`](@ref), +# - [`Center`](@ref) +# - [`End`](@ref) + +# Which specifies the point of the interval represented in the index, to match +# different data standards, e.g. GeoTIFF (`Start`) and NetCDF (`Center`). + +# 4. A [`Span`](@ref) specifies the gap between `Points` or the size of +# `Intervals`. This may be: + +# - [`Regular`](@ref), in the case of a range and equally spaced vector, +# - [`Irregular`](@ref) for unequally spaced vectors +# - [`Explicit`](@ref) for the case where all interval start and end points are +# specified explicitly - as is common in the NetCDF standard. + +# These traits all for subtypes of [`Aligned`](@ref). + +# [`Unaligned`](@ref) also exists to handle dimensions with an index that is +# rotated or otherwise transformed in relation to the underlying array, such as +# [`Transformed`](@ref). + + +# ## LookupArray detection + +# [`Aligned`](@ref) types will be detected automatically if not specified - which +# usually isn't required. + +# - An empty `Dimension` or a `Type` or `Symbol` will be assigned `NoLookup` - +# this behaves as a simple named dimension without a lookup index. +# - A `Dimension` containing and index of `String`, `Char`, `Symbol` or mixed +# types will be given the [`Categorical`](@ref) mode, +# - A range will be assigned [`Sampled`](@ref), defaulting to +# [`Regular`](@ref), [`Points`](@ref) +# - Other `AbstractVector` will be assigned [`Sampled`](@ref) [`Irregular`](@ref) +# [`Points`](@ref). + +# In all cases the [`Order`](@ref) of [`ForwardOrdered`](@ref) or +# [`ReverseOrdered`](@ref) will be be detected, otherwise [`Unordered`](@ref) +# for an unsorted `Array`. + +# See the [`LookupArray`](@ref) API docs for more detail. + +# ## Referenced dimensions + +# The reference dimensions record the previous dimensions that an array was +# selected from. These can be use for plot labelling, and tracking array changes +# so that `cat` can reconstruct the lookup array from previous dimensions that +# have been sliced. + +# ## Warnings + +# Indexing with unordered or reverse-ordered arrays has undefined behaviour. +# It will trash the dimension index, break `searchsorted` and nothing will make +# sense any more. So do it at you own risk. + +# However, indexing with sorted vectors of `Int` can be useful, so it's allowed. +# But it may do strange things to interval sizes for [`Intervals`](@ref) that are +# not [`Explicit`](@ref). + +# This selects the first 5 entries of the underlying array. In the case that `A` +# has only one dimension, it will be retained. Multidimensional `AbstracDimArray` +# indexed this way will return a regular array. diff --git a/docs/genfiles.jl b/docs/genfiles.jl new file mode 100644 index 000000000..2f2bd58b5 --- /dev/null +++ b/docs/genfiles.jl @@ -0,0 +1,28 @@ +using Documenter, DocumenterMarkdown +using Literate + +get_example_path(p) = joinpath(@__DIR__, ".", "crash", p) +OUTPUT = joinpath(@__DIR__, "src", "crash", "generated") + +folders = readdir(joinpath(@__DIR__, ".", "crash")) +setdiff!(folders, [".DS_Store"]) + +function getfiles() + srcsfiles = [] + for f in folders + names = readdir(joinpath(@__DIR__, ".", "crash", f)) + setdiff!(names, [".DS_Store"]) + fpaths = "$(f)/" .* names + srcsfiles = vcat(srcsfiles, fpaths...) + end + return srcsfiles +end + +srcsfiles = getfiles() + +for (d, paths) in (("tutorial", srcsfiles),) + for p in paths + Literate.markdown(get_example_path(p), joinpath(OUTPUT, dirname(p)); + documenter=true) + end +end \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 1f7befc21..78b8070f7 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,37 +1,29 @@ -using Pkg -Pkg.activate(@__DIR__) - -using Documenter, DimensionalData, CoordinateTransformations, Dates, Unitful +using Documenter, DocumenterMarkdown +using DimensionalData using DimensionalData.LookupArrays, DimensionalData.Dimensions - -CI = get(ENV, "CI", nothing) == "true" || get(ENV, "GITHUB_TOKEN", nothing) !== nothing -DEPLOY_DOCS = get(ENV, "DEPLOY_DOCS", "$CI") == "true" - -docsetup = quote - using DimensionalData, Random, Dates - Random.seed!(1234) -end -DocMeta.setdocmeta!(DimensionalData, :DocTestSetup, docsetup; recursive=true) +using CoordinateTransformations, Dates, Unitful makedocs( modules = [DimensionalData], - sitename = "DimensionalData.jl", - format = Documenter.HTML( - prettyurls = CI, - ), - pages = [ - "Introduction" => "index.md", - "Crash course" => "course.md", - "API" => "api.md", - "For Developers" => "developer.md" - ], - strict=true, + clean=true, + doctest=false, + #format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"), + sitename="DimensionalData.jl", + authors="Rafael Schouten et al.", + strict=[ + :doctest, + :linkcheck, + :parse_error, + :example_block, + # Other available options are + # :autodocs_block, :cross_references, :docs_block, :eval_block, :example_block, + # :footnote, :meta_block, :missing_docs, :setup_block + ], checkdocs=:all, format=Markdown(), draft=false, + build=joinpath(@__DIR__, "docs") ) -if DEPLOY_DOCS - deploydocs( - repo = "github.com/rafaqz/DimensionalData.jl.git", - target = "build", - push_preview = true - ) -end +deploydocs(; repo="github.com/rafaqz/DimensionalData.jl.git", push_preview=true, + deps=Deps.pip("mkdocs", "pygments", "python-markdown-math", "mkdocs-material", + "pymdown-extensions", "mkdocstrings", "mknotebooks", + "pytkdocs_tweaks", "mkdocs_include_exclude_files", "jinja2"), + make=() -> run(`mkdocs build`), target="site", devbranch="main") \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 000000000..4521e7b5a --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,119 @@ +theme: + name: material + #logo: assets/DimensionalData_logo.png + features: + # - announce.dismiss + #- content.code.annotate + # - content.tabs.link + #- content.tooltips + # - header.autohide + # - navigation.expand + #- navigation.indexes + # - navigation.instant + # - navigation.prune + #- navigation.sections + #- navigation.tabs + # - navigation.tabs.sticky + - navigation.top + - navigation.footer + #- navigation.tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + #- toc.integrate # Table of contents is integrated on the left; does not appear separately on the right. + - header.autohide # header disappears as you scroll + palette: + + # Light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: grey + accent: orange + toggle: + icon: material/weather-sunny + name: Switch to dark mode + + # Dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: blue grey + accent: orange + toggle: + icon: material/weather-night + name: Switch to light mode + font: + text: Lato + icon: + repo: fontawesome/brands/github # GitHub logo in top right + #logo: "material/gridoff" # Equinox logo in top left + # favicon: "_static/icon_transparent.svg" + custom_dir: "_overrides" # Overriding part of the HTML + + # These additions are my own custom ones, having overridden a partial. + #twitter_name: "" + #twitter_url: "" +site_name: DimensionalData.jl +site_description: DimensionalData.jl +site_author: Lazaro Alonso and Rafael Schouten +site_url: "" + +repo_url: https://github.com/rafaqz/DimensionalData.jl +repo_name: DimensionalData.jl +edit_uri: "" # No edit button, as some of our pages are in /docs and some in /examples via symlink, so it's impossible for them all to be accurate + +strict: true # Don't allow warnings during the build process +extra_javascript: + # The below three make MathJax work, see https://squidfunk.github.io/mkdocs-material/reference/mathjax/ + - _static/mathjax.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + +extra: + social: + - icon: fontawesome/brands/github + #link: + - icon: fontawesome/brands/twitter + #link: + +extra_css: + - stylesheets/custom.css + - assets/Documenter.css + +extra_javascript: + - javascripts/mathjax.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + +markdown_extensions: + - tables + - admonition + - toc: + permalink: "¤" # Adds a clickable permalink to each section heading + toc_depth: 4 + - pymdownx.arithmatex: # Render LaTeX via MathJax + generic: true + - pymdownx.details # Allowing hidden expandable regions denoted by ??? + - pymdownx.highlight + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences # Seems to enable syntax highlighting when used with the Material theme. + - pymdownx.tasklist: + custom_checkbox: true + - def_list + - pymdownx.tabbed: + alternate_style: true + - attr_list + - md_in_html +plugins: + - search # default search plugin; needs manually re-enabling when using any other plugins + - autorefs # Cross-links to headings + - include_exclude_files: + exclude: + - "_overrides" +# - mknotebooks # Jupyter notebooks +# - mkdocs-video +nav: + - "Home": "index.md" + - "Crash course" : "crash/generated/course/course.md" + - "Reference" : "reference.md" \ No newline at end of file diff --git a/docs/src/course.md b/docs/src/course.md deleted file mode 100644 index ade785402..000000000 --- a/docs/src/course.md +++ /dev/null @@ -1,311 +0,0 @@ -# Crash course - -## Dimensions and DimArrays - -The core type of DimensionalData.jl is the [`Dimension`](@ref) and the types -that inherit from it, such as `Ti`, `X`, `Y`, `Z`, the generic `Dim{:x}`, or -others that you define manually using the [`@dim`](@ref) macro. - -`Dimension`s are primarily used in [`DimArray`](@ref), other -[`AbstractDimArray`](@ref). - -We can use dimensions without a value index - these simply label the axis. -A `DimArray` with labelled dimensions is constructed by: - -```@example main -using DimensionalData -A = rand(X(5), Y(5)) -A[Y(1), X(2)] -``` - -As shown above, `Dimension`s can be used to construct arrays in `rand`, `ones`, -`zeros` and `fill` with either a range for a lookup index or a number for the -dimension length. - -Or we can use the `Dim{X}` dims by using `Symbol`s, and indexing with keywords: - -```@example main -A = DimArray(rand(5, 5), (:a, :b)) -A[a=3, b=5] -``` - -Often, we want to provide a lookup index for the dimension: - -```@example main -using Dates -t = DateTime(2001):Month(1):DateTime(2001,12) -x = 10:10:100 -A = rand(X(x), Ti(t)) -``` - -Here both `X` and `Ti` are dimensions from `DimensionalData`. The currently -exported dimensions are `X, Y, Z, Ti` (`Ti` is shortening of `Time`). - -The length of each dimension index has to match the size of the corresponding -array axis. - -This can also be done with `Symbol`, using `Dim{X}`: - -```@example main -A2 = DimArray(rand(12, 10), (time=t, distance=x)) -``` - -Symbols can be more convenient to use than defining custom dims with `@dim`, but -have some downsides. They don't inherit from a specific `Dimension` type, so -plots will not know what axis to put them on. They also cannot use the basic -constructor methods like `rand` or `zeros`, as we cannot dispatch on `Symbol` -for Base methods without "type-piracy". - - -## Indexing the array by name and index - -Dimensions can be used to index the array by name, without having to worry -about the order of the dimensions. - -The simplest case is to select a dimension by index. Let's say every 2nd point -of the `Ti` dimension and every 3rd point of the `X` dimension. This is done -with the simple `Ti(range)` syntax like so: - -```@example main -A[X(1:3:11), Ti(1:2:11)] -``` - -When specifying only one dimension, all elements of the other -dimensions are assumed to be included: - -```@example main -A[X(1:3:10)] -``` - -!!! info "Indexing" - Indexing `AbstractDimArray`s works with `getindex`, `setindex!` and - `view`. The result is still an `AbstracDimArray`, unless using all single - `Int` or `Selector`s that resolve to `Int`. - - -`Dimension`s can be used to construct arrays in `rand`, `ones`, `zeros` and -`fill` with either a range for a lookup index or a number for the dimension -length. - -```@example ones -using DimensionalData -A1 = ones(X(1:40), Y(50)) -``` - -We can also use dim wrappers for indexing, so that the dimension order in the underlying array -does not need to be known: - -```@example ones -A1[Y(1), X(1:10)] -``` - -## Indexing Performance - -Indexing with `Dimension` has no runtime cost: - -```julia -julia> A2 = ones(X(3), Y(3)) -3×3 DimArray{Float64,2} with dimensions: X, Y - 1.0 1.0 1.0 - 1.0 1.0 1.0 - 1.0 1.0 1.0 - -julia> @btime $A2[X(1), Y(2)] - 1.077 ns (0 allocations: 0 bytes) -1.0 - -julia> @btime parent($A2)[1, 2] - 1.078 ns (0 allocations: 0 bytes) -1.0 -``` - -## Specifying `dims` keyword arguments with `Dimension` - -In many Julia functions like `size` or `sum`, you can specify the dimension -along which to perform the operation as an `Int`. It is also possible to do this -using [`Dimension`](@ref) types with `AbstractDimArray`: - -```@example main -A3 = rand(X(3), Y(4), Ti(5)); -sum(A3; dims=Ti) -``` - -This also works in methods from `Statistics`: - -```@example main -using Statistics -mean(A3; dims=Ti) -``` - -### Methods where dims, dim types, or `Symbol`s can be used to indicate the array dimension: - -- `size`, `axes`, `firstindex`, `lastindex` -- `cat`, `reverse`, `dropdims` -- `reduce`, `mapreduce` -- `sum`, `prod`, `maximum`, `minimum`, -- `mean`, `median`, `extrema`, `std`, `var`, `cor`, `cov` -- `permutedims`, `adjoint`, `transpose`, `Transpose` -- `mapslices`, `eachslice` - - -## LookupArrays and Selectors - -Indexing by value in `DimensionalData` is done with [Selectors](@ref). -IntervalSets.jl is now used for selecting ranges of values (formerly `Between`). - - -| Selector | Description | -| :---------------------- | :------------------------------------------------------------------ | -| [`At(x)`] | get the index exactly matching the passed in value(s) | -| [`Near(x)`] | get the closest index to the passed in value(s) | -| [`Contains(x)`] | get indices where the value x falls within an interval | -| [`Where(f)`] | filter the array axis by a function of the dimension index values. | -| [`a..b`] | get all indices between two values, inclusively. | -| [`OpenInterval(a, b)`] | get all indices between `a` and `b`, exclusively. | -| [`Interval{A,B}(a, b)`] | get all indices between `a` and `b`, as `:closed` or `:open`. | - - -Selectors find indices in the `LookupArray`, for each dimension. -Here we use an `Interval` to select a range between integers and `DateTime`: - -```@example main -A[X(12..35), Ti(Date(2001, 5)..Date(2001, 7))] -``` - -Selectors can be used in `getindex`, `setindex!` and -`view` to select indices matching the passed in value(s) - -We can use selectors inside dim wrappers, here selecting values from `DateTime` and `Int`: - -```@example main -using Dates -timespan = DateTime(2001,1):Month(1):DateTime(2001,12) -A4 = rand(Ti(timespan), X(10:10:100)) -A4[X(Near(35)), Ti(At(DateTime(2001,5)))] -``` - -Without dim wrappers selectors must be in the right order, and specify all axes: - -```@example main -using Unitful -A5 = rand(Y((1:10:100)u"m"), Ti((1:5:100)u"s")); -A5[10.5u"m" .. 50.5u"m", Near(23u"s")] -``` - -We can also use Linear indices as in standard `Array`: - -```@example main -A5[1:5] -``` - -But unless the `DimArray` is one dimensional, this will return a regular -`Array`. It is not possible to keep the `LookupArray` or even `Dimension`s after -linear indexing is used. - -## LookupArrays and traits - -Using a regular range or `Vector` as a lookup index has a number of downsides. -We cannot use `searchsorted` for fast searches without knowing the order of the -array, and this is slow to compute at runtime. It also means `reverse` or -rotations cannot be used while keeping the `DimArray` wrapper. - -Step sizes are also a problem. Some ranges like `LinRange` lose their step size -with a length of `1`. Often, instead of a range, multi-dimensional data formats -provide a `Vector` of evenly spaced values for a lookup, with a step size -specified separately. Converting to a range introduces floating point errors -that means points may not be selected with `At` without setting tolerances. - -This means using a lookup wrapper with traits is more generally robust and -versatile than simply using a range or vector. DimensionalData provides types -for specifying details about the dimension index, in the [`LookupArrays`](@ref) -sub-module: - -```julia -using DimensionalData -using .LookupArrays -``` - -The main [`LookupArray`](@ref) are : - -- [`Sampled`](@ref) -- [`Categorical`](@ref), -- [`NoLookup`](@ref) - -Each comes with specific traits that are either fixed or variable, depending -on the contained index. These enable optimisations with `Selector`s, and modified -behaviours, such as: - -1. Selection of [`Intervals`](@ref) or [`Points`](@ref), which will give slightly - different results for selectors like `..` - as whole intervals are - selected, and have different `bounds` values. - -2. Tracking of lookup order. A reverse order is labelled `ReverseOrdered` and - will still work with `searchsorted`, and for plots to always be the right way - up when either the index or the array is backwards. Reversing a `DimArray` - will reverse the `LookupArray` for that dimension, swapping `ReverseOrdered` - to `ForwardOrdered`. - -3. `Sampled` [`Intervals`](@ref) can have index located at a [`Locus`](@ref) of: - -- [`Start`](@ref), -- [`Center`](@ref) -- [`End`](@ref) - -Which specifies the point of the interval represented in the index, to match -different data standards, e.g. GeoTIFF (`Start`) and NetCDF (`Center`). - -4. A [`Span`](@ref) specifies the gap between `Points` or the size of -`Intervals`. This may be: - -- [`Regular`](@ref), in the case of a range and equally spaced vector, -- [`Irregular`](@ref) for unequally spaced vectors -- [`Explicit`](@ref) for the case where all interval start and end points are - specified explicitly - as is common in the NetCDF standard. - -These traits all for subtypes of [`Aligned`](@ref). - -[`Unaligned`](@ref) also exists to handle dimensions with an index that is -rotated or otherwise transformed in relation to the underlying array, such as -[`Transformed`](@ref). - - -## LookupArray detection - -[`Aligned`](@ref) types will be detected automatically if not specified - which -usually isn't required. - -- An empty `Dimension` or a `Type` or `Symbol` will be assigned `NoLookup` - - this behaves as a simple named dimension without a lookup index. -- A `Dimension` containing and index of `String`, `Char`, `Symbol` or mixed - types will be given the [`Categorical`](@ref) mode, -- A range will be assigned [`Sampled`](@ref), defaulting to - [`Regular`](@ref), [`Points`](@ref) -- Other `AbstractVector` will be assigned [`Sampled`](@ref) [`Irregular`](@ref) - [`Points`](@ref). - -In all cases the [`Order`](@ref) of [`ForwardOrdered`](@ref) or -[`ReverseOrdered`](@ref) will be be detected, otherwise [`Unordered`](@ref) -for an unsorted `Array`. - -See the [`LookupArray`](@ref) API docs for more detail. - -## Referenced dimensions - -The reference dimensions record the previous dimensions that an array was -selected from. These can be use for plot labelling, and tracking array changes -so that `cat` can reconstruct the lookup array from previous dimensions that -have been sliced. - -## Warnings - -Indexing with unordered or reverse-ordered arrays has undefined behaviour. -It will trash the dimension index, break `searchsorted` and nothing will make -sense any more. So do it at you own risk. - -However, indexing with sorted vectors of `Int` can be useful, so it's allowed. -But it may do strange things to interval sizes for [`Intervals`](@ref) that are -not [`Explicit`](@ref). - -This selects the first 5 entries of the underlying array. In the case that `A` -has only one dimension, it will be retained. Multidimensional `AbstracDimArray` -indexed this way will return a regular array. diff --git a/docs/src/developer.md b/docs/src/developer.md deleted file mode 100644 index 823450fa4..000000000 --- a/docs/src/developer.md +++ /dev/null @@ -1,78 +0,0 @@ -# For package developers - -## Goals: - -- Maximum extensibility: always use method dispatch. Regular types over special - syntax. Recursion over @generated. -- Flexibility: dims and selectors are parametric types with multiple uses -- Abstraction: never dispatch on concrete types, maximum re-usability of methods -- Clean, readable syntax. Minimise required parentheses, minimise of exported - methods, and instead extend Base methods whenever possible. -- Minimal interface: implementing a dimension-aware type should be easy. -- Functional style: structs are always rebuilt, and other than the array data, - fields are not mutated in place. -- Laziness. Label data correctly, and manipulate them when needed - - instead of standardising eagerly. -- Least surprise: everything works the same as in Base, but with named dims. If - a method accepts numeric indices or `dims=X` in base, you should be able to - use DimensionalData.jl dims. -- Type stability: dimensional methods should be type stable _more often_ than Base methods -- Zero cost dimensional indexing `a[Y(4), X(5)]` of a single value. -- Low cost indexing for range getindex and views: these cant be zero cost as dim - ranges have to be updated. -- Plotting is easy: data should plot sensibly and correctly with useful labels - - after all transformations using dims or indices -- Prioritise spatial data: other use cases are a free bonus of the modular - approach. - -## Why this package - -Why not [AxisArrays.jl](https://github.com/JuliaArrays/AxisArrays.jl) or -[NamedDims.jl](https://github.com/invenia/NamedDims.jl/)? - -### Structure - -Both AxisArrays and NamedDims use concrete types for dispatch on arrays, and for -dimension type `Axis` in AxisArrays. This makes them hard to extend. - -Its a little easier with DimensionalData.jl. You can inherit from -`AbstractDimArray`, or just implement `dims` and `rebuild` methods. Dims -and selectors in DimensionalData.jl are also extensible. Recursive primitive -methods allow inserting whatever methods you want to add extra types. -`@generated` is only used to match and permute arbitrary tuples of types, and -contain no type-specific details. The `@generated` functions in AxisArrays -internalise axis/index conversion behaviour preventing extension in external -packages and scripts. - -### Syntax - -AxisArrays.jl is verbose by default: `a[Axis{:y}(1)]` vs `a[Y(1)]` used here. -NamedDims.jl has concise syntax, but the dimensions are no longer types, -NamedDims.jl syntax can now be replicated using `Dim{:X}`: - -```julia -A = DimArray(rand(4, 5), (:a, :b)) -A[:b=5, :a=3] = 25.0 -``` - -## Data types and the interface - -DimensionalData.jl provides the concrete `DimArray` type. But it's -core purpose is to be easily used with other array types. - -Some of the functionality in DimensionalData.jl will work without inheriting -from `AbstractDimArray`. The main requirement define a `dims` method -that returns a `Tuple` of `Dimension` that matches the dimension order -and axis values of your data. Define `rebuild`, and base methods for `similar` -and `parent` if you want the metadata to persist through transformations (see -the `DimArray` and `AbstractDimArray` types). A `refdims` method -returns the lost dimensions of a previous transformation, passed in to the -`rebuild` method. `refdims` can be discarded, the main loss being plot labels. - -Inheriting from `AbstractDimArray` will give nearly all the functionality -of using `DimArray`. - - -## LookupArrays and Dimensions - -[`LookupArrays`](@ref) and [`Dimensions`](@ref) diff --git a/docs/src/index.md b/docs/src/index.md index 5ef183e74..d0f99ca01 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,100 @@ -```@docs -DimensionalData +## DimensionalData + +DimensionalData.jl provides tools and abstractions for working with datasets +that have named dimensions, and optionally a lookup index. It provides no-cost +abstractions for named indexing, and fast index lookups. + +DimensionalData is a pluggable, generalised version of +[AxisArrays.jl](https://github.com/JuliaArrays/AxisArrays.jl) with a cleaner +syntax, and additional functionality found in NamedDims.jl. It has similar goals +to pythons [xarray](http://xarray.pydata.org/en/stable/), and is primarily +written for use with spatial data in [Rasters.jl](https://github.com/rafaqz/Rasters.jl). + +## Goals +!!! info "" + - Maximum extensibility: always use method dispatch. Regular types over special + syntax. Recursion over @generated. + - Flexibility: dims and selectors are parametric types with multiple uses + - Abstraction: never dispatch on concrete types, maximum re-usability of methods + - Clean, readable syntax. Minimise required parentheses, minimise of exported + methods, and instead extend Base methods whenever possible. + - Minimal interface: implementing a dimension-aware type should be easy. + - Functional style: structs are always rebuilt, and other than the array data, + fields are not mutated in place. + - Laziness. Label data correctly, and manipulate them when needed - + instead of standardising eagerly. + - Least surprise: everything works the same as in Base, but with named dims. If + a method accepts numeric indices or `dims=X` in base, you should be able to + use DimensionalData.jl dims. + - Type stability: dimensional methods should be type stable _more often_ than Base methods + - Zero cost dimensional indexing `a[Y(4), X(5)]` of a single value. + - Low cost indexing for range getindex and views: these cant be zero cost as dim + ranges have to be updated. + - Plotting is easy: data should plot sensibly and correctly with useful labels - + after all transformations using dims or indices + - Prioritise spatial data: other use cases are a free bonus of the modular + approach. + +## For package developers + +### Why this package? + +Why not [AxisArrays.jl](https://github.com/JuliaArrays/AxisArrays.jl) or +[NamedDims.jl](https://github.com/invenia/NamedDims.jl/)? + + +### Structure + +Both AxisArrays and NamedDims use concrete types for dispatch on arrays, and for +dimension type `Axis` in AxisArrays. This makes them hard to extend. + +```@raw html +??? question "more" + + Its a little easier with DimensionalData.jl. You can inherit from + `AbstractDimArray`, or just implement `dims` and `rebuild` methods. Dims + and selectors in DimensionalData.jl are also extensible. Recursive primitive + methods allow inserting whatever methods you want to add extra types. + `@generated` is only used to match and permute arbitrary tuples of types, and + contain no type-specific details. The `@generated` functions in AxisArrays + internalise axis/index conversion behaviour preventing extension in external + packages and scripts. +``` + +### Syntax + +AxisArrays.jl is verbose by default: `a[Axis{:y}(1)]` vs `a[Y(1)]` used here. +NamedDims.jl has concise syntax, but the dimensions are no longer types, +NamedDims.jl syntax can now be replicated using `Dim{:X}`: + +```julia +A = DimArray(rand(4, 5), (:a, :b)) +A[:b=5, :a=3] = 25.0 +``` + +## Data types and the interface + +DimensionalData.jl provides the concrete `DimArray` type. But it's +core purpose is to be easily used with other array types. + +```@raw html +??? question "more" + + Some of the functionality in DimensionalData.jl will work without inheriting + from `AbstractDimArray`. The main requirement define a `dims` method + that returns a `Tuple` of `Dimension` that matches the dimension order + and axis values of your data. Define `rebuild`, and base methods for `similar` + and `parent` if you want the metadata to persist through transformations (see + the `DimArray` and `AbstractDimArray` types). A `refdims` method + returns the lost dimensions of a previous transformation, passed in to the + `rebuild` method. `refdims` can be discarded, the main loss being plot labels. + + Inheriting from `AbstractDimArray` will give nearly all the functionality + of using `DimArray`. ``` -To learn how to use this package, see the [Crash course](@ref). + +## LookupArrays and Dimensions + +[`LookupArrays`](@ref) and [`Dimensions`](@ref) + diff --git a/docs/src/javascripts/mathjax.js b/docs/src/javascripts/mathjax.js new file mode 100644 index 000000000..a80ddbff7 --- /dev/null +++ b/docs/src/javascripts/mathjax.js @@ -0,0 +1,16 @@ +window.MathJax = { + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } +}; + +document$.subscribe(() => { + MathJax.typesetPromise() +}) \ No newline at end of file diff --git a/docs/src/api.md b/docs/src/reference.md similarity index 92% rename from docs/src/api.md rename to docs/src/reference.md index 5cf88794c..98cf1e167 100644 --- a/docs/src/api.md +++ b/docs/src/reference.md @@ -1,251 +1,251 @@ - -# API - -## Arrays - -```@docs -AbstractDimArray -DimArray -``` - -## Multi-array datasets - -```@docs -AbstractDimStack -DimStack -``` - -## Dimension indices generators - -```@docs -DimIndices -DimKeys -DimPoints -``` - -## Tables.jl/TableTraits.jl interface - -```@docs -DimensionalData.AbstractDimTable -DimTable -DimensionalData.DimColumn -``` - -## Common methods - -Common functions for obtaining information from objects: - -```@docs -dims -refdims -metadata -name -``` - -Utility methods for transforming DimensionalData objects: - -```@docs -set -rebuild -modify -broadcast_dims -broadcast_dims! -reorder -Base.cat -Base.map -Base.copy! -Base.eachslice -``` - -Most base methods work as expected, using `Dimension` wherever a `dims` -keyword is used. They are not allspecifically documented here. - - -Shorthand constructors: - -```@docs -Base.fill -Base.rand -Base.zeros -Base.ones -``` - -# Dimensions - -Handling of Dimensions is kept in a sub-module `Dimensions`. - -```@docs -Dimensions.Dimensions -``` - -Dimensions have a type-heirarchy that organises plotting and -dimension matching. - -```@docs -Dimensions.Dimension -Dimensions.DependentDim -Dimensions.IndependentDim -Dimensions.XDim -Dimensions.YDim -Dimensions.ZDim -Dimensions.TimeDim -X -Y -Z -Ti -Dim -Coord -Dimensions.AnonDim -@dim -``` - -### Exported methopds - -```@docs -hasdim -dimnum -``` - - -### Non-exported methods - -```@docs -Dimensions.lookup -Dimensions.label -DimensionalData.dim2key -DimensionalData.key2dim -DimensionalData.dims2indices -DimensionalData.selectindices -DimensionalData.format -DimensionalData.reducedims -DimensionalData.swapdims -DimensionalData.slicedims -DimensionalData.comparedims -DimensionalData.combinedims -DimensionalData.otherdims -DimensionalData.commondims -DimensionalData.sortdims -DimensionalData.basetypeof -DimensionalData.setdims -DimensionalData.dimsmatch -DimensionalData.dimstride -DimensionalData.refdims_title -DimensionalData.rebuild_from_arrays -``` - -# LookupArrays - -```@docs -LookupArrays.LookupArrays -``` - -## Selectors - -```@docs -LookupArrays.Selector -LookupArrays.IntSelector -LookupArrays.ArraySelector -At -Near -Between -Touches -Contains -Where -All -``` - -Lookup properties: - -```@docs -bounds -LookupArrays.val -``` - -```@docs -LookupArrays.LookupArray -LookupArrays.Aligned -LookupArrays.AbstractSampled -LookupArrays.Sampled -LookupArrays.AbstractCategorical -LookupArrays.Categorical -LookupArrays.Unaligned -LookupArrays.Transformed -Dimensions.MergedLookup -LookupArrays.NoLookup -LookupArrays.AutoLookup -LookupArrays.AutoIndex -``` - -## Metadata - -```@docs -LookupArrays.AbstractMetadata -LookupArrays.Metadata -LookupArrays.NoMetadata -``` - -## LookupArray traits - -```@docs -LookupArrays.LookupArrayTrait -``` - -### Order - -```@docs -LookupArrays.Order -LookupArrays.Ordered -LookupArrays.ForwardOrdered -LookupArrays.ReverseOrdered -LookupArrays.Unordered -LookupArrays.AutoOrder -``` - -### Span - -```@docs -LookupArrays.Span -LookupArrays.Regular -LookupArrays.Irregular -LookupArrays.Explicit -LookupArrays.AutoSpan -``` - -### Sampling - -```@docs -LookupArrays.Sampling -LookupArrays.Points -LookupArrays.Intervals -``` - -### Loci - -```@docs -LookupArrays.Locus -LookupArrays.Center -LookupArrays.Start -LookupArrays.End -LookupArrays.AutoLocus -``` - -## LookupArrays methods - -```@docs -hasselection -LookupArrays.shiftlocus -LookupArrays.sampling -LookupArrays.span -LookupArrays.order -LookupArrays.index -LookupArrays.locus -LookupArrays.units -``` - -## Name - -```@docs -DimensionalData.AbstractName -DimensionalData.Name -DimensionalData.NoName -``` + +# API + +## Arrays + +```@docs +AbstractDimArray +DimArray +``` + +## Multi-array datasets + +```@docs +AbstractDimStack +DimStack +``` + +## Dimension indices generators + +```@docs +DimIndices +DimKeys +DimPoints +``` + +## Tables.jl/TableTraits.jl interface + +```@docs +DimensionalData.AbstractDimTable +DimTable +DimensionalData.DimColumn +``` + +## Common methods + +Common functions for obtaining information from objects: + +```@docs +dims +refdims +metadata +name +``` + +Utility methods for transforming DimensionalData objects: + +```@docs +set +rebuild +modify +broadcast_dims +broadcast_dims! +reorder +Base.cat +Base.map +Base.copy! +Base.eachslice +``` + +Most base methods work as expected, using `Dimension` wherever a `dims` +keyword is used. They are not allspecifically documented here. + + +Shorthand constructors: + +```@docs +Base.fill +Base.rand +Base.zeros +Base.ones +``` + +# Dimensions + +Handling of Dimensions is kept in a sub-module `Dimensions`. + +```@docs +Dimensions.Dimensions +``` + +Dimensions have a type-heirarchy that organises plotting and +dimension matching. + +```@docs +Dimensions.Dimension +Dimensions.DependentDim +Dimensions.IndependentDim +Dimensions.XDim +Dimensions.YDim +Dimensions.ZDim +Dimensions.TimeDim +X +Y +Z +Ti +Dim +Coord +Dimensions.AnonDim +@dim +``` + +### Exported methods + +```@docs +hasdim +dimnum +``` + + +### Non-exported methods + +```@docs +Dimensions.lookup +Dimensions.label +DimensionalData.dim2key +DimensionalData.key2dim +DimensionalData.dims2indices +DimensionalData.selectindices +DimensionalData.format +DimensionalData.reducedims +DimensionalData.swapdims +DimensionalData.slicedims +DimensionalData.comparedims +DimensionalData.combinedims +DimensionalData.otherdims +DimensionalData.commondims +DimensionalData.sortdims +DimensionalData.basetypeof +DimensionalData.setdims +DimensionalData.dimsmatch +DimensionalData.dimstride +DimensionalData.refdims_title +DimensionalData.rebuild_from_arrays +``` + +# LookupArrays + +```@docs +LookupArrays.LookupArrays +``` + +## Selectors + +```@docs +LookupArrays.Selector +LookupArrays.IntSelector +LookupArrays.ArraySelector +At +Near +Between +Touches +Contains +Where +All +``` + +Lookup properties: + +```@docs +bounds +LookupArrays.val +``` + +```@docs +LookupArrays.LookupArray +LookupArrays.Aligned +LookupArrays.AbstractSampled +LookupArrays.Sampled +LookupArrays.AbstractCategorical +LookupArrays.Categorical +LookupArrays.Unaligned +LookupArrays.Transformed +Dimensions.MergedLookup +LookupArrays.NoLookup +LookupArrays.AutoLookup +LookupArrays.AutoIndex +``` + +## Metadata + +```@docs +LookupArrays.AbstractMetadata +LookupArrays.Metadata +LookupArrays.NoMetadata +``` + +## LookupArray traits + +```@docs +LookupArrays.LookupArrayTrait +``` + +### Order + +```@docs +LookupArrays.Order +LookupArrays.Ordered +LookupArrays.ForwardOrdered +LookupArrays.ReverseOrdered +LookupArrays.Unordered +LookupArrays.AutoOrder +``` + +### Span + +```@docs +LookupArrays.Span +LookupArrays.Regular +LookupArrays.Irregular +LookupArrays.Explicit +LookupArrays.AutoSpan +``` + +### Sampling + +```@docs +LookupArrays.Sampling +LookupArrays.Points +LookupArrays.Intervals +``` + +### Loci + +```@docs +LookupArrays.Locus +LookupArrays.Center +LookupArrays.Start +LookupArrays.End +LookupArrays.AutoLocus +``` + +## LookupArrays methods + +```@docs +hasselection +LookupArrays.shiftlocus +LookupArrays.sampling +LookupArrays.span +LookupArrays.order +LookupArrays.index +LookupArrays.locus +LookupArrays.units +``` + +## Name + +```@docs +DimensionalData.AbstractName +DimensionalData.Name +DimensionalData.NoName +``` diff --git a/docs/src/stylesheets/custom.css b/docs/src/stylesheets/custom.css new file mode 100644 index 000000000..84d99c0e2 --- /dev/null +++ b/docs/src/stylesheets/custom.css @@ -0,0 +1,157 @@ +/* Fix /page#foo going to the top of the viewport and being hidden by the navbar */ +html { + scroll-padding-top: 50px; + } + + /* Fit the Twitter handle alongside the GitHub one in the top right. */ + + div.md-header__source { + width: revert; + max-width: revert; + } + + a.md-source { + display: inline-block; + } + + .md-source__repository { + max-width: 100%; + } + + /* Emphasise sections of nav on left hand side */ + + nav.md-nav { + padding-left: 5px; + } + + nav.md-nav--secondary { + border-left: revert !important; + } + + .md-nav__title { + font-size: 0.9rem; + } + + .md-nav__item--section > .md-nav__link { + font-size: 0.9rem; + } + + /* Indent autogenerated documentation */ + + div.doc-contents { + padding-left: 25px; + border-left: 4px solid rgba(230, 230, 230); + } + + /* Increase visibility of splitters "---" */ + + [data-md-color-scheme="default"] .md-typeset hr { + border-bottom-color: rgb(0, 0, 0); + border-bottom-width: 1pt; + } + + [data-md-color-scheme="slate"] .md-typeset hr { + border-bottom-color: rgb(230, 230, 230); + } + + /* More space at the bottom of the page */ + + .md-main__inner { + margin-bottom: 1.5rem; + } + + /* Remove prev/next footer buttons */ + + .md-footer__inner { + display: none; + } + + /* Bugfix: remove the superfluous parts generated when doing: + + ??? Blah + + ::: library.something + */ + + .md-typeset details .mkdocstrings > h4 { + display: none; + } + + .md-typeset details .mkdocstrings > h5 { + display: none; + } + + /* Change default colours for tags */ + + [data-md-color-scheme="default"] { + --md-typeset-a-color: rgb(0, 150, 255) !important; + } + [data-md-color-scheme="slate"] { + --md-typeset-a-color: rgb(0, 150, 255) !important; + } + + /* Highlight functions, classes etc. type signatures. Really helps to make clear where + one item ends and another begins. */ + + [data-md-color-scheme="default"] { + --doc-heading-color: #DDD; + --doc-heading-border-color: #CCC; + --doc-heading-color-alt: #F0F0F0; + } + [data-md-color-scheme="slate"] { + --doc-heading-color: rgb(25,25,33); + --doc-heading-border-color: rgb(25,25,33); + --doc-heading-color-alt: rgb(33,33,44); + --md-code-bg-color: rgb(38,38,50); + } + + h4.doc-heading { + /* NOT var(--md-code-bg-color) as that's not visually distinct from other code blocks.*/ + background-color: var(--doc-heading-color); + border: solid var(--doc-heading-border-color); + border-width: 1.5pt; + border-radius: 2pt; + padding: 0pt 5pt 2pt 5pt; + } + h5.doc-heading, h6.heading { + background-color: var(--doc-heading-color-alt); + border-radius: 2pt; + padding: 0pt 5pt 2pt 5pt; + } + + /* From Pretty Pandas Dataframes */ +/* Supports mkdocs-material color variables */ +.data-frame { + border: 0; + font-size: smaller; +} +.data-frame tr { + border: none; + background: var(--md-code-bg-color, #ffffff); +} +.data-frame tr:nth-child(even) { + background: var(--md-default-bg-color, #f5f5f5); +} +.data-frame tr:hover { + background-color: var(--md-footer-bg-color--dark, #e1f5fe); +} + +.data-frame thead th { + background: var(--md-default-bg-color, #ffffff); + border-bottom: 1px solid #aaa; + font-weight: bold; +} +.data-frame th { + border: none; + padding-left: 10px; + padding-right: 10px; +} + +.data-frame td{ + /* background: #fff; */ + border: none; + text-align: right; + min-width:5em; + padding-left: 10px; + padding-right: 10px; +} \ No newline at end of file