text:
@doc doc"""
    LogCholeskyMetric <: Metric

The Log-Cholesky metric imposes a metric based on the Cholesky decomposition as
introduced by [^Lin2019].

[^Lin2019]:
    > Lin, Zenhua: "Riemannian Geometry of Symmetric Positive Definite Matrices via
    > Cholesky Decomposition", arXiv: [1908.09326](https://arxiv.org/abs/1908.09326).
"""
struct LogCholeskyMetric <: RiemannianMetric end

cholesky_to_spd(l, w) = (l * l', w * l' + l * w')

tangent_cholesky_to_tangent_spd!(l, w) = (w .= w * l' + l * w')

spd_to_cholesky(x, v) = spd_to_cholesky(x, cholesky(x).L, v)

function spd_to_cholesky(x, l, v)
    w = inv(l) * v * inv(transpose(l))
    # strictly lower triangular plus half diagonal
    return (l, l * (LowerTriangular(w) - Diagonal(w) / 2))
end

@doc doc"""
    distance(M::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, x, y)

Compute the distance on the manifold of [`SymmetricPositiveDefinite`](@ref)
nmatrices, i.e. between two symmetric positive definite matrices `x` and `y`
with respect to the [`LogCholeskyMetric`](@ref). The formula reads

````math
d_{\mathcal P(n)}(x,y) = \sqrt{
 \lVert \lfloor l \rfloor - \lfloor k \rfloor \rVert_{\mathrm{F}}^2
 + \lVert \log(\operatorname{diag}(l)) - \log(\operatorname{diag}(k))\rVert_{\mathrm{F}}^2 }\ \ ,
````

where $l$ and $k$ are the cholesky factors of $x$ and $y$, respectively,
$\lfloor\cdot\rfloor$ denbotes the strictly lower triangular matrix of its argument,
and $\lVert\cdot\rVert_{\mathrm{F}}$ denotes the Frobenius norm.
"""
function distance(
    M::MetricManifold{SymmetricPositiveDefinite{N},LogCholeskyMetric},
    x,
    y,
) where {N}
    return distance(CholeskySpace{N}(), cholesky(x).L, cholesky(y).L)
end

@doc doc"""
    exp(M::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, x, v)

Compute the exponential map on the [`SymmetricPositiveDefinite`](@ref) `M` with
[`LogCholeskyMetric`](@ref) from `x` into direction `v`. The formula reads

````math
\exp_x v = (\exp_l w)(\exp_l w)^\mathrm{T}
````

where $\exp_lw$ is the exponential map on [`CholeskySpace`](@ref), $l$ is the cholesky
decomposition of $x$, $w = l(l^{-1}vl^{-\mathrm{T}})_\frac{1}{2}$,
and $(\cdot)_\frac{1}{2}$
denotes the lower triangular matrix with the diagonal multiplied by $\frac{1}{2}$.
"""
exp(::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, ::Any...)

function exp!(
    M::MetricManifold{SymmetricPositiveDefinite{N},LogCholeskyMetric},
    y,
    x,
    v,
) where {N}
    (l, w) = spd_to_cholesky(x, v)
    z = exp(CholeskySpace{N}(), l, w)
    return copyto!(y, z * z')
end

@doc doc"""
    inner(M::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, x, v, w)

Compute the inner product of two matrices `v`, `w` in the tangent space of `x`
on the [`SymmetricPositiveDefinite`](@ref) manifold `M`, as
a [`MetricManifold`](@ref) with [`LogCholeskyMetric`](@ref). The formula reads

````math
    (v,w)_x = (p_l(w),p_l(v))_l,
````

where the right hand side is the inner product on the [`CholeskySpace`](@ref),
$l$ is the cholesky factor of $x$,
$p_l(w) = l (l^{-1}wl^{-\mathrm{T}})_{\frac{1}{2}}$, and $(\cdot)_\frac{1}{2}$
denotes the lower triangular matrix with the diagonal multiplied by $\frac{1}{2}$
"""
function inner(
    M::MetricManifold{SymmetricPositiveDefinite{N},LogCholeskyMetric},
    x,
    v,
    w,
) where {N}
    (l, vl) = spd_to_cholesky(x, v)
    (l, wl) = spd_to_cholesky(x, l, w)
    return inner(CholeskySpace{N}(), l, vl, wl)
end

@doc doc"""
    log(M::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, x, y)

Compute the logarithmic map on [`SymmetricPositiveDefinite`](@ref) `M` with
respect to the [`LogCholeskyMetric`](@ref) eminating from `x` to `y`.
The formula can be adapted from the [`CholeskySpace`](@ref) as
````math
\log_x y = lw^{\mathrm{T}} + wl^{\mathrm{T}},
````
where $l$ is the colesky factor of $x$ and $w=\log_lk$ for $k$ the cholesky factor
of $y$ and the just mentioned logarithmic map is the one on [`CholeskySpace`](@ref).
"""
log(::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric}, ::Any...)

function log!(
    M::MetricManifold{SymmetricPositiveDefinite{N},LogCholeskyMetric},
    v,
    x,
    y,
) where {N}
    l = cholesky(x).L
    k = cholesky(y).L
    log!(CholeskySpace{N}(), v, l, k)
    return tangent_cholesky_to_tangent_spd!(l, v)
end

@doc doc"""
    vector_transport_to(
        M::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric},
        x,
        v,
        y,
        ::ParallelTransport,
    )

Parallely transport the tangent vector `v` at `x` along the geodesic to `y` with respect to
the [`SymmetricPositiveDefinite`](@ref) manifold `M` and [`LogCholeskyMetric`](@ref).
The parallel transport is based on the parallel transport on [`CholeskySpace`](@ref):
Let $l$ and $k$ denote the cholesky factors of `x` and `y`, respectively and
$w = l(l^{-1}vl^{-\mathrm{T}})_\frac{1}{2}$, where $(\cdot)_\frac{1}{2}$ denotes the lower
triangular matrix with the diagonal multiplied by $\frac{1}{2}$. With $u$ the parallel
transport on [`CholeskySpace`](@ref) from $l$ to $k$. The formula hear reads

````math
    \mathcal P_{y\gets x}(v) = ku^{\mathrm{T}} + uk^{\mathrm{T}}.
````
"""
vector_transport_to(
    ::MetricManifold{SymmetricPositiveDefinite,LogCholeskyMetric},
    ::Any,
    ::Any,
    ::Any,
    ::ParallelTransport,
)

function vector_transport_to!(
    M::MetricManifold{SymmetricPositiveDefinite{N},LogCholeskyMetric},
    vto,
    x,
    v,
    y,
    ::ParallelTransport,
) where {N}
    k = cholesky(y).L
    (l, w) = spd_to_cholesky(x, v)
    vector_transport_to!(CholeskySpace{N}(), vto, l, w, k, ParallelTransport())
    return tangent_cholesky_to_tangent_spd!(k, vto)
end


text:
happy_hour_price(x) = x÷2
normal_price(x) = x

struct Customer
    drinks::Vector{Int}
    Customer() = new(Int[])
end

add_drink!(c::Customer, strategy, price, quantity) =
    push!(c.drinks, strategy(price * quantity))

function print_bill!(c::Customer)
    println("total due: ", sum(c.drinks))
    empty!(c.drinks)
end

function main()
    strategy = normal_price
    add!(customer, price, quantity) =
        add_drink!(customer, strategy, price, quantity)

    first_customer = Customer()
    add!(first_customer, 100, 1)

    strategy = happy_hour_price
    add!(first_customer, 100, 2)

    second_customer = Customer()
    add!(second_customer, 80, 1)

    print_bill!(first_customer)

    strategy = normal_price
    add!(second_customer, 130, 2)
    add!(second_customer, 250, 1)
    print_bill!(second_customer)
end

main()

ext: jl

max_stars_repo_name: ninjaaron/dispatching-design-patterns

max_issues_repo_name: ninjaaron/dispatching-design-patterns

max_forks_repo_name: ninjaaron/dispatching-design-patterns


text:
# TODO: refactor

function convert_test(outfile, infile="documents/chunk_options.noweb")
  outfile = joinpath("documents/convert", outfile)
  convert_doc(infile, outfile)
  result =  read(outfile, String)
  ref =  read(outfile * ".ref", String)
  @test result == ref
  rm(outfile)
end

convert_test("chunk_options.jmd")
convert_test("chunk_options.jl")
convert_test("chunk_options.mdw")
convert_test("chunk_options_nb.mdw", "documents/chunk_options.ipynb")

# Separate test for notebook (output depends on julia version)
contents(chunk::Weave.DocChunk) = join([strip(c.content) for c in chunk.content], "")
contents(chunk::Weave.CodeChunk) = chunk.content
contents(doc::Weave.WeaveDoc) = join([contents(chunk) for chunk in doc.chunks], "")

outfile = "documents/convert/chunk_options.ipynb"
infile = "documents/chunk_options.noweb"
convert_doc(infile, outfile)
input = contents(Weave.WeaveDoc(infile))
output = contents(Weave.WeaveDoc(outfile))
@test input == output
rm(outfile)

# Test script reader
@test contents(Weave.WeaveDoc("documents/chunk_options.noweb")) == contents(Weave.WeaveDoc("documents/chunk_options.jl"))


text:
const orgnames = Dict(
                     "AbstractAlgebra" => "Nemocas",
                     "Hecke" => "thofma",
                     "Nemo" => "Nemocas"
                )

const default_dev_dir = "oscar-dev"

pkg_org(pkg::AbstractString) = get(orgnames, pkg, "oscar-system")

pkg_from_repo(repo) = isnothing(repo) ? nothing : match(r"/(\w+).jl",repo)[1]

function pkg_url(pkg::AbstractString; full=true, fork=nothing)
   org = isnothing(fork) ? pkg_org(pkg) : fork
   return (full ? "https://github.com/" : "") * org * "/$pkg.jl"
end

function pkg_giturl(pkg::AbstractString; fork=nothing)
   org = isnothing(fork) ? pkg_org(pkg) : fork
   return "git@github.com:$org/$pkg.jl"
end

function pkg_names(dir::AbstractString=default_dev_dir)
   return filter(x -> (isdir(joinpath(dir,x)) && x != "project"), readdir(dir))
end


text:
function RBMs.initialize!(rbm::CenteredRBM, data::AbstractArray; ϵ::Real = 1e-6)
    RBMs.initialize!(RBM(rbm), data; ϵ)
    center_from_data!(rbm, data)
    return rbm
end


text:
using BinDeps

@BinDeps.setup

rsvg = library_dependency("rsvg", aliases = ["librsvg", "librsvg-2.2", "librsvg-2-2", "librsvg-2", "librsvg-2.so.2"])

@linux_only begin
    provides(AptGet, "librsvg2-2",rsvg)
end

@osx_only begin
    using Homebrew
    provides(Homebrew.HB, "librsvg", [rsvg], os=:Darwin)
end

@windows_only begin
    using WinRPM
    provides(WinRPM.RPM,"librsvg-2-2",rsvg,os = :Windows)
end

@BinDeps.install Dict(:rsvg => :librsvg)


text:
# delegation of samplers

"""
    rand!(::AbstractRNG, ::Sampleable, ::AbstractArray)

Samples in-place from the sampler and stores the result in the provided array.
"""
rand!(::AbstractRNG, ::Sampleable, ::AbstractArray)

"""
    rand(::AbstractRNG, ::Sampleable)

Samples from the sampler and returns the result.
"""
rand(::AbstractRNG, ::Sampleable)

for fname in ["aliastable.jl",
              "binomial.jl",
              "poissonbinomial.jl",
              "poisson.jl",
              "exponential.jl",
              "gamma.jl",
              "multinomial.jl",
              "vonmises.jl",
              "vonmisesfisher.jl",
              "discretenonparametric.jl",
              "categorical.jl"]

    include(joinpath("samplers", fname))
end


text:
function king_in_check(board::Bitboard, color::String="white")
    if color == "white"
        if board.K & board.black_attacks == EMPTY
            return false
        end
    else
        if board.k & board.white_attacks == EMPTY
            return false
        end
    end
    return kingtrace(board, color)
end

function square_in_check(board::Bitboard, ui::UInt64, color::String="white")
    if color == "white"
        if ui & board.a[1] != EMPTY
            return true
        end
        if ui & board.a[2] != EMPTY
            return true
        end
        if ui & board.a[4] != EMPTY || ui & board.a[3] != EMPTY
            squares, edges = orthogonal_attack(board.taken, ui)
            for rook in board.r
                if rook in edges
                    return true
                end
            end
            for queen in board.q
                if queen in edges
                    return true
                end
            end
        end
        if ui & board.a[5] != EMPTY || ui & board.a[3] != EMPTY
            squares, edges = cross_attack(board.taken, ui)
            for bishop in board.b
                if bishop in edges
                    return true
                end
            end
            for queen in board.q
                if queen in edges
                    return true
                end
            end
        end
        return false
    else
        if ui & board.A[1] != EMPTY
            return true
        end
        if ui & board.A[2] != EMPTY
            return true
        end
        if ui & board.A[4] != EMPTY || ui & board.A[3] != EMPTY
            squares, edges = orthogonal_attack(board.taken, ui)
            for rook in board.R
                if rook in edges
                    return true
                end
            end
            for queen in board.Q
                if queen in edges
                    return true
                end
            end
        end
        if ui & board.A[5] != EMPTY || ui & board.A[3] != EMPTY
            squares, edges = cross_attack(board.taken, ui)
            for bishop in board.B
                if bishop in edges
                    return true
                end
            end
            for queen in board.Q
                if queen in edges
                    return true
                end
            end
        end
        return false
    end
end

function kingtrace(board::Bitboard, color::String="white")
    if color == "white"
        return square_in_check(board, board.K, color)
    else
        return square_in_check(board, board.k, color)
    end
end

function check_mate(board::Bitboard, color::String="white")
    if color == "white"
        king = board.K
    else
        king = board.k
    end

    if length(get_current_king_valid(board, color)) != 0
        return false
    else
        if length(get_all_valid_moves(board, color)) == 0
            return true
        else
            return false
        end
    end
end


text:
@testset "LMM LRT" begin
    data,evts = loadtestdata("testCase3",dataPath="data");
    data = reshape(data,1,length(data)) # add second channel
    data = vcat(data,data);

        evts[!,:subject] .= string.(evts.subject);
        data_epoch,times = Unfold.epoch(data=data.+1.1.*randn(MersenneTwister(1),size(data)),tbl=evts,τ=(-0.1,0.3),sfreq=10);
        evts_epoch,data_epoch = Unfold.dropMissingEpochs(evts,data_epoch)

        f0  = @formula 0~1+condA + (1|subject);
        f1  = @formula 0~1+condA+condB + (1|subject);

        m0 = fit(UnfoldModel,Dict(Any=>(f0,times)),evts_epoch,data_epoch);
        m1 = fit(UnfoldModel,Dict(Any=>(f1,times)),evts_epoch,data_epoch);

        evts[!,:y] = data_epoch[1,1,:]

        f0  = @formula y~1+condA + (1|subject);
        f1  = @formula y~1+condA+condB + (1|subject);

        lmm0 = fit(MixedModel,f0,evts)
        lmm1 = fit(MixedModel,f1,evts)

        uf_lrt = likelihoodratiotest(m0,m1)
        mm_lrt = MixedModels.likelihoodratiotest(lmm0,lmm1)

        @test mm_lrt.pvalues ≈ uf_lrt[1].pvalues

end

max_stars_repo_name: unfoldtoolbox/jlunfold

max_issues_repo_name: unfoldtoolbox/jlunfold

max_forks_repo_name: unfoldtoolbox/jlunfold


text:
"""
Compute the vertical integrated volume flux from the bottom to z=0 (i.e. linear free-surface)

```
U★ = ∫ᶻ Ax * u★ dz`
V★ = ∫ᶻ Ay * v★ dz`
"""
### Note - what we really want is RHS = divergence of the vertically integrated volume flux
###        we can optimize this a bit later to do this all in one go to save using intermediate variables.
function compute_vertically_integrated_volume_flux!(∫ᶻ_U, model)

    # Fill halo regions for predictor velocity.
    fill_halo_regions!(model.velocities, model.architecture, model.clock, fields(model))

    # Compute the vertically integrated volume flux
    event = launch!(model.architecture, model.grid, :xy,
                    _compute_vertically_integrated_volume_flux!,
                    ∫ᶻ_U, model.grid, model.velocities,
                    dependencies = device_event(model.architecture))
                    # include_right_boundaries = true) # <- get this to work with layout = :xy

    wait(device(model.architecture), event)

    # We didn't include right boundaries, so...
    fill_halo_regions!(∫ᶻ_U, model.architecture, model.clock, fields(model))

    return nothing
end

@kernel function _compute_vertically_integrated_volume_flux!(∫ᶻ_U, grid, U)
    i, j = @index(Global, NTuple)

    @inbounds begin

        ∫ᶻ_U.u[i, j, 1] = 0
        ∫ᶻ_U.v[i, j, 1] = 0

        @unroll for k in 1:grid.Nz
            ∫ᶻ_U.u[i, j, 1] += Axᶠᶜᶜ(i, j, k, grid) * U.u[i, j, k]
            ∫ᶻ_U.v[i, j, 1] += Ayᶜᶠᶜ(i, j, k, grid) * U.v[i, j, k]
        end

     end
end


text:
"""
Abstract atomistic or single-step solution.

## Constructors:

```julia
AtomicSolution(equation)
AtomicSolution(solution)
AtomicSolution(solution, integrator)
```

Automatically construct the appropriate atomistic solution based on the
given `equation` or `solution` type. If an `integrator` is provided as,
the `internal` field of the atomic solution is constructed according to
the internal state of the integrator as obtained from the function
`get_internal_variables`.

"""
abstract type AtomicSolution{dType <: Number, tType <: Real, aType <: AbstractArray{dType}} end

"""
```julia
copy_solution!(solution, atomic_solution, n, m)
```

Copy solution for time step `n` and initial condition `m` from atomic solution
to solution object.

"""
function copy_solution!(sol::Solution, asol::AtomicSolution, n, m)
    copy_solution!(sol, get_solution(asol)..., n, m)
end

function GeometricBase.cut_periodic_solution!(asol::AtomicSolution{DT,TT,AT}, periodicity::AT) where {DT,TT,AT}
    @assert axes(asol.q) == axes(periodicity)
    for k in eachindex(asol.q, asol.q̄, periodicity)
        if periodicity[k] ≠ 0
            while asol.q[k] < 0
                asol.q[k], asol.q̃[k] = compensated_summation(+periodicity[k], asol.q[k], asol.q̃[k])
                asol.q̄[k] += periodicity[k]
            end
            while asol.q[k] ≥ periodicity[k]
                asol.q[k], asol.q̃[k] = compensated_summation(-periodicity[k], asol.q[k], asol.q̃[k])
                asol.q̄[k] -= periodicity[k]
            end
        end
    end
end


text:
module GraphUtil

using LightGraphs
import LightGraphs: add_edge!
using GraphPlot
using MetaGraphs

import Base: show, length

export get_weight, set_weight!

struct _Raise end
const _raise = _Raise()

const AMG = AbstractMetaGraph

"""
    get_weight(graph, vertex)
    get_weight(graph, edge, [nonexistent])
    get_weight(graph, src, dst, [nonexistent])

Return a vertex or edge weight of a ``MetaGraph``.

If `nonexistent` is specified, it will be returned when a missing edge is
queried.  Otherwise a ``KeyError`` is raised.
"""
function get_weight end

function get_weight(g::AMG, s, d, nonexistent=_raise)
    get_weight(g, Edge(s, d), nonexistent)
end

function get_weight(g::AMG, e::AbstractEdge, nonexistent=_raise)
    if !has_edge(g, e)
        nonexistent === _raise && throw(KeyError("$e does not exist"))
        nonexistent
    elseif has_prop(g, e, :weight)
        get_prop(g, e, :weight)
    else
        defaultweight(g)
    end
end

function get_weight(g::AMG, v)
    if has_prop(g, v, :weight)
        get_prop(g, v, :weight)
    else
        defaultweight(g)
    end
end

set_weight!(g::AMG, s, d, w) = set_prop!(g, s, d, :weight, w)
set_weight!(g::AMG, e::Edge, w) = set_prop!(g, e, :weight, w)
set_weight!(g::AMG, v, w) = set_prop!(g, v, :weight, w)

add_edge!(g::AMG, e::Edge, weight) = add_edge!(g, e.src, e.dst, weight)
add_edge!(g::AMG, s, d, weight) = add_edge!(g, s, d, :weight, weight)

"""
Expand `Edge` like a tuple: `x, y = Edge(1, 2)`.
"""
Base.iterate(edge::Edge) = edge.src, false
Base.iterate(edge::Edge, done::Bool) = done ? nothing : (edge.dst, true)
Base.length(edge::Edge) = 2

"""
Draw graphs directly as SVG without typing gplot(g, ...).
"""
function show(io, mime::MIME"image/svg+xml", g::AbstractGraph)
    length(g) > 0 || throw(ArgumentError)
    context = gplot(g, nodelabel=1:nv(g))
    show(io, mime, context)
end

function show(io, mime::MIME"image/svg+xml", g::AbstractMetaGraph)
    length(g) > 0 || throw(ArgumentError)
    w = weights(g)
    edgelabel = [
        get_weight(g, edge)
        for edge in edges(g)
    ]
    context = gplot(g, nodelabel=1:nv(g), edgelabel=edgelabel)
    show(io, mime, context)
end

end


text:
_checktype(type) = (type != :reg && type != :wire) &&
    error("Cannot create net with type $type (use :reg or :wire)")
_checkclass(class) = (class != :input &&
                      class != :output &&
                      class != :internal &&
                      class != :constant &&
                      class != :parameter) &&
    error("Cannot create net with class $class (use :input, :output, :internal, :constant, or :parameter)")

struct Net
    name
    value
    type::Symbol
    class::Symbol
    signed::Bool
    bitwidth::Int
    size

    function Net(name, value, type, class, signed, bitwidth, size)
        _checktype(type)
        _checkclass(class)

        new(name, value, type, class, signed, bitwidth, size)
    end
end
Net(; name = "",
      value = missing,
      type = :wire,
      class = :internal,
      signed = false,
      bitwidth = 1,
      size = (1, 1)) = Net(name, value, type, class, signed, bitwidth, size)
Net(x; kwargs...) = Net(; value = x, size = netsize(x), kwargs...)

function Base.show(io::IO, n::Net)
    limitedshow(x) = sprint(show, x; context = IOContext(stdout, :compact => true, :limit => true))

    if isconstant(n)
        netname = limitedshow(n.value)
        print(io, "Net{$(n.class), $(n.type)}($(netname)::$(jltypeof(n)))($(join(n.size, "x")))")
    else
        print(io, "Net{$(n.class), $(n.type)}($(n.name)::$(jltypeof(n)))($(join(n.size, "x")))")
    end
end

Base.:(==)(x::Net, y::Net) = name(x) == name(y)
Base.isequal(x::Net, y::Net) = (x == y)
Base.hash(x::Net, h::UInt) = hash(x.name, h)

name(x::Net) = x.name

value(x::Net) = x.value

jltypeof(x::Net) = typeof(value(x))

bitwidth(x::Net) = x.bitwidth

netsize(x) = (1, 1)
netsize(x::AbstractArray) = size(x)
netsize(x::AbstractVector) = (length(x), 1)
function netsize(x::Net)
    isparameter(x) || return x.size

    actual_size = netsize(value(x))
    return ntuple(i -> "$(name(x))_sz_$i", length(actual_size))
end

isreg(x::Net) = (x.type == :reg)
iswire(x::Net) = !isreg(x)

isinput(x::Net) = (x.class == :input)
isoutput(x::Net) = (x.class == :output)
isinternal(x::Net) = (x.class == :internal)
isconstant(x::Net) = (x.class == :constant)
isparameter(x::Net) = (x.class == :parameter)

issigned(x::Net) = x.signed

const Netlist = Vector{Net}

inputs(n::Netlist) = filter(isinput, n)
outputs(n::Netlist) = filter(isoutput, n)

find(n::Netlist, x::Net) = findall(==(name(x)), name.(n))
Base.in(x::Net, n::Netlist) = !isempty(find(n, x))

# function getsize(n::Netlist, x::String)
#     i = find(n, x)
#     isnothing(i) && error("Cannot get size for net $x since it does not exist in netlist.")

#     return n[i].size
# end
# getsize(n::Netlist, x::Vector{String}) = map(λ -> getsize(n, λ), x)

Base.delete!(n::Netlist, x::Net) = deleteat!(n, find(n, x))

function setname(x::Net, name)
    @set! x.name = name

    return x
end
function setname!(n::Netlist, x::Net, name)
    is = find(n, x)
    isempty(is) && error("Cannot name net $x to $name because it does not exist in netlist.")
    for i in is
        n[i] = setname(n[i], name)
    end

    return n
end

function setvalue(x::Net, value)
    @set! x.value = value

    return x
end
function setvalue!(n::Netlist, x::Net, value)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x value to $value because it does not exist in netlist.")
    for i in is
        n[i] = setvalue(n[i], value)
    end

    return n
end

function setclass(x::Net, class)
    _checkclass(class)
    @set! x.class = class

    return x
end
function setclass!(n::Netlist, x::Net, class)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x as $class because it does not exist in netlist.")
    for i in is
        n[i] = setclass(n[i], class)
    end

    return n
end

function setreg(x::Net)
    @set! x.type = :reg

    return x
end
function setreg!(n::Netlist, x::Net)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x as register because it does not exist in netlist.")
    for i in is
        n[i] = setreg(n[i])
    end

    return n
end

function setwire(x::Net)
    @set! x.type = :wire

    return x
end
function setwire!(n::Netlist, x::Net)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x as wire because it does not exist in netlist.")
    for i in is
        n[i] = setwire(n[i])
    end

    return n
end

function setsigned(x::Net, signed)
    @set! x.signed = signed

    return x
end
function setsigned!(n::Netlist, x::Net, signed)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x as signed = $signed because it does not exist in netlist.")
    for i in is
        n[i] = setsigned(n[i], signed)
    end

    return n
end

function setwidth(x::Net, width)
    @set! x.bitwidth = width

    return x
end
function setwidth!(n::Netlist, x::Net, width)
    is = find(n, x)
    isempty(is) && error("Cannot set net $x bitwidth = $width because it does not exist in netlist.")
    for i in is
        n[i] = setwidth(n[i], width)
    end

    return n
end


text:
module LoggingProfiler
struct Calls
    stamps::Vector{Float64} # contains the time stamps
    event::Vector{Symbol}  # name of the function that is being recorded
    startstop::Vector{Symbol} # if the time stamp corresponds to start or to stop
    i::Ref{Int}
end

function Calls(n::Int)
    Calls(Vector{Float64}(undef, n+1), Vector{Symbol}(undef, n+1), Vector{Symbol}(undef, n+1), Ref{Int}(0))
end

function Base.show(io::IO, calls::Calls)
    offset = 0
    if calls.i[] >= length(calls.stamps)
        @warn "The recording buffer was too small, consider increasing it"
    end
    for i in 1:min(calls.i[], length(calls.stamps))
        offset -= calls.startstop[i] == :stop
        foreach(_ -> print(io, " "), 1:max(offset, 0))
        rel_time = calls.stamps[i] - calls.stamps[1]
        println(io, calls.event[i], ": ", rel_time)
        offset += calls.startstop[i] == :start
    end
end

global const to = Calls(100)

"""
    record_start(ev::Symbol)

    record the start of the event, the time stamp is recorded after all counters are
    appropriately increased
"""
record_start(ev::Symbol) = record_start(to, ev)
function record_start(calls, ev::Symbol)
    n = calls.i[] = calls.i[] + 1
    n > length(calls.stamps) && return
    calls.event[n] = ev
    calls.startstop[n] = :start
    calls.stamps[n] = time_ns()
end

"""
    record_end(ev::Symbol)

    record the end of the event, the time stamp is recorded before all counters are
    appropriately increased
"""
record_end(ev::Symbol) = record_end(to, ev::Symbol)
function record_end(calls, ev::Symbol)
    t = time_ns()
    n = calls.i[] = calls.i[] + 1
    n > length(calls.stamps) && return
    calls.event[n] = ev
    calls.startstop[n] = :stop
    calls.stamps[n] = t
end

reset!() = to.i[] = 0

function Base.resize!(calls::Calls, n::Integer)
  resize!(calls.stamps, n)
  resize!(calls.event, n)
  resize!(calls.startstop, n)
end

end


text:
using Documenter,RobotOS

makedocs(
    modules=[RobotOS],
    authors="Josh Langsfeld",
    )

deploydocs(
    target="site",
    repo="github.com/jdlangs/RobotOS.jl",
    branch = "gh-pages",
    latest = "master",
    osname="linux",
    julia="1.0",
    deps=Deps.pip("mkdocs"),
    )


text:
datapath = "/home/ubuntu/datasets/"
using OpenStreetMapX
using OpenStreetMapXSim

mutable struct RouteData
    shortest_route
    fastest_route
    google_route
end

function find_routes(sim_data::OpenStreetMapXSim.SimData,demographic_profile::Function,google = false)::RouteData
    loc = OpenStreetMapXSim.start_location(sim_data.demographic_data)
    agent = demographic_profile(loc, sim_data.demographic_data[loc])
    OpenStreetMapXSim.destination_location!(agent,sim_data.business_data)
    activity = additional_activity(agent,true,sim_data)
    start_node = sim_data.DAs_to_intersection[agent.DA_home[1]]
    fin_node = sim_data.DAs_to_intersection[agent.DA_work[1]]
    shortest_route,fastest_route,google_route = nothing,nothing,nothing
    if isa(activity,Nothing)
        if google
            google_route, mode = OpenStreetMapXSim.get_google_route(start_node,fin_node,sim_data.map_data)
        end
        shortest_route, shortest_distance, shortest_time = OpenStreetMapX.shortest_route(sim_data.map_data.network, start_node,fin_node)
        fastest_route, fastest_distance, fastest_time = OpenStreetMapX.fastest_route(sim_data.map_data.network, start_node,fin_node)
    else
        waypoint = OpenStreetMapXSim.get_waypoint(start_node,fin_node,activity,sim_data,false)
        if google
            google_route, mode = OpenStreetMapXSim.get_google_route(start_node,fin_node,waypoint,sim_data.map_data)
        end
        shortest_route, shortest_distance, shortest_time = OpenStreetMapX.shortest_route(sim_data.map_data.network, start_node, waypoint,fin_node)
        fastest_route, fastest_distance, fastest_time = OpenStreetMapX.fastest_route(sim_data.map_data.network, start_node, waypoint,fin_node)
    end

    return RouteData(shortest_route,
    fastest_route,
    google_route)

end

include("simparams/_loadparams.jl")
sim_data = get_sim_data(datapath);
r = find_routes(sim_data,demographic_profile, true)


text:
# ---
# title: 985. Sum of Even Numbers After Queries
# id: problem985
# author: Tian Jun
# date: 2020-10-31
# difficulty: Easy
# categories: Array
# link: <https://leetcode.com/problems/sum-of-even-numbers-after-queries/description/>
# hidden: true
# ---
#
# We have an array `A` of integers, and an array `queries` of queries.
#
# For the `i`-th query `val = queries[i][0], index = queries[i][1]`, we add val
# to `A[index]`.  Then, the answer to the `i`-th query is the sum of the even
# values of `A`.
#
# _(Here, the given`index = queries[i][1]` is a 0-based index, and each query
# permanently modifies the array `A`.)_
#
# Return the answer to all queries.  Your `answer` array should have `answer[i]`
# as the answer to the `i`-th query.
#
#
#
# **Example 1:**
#
#
#
#     Input: A = [1,2,3,4], queries = [[1,0],[-3,1],[-4,0],[2,3]]
#     Output: [8,6,2,4]
#     Explanation:
#     At the beginning, the array is [1,2,3,4].
#     After adding 1 to A[0], the array is [2,2,3,4], and the sum of even values is 2 + 2 + 4 = 8.
#     After adding -3 to A[1], the array is [2,-1,3,4], and the sum of even values is 2 + 4 = 6.
#     After adding -4 to A[0], the array is [-2,-1,3,4], and the sum of even values is -2 + 4 = 2.
#     After adding 2 to A[3], the array is [-2,-1,3,6], and the sum of even values is -2 + 6 = 4.
#
#
#
#
# **Note:**
#
#   1. `1 <= A.length <= 10000`
#   2. `-10000 <= A[i] <= 10000`
#   3. `1 <= queries.length <= 10000`
#   4. `-10000 <= queries[i][0] <= 10000`
#   5. `0 <= queries[i][1] < A.length`
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule MLIR_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("MLIR")
JLLWrappers.@generate_main_file("MLIR", UUID("a70bccb4-a5c0-5e2e-a329-e731972457e8"))
end  # module MLIR_jll


text:
# Bayesian student-t multivariate regression with PseudoHuber priors
# Prior pi(beta; mu, delta)
#   \propto exp(delta^2 (1 - sqrt(1+||beta-mu||_2^2/delta^2))

type SteinMultivariateStudentTRegressionPseudoHuberPrior <: SteinMultivariateStudentTRegressionPosterior
    X::Array{Float64,2}
    y::Array{Float64,1}
    nu::Float64  # the number of degrees of freedom for the t-distribution
    sigma::AbstractArray{Float64,2} # the covariance of the multivariate t-distribution (abstract allows for optimization)
    priormu::Array{Float64,1}
    priordelta::Float64 # transition point from quadratic to linear
    priorlogZ::Float64 # the log of the normalizing constant of the prior probability density
    c1::Float64
    c2::Float64
    c3::Float64
    # internal constructor that saves the normalizing constant
    SteinMultivariateStudentTRegressionPseudoHuberPrior(
        X, y, nu, sigma, priormu, priordelta, c1, c2, c3
    ) = (
        logZ = priorlogZ(priordelta, size(X,2));
        new(X, y, nu, sigma, priormu, priordelta, logZ, c1, c2, c3)
    )
end

SteinMultivariateStudentTRegressionPseudoHuberPrior(X::Array{Float64, 2},
                                                    y::Array{Float64, 1},
                                                    nu::Float64) =
SteinMultivariateStudentTRegressionPseudoHuberPrior(X, y, nu, Diagonal(ones(size(X, 1))))

SteinMultivariateStudentTRegressionPseudoHuberPrior(X::Array{Float64, 2},
                                                    y::Array{Float64, 1},
                                                    nu::Float64,
                                                    sigma::AbstractArray{Float64, 2}) =
SteinMultivariateStudentTRegressionPseudoHuberPrior(X, y, nu, sigma,
                                                    repmat([0.0], size(X, 2)),
                                                    repmat([1.0], size(X, 2)))

# Constructor with canonical setting of (c1,c2,c3) = (1,1,1)
SteinMultivariateStudentTRegressionPseudoHuberPrior(X::Array{Float64, 2},
                                                    y::Array{Float64, 1},
                                                    nu::Float64,
                                                    sigma::AbstractArray{Float64, 2},
                                                    priormu::Array{Float64, 1},
                                                    priordelta::Float64) =
SteinMultivariateStudentTRegressionPseudoHuberPrior(X, y, nu, sigma, priormu, priordelta,
                                                    1.0, 1.0, 1.0)
function priorlogZ(delta::Float64, p::Int)
    # Log volume, log(V_p), of p-dimensional hypersphere
    logvolume = log(pi)*p/2 - lgamma(p/2+1)
    # int f(||beta||) = p * V_p * int f(r) r^{p-1} dr
    (integral, error) = quadgk(
        x -> exp(x^(p-1) * delta^2 * (1 - sqrt(1 + (x / delta)^2))),
        0.0,
        Inf)
    log(p)+logvolume+log(integral)
end

function logprior(d::SteinMultivariateStudentTRegressionPseudoHuberPrior,
                  beta::Array{Float64, 1})
    # Compute PseudoHuber prior
    delta = d.priordelta
    logZ = d.priorlogZ
    residuals = beta .- d.priormu
    underroot = 1 + sum(residuals.^2) / delta^2

    delta^2 * (1 - sqrt(underroot))-logZ
end

function gradlogprior(d::SteinMultivariateStudentTRegressionPseudoHuberPrior,
                      beta::Array{Float64, 1})
    delta = d.priordelta
    residuals = beta .- d.priormu
    underroot = 1 + sum(residuals .^ 2) / delta^2
    -residuals / sqrt(underroot)
end

function numdimensions(d::SteinMultivariateStudentTRegressionPseudoHuberPrior)
    length(d.priormu)
end


text:
# ncondition tests
using OrdinaryDiffEq, Test

function f(u,p,t)
	return 5*u
end
u0 = [1.0, 1.0]
tspan = (0.0,1.0)
prob = ODEProblem(f,u0,tspan)
x = Ref(0)

condtion = function (u,t,integrator)
  x[] += 1
  return 0
end
affect! = function (integrator) end
cb = ContinuousCallback(condtion,affect!)
sol = solve(prob,Vern9(), callback=cb)
@test x[] == sol.destats.ncondition

condtion = function (u,t,integrator)
  x[] += 1
  return t - 0.46
end
x[] = 0
cb = ContinuousCallback(condtion,affect!)
sol = solve(prob,Vern9(), callback=cb)
@test x[] == sol.destats.ncondition

condtion = function (u,t,integrator)
  x[] += 1
  return 1
end
x[] = 0
cb = ContinuousCallback(condtion,affect!)
sol = solve(prob,Vern9(), callback=cb)
@test x[] == sol.destats.ncondition

condtion = function (u,t,integrator)
  x[] += 1
  return true
end
x[] = 0
cb = DiscreteCallback(condtion,affect!)
sol = solve(prob,Vern9(), callback=cb)
@test x[] == sol.destats.ncondition


text:
# This file includes an example file for 1D integrate.

using FractalTools
using Makie

# Generate data
line = [[0.], [10.]]
f(x) = [sin(x), cos(x)]
pts = getdata(f, line, 1001)
# xi, dx, xf = 0., 0.01, 10.
# x = collect(xi : dx : xf)
# y = sin.(x)
# z = cos.(x)
# pts = collect.(zip(x, y, z))
res = integrate(pts, HInterp1D(0.001 * ones(2, 2)))


text:
module TheNaNTrap

using Cassette, ReplMaker

Cassette.@context NaNTrap

nonnan(s, x::Number) = (@assert(!isnan(x), string(s, " returned NaN")); x)
nonnan(s, A::AbstractArray) = (foreach(x->nonnan(s, x), A); A)
nonnan(s, x) = x

Cassette.overdub(::NaNTrap, f, args...; kwargs...) = nonnan(string(f, args), Cassette.recurse(NaNTrap(), f, args...; kwargs...))
function parse_to_expr(s)
    p = Meta.parse(s)
    isa(p, Expr) && p.head in (:using, :import) && return p
    quote $Cassette.@overdub($(NaNTrap()), (()->$p)()) end
end
# This should probably be in an init or something...
initrepl(parse_to_expr,
                prompt_text="NaNTrap> ",
                prompt_color = :blue,
                start_key=')',
                mode_name="no_nan_mode")
end


text:
using Test
using SymbolicRegression
using SymbolicRegression: eval_diff_tree_array, eval_grad_tree_array
using Random
using Zygote
using LinearAlgebra

seed = 0
pow_abs(x::T, y::T) where {T<:Real} = abs(x)^y
custom_cos(x::T) where {T<:Real} = cos(x)^2

# Define these custom functions for Node data types:
pow_abs(l::Node, r::Node)::Node =
    (l.constant && r.constant) ? Node(pow_abs(l.val, r.val)::AbstractFloat) : Node(5, l, r)
pow_abs(l::Node, r::AbstractFloat)::Node =
    l.constant ? Node(pow_abs(l.val, r)::AbstractFloat) : Node(5, l, r)
pow_abs(l::AbstractFloat, r::Node)::Node =
    r.constant ? Node(pow_abs(l, r.val)::AbstractFloat) : Node(5, l, r)
custom_cos(x::Node)::Node = x.constant ? Node(custom_cos(x.val)::AbstractFloat) : Node(1, x)

equation1(x1, x2, x3) = x1 + x2 + x3 + 3.2f0
equation2(x1, x2, x3) = pow_abs(x1, x2) + x3 + custom_cos(1.0f0 + x3) + 3.0f0 / x1
function equation3(x1, x2, x3)
    return (
        ((x2 + x2) * ((-0.5982493 / pow_abs(x1, x2)) / -0.54734415)) + (
            sin(
                custom_cos(
                    sin(1.2926733 - 1.6606787) / sin(
                        ((0.14577048 * x1) + ((0.111149654 + x1) - -0.8298334)) - -1.2071426
                    ),
                ) * (custom_cos(x3 - 2.3201916) + ((x1 - (x1 * x2)) / x2)),
            ) / (0.14854191 - ((custom_cos(x2) * -1.6047639) - 0.023943262))
        )
    )
end

nx1 = Node("x1")
nx2 = Node("x2")
nx3 = Node("x3")

# Equations to test gradients on:

function array_test(ar1, ar2; rtol=0.1)
    return isapprox(ar1, ar2; rtol=rtol)
end

for type in [Float32, Float64]
    println("Testing derivatives with respect to variables, with type=$(type).")
    rng = MersenneTwister(seed)
    nfeatures = 3
    N = 100

    X = rand(rng, type, nfeatures, N) * 10

    options = Options(;
        binary_operators=(+, *, -, /, pow_abs),
        unary_operators=(custom_cos, exp, sin),
        enable_autodiff=true,
    )

    for j in 1:3
        equation = [equation1, equation2, equation3][j]

        tree = equation(nx1, nx2, nx3)
        predicted_output = eval_tree_array(tree, X, options)[1]
        true_output = equation.([X[i, :] for i in 1:nfeatures]...)

        # First, check if the predictions are approximately equal:
        @test array_test(predicted_output, true_output)

        true_grad = gradient(
            (x1, x2, x3) -> sum(equation.(x1, x2, x3)), [X[i, :] for i in 1:nfeatures]...
        )
        # Convert tuple of vectors to matrix:
        true_grad = reduce(hcat, true_grad)'
        predicted_grad = eval_grad_tree_array(tree, X, options; variable=true)[2]
        predicted_grad2 =
            reduce(
                hcat, [eval_diff_tree_array(tree, X, options, i)[2] for i in 1:nfeatures]
            )'

        # Print largest difference between predicted_grad, true_grad:
        @test array_test(predicted_grad, true_grad)
        @test array_test(predicted_grad2, true_grad)

        # Make sure that the array_test actually works:
        @test !array_test(predicted_grad .* 0, true_grad)
        @test !array_test(predicted_grad2 .* 0, true_grad)
    end
    println("Done.")
    println("Testing derivatives with respect to constants, with type=$(type).")

    # Test gradient with respect to constants:
    equation4(x1, x2, x3) = 3.2f0 * x1
    # The gradient should be: (C * x1) => x1 is gradient with respect to C.
    tree = equation4(nx1, nx2, nx3)
    predicted_grad = eval_grad_tree_array(tree, X, options; variable=false)[2]
    @test array_test(predicted_grad[1, :], X[1, :])

    # More complex expression:
    const_value = 2.1f0
    const_value2 = -3.2f0

    function equation5(x1, x2, x3)
        return pow_abs(x1, x2) + x3 + custom_cos(const_value + x3) + const_value2 / x1
    end
    function equation5_with_const(c1, c2, x1, x2, x3)
        return pow_abs(x1, x2) + x3 + custom_cos(c1 + x3) + c2 / x1
    end

    tree = equation5(nx1, nx2, nx3)

    # Use zygote to explicitly find the gradient:
    true_grad = gradient(
        (c1, c2, x1, x2, x3) -> sum(equation5_with_const.(c1, c2, x1, x2, x3)),
        fill(const_value, N),
        fill(const_value2, N),
        [X[i, :] for i in 1:nfeatures]...,
    )[1:2]
    true_grad = reduce(hcat, true_grad)'
    predicted_grad = eval_grad_tree_array(tree, X, options; variable=false)[2]

    @test array_test(predicted_grad, true_grad)
    println("Done.")
end

println("Testing NodeIndex.")

import SymbolicRegression: get_constants, NodeIndex, index_constants

options = Options(;
    binary_operators=(+, *, -, /, pow_abs),
    unary_operators=(custom_cos, exp, sin),
    enable_autodiff=true,
)
tree = equation3(nx1, nx2, nx3)

"""Check whether the ordering of constant_list is the same as the ordering of node_index."""
function check_tree(tree::Node, node_index::NodeIndex, constant_list::AbstractVector)
    if tree.degree == 0
        (!tree.constant) || tree.val == constant_list[node_index.constant_index]
    elseif tree.degree == 1
        check_tree(tree.l, node_index.l, constant_list)
    else
        check_tree(tree.l, node_index.l, constant_list) &&
            check_tree(tree.r, node_index.r, constant_list)
    end
end

@test check_tree(tree, index_constants(tree), get_constants(tree))

println("Done.")


text:
module TestTasklet

using ConcurrentUtils
using Test

adder(x) = @tasklet Ref(x + 1)

function test_serial_tasklet()
    t = adder(2)
    @test try_race_fetch(t) == Err(NotSetError())
    @test t()[] == 3
    @test t() === t()
    @test try_race_fetch(t) == Ok(t())
end

end  # module


text:
using Boltzmann
using MNIST
using Logging

function run_mnist()
    # Set parameters
    Epochs         = 20
    HiddenUnits    = 256
    Approx         = "tap2"
    ApproxSteps    = 3
    LearnRate      = 0.005
    MonitorEvery   = 5
    PersistStart   = 5
    Momentum       = 0.5
    DecayMagnitude = 0.01
    DecayType      = "l1"

    # Load MNIST Training data
    X, y = traindata()              # Raw data and labels

    normalize_samples!(X)           # Pin to range [0,1]
    binarize!(X;threshold=0.001)    # Create binary data
    # Hold out a validation set
    TrainSet     = X[:,1:50000]
    ValidSet     = X[:,50001:end]

    # Initialize Model
    m = BernoulliRBM(28*28, HiddenUnits,(28,28);
                     momentum  = Momentum,
                     TrainData = TrainSet,
                     sigma     = 0.001)

    # Run Training
    rbm,monitor = fit(m, TrainSet; n_iter           = Epochs,
                                   weight_decay     = DecayType,
                                   decay_magnitude  = DecayMagnitude,
                                   lr               = LearnRate,
                                   persistent       = false,
                                   validation       = ValidSet,
                                   NormalizationApproxIter = ApproxSteps,
                                   monitor_every    = MonitorEvery,
                                   monitor_vis      = true,
                                   approx           = Approx,
                                   persistent_start = PersistStart)

    WriteMonitorChartPDF(rbm,monitor,X,"mnist_tap2.pdf")
    save_params("mnist_tap2.h5",rbm,"mnistexample");
end

Logging.configure(level=CRITICAL)
run_mnist()

println("Press RETURN when ready")
readline(STDIN)


text:
# Copyright 2018 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module OntologyDBs
export OntologyDB, OntologyError,
  concept, concept_document, concepts, has_concept,
  annotation, annotation_document, annotations, has_annotation,
  load_concepts, load_annotation, load_annotations, load_ontology_file

using Compat
using DataStructures: OrderedDict
import JSON, HTTP

using Catlab
using ...Doctrine, ..Ontology

const api_url_default = "https://api.datascienceontology.org"

# Data types
############

""" Ontology database, containing concepts and annotations.
"""
mutable struct OntologyDB
  api_url::String
  concepts::Presentation
  concept_docs::OrderedDict{String,AbstractDict}
  annotations::OrderedDict{String,Annotation}
  annotation_docs::OrderedDict{String,AbstractDict}

  function OntologyDB(api_url)
    new(api_url, Presentation{String}(Monocl),
        OrderedDict(), OrderedDict(), OrderedDict())
  end
end
OntologyDB() = OntologyDB(api_url_default)

struct OntologyError <: Exception
  message::String
end

# Ontology accessors
####################

function concept(db::OntologyDB, id::String)
  if !has_generator(db.concepts, id)
    throw(OntologyError("No concept named '$id'"))
  end
  generator(db.concepts, id)
end

concept_document(db::OntologyDB, id::String) = db.concept_docs[id]
has_concept(db::OntologyDB, id::String) = has_generator(db.concepts, id)

concepts(db::OntologyDB) = db.concepts
concepts(db::OntologyDB, ids) = [ concept(db, id) for id in ids ]

function annotation(db::OntologyDB, id)
  doc_id = annotation_document_id(id)
  if !haskey(db.annotations, doc_id)
    throw(OntologyError("No annotation named '$id'"))
  end
  db.annotations[doc_id]
end

function annotation_document(db::OntologyDB, id)
  db.annotation_docs[annotation_document_id(id)]
end

function has_annotation(db::OntologyDB, id)
  haskey(db.annotations, annotation_document_id(id))
end

annotations(db::OntologyDB) = values(db.annotations)
annotations(db::OntologyDB, ids) = [ annotation(db, id) for id in ids ]

function annotation_document_id(id::String)
  startswith(id, "annotation/") ? id : "annotation/$id"
end
function annotation_document_id(id::AnnotationID)
  join(["annotation", id.language, id.package, id.id], "/")
end

# Local file
############

""" Load concepts/annotations from a list of JSON documents.
"""
function load_documents(db::OntologyDB, docs)
  concept_docs = filter(doc -> doc["schema"] == "concept", docs)
  merge_presentation!(db.concepts, presentation_from_json(concept_docs))
  merge!(db.concept_docs, OrderedDict(doc["id"] => doc for doc in concept_docs))

  annotation_docs = filter(doc -> doc["schema"] == "annotation", docs)
  load_reference = id -> concept(db, id)
  for doc in annotation_docs
    db.annotations[doc["_id"]] = annotation_from_json(doc, load_reference)
    db.annotation_docs[doc["_id"]] = doc
  end
end

""" Load concepts/annotations from a local JSON file.
"""
function load_ontology_file(db::OntologyDB, filename::String)
  open(filename) do file
    load_ontology_file(db, file)
  end
end
function load_ontology_file(db::OntologyDB, io::IO)
  load_documents(db, JSON.parse(io)::Vector)
end

""" Merge the second presentation into the first.

The first presentation is mutated and returned; the second is not.
"""
function merge_presentation!(pres::Presentation, other::Presentation)
  for expr in generators(other)
    name = first(expr)
    if isnothing(name) || !has_generator(pres, name)
      add_generator!(pres, expr)
    end
  end
  union!(pres.equations, other.equations)
  return pres
end

# Remote database
#################

""" Load all concepts in ontology from remote database.
"""
function load_concepts(db::OntologyDB; ids=nothing)
  load_documents(db, api_get(db, "/concepts"))
end

""" Load annotations in ontology from remote database.
"""
function load_annotations(db::OntologyDB; language=nothing, package=nothing)
  endpoint = if isnothing(language)
    "/annotations"
  elseif isnothing(package)
    "/annotations/$language"
  else
    "/annotations/$language/$package"
  end
  load_documents(db, api_get(db, endpoint))
end

""" Load single annotation from remote database, if it's not already loaded.
"""
function load_annotation(db::OntologyDB, id)::Annotation
  if has_annotation(db, id)
    return annotation(db, id)
  end
  doc = try
    api_get(db, "/$(annotation_document_id(id))")
  catch err
    if isa(err, HTTP.StatusError) && err.status == 404
      throw(OntologyError("No annotation named '$id'"))
    end
    rethrow()
  end
  load_documents(db, [doc])
  annotation(db, id)
end

# REST API client
#################

function api_get(api_url::String, endpoint::String)
  response = HTTP.get(string(api_url, endpoint))
  JSON.parse(String(response.body), dicttype=OrderedDict)
end

api_get(db::OntologyDB, endpoint::String) = api_get(db.api_url, endpoint)

end

max_stars_repo_name: IBM/semanticflowgraph

max_issues_repo_name: epatters/semanticflowgraph

max_forks_repo_name: IBM/semanticflowgraph


text:
"""
```
load_fred_data(m::AbstractDSGEModel; start_date="1959-03-31", end_date=prev_quarter())
```

Checks in `inpath(m, raw)` for a FRED dataset corresponding to `data_vintage(m)`.
If a FRED vintage exists on disk, any required FRED series that is contained therein will be
imported. All missing series will be downloaded directly from FRED using the *FredData*
package. The full dataset is written to the appropriate data vintage file and returned.

# Arguments
- `m::AbstractDSGEModel`: the model object
- `start_date`: starting date.
- `end_date`: ending date.

# Notes

The FRED API reports observations according to the quarter-start date. `load_fred_data`
returns data indexed by quarter-end date for compatibility with other datasets.
"""
function load_fred_data(m::AbstractDSGEModel;
                        start_date::Dates.Date = Dates.Date("1959-01-01", "y-m-d"),
                        end_date::Dates.Date   = prev_quarter(),
                        verbose::Symbol  = :low)

    data_series = parse_data_series(m)
    if haskey(data_series, :FRED)
        mnemonics = data_series[:FRED]
    else
        # Then no FRED data used, return DataFrame with dates
        return DataFrame(date = get_quarter_ends(start_date,end_date))
    end
    vint = data_vintage(m)
    dateformat = "yymmdd"

    # Set up dataset and labels
    missing_series = Vector{Symbol}()
    data = []

    datafile = inpath(m, "raw", "fred_$vint.csv")
    if isfile(datafile)

        # Read in dataset and check that the file contains data for the proper dates
        data = CSV.read(datafile, DataFrame)

        # Convert dates from strings to dates for date arithmetic
        format_dates!(:date, data)

        qstart = lastdayofquarter(start_date)
        qend = lastdayofquarter(end_date)

        if !in(qstart, data[!,:date]) || !in(qend, data[!,:date])
            println(verbose, :low, "FRED dataset on disk missing start or end date. Fetching data from FRED.")
            data = DataFrame(date = get_quarter_ends(start_date,end_date))
            missing_series = mnemonics
        else
            # If we have the right dates but the series isn't in the file, add it to
            # missing_series
            for series in mnemonics
                if !in(series, propertynames(data))
                    push!(missing_series,series)
                end
            end
        end
    else
        missing_series = mnemonics
        data = DataFrame(date = get_quarter_ends(start_date,end_date))
    end

    # Get the missing data series
    if !isempty(missing_series)

        # Have to do this wacky parsing to prepend the century to the data vintage
        vint_date = if parse(Int,vint[1:2]) < 59
            Year(2000) + Dates.Date(vint, dateformat)
        else
            Year(1900) + Dates.Date(vint, dateformat)
        end

        fredseries = Array{FredSeries, 1}(undef, length(missing_series))
        f = Fred()

        for (i,s) in enumerate(missing_series)
            println(verbose, :low, "Fetching FRED series $s...")
            try
                fredseries[i] = get_data(f, string(s); frequency="q",
                                                       observation_start=string(start_date),
                                                       observation_end=string(end_date),
                                                       vintage_dates=string(vint_date))
            catch err
                if :msg in fieldnames(typeof(err))
                    @warn err.msg
                else
                    show(err)
                end
                @warn "FRED series $s could not be fetched at vintage $vint."

                try
                    println(verbose, :low, "Fetching FRED series $s without vintage...")
                    fredseries[i] = get_data(f, string(s); frequency="q",
                                                           observation_start=string(start_date),
                                                           observation_end=string(end_date))
                catch err
                    if :msg in fieldnames(typeof(err))
                        @warn err.msg
                    else
                        show(err)
                    end
                    @warn "FRED series $s could not be fetched."
                    continue
                end
            end
        end

        # Extract dataframe from each series and merge on date
        has_oj = isdefined(DataFrames, :outerjoin)
        for i = 1:length(fredseries)
            if isassigned(fredseries, i)
                series = fredseries[i]
                series_id = Symbol(series.id)
                rename!(series.df, :value => series_id)
                map!(x->lastdayofquarter(x), series.df[!, :date], series.df[!, :date])
                data = has_oj ? outerjoin(data, series.df[!, [:date, series_id]], on = :date) :
                    join(data, series.df[!, [:date, series_id]], on = :date, kind = :outer)
            end
        end

        # Change the dates to be the last day of each quarter
        n_rows, n_cols = size(data)

        for i = 1:n_rows
            data[i,:date] = Dates.lastdayofquarter(data[i,:date])
        end

        if !m.testing
            CSV.write(datafile, data, missingstring = "")
            println(verbose, :low, "Updated data from FRED written to $datafile.")
        end
    end

    # Make sure to only return the series and dates that are specified for this
    # model (there may be additional series in the file)

    rows = start_date .<= data[!, :date] .<= end_date
    cols = [:date; mnemonics]
    return data[rows, cols]
end


text:
# Largest prime factor

NUMBER = 600_851_475_143

function solve()
    n = NUMBER
    i = 2
    while n > 1
        if n % i == 0
            n /= i
        else
            i += 1
        end
    end
    return i
end

print(Int(solve()))

max_stars_repo_name: wephy/project-euler

max_issues_repo_name: wephy/project-euler

max_forks_repo_name: wephy/project-euler


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct EncryptionSetProperties <: SwaggerModel
    encryptionType::Any # spec type: Union{ Nothing, EncryptionType } # spec name: encryptionType
    activeKey::Any # spec type: Union{ Nothing, KeyVaultAndKeyReference } # spec name: activeKey
    previousKeys::Any # spec type: Union{ Nothing, Vector{KeyVaultAndKeyReference} } # spec name: previousKeys
    provisioningState::Any # spec type: Union{ Nothing, String } # spec name: provisioningState

    function EncryptionSetProperties(;encryptionType=nothing, activeKey=nothing, previousKeys=nothing, provisioningState=nothing)
        o = new()
        validate_property(EncryptionSetProperties, Symbol("encryptionType"), encryptionType)
        setfield!(o, Symbol("encryptionType"), encryptionType)
        validate_property(EncryptionSetProperties, Symbol("activeKey"), activeKey)
        setfield!(o, Symbol("activeKey"), activeKey)
        validate_property(EncryptionSetProperties, Symbol("previousKeys"), previousKeys)
        setfield!(o, Symbol("previousKeys"), previousKeys)
        validate_property(EncryptionSetProperties, Symbol("provisioningState"), provisioningState)
        setfield!(o, Symbol("provisioningState"), provisioningState)
        o
    end
end # type EncryptionSetProperties

const _property_map_EncryptionSetProperties = Dict{Symbol,Symbol}(Symbol("encryptionType")=>Symbol("encryptionType"), Symbol("activeKey")=>Symbol("activeKey"), Symbol("previousKeys")=>Symbol("previousKeys"), Symbol("provisioningState")=>Symbol("provisioningState"))
const _property_types_EncryptionSetProperties = Dict{Symbol,String}(Symbol("encryptionType")=>"EncryptionType", Symbol("activeKey")=>"KeyVaultAndKeyReference", Symbol("previousKeys")=>"Vector{KeyVaultAndKeyReference}", Symbol("provisioningState")=>"String")
Base.propertynames(::Type{ EncryptionSetProperties }) = collect(keys(_property_map_EncryptionSetProperties))
Swagger.property_type(::Type{ EncryptionSetProperties }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_EncryptionSetProperties[name]))}
Swagger.field_name(::Type{ EncryptionSetProperties }, property_name::Symbol) =  _property_map_EncryptionSetProperties[property_name]

function check_required(o::EncryptionSetProperties)
    true
end

function validate_property(::Type{ EncryptionSetProperties }, name::Symbol, val)
end


text:
# handy ways to specify cards
export ♣, ♢, ♡, ♠, ♦, ♥
import Base: (*)

const ♣ = Suit(:clubs)
const ♢ = Suit(:diamonds)
const ♡ = Suit(:hearts)
const ♠ = Suit(:spades)
const ♦ = ♢
const ♥ = ♡

(*)(r::Int, s::Suit) = Card(s, r)

export A♣, T♣, J♣, Q♣, K♣

const A♣ = Card(♣, 1)
const T♣ = Card(♣, 10)
const J♣ = Card(♣, 11)
const Q♣ = Card(♣, 12)
const K♣ = Card(♣, 13)

export A♢, T♢, J♢, Q♢, K♢
export A♦, T♦, J♦, Q♦, K♦

const A♦ = Card(♢, 1)
const T♦ = Card(♢, 10)
const J♦ = Card(♢, 11)
const Q♦ = Card(♢, 12)
const K♦ = Card(♢, 13)

const A♢ = Card(♢, 1)
const T♢ = Card(♢, 10)
const J♢ = Card(♢, 11)
const Q♢ = Card(♢, 12)
const K♢ = Card(♢, 13)

export A♡, T♡, J♡, Q♡, K♡
export A♥, T♥, J♥, Q♥, K♥

const A♡ = Card(♡, 1)
const T♡ = Card(♡, 10)
const J♡ = Card(♡, 11)
const Q♡ = Card(♡, 12)
const K♡ = Card(♡, 13)

const A♥ = Card(♡, 1)
const T♥ = Card(♡, 10)
const J♥ = Card(♡, 11)
const Q♥ = Card(♡, 12)
const K♥ = Card(♡, 13)

export A♠, T♠, J♠, Q♠, K♠

const A♠ = Card(♠, 1)
const T♠ = Card(♠, 10)
const J♠ = Card(♠, 11)
const Q♠ = Card(♠, 12)
const K♠ = Card(♠, 13)


text:
module WaterPhysics

using DocStringExtensions: METHODLIST, TYPEDEF, TYPEDFIELDS
using PkgUtility: CP_L, CP_V, GAS_R, K_BOLTZMANN, LH_V0, PRESS_TRIPLE, R_V,
            T_25, T_TRIPLE, V_H₂O
using UnPack: @unpack

# export public types
export TraceGasAir, TraceGasCO₂, TraceGasH₂O, TraceGasN₂, TraceGasO₂,
       TraceLiquidH₂O

# export public functions
export capillary_pressure, diffusive_coefficient, latent_heat_vapor,
       pressure_correction, relative_diffusive_coefficient,
       relative_surface_tension, relative_viscosity, saturation_vapor_pressure,
       saturation_vapor_pressure_slope, surface_tension, viscosity

###############################################################################
#
# Trace gas or liquid
#
###############################################################################
"""
`WaterPhysics` uses the multiple dispatch approach to calculate the temperature
    and pressure dependent physical properties of water and other molecules,
    such as CO₂. The trace molecules and mediums are catergorized to gas or
    liquid subject to a general type `AbstractTrace`. Hierarchy of
    `AbstractTrace`:

- [`AbstractTraceGas`](@ref)
- [`AbstractTraceLiquid`](@ref)

$(TYPEDEF)

"""
abstract type AbstractTrace{FT<:AbstractFloat} end

"""
The gas can be either the target trace molecule (e.g., when computing diffusive
    coefficient of CO₂ in water using [`diffusive_coefficient`](@ref)) or the
    medium (e.g., when computing diffusive coefficient or CO₂ in air using
    [`diffusive_coefficient`](@ref)). Currently, `WaterPhysics` supports the
    following subtypes of `AbstractTraceGas`:

- [`TraceGasAir`](@ref)
- [`TraceGasCO₂`](@ref)
- [`TraceGasH₂O`](@ref)
- [`TraceGasO₂`](@ref)

$(TYPEDEF)

"""
abstract type AbstractTraceGas{FT<:AbstractFloat} <: AbstractTrace{FT} end

"""
The liquid can be either the medium for gas (e.g., when computing diffusive
    coefficient of CO₂ in water using [`diffusive_coefficient`](@ref)) or the
    target molecule (e.g., when computing surface tension of water using
    [`surface_tension`](@ref)). Currently. `WaterPhysics` supports the
    following subtypes of `AbstractTraceLiquid`:

- [`TraceLiquidH₂O`](@ref)

$(TYPEDEF)

"""
abstract type AbstractTraceLiquid{FT<:AbstractFloat} <: AbstractTrace{FT} end

"""
Identity trace label for air.

$(TYPEDEF)

---
Examples
```julia
# load package before using the public functions
using WaterPhysics
# gas-phase air trace
trace = TraceGasAir{Float64}();
```
"""
struct TraceGasAir{FT<:AbstractFloat} <: AbstractTraceGas{FT} end

"""
Identity trace label for gas phase CO₂.

$(TYPEDEF)

# Fields

$(TYPEDFIELDS)

---
Examples
```julia
# gas-phase CO₂ trace
trace = TraceGasCO₂{Float64}();
```
"""
Base.@kwdef struct TraceGasCO₂{FT<:AbstractFloat} <: AbstractTraceGas{FT}
    # related to diffusive coefficient in air
    "Diffusive coefficient in air in `[m² s⁻¹]`"
    d_air  ::FT = 2.82e-5 / 1.6

    # related to diffusive coefficient in liquid water
    "Hydrodynamic radius of the solute in `[m]`"
    a_298  ::FT = 1.68e-10
    "Coefficient to make temperature correction over ydrodynamic radius"
    a_a    ::FT = 2e-3
    "Diffusive coefficient in liquid water in `[m² s⁻¹]`"
    d_water::FT = 2.147813e-9
end

"""
Identity trace label for gas phase H₂O.

$(TYPEDEF)

# Fields

$(TYPEDFIELDS)

---
Examples
```julia
# gas-phase H₂O trace
trace = TraceGasH₂O{Float64}();
```
"""
Base.@kwdef struct TraceGasH₂O{FT<:AbstractFloat} <: AbstractTraceGas{FT}
    # related to diffusive coefficient in air
    "Diffusive coefficient in air in `[m² s⁻¹]`"
    d_air::FT = 2.82e-5
end

"""
Identity trace label for gas phase N₂.

$(TYPEDEF)

# Fields

$(TYPEDFIELDS)

---
Examples
```julia
# gas-phase N₂ trace
trace = TraceGasN₂{Float64}();
```
"""
Base.@kwdef struct TraceGasN₂{FT<:AbstractFloat} <: AbstractTraceGas{FT}
    # related to diffusive coefficient in liquid water
    "Hydrodynamic radius of the solute in `[m]`"
    a_298  ::FT = 1.90e-10
    "Coefficient to make temperature correction over ydrodynamic radius"
    a_a    ::FT = 2.2e-3
    "Diffusive coefficient in liquid water in `[m² s⁻¹]`"
    d_water::FT = 1.899062e-9
end

"""
Identity trace label for gas phase O₂.

$(TYPEDEF)

# Fields

$(TYPEDFIELDS)

---
Examples
```julia
# gas-phase O₂ trace
trace = TraceGasO₂{Float64}();
```
"""
Base.@kwdef struct TraceGasO₂{FT<:AbstractFloat} <: AbstractTraceGas{FT}
    # related to diffusive coefficient in air
    "Diffusive coefficient in air in `[m² s⁻¹]`"
    d_air  ::FT = 1.76e-5

    # related to diffusive coefficient in liquid water
    "Diffusive coefficient in liquid water in `[m² s⁻¹]`"
    d_water::FT = 2.10e-9
end

"""
Identity trace label for liquid phase H₂O.

$(TYPEDEF)

# Fields

$(TYPEDFIELDS)

---
Examples
```julia
# liquid-phase water trace
trace = TraceLiquidH₂O{Float64}();
```
"""
Base.@kwdef struct TraceLiquidH₂O{FT<:AbstractFloat} <: AbstractTraceLiquid{FT}
    # Surface tension related
    # γ = γ_k * (1-T/γ_T_c)^γ_exp * [1 - γ_cor*(1-T/γ_T_c)]
    "Surface tension coefficient correction"
    γ_cor::FT = 0.625
    "Surface tension coefficient exponent"
    γ_exp::FT = 1.256
    "Surface tension coefficient k in `[N m⁻¹]`"
    γ_k  ::FT = 0.2358
    "Surface tension at 298.15 K in `[N m⁻¹]`"
    γ_ref::FT = 0.07197220523
    "Surface tension coefficient T_crit in `[K]`"
    γ_T_c::FT = 647.096

    # Viscosity related
    # υ = A ⋅ exp( A/T + C⋅T + D⋅T^2 )
    "Viscosity coefficient A in `[Pa s]`"
    υ_A::FT = 1.856e-14
    "Viscosity coefficient B in `[K]`"
    υ_B::FT = 4209.0
    "Viscosity coefficient C in `[K⁻¹]`"
    υ_C::FT = 0.04527
    "Viscosity coefficient D in `[K⁻²]`"
    υ_D::FT = -3.376e-5
end

###############################################################################
#
# Capillary pressure
#
###############################################################################
"""
Capillary pressure of the trace liquid in a pipe is a function of surface
    tension (`γ`), pipe raduis (`r`), and contact angle (`α`):

```math
P_{c} = \\dfrac{2 ⋅ γ ⋅ \\text{cos}(α)}{r}
```

`WaterPhysics` supports the following methods to compute capillary pressure:

$(METHODLIST)

"""
function capillary_pressure end

"""
When the contact angle is not given, capillary pressure is computed using

    capillary_pressure(
                r::FT,
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Capillary pressure of trace liquid in `[Pa]`, given
- `r` Curvature radius in `[m]`
- `T` Trace liquid temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# capillary pressure of liquid water
p_1 = capillary_pressure(3e-6, 298.15);
p_2 = capillary_pressure(3e-6, 298.15, TraceLiquidH₂O{Float64}());
```
"""
capillary_pressure(
            r::FT,
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
     return 2 * surface_tension(T, med) / r
)

"""
When the contact angle is given, capillary pressure is computed using

    capillary_pressure(
                r::FT,
                T::FT,
                α::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Capillary pressure of trace liquid in `[Pa]`, given
- `r` Pipe radius in `[m]`
- `T` Trace liquid temperature in `[K]`
- `α` Contact angle in `[°]`
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# capillary pressure of liquid water with contact angle
p_1 = capillary_pressure(3e-6, 298.15, 30.0);
p_2 = capillary_pressure(3e-6, 298.15, 30.0, TraceLiquidH₂O{Float64}());
```
"""
capillary_pressure(
            r::FT,
            T::FT,
            α::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
     return cosd(α) * capillary_pressure(r, T, med)
)

###############################################################################
#
# Diffusive coefficient
#
###############################################################################
"""
Diffusion of trace molecules in medium is temperature dependent, to calculate
    this temperature dependency, we provide a function to quick estimate this
    value for different trace molecules using `diffusive_coefficient`. The
    supported methods are:

$(METHODLIST)

"""
function diffusive_coefficient end

"""
For the diffusive coefficient of gas in air, the coefficient is simply treated
    as a function of temperature and the reference coefficient at 298.15 K:

```@math
D = D_\\text{ref} ⋅ \\left( \\dfrac{T}{298.15} \\right)^{1.8}
```

This temperature correction is also available as a stand alone function:
    [`relative_diffusive_coefficient`](@ref).

    diffusive_coefficient(
                T::FT,
                mol::Union{TraceGasCO₂{FT}, TraceGasH₂O{FT}, TraceGasO₂{FT}},
                med::TraceGasAir{FT}
    ) where {FT<:AbstractFloat}

Diffusive coefficient of trace molecule in `[m² s⁻¹]`, given
- `T` Trace medium temperature in `[K]`
- `mol` Trace molecule
- `med` Diffusion medium (air)

---
Examples
```julia
# diffusive coefficient of gas-phase CO₂, H₂O, and O₂ in air
air   = TraceGasAir{Float64}();
d_CO₂ = diffusive_coefficient(298.15, TraceGasCO₂{Float64}(), air);
d_H₂O = diffusive_coefficient(298.15, TraceGasH₂O{Float64}(), air);
d_O₂  = diffusive_coefficient(298.15, TraceGasO₂{Float64}(), air);
```
"""
diffusive_coefficient(
            T::FT,
            mol::Union{TraceGasCO₂{FT}, TraceGasH₂O{FT}, TraceGasO₂{FT}},
            med::TraceGasAir{FT}
) where {FT<:AbstractFloat} =
(
    return mol.d_air * relative_diffusive_coefficient(T, mol, med)
)

"""
The diffusive coefficient of disolved gas in liquid water is also a function of
    temperature. The calculation is based on the empirical formulation and
    variables from Cadogen et al. (2015) Diffusion coefficients of CO₂ and N₂
    in water at temperatures between 298.15 K and 423.15 K at pressures up to
    45 MPa.

    diffusive_coefficient(
                T::FT,
                mol::Union{TraceGasCO₂{FT}, TraceGasN₂{FT}},
                med::TraceLiquidH₂O{FT}
    ) where {FT<:AbstractFloat}

Diffusive coefficient of trace molecule in `[m² s⁻¹]`, given
- `T` Trace medium temperature in `[K]`
- `mol` Trace molecule
- `med` Diffusion medium (liquid water)

---
Examples
```julia
# diffusive coefficient of CO₂ and N₂ in liquid water
water = TraceLiquidH₂O{Float64}();
d_CO₂ = diffusive_coefficient(298.15, TraceGasCO₂{FT}(), water);
d_N₂  = diffusive_coefficient(298.15, TraceGasN₂{FT}(), water);
```
"""
diffusive_coefficient(
            T::FT,
            mol::Union{TraceGasCO₂{FT}, TraceGasN₂{FT}},
            med::TraceLiquidH₂O{FT}
) where {FT<:AbstractFloat} =
(
    @unpack a_298, a_a = mol;
    _a = a_298 * (1 + a_a *  (T-298));

    return K_BOLTZMANN(FT) * T / (4 * FT(pi) * viscosity(T, med) * _a)
)

"""
The temperature dependency of diffusive coefficient impacts leaf gas exchange
    via change the maximal stomatal conductance to H₂O vapor and CO₂, given
    that Since the stomatal conductance should not exceed its structural limit.
    To account for this effect, we provide a function to calculate the
    diffusive coefficient relative to 25 Celcius.

$(METHODLIST)

"""
function relative_diffusive_coefficient end

"""
As mentioned in [`diffusive_coefficient`](@ref), relative diffusive coefficient
    of target gas in gas medium is calculated as an exponential function of
    temperature. The shortcut method is

    relative_diffusive_coefficient(
                T::FT,
                mol::AbstractTraceGas{FT} = TraceGasH₂O{FT}(),
                med::AbstractTraceGas{FT} = TraceGasAir{FT}()
    ) where {FT<:AbstractFloat}

Relative diffusive coefficient of trace gas in medium, given
- `T` Water vapor temperature in `[K]`
- `mol` Trace molecule. Optional, default is water vapor
- `med` Medium. Optional, default is air

---
Examples
```julia
# relative diffusive coefficient of gas in air
rat_1 = relative_diffusive_coefficient(298.15);
rat_2 = relative_diffusive_coefficient(298.15, TraceGasH₂O{Float64}());
rat_3 = relative_diffusive_coefficient(298.15, TraceGasH₂O{Float64}(),
                                       TraceGasAir{Float64});
```
"""
relative_diffusive_coefficient(
            T::FT,
            mol::AbstractTraceGas{FT} = TraceGasH₂O{FT}(),
            med::AbstractTraceGas{FT} = TraceGasAir{FT}()
) where {FT<:AbstractFloat} =
(
    return (T / T_25(FT)) ^ FT(1.8)
)

"""
As to disolved gas diffsuin in liquid medium, the relative coefficient is also
    computed based on the empirical formulation from Cadogan et al. (2014).

    relative_diffusive_coefficient(
                T::FT,
                mol::AbstractTraceGas{FT}
                med::AbstractTraceGas{FT}
    ) where {FT<:AbstractFloat}

Relative diffusive coefficient of trace gas in medium, given
- `T` Water vapor temperature in `[K]`
- `mol` Trace molecule. Optional, default is water vapor
- `med` Medium. Optional, default is air

---
Examples
```julia
# relative diffusive coefficient of CO₂ and N₂ in liquid water
water = TraceLiquidH₂O{Float64}();
rat_1 = relative_diffusive_coefficient(298.15, TraceGasCO₂{Float64}(), water);
rat_2 = relative_diffusive_coefficient(298.15, TraceGasN₂{Float64}(), water);
```
"""
relative_diffusive_coefficient(
            T::FT,
            mol::Union{TraceGasCO₂{FT}, TraceGasN₂{FT}},
            med::TraceLiquidH₂O{FT}
) where {FT<:AbstractFloat} =
(
    @unpack d_water = mol;

    return diffusive_coefficient(T, mol, med) / d_water
)

###############################################################################
#
# Latent heat of evaporation
# Adapted from the ClimateMachine/Common/ThermoDynamics/relations.jl
#
###############################################################################
"""
Water evaporation from liquid phase is a key process to regulate leaf
    temperature, and to best represent this process. We computed the latent
    heat coefficient from water temperature:

$(METHODLIST)

"""
function latent_heat_vapor end

"""
    latent_heat_vapor(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Latent heat of vaporization in `[J kg⁻¹]`, given
- `T` Medium temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# latent heat of vapor of liquid water
λ_1 = latent_heat_vapor(298.15);
λ_2 = latent_heat_vapor(298.15, TraceLiquidH₂O{Float64}());
```
"""
latent_heat_vapor(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    _LH_v0::FT = LH_V0(FT);
    _T_0  ::FT = T_TRIPLE(FT);
    _Δcp_v::FT = CP_V(FT) - CP_L(FT);

    return _LH_v0 + _Δcp_v * (T - _T_0)
)

###############################################################################
#
# Saturated vapor pressure
# Adapted from the ClimateMachine/Common/ThermoDynamics/relations.jl
#
###############################################################################
"""
Yet, the saturation vapor pressure is not only a function of temperature, but
    also a function of the air-water interface curvature, known as the Kelvin
    equation. The package provide [`pressure_correction`](@ref) to make the
    correction.

$(METHODLIST)

"""
function pressure_correction end

"""
    pressure_correction(
                T::FT,
                Ψ::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Kelvin correction factor for saturation vapor pressure, given
- `T` Liquid water temperature in `[K]`
- `Ψ` Liquid water pressure in `[Pa]`, positive/negative for convex/concave
    interface
- `med` Medium. Optional. Default is liquid water

The Kelvin equation is
```math
\\log \\left( \\dfrac{P_{sat}}{P_{sat}^{*}} \\right) =
\\dfrac{Ψ ⋅ V_{m}}{R ⋅ T}
```

---
Examples
```julia
# correction to saturation vapor pressure of liquid water with non-flat surface
cor_1 = pressure_correction(298.15, -1e6);
cor_2 = pressure_correction(298.15, -1e6, TraceLiquidH₂O{Float64}());
```
"""
pressure_correction(
            T::FT,
            Ψ::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    return exp((Ψ * V_H₂O(FT)) / (GAS_R(FT) * T))
)

"""
When temperature increases, liquid water vapor pressure increases
    exponentially. And this correlation is accounted for using the functions
    below:

$(METHODLIST)

"""
function saturation_vapor_pressure end

"""
    saturation_vapor_pressure(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Saturation vapor pressure in `[Pa]`, given
- `T` Liquid water temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# saturation vapor pressure of liquid water with flat surface
p_1 = saturation_vapor_pressure(298.15);
p_2 = saturation_vapor_pressure(298.15, TraceLiquidH₂O{Float64}());
```
"""
saturation_vapor_pressure(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    _LH_v0       ::FT = LH_V0(FT);
    _cp_v        ::FT = CP_V(FT);
    _cp_l        ::FT = CP_L(FT);
    _press_triple::FT = PRESS_TRIPLE(FT);
    _R_v         ::FT = R_V(FT);
    _T_triple    ::FT = T_TRIPLE(FT);
    _T_0         ::FT = T_TRIPLE(FT);
    _Δcp         ::FT = _cp_v - _cp_l;

    return _press_triple *
           (T / _T_triple)^(_Δcp / _R_v) *
           exp((_LH_v0 - _Δcp * _T_0) / _R_v * (1 / _T_triple - 1 / T))
)

"""
    saturation_vapor_pressure(
                T::FT,
                Ψ::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Saturation vapor pressure in `[Pa]`, given
- `T` Liquid water temperature in `[K]`
- `Ψ` Liquid water pressure in `[Pa]`, positive/negative for convex/concave
    interface; if `Ψ` is given, [`pressure_correction`](@ref) is made
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# saturation vapor pressure of liquid water with non-flat surface
p_1 = saturation_vapor_pressure(298.15, -1e6);
p_2 = saturation_vapor_pressure(298.15, -1e6, TraceLiquidH₂O{Float64}());
```
"""
saturation_vapor_pressure(
            T::FT,
            Ψ::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    return saturation_vapor_pressure(T, med) * pressure_correction(T, Ψ, med)
)

"""
First order derivative of saturation vapor pressure.

$(METHODLIST)

"""
function saturation_vapor_pressure_slope end

"""
    saturation_vapor_pressure_slope(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

First order derivative of saturation vapor pressure in `[Pa K⁻¹]`, given
- `T` Liquid water temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

Compute the the 1st order derivative of saturation vapor pressure over a plane
    surface by integration of the Clausius-Clapeyron relation.

The re-arranged Clausius-Clapeyron relation
```math
\\frac{∂P_{sat}^{*}}{∂T} = P_{sat} ⋅ \\dfrac{ LH_0 + Δc_p ⋅ (T - T_{triple})}
                                        { R_v ⋅ T^2 }
```

---
Examples
```julia
# slope of saturation vapor pressure of liquid water with flat surface
s_1 = saturation_vapor_pressure_slope(298.15);
s_2 = saturation_vapor_pressure_slope(298.15, TraceLiquidH₂O{Float64}());
```
"""
saturation_vapor_pressure_slope(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    _LH_v0::FT = LH_V0(FT);
    _cp_v ::FT = CP_V(FT);
    _cp_l ::FT = CP_L(FT);
    _R_v  ::FT = R_V(FT);
    _T_0  ::FT = T_TRIPLE(FT);
    _Δcp  ::FT = _cp_v - _cp_l;

    return (_LH_v0 + _Δcp * (T - _T_0)) / (_R_v*T^2)
)

"""
    saturation_vapor_pressure_slope(
                T::FT,
                Ψ::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

First order derivative of saturation vapor pressure in `[Pa K⁻¹]`, given
- `T` Liquid water temperature in `[K]`
- `Ψ` Liquid water pressure in `[Pa]`, positive/negative for convex/concave
    interface; if `Ψ` is given, [`pressure_correction`](@ref) is made
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# slope of saturation vapor pressure of liquid water with non-flat surface
s_1 = saturation_vapor_pressure_slope(298.15, -1e6);
s_2 = saturation_vapor_pressure_slope(298.15, -1e6, TraceLiquidH₂O{Float64}());
```
"""
saturation_vapor_pressure_slope(
            T::FT,
            Ψ::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    return saturation_vapor_pressure_slope(T, med) *
           pressure_correction(T, Ψ, med)
)

###############################################################################
#
# Surface tension
#
###############################################################################
"""
When water temperature increases, the surface tension at the air-water
    interface decreases. Surface tension changes impacts the plant water
    transport via two aspects. First, if surface tension is lower, for a
    constant soil water content, the soil matrix potential gets less negative
    because the capillary pressure at the air-water interface decreases. And
    this is beneficial to plants. Second, the air-water interface at the pit
    membrane also has lower capillary pressure when temperature increases,
    meaning that the xylem conduits are less resistant to drought-induced
    air-seeded cavitation. And this is harmful for plants. Though the surface
    tension does not differ much with temperature change within the plant
    physiological active range, we account for this effect in our Land model.

$(METHODLIST)

"""
function surface_tension end

"""
    surface_tension(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Surface tension of trace liquid in `[N m⁻¹]`, given
- `T` Liquid water temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

The equation used is
```math
γ = 0.2358 ⋅
    \\left( 1 - \\dfrac{T}{T_c} \\right)^{1.256} ⋅
    \\left[ 1 - 0.625 ⋅ \\left( 1 - \\dfrac{T}{T_c} \\right) \\right]
```
See http://www.iapws.org/relguide/Surf-H2O.html

---
Examples
```julia
# surface tension of liquid water
γ_1 = surface_tension(298.15);
γ_2 = surface_tension(298.15, TraceLiquidH₂O{Float64}());
```
"""
surface_tension(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    @unpack γ_cor, γ_exp, γ_k, γ_T_c = med;
    _γ_T_r_diff = 1 - T / γ_T_c;

    return γ_k * _γ_T_r_diff^γ_exp * (1 - γ_cor*_γ_T_r_diff)
)

"""
Relative surface tension of trace liquid relative to 298.15 K.

$(METHODLIST)

"""
function relative_surface_tension end

"""
    relative_surface_tension(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Relative surface tension of trace liquid relative to 298.15 K, given
- `T` Liquid water temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

---
Examples
```julia
# relative surface tension of liquid water
γ_1 = relative_surface_tension(298.15);
γ_2 = relative_surface_tension(298.15, TraceLiquidH₂O{Float64}());
```
"""
relative_surface_tension(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    return surface_tension(T, med) / med.γ_ref
)

###############################################################################
#
# Viscosity
#
###############################################################################
"""
When temperature increases, liquid water viscosuty decreases, meaning that the
    resistance for water decreases and the pressure drop per flow rate
    decreases. This effect is pretty significant as 1 degree increase of
    temperature results in about 2.4% drop in viscosity, and this is very
    beneficial to plant water transport. Unfortunately, to our knowledge, very
    few models account for this effect when modeling plant hydraulics because
    of the difficulty in modeling the energy budget along the flow path. We
    plan to have this effect accounted for in our CliMA Land model, by
    computing the water tempreature along the flow path and thus the viscosity
    change. The functions to be used are:

$(METHODLIST)

"""
function viscosity end

"""
    viscosity(T::FT,
              med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Viscosity in `[Pa s]`, given
- `T` Liquid water temperature in `[K]`
- `med` Medium. Optional. Default is liquid water

Equation used is
```math
υ = A ⋅ \\exp \\left( \\dfrac{B}{T} + C⋅T + D⋅T^2 \\right)
```
and the fitting parameters are from Reid, Prausnitz, & Poling (1987), valid
through 273-643 K
```
A = 1.856E-14 # Pa s
B = 4209      # K
C = 0.04527   # K⁻¹
D = -3.376E-5 # K⁻²
```

---
Examples
```julia
# viscosity of liquid water
γ_1 = viscosity(298.15);
γ_2 = viscosity(298.15, TraceLiquidH₂O{Float64}());
```
"""
viscosity(T::FT,
          med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    @unpack υ_A, υ_B, υ_C, υ_D = med;

    return υ_A * exp( υ_B/T + υ_C*T + υ_D*T^2 )
)

"""
Viscosity relative to 298.15 K

$(METHODLIST)

"""
function relative_viscosity end

"""
    relative_viscosity(
                T::FT,
                med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
    ) where {FT<:AbstractFloat}

Viscosity relative to 298.15 K, given
- `T` Liquid water temperature in `[K]`
- `liquid` Optional. Default is liquid water

Equation used is
```math
υ = A ⋅ \\exp \\left( \\dfrac{B}{T} + C⋅T + D⋅T^2 \\right)
```
and the fitting parameters are from Reid, Prausnitz, & Poling (1987), valid
through 273-643 K
```
B = 4209      # K
C = 0.04527   # K⁻¹
D = -3.376E-5 # K⁻²
```

---
Examples
```julia
# relative viscosity of liquid water
γ_1 = relative_viscosity(298.15);
γ_2 = relative_viscosity(298.15, TraceLiquidH₂O{Float64}());
```
"""
relative_viscosity(
            T::FT,
            med::TraceLiquidH₂O{FT} = TraceLiquidH₂O{FT}()
) where {FT<:AbstractFloat} =
(
    @unpack υ_B, υ_C, υ_D = med;
    _K = T_25(FT);

    return exp( υ_B * ( 1/T - 1/_K) + υ_C * (T - _K) + υ_D * (T^2 - _K^2) )
)

end # module


text:
# Box-Muller test
Nsim = 500000000

function f(N)
    for i = 1:N
        r = rand(2)
        theta = 2*pi*r[1]
        r2 = -2*log(r[2])

        x = sqrt(r2)*cos(theta)
        y = sqrt(r2)*sin(theta)
    end
end

@time f(Nsim)


text:
"""
RootInterface is the root of an interface hierarchy.
Interfaces are modelled with abstract types.
"""
abstract type RootInterface end

"""
Implementation is marked with subtyping the interface
"""
struct RootImpl <: RootInterface end

"""
Interfaces have single inheritance with subtype semantics:
An implementation of a subinterface must also implement
the superinterface.
"""
abstract type SubInterfaceLeft <: RootInterface end
struct SubImplLeft <: SubInterfaceLeft end

abstract type SubInterfaceRight <: RootInterface end
struct SubImplRight <: SubInterfaceRight end

abstract type SubSubInterfaceLeft <: SubInterfaceLeft end
struct SubSubImplLeft <: SubSubInterfaceLeft end

@testset "Finding implementations for single interfaces" begin
    # Throws an error when the required interface is unimplemented
    @test_throws Any Plugins.instantiation_order([RootInterface])
    @test_throws Any Plugins.instantiation_order([SubInterfaceLeft])

    # Registration is programmatic for now
    Plugins.register(RootImpl)

    # Finds the trivial implementation
    @test Plugins.instantiation_order([RootInterface]) == [RootImpl]

    # Throws an error when the required interface has unimplemented dependencies
    @test_throws Any Plugins.instantiation_order([SubInterfaceLeft])

    # Finds the most specific implementation if multiple are available
    Plugins.register(SubImplLeft)
    @test Plugins.instantiation_order([RootInterface]) == [SubImplLeft]
    @test Plugins.instantiation_order([SubInterfaceLeft]) == [SubImplLeft]

    # If there are multiple most specific implementations, selects one undefinedly
    Plugins.register(SubImplRight)
    @test Plugins.instantiation_order([RootInterface])[1] <: RootInterface

    # Still works
    @test Plugins.instantiation_order([SubInterfaceLeft]) == [SubImplLeft]
    @test Plugins.instantiation_order([SubInterfaceRight]) == [SubImplRight]

    # A two-level hierarchy also works as expected
    Plugins.register(SubSubImplLeft)
    @test Plugins.instantiation_order([RootInterface])[1] <: RootInterface
    @test Plugins.instantiation_order([SubInterfaceLeft]) == [SubSubImplLeft]
    @test Plugins.instantiation_order([SubSubInterfaceLeft]) == [SubSubImplLeft]
    @test Plugins.instantiation_order([SubInterfaceRight]) == [SubImplRight]
end

# ------------------------------------------------------------------------------------------

# Helper for checking permutation equivalence of type arrays
Base.isless(a::Type, b::Type) = isless(nameof(a), nameof(b))

"""
A more realistic example is a small module structure with complex dependencies.
Instantiated implementations receive instances of their dependencies as arguments
to the constructor, and may also receive options through kwargs.
"""
abstract type MI1 <: Plugin  end
struct MImpl1 <: MI1
    x1
    x2
    MImpl1(; x1=nothing, x2=nothing, options...) = new(x1, x2)
end

abstract type MI2 <: Plugin  end
struct MImpl2 <: MI2
    MImpl2(::MI1; options...) = new()
end
Plugins.deps(::Type{MImpl2}) = [MImpl1]

abstract type MI3 <: Plugin  end
struct MImpl3 <: MI3
    MImpl3(::MI1; options...) = new()
end

abstract type MI4 <: Plugin  end
struct MImpl4 <: MI4
    MImpl4(::MI1, ::MI2; options...) = new()
end

abstract type MI5 <: Plugin end
struct MImpl5 <: MI5
    MImpl5(::MI4, ::MI2; options...) = new()
end
Plugins.deps(::Type{MImpl5}) = [MImpl4, MI2]

@testset "Dependency hierarchies are tracked" begin
    Plugins.register(MImpl1)
    Plugins.register(MImpl2)
    Plugins.register(MImpl3, [MI2])
    Plugins.register(MImpl4, [MI1, MI2])
    Plugins.autoregister() # MImpl5
    @test sort(Plugins.instantiation_order([MI1, MI2])) == sort([MImpl1, MImpl2])
    @test sort(Plugins.instantiation_order([MI1, MI3])) == sort([MImpl1, MImpl2, MImpl3])
    @test sort(Plugins.instantiation_order([MImpl3, MImpl1])) == sort([MImpl1, MImpl2, MImpl3])
    @test sort(Plugins.instantiation_order([MI1, MI2, MI3, MI4, MI5])) == sort([MImpl1, MImpl2, MImpl3, MImpl4, MImpl5])
    @test sort(Plugins.instantiation_order([MI5, MI4])) == sort([MImpl5, MImpl4, MImpl2, MImpl1])
    @test sort(Plugins.instantiation_order([MI5, MI3])) == sort([MImpl5, MImpl4, MImpl3, MImpl2, MImpl1])
end

@testset "Instantiation" begin
    @show mi1 = Plugins.instantiate([MI1]; x1=42, x2=43)
    @test length(mi1) == 1
    @test mi1[1] isa MImpl1
    @test mi1[1].x1 == 42
    @test mi1[1].x2 == 43

    @show mi2 = Plugins.instantiate([MI1, MI2]; x1=42, plugins_tests_extraop=:plugins_tests_extraop)
    @test length(mi2) == 2
    @test mi2[1] isa MImpl1
    @test mi2[2] isa MImpl2

    @show mi3 = Plugins.instantiate([MI1, MI4])
    @test length(mi3) == 3
    @test mi3[1] isa MImpl1
    @test mi3[2] isa MImpl4
    @test mi3[3] isa MImpl2

    @show mi4 = Plugins.instantiate([MI1, MI4, MI5])
    @test length(mi4) == 4
    @test mi4[1] isa MImpl1
    @test mi4[2] isa MImpl4
    @test mi4[3] isa MImpl5
    @test mi4[4] isa MImpl2

    @test_throws ErrorException Plugins.getplugin(42)
end


text:
type Location
	x_loc::Float64
	y_loc::Float64

	Location(x,y) = new(x, y)
	Location() = new(nullValue, nullValue)

end

type Vehicle
	index::Int
	capacity::Int #capacity of vehicle
	cost_coeff::Float64 #cost of travelling for a km
	max_time::Float64 #maximum time vehicle can take before returning to depot
	speed::Float64 #average speed of vehicle in km/h

	Vehicle() = new(nullIndex, nullValue, nullValue, nullValue)
end

type Request
	index::Int
	num_pass::Int #number of passengers requested for
	origin::Location
	destination::Location
	#from_x_loc::Float64 #origin longitude from depot
	#from_y_loc::Float64 #origin latitude from depot
	#to_x_loc::Float64 #destination longitude from depot
	#to_y_loc::Float64 #destination latitude from depot
	early::String #earliest time the pickup can occur
	late::String #latest time the delivery can occur

	Request() = new(nullIndex, nullValue, Location(), Location(), nullString, nullString)
end

type Node
	index::Int
	name::String #name of the location
	x_loc::Float64 #latitude relative to the depot in km
	y_loc::Float64 #longitude relative to the depot in km

	Node() = new(nullIndex, nullString, nullValue, nullValue)
end

type Test
	origin::Location
end

max_stars_repo_name: jprendo/TaaSSim


text:
using BinDeps

@BinDeps.setup

libmongoc = library_dependency(
    "libmongoc",
    aliases = ["libmongoc", "libmongoc-1.0"]
    )

provides(Sources, Dict(
    URI("http://github.com/mongodb/mongo-c-driver/releases/download/1.3.5/mongo-c-driver-1.3.5.tar.gz") => libmongoc
    ))

provides(
    BuildProcess,
    Autotools(libtarget = "libmongoc-1.0.la"),
    libmongoc,
    os = :Unix
    )

@static if is_apple()
    using Homebrew
    provides(Homebrew.HB, Dict("mongo-c-driver" => libmongoc))
end

@BinDeps.install Dict(:libmongoc => :libmongoc)


text:
module MzPlots

using Unitful
using MzCore
using MzCore.IntervalSets
import MzCore.AxisArrays
using Observables
import AbstractPlotting
using AbstractPlotting: Scene, image!, xlabel!, ylabel!, cam2d!
using AbstractPlotting.MakieLayout
import RecipesBase
using UnitfulRecipes
using UnitfulRecipes: fixaxis!

export dynamic_binning, mzplot

function dynamic_binning(f, scans, limits::Observable; buffersz=(1000,1000))
    map(limits) do lims
        time, mz = lims
        axt  = Axis{:time}(range(minimum(time), stop=maximum(time), length=buffersz[1]))
        axmz = Axis{:mz}(range(minimum(mz), stop=maximum(mz), length=buffersz[2]))
        T = intensitytype(eltype(scans))
        tmp = AxisArray(Matrix{T}(undef, buffersz), axmz, axt)
        copyto!(tmp, scans)
        return f.(transpose(tmp.data))
    end
end

interval_width(left, w) = left .. left+w
interval_width(left, w, scale) = left*scale .. (left+w)*scale

function mzplot(f, scans; title=" ", resolution=(800,800), buffersz=resolution, kwargs...)
    axmz, axtime = limits(scans)
    limmz, limtime = axisvalues(axmz)[1], axisvalues(axtime)[1]
    timeu = unit(limtime.left)

    scene, layout = layoutscene(30, resolution=resolution)
    ax = layout[1,1] = LAxis(scene, title=title, xlabel="Time ($timeu)", ylabel="m/z")
    isfirst = true
    axlimits = async_latest(ax.limits)
    lims = map(axlimits) do box
        if isfirst
            isfirst = false
            return limtime, limmz
        end
        return interval_width(box.origin[1], box.widths[1], timeu), interval_width(box.origin[2], box.widths[2])
    end
    imgbin = dynamic_binning(f, scans, lims; buffersz=buffersz)
    xi, yi = ustrip(lims[][1]), lims[][2]
    image!(ax, xi, yi, imgbin)
    return scene, ax
end
mzplot(scans; kwargs...) = mzplot(sqrt, scans; kwargs...)

# User recipe for Plots
RecipesBase.@recipe function f(img::AA) where AA<:AxisArray{T,2} where T
    y, x = axisvalues(img)
    yname, xname = axisnames(img)
    xguide --> string(xname)
    yguide --> string(yname)
    if eltype(x) <: Quantity
        x = fixaxis!(plotattributes, x, :x)
    end
    if eltype(y) <: Quantity
        y = fixaxis!(plotattributes, y, :y)
    end
    return x, y, parent(img)
end

end


text:
using Documenter, AstroTime

setup = quote
    using AstroTime
end
DocMeta.setdocmeta!(AstroTime, :DocTestSetup, setup; recursive = true)

makedocs(
    format = Documenter.HTML(
	prettyurls = get(ENV, "CI", nothing) == "true",
    ),
    modules = [AstroTime],
    sitename = "AstroTime.jl",
    authors = "Helge Eichhorn and the AstroTime.jl contributors",
    pages = [
	"Home" => "index.md",
	"Tutorial" => "tutorial.md",
	"API" => [
	    "Time Scales" => joinpath("api", "timescales.md"),
	    "Periods" => joinpath("api", "periods.md"),
	    "Epochs" => joinpath("api", "epochs.md"),
	],
    ],
    strict = true,
)

deploydocs(
    repo = "github.com/JuliaAstro/AstroTime.jl.git",
    push_preview = true,
)

max_stars_repo_name: JuliaAstrodynamics/AstronomicalTime

max_issues_repo_name: JuliaAstrodynamics/AstronomicalTime

max_forks_repo_name: JuliaAstrodynamics/AstronomicalTime


text:
using SimpleCG

plane_g = Plane(Vector3(0, 1, 0), 0);
sphere1_g = Sphere(Vector3(-10, 10, -10), 10);
sphere2_g = Sphere(Vector3(10, 10, -10), 10);
plane = GeometryWithMaterial(plane_g, CheckerMaterial(0.1, 0.5))
sphere1 = GeometryWithMaterial(sphere1_g, PhongMaterial(Red, White, 16, 0.25))
sphere2 = GeometryWithMaterial(sphere2_g, PhongMaterial(Blue, White, 16, 0.25))

canvas = Canvas(1600, 1600);
camera = PerspectiveCamera(Vector3(0, 5, 15), Vector3(0, 0, -1), Vector3(0, 1, 0), π/2)
scene = UnionGeometry([plane, sphere1, sphere2])
render!(canvas, scene, camera, 3);
imshow(canvas)


text:
"""
    EmbeddedManifold{𝔽, MT <: AbstractManifold, NT <: AbstractManifold} <: AbstractDecoratorManifold{𝔽}

A type to represent an explicit embedding of a [`AbstractManifold`](@ref) `M` of type `MT` embedded
into a manifold `N` of type `NT`.
By default, an embedded manifold is set to be embedded, but neither isometrically embedded
nor a submanifold.

!!! note
    This type is not required if a manifold `M` is to be embedded in one specific manifold `N`.
     One can then just implement [`embed!`](@ref) and [`project!`](@ref).
    You can further pass functions to the embedding, for example, when it is an isometric embedding,
    by using an [`AbstractDecoratorManifold`](@ref).
    Only for a second –maybe considered non-default–
    embedding, this type should be considered in order to dispatch on different embed
    and project methods for different embeddings `N`.

# Fields

* `manifold` the manifold that is an embedded manifold
* `embedding` a second manifold, the first one is embedded into

# Constructor

    EmbeddedManifold(M, N)

Generate the `EmbeddedManifold` of the [`AbstractManifold`](@ref) `M` into the
[`AbstractManifold`](@ref) `N`.
"""
struct EmbeddedManifold{𝔽,MT<:AbstractManifold{𝔽},NT<:AbstractManifold} <:
       AbstractDecoratorManifold{𝔽}
    manifold::MT
    embedding::NT
end

@inline active_traits(f, ::EmbeddedManifold, ::Any...) = merge_traits(IsEmbeddedManifold())

function allocate_result(M::EmbeddedManifold, f::typeof(project), x...)
    T = allocate_result_type(M, f, x)
    return allocate(x[1], T, representation_size(base_manifold(M)))
end

"""
    decorated_manifold(M::EmbeddedManifold, d::Val{N} = Val(-1))

Return the manifold of `M` that is decorated with its embedding. For this specific
type the internally stored enhanced manifold `M.manifold` is returned.

See also [`base_manifold`](@ref), where this is used to (potentially) completely undecorate the manifold.
"""
decorated_manifold(M::EmbeddedManifold) = M.manifold

"""
    get_embedding(M::EmbeddedManifold)

Return the embedding [`AbstractManifold`](@ref) `N` of `M`, if it exists.
"""
function get_embedding(M::EmbeddedManifold)
    return M.embedding
end

function project(M::EmbeddedManifold, p)
    q = allocate_result(M, project, p)
    project!(M, q, p)
    return q
end

function show(
    io::IO,
    M::EmbeddedManifold{𝔽,MT,NT},
) where {𝔽,MT<:AbstractManifold{𝔽},NT<:AbstractManifold}
    return print(io, "EmbeddedManifold($(M.manifold), $(M.embedding))")
end