const MatOrVec{T} = Union{Matrix{T}, Vector{T}} where T

Base.@irrational sqrt2invpi 0.79788456080286535587 sqrt(big(2)/big(π))

#from here https://stackoverflow.com/questions/46671965/printing-variable-subscripts-in-julia
subscript(i::Integer) = i<0 ? error("$i is negative") : join('₀'+d for d in reverse(digits(i)))

#count the number of type vars. there's probably a better way.
function my_unwrap_unionall(@nospecialize a)
    count = 0
    while isa(a, UnionAll)
        a = a.body
        count += 1
    end
    return count
end

@inline function to_corr(Σ)
	D = sqrt(Diagonal(Σ))
    iD = inv(D)
    R = iD * Σ * iD
    R = (R + R') / 2
end

#=
    analytical_shrinkage(X::Matrix)
Analytical nonlinear shrinkage estimator of the covariance matrix. Based on the
Matlab code from [1]. Translated to Julia and used here under MIT license by
permission from the authors.

[1] Ledoit, O., and Wolf, M. (2018), "Analytical Nonlinear Shrinkage of
Large-Dimensional Covariance Matrices", University of Zurich Econ WP 264.
https://www.econ.uzh.ch/static/workingpapers_iframe.php?id=943
=#
function analytical_shrinkage(X)
n, p = size(X)
@assert n >= 12 # important: sample size n must be >= 12
sample = Symmetric(X'*X) / n
E = eigen(sample)
lambda = E.values
u = E.vectors

# compute analytical nonlinear shrinkage kernel formula
lambda = lambda[max(1, p-n+1):p]
L = repeat(lambda, 1, min(p, n))
h = n^(-1/3) # Equation (4.9)
H = h*L'
x = (L-L') ./ H
ftilde = (3/4/sqrt(5)) * mean(max.(1 .- x.^2 ./ 5, 0) ./ H, dims=2) # Equation (4.7)
Hftemp = (-3/10/pi) * x + (3/4/sqrt(5)/pi) * (1 .- x.^2 ./ 5) .* log.(abs.((sqrt(5).-x) ./ (sqrt(5).+x))) # Equation (4.8)
Hftemp[abs.(x) .== sqrt(5)] .= (-3/10/pi) .* x[abs.(x) .== sqrt(5)]
Hftilde = mean(Hftemp./H, dims=2)
if p<=n
    dtilde = lambda ./ ((pi * (p/n) *lambda .* ftilde).^2  + (1 .- (p/n) .- pi * (p/n) * lambda .* Hftilde).^2) # Equation (4.3)
else
    Hftilde0 = (1/pi) * (3/10/h^2 + 3/4/sqrt(5)/h*(1-1/5/h^2) * log((1+sqrt(5)*h)/(1-sqrt(5)*h)))*mean(1 ./ lambda) # Equation (C.8)
    dtilde0 = 1 / (pi * (p-n) / n * Hftilde0) # Equation (C.5)
    dtilde1 = lambda ./ (pi^2*lambda.^2 .* (ftilde.^2 + Hftilde.^2)) # Eq. (C.4)
    dtilde = [dtilde0*ones(p-n,1); dtilde1]
end
return u * Diagonal(dtilde[:]) * u'
end


using DataFrames
using CSV
using Plots
#%%
# run(`./pi2`)
file1 = open("error_empirical.dat")
file2 = open("error_theo.dat")
df1=CSV.read(file1, header=false, delim=" ")
df2=CSV.read(file2, header=false, delim=" ")

plot(df1[1],df1[2], label="empirical", title="Monte Carlo Pi error")
plot!(df2[1],df2[2], label="theoretical")
xaxis!("N", xscale= :log10)
yaxis!("error", ylims=(1e-5,10), yscale= :log10)


const _basis{N} = SVector{N,SVector{N,Float64}}

"""
    _basis{N}()

Returns a set of `N` `N`-dimensional zero vectors, which can serve to indicate that the basis
vectors of a dataset arecons missing, or that the structure is aperiodic.
"""
function _basis{N}() where N
    return zeros(SVector{N,SVector{N,Float64}})
end

"""
    _allsame(itr)

Returns `true` if all the elements of an iterator are identical.
"""
_allsame(itr) = all(x -> x == itr[1], itr)

"""
    _tovectors(M::AbstractMatrix)

Converts a matrix of basis vectors to a vector of vectors. This is the preferred representation of
basis vectors throughout Crystalline.jl.
"""
_tovectors(M::AbstractMatrix) = [M[:,n] for n in 1:size(M)[2]]

"""
    _tomatrix(V::AbstractVector{<:AbstractVector})

Converts a vector of basis vectors to a matrix. The preferred represenation of basis vectors in
Crystalline.jl is a vector of vectors, so this should only be used when matrix-specific operations
are needed.
"""
_tomatrix(V::AbstractVector{<:AbstractVector}) = hcat(V...)

"""
    _is_linearly_independent(vecs::AbstractMatrix{<:Number}) -> Bool

Returns `true` if a matrix consists of linearly independent vectors, `false` otherwise.

This test is performed by checking that the rank of the matrix is equal to the smallest dimension
of the matrix.
"""
function _is_linearly_independent(vecs::AbstractMatrix{<:Number})
    return LinearAlgebra.rank(vecs) == minimum(size(vecs))
end

"""
    _is_linearly_independent(vecs::NTuple{N,NTuple{M,<:Number}}) -> Bool
    _is_linearly_independent(vecs::NTuple{M,<:Number}...) -> Bool
    _is_linearly_independent(vecs::AbstractVector{<:AbstractVector{<:Number}}) -> Bool

Returns `true` if a set of vectors is linearly independent, false otherwise.
"""
function _is_linearly_independent(vecs::NTuple{N,NTuple{M,<:Number}}) where {M,N}
    # if M is greater than N, they cannot be linearly independent
    M < N && return false
    mat = [vecs[n][m] for m = 1:M, n = 1:N]
    return _is_linearly_independent(mat)
end

_is_linearly_independent(vecs::NTuple{M,<:Number}...) where M = _is_linearly_independent(vecs)

function _is_linearly_independent(vecs::AbstractVector{<:AbstractVector{<:Number}})
    # Get number of vectors
    N = length(vecs)
    # Get length of each vector in the vector
    M = let l = [length(v) for v in vecs]
        _allsame(l) ? l[1] : throw(ErrorException("Vectors have inconsistent dimensions"))
    end
    # if M is greater than N, they cannot be linearly independent
    M < N && return false
    # Convert to a matrix for rank checking
    mat = [vecs[m][n] for n = 1:N, m = 1:M]
    return _is_linearly_independent(mat)
end

"""
    _reducecoords(B::AbstractMatrix{<:Number}, v::AbstractVector{<:Number})

Converts a vector `v` from Cartesian coordinates to reduced coordinates relative to the basis
vectors `B` of a unit cell, expressed as a collection of vectors.
"""
function _reducecoords(b::AbstractVector{AbstractVector{<:Number}}, v::AbstractVector{<:Number})
    B = hcat(b...)
    return inv(B) * v
end

"""
    printbasis(io::IO, basis::AbstractVector{<:AbstractVector{<:Real}})

Prints the basis vectors in the following format:

```
Basis vectors:
a:    2.847216    0.000000    0.000000
b:   -1.423608    2.465762   -0.000000
c:    0.000000    0.000000    4.538054
```
"""
function printbasis(io::IO, basis::AbstractVector{<:AbstractVector{<:Real}})
    tostr(x::Number) = lpad(@sprintf("%f", x), 12)
    # Check if basis vectors are empty or zero
    if isempty(basis) || any(all.(iszero, v for v in basis))
        println(io, "Aperiodic (no basis vectors specified)")
    else
        println(io, "Basis vectors:")
        for (n,v) in enumerate(basis)
            # '`' is 0x60, and all letters come after this in Unicode
            # e.g. 'a' is 0x61, 'b' is 0x62, 'c' is 0x63...
            println(io, ('`' + n) * ':' * join(tostr.(v)))
        end
    end
    return nothing
end


cd(@__DIR__)
using Pkg; Pkg.activate("."); Pkg.instantiate()
using Revise
using Zygote, Optim
using OrdinaryDiffEq, Flux, DiffEqFlux, LinearAlgebra, Plots
using DiffEqSensitivity
const EIGEN_EST = Ref(0.0f0)
const USE_GPU = Ref(false)

USE_GPU[] = false # the network is small enough such that CPU works just great

USE_GPU[] && (using CUDA)

_gpu(arg) = USE_GPU[] ? gpu(arg) : cpu(arg)
_cu(arg) = USE_GPU[] ? cu(arg) : identity(arg)

function getops(grid, T=Float32)
    N, dz = length(grid), step(grid)
    d = ones(N-2)
    dl = ones(N-3) # super/lower diagonal
    zv = zeros(N-2) # zero diagonal used to extend D* for boundary conditions

    # D1 first order discretization of ∂_z
    D1= diagm(-1 => -dl, 0 => d)
    D1_B = hcat(zv, D1, zv)
    D1_B[1,1] = -1
    D1_B = _cu((1/dz)*D1_B)

    # D2 discretization of ∂_zz
    D2 = diagm(-1 => dl, 0 => -2*d, 1 => dl)
    κ = 0.05
    D2_B = hcat(zv, D2, zv) #add space for the boundary conditions space for "ghost nodes"
    #we only solve for the interior space steps
    D2_B[1,1] = D2_B[end, end] = 1

    D2_B = _cu((κ/(dz^2)).*D2_B) #add the constant κ as the equation requires and finish the discretization

    # Boundary conditions matrix QQ
    Q = Matrix{Int}(I, N-2, N-2)
    QQ = _cu(vcat(zeros(1,N-2), Q, zeros(1,N-2)))

    D1 = D1_B * QQ
    D2 = D2_B * QQ
    EIGEN_EST[] = maximum(abs, eigvals(Matrix(D2)))
    return (D1=T.(D1), D2=T.(D2))
end

function getu0(grid, T=Float32)
    z = grid[2:N-1]
    f0 = z -> T(exp(-200*(z-0.75)^2))
    u0 = f0.(z) |> _gpu
end

function ode_i(u, p, t)
    Φ = u -> cos.(sin.(u.^3) .+ sin.(cos.(u.^2)))
    return p.D1*Φ(u) + p.D2*u
end

function ground_truth(grid, tspan)
    prob = ODEProblem(ode_i, u0, (tspan[1], tspan[2]+0.1), ops)
    sol = solve(prob, ROCK4(eigen_est = (integ)->integ.eigen_est = EIGEN_EST[]), abstol = 1e-9, reltol = 1e-9)
    return sol
end

N = 32
grid = range(0, 1, length = N)
tspan = (0.0f0, 1.5f0)
u0 = getu0(grid)
ops = getops(grid)
soldata = ground_truth(grid, tspan)

ann = Chain(Dense(30,8,tanh), Dense(8,30,tanh)) |> _gpu
pp, re = Flux.destructure(ann)
lyrs = Flux.params(pp)
function dudt_(u,p,t)
    Φ = re(p)
    return ops.D1*Φ(u) + ops.D2*u
end

function predict_adjoint(fullp)
    Array(concrete_solve(prob,
                         ROCK4(eigen_est = (integ)->integ.eigen_est = EIGEN_EST[]),
    u0, fullp, saveat = saveat))
end

function loss_adjoint(fullp)
    pre = predict_adjoint(fullp)
    sum(abs2, training_data - pre)
end

function cb(opt_state:: Optim.OptimizationState)
    cur_pred = collect(predict_adjoint(opt_state.metadata["x"]))
    n = size(training_data, 1)
    pl = scatter(1:n,training_data[:,10],label="data", legend =:bottomright,title="Spatial Plot at t=$(saveat[10])")
    scatter!(pl,1:n,cur_pred[:,10],label="prediction")
    pl2 = scatter(saveat,training_data[N÷2,:],label="data", legend =:bottomright, title="Timeseries Plot at Middle X")
    scatter!(pl2,saveat,cur_pred[N÷2,:],label="prediction")
    display(plot(pl, pl2, size=(600, 300)))
    display(opt_state.value)
    false
end

cb(trace::Optim.OptimizationTrace) = cb(last(trace))

saveat = range(tspan..., length = 30) #time range
prob = ODEProblem{false}(dudt_,u0,tspan,pp)
training_data = _cu(soldata(saveat))
concrete_solve(prob, ROCK4(eigen_est = (integ)->integ.eigen_est = EIGEN_EST[]), u0, pp)
loss_adjoint(pp)

function loss_adjoint_gradient!(G, fullp)
    G .= Zygote.gradient(loss_adjoint, fullp)[1]
end

result =  optimize(loss_adjoint, loss_adjoint_gradient!, pp, BFGS(), Optim.Options(extended_trace=true,callback = cb))

prob2 = ODEProblem{false}(dudt_,u0,(0f0,10f0),pp)
@time full_sol = solve(prob2,
                       ROCK2(eigen_est = (integ)->integ.eigen_est = EIGEN_EST[]),
                       saveat = saveat, abstol=1e-4, reltol=1e-2)

cur_pred = collect((predict_adjoint(result.minimizer)))
n = size(training_data, 1)
pl = scatter(1:n,training_data[:,10],label="data", legend =:bottomright)
scatter!(pl,1:n,cur_pred[:,10],label="prediction",title="Spatial Plot at t=$(saveat[10])")
pl2 = scatter(saveat,training_data[N÷2,:],label="data", legend =:bottomright, title="Time Series Plot: Middle X")
scatter!(pl2,saveat,cur_pred[N÷2,:],label="prediction")
plot(pl, pl2, size=(600, 300))
savefig("npde_fit.pdf")


### BatchBernoulli

struct BatchBernoulli{T<:AbstractArray{<:AbstractFloat}} <: DiscreteBatchDistribution
    p::T
end

Broadcast.broadcastable(b::BatchBernoulli) = Ref(b)

Bernoulli(p::AbstractArray) = BatchBernoulli(p)

function logpdf(b::BatchBernoulli, x)
    ϵ = eps(b.p)
    lp = x .* log.(b.p .+ ϵ) + (1 .- x) .* log.(1 + ϵ .- b.p)
    return lp
end

function rand(rng::AbstractRNG, b::BatchBernoulli, dims::Int...)
    u = randsimilar(rng, b.p, dims...)
    x = convert.(eltype(b.p), b.p .> u)
    return x
end

mean(b::BatchBernoulli) = b.p

function var(b::BatchBernoulli)
    p = mean(b)
    return p .* (1 .- p)
end

function mode(b::BatchBernoulli)
    T = eltype(b.p)
    return convert.(T, b.p .> T(0.5))
end

function kldiv(
    b1::BatchBernoulli{<:AbstractArray{T}},
    b2::BatchBernoulli{<:AbstractArray{T}}
) where {T<:AbstractFloat}
    ϵ = eps(T)
    kl = b1.p .* (log.(b1.p .+ ϵ) .- log.(b2.p .+ ϵ)) .+
         (1 .- b1.p) .* (log.(1 + ϵ .- b1.p) .- log.(1 + ϵ .- b2.p))
    return kl
end

### BatchBernoulliLogit

struct BatchBernoulliLogit{T<:AbstractArray{<:AbstractFloat}} <: DiscreteBatchDistribution
    logitp::T
end

Broadcast.broadcastable(bl::BatchBernoulliLogit) = Ref(bl)

BernoulliLogit(logitp) = BatchBernoulliLogit(logitp)

logpdf(bl::BatchBernoulliLogit, x) = x .* bl.logitp .- log.(1 .+ exp.(bl.logitp))

mean(bl::BatchBernoulliLogit) = StatsFuns.logistic.(bl.logitp)

function var(b::BatchBernoulliLogit)
    p = mean(b)
    return p .* (1 .- p)
end

mode(bl::BatchBernoulliLogit) = mode(Bernoulli(mean(bl)))


using LinearAlgebraicRepresentation
using Plasm, SparseArrays
Lar = LinearAlgebraicRepresentation
using Debugger

V = [0.0 0.0 0.0; 1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0; 0.5 0.25 0.25; 0.25 0.5 0.25; 0.25 0.25 0.5; 0.25 0.25 0.25; 1.25 0.25 0.25; 0.25 1.25 0.25; 0.25 0.25 1.25]
ld_bounds = ([1, 2, 3, 1, 4, 5, 2, 4, 6, 3, 5, 6, 7, 8, 9, 7, 8, 9, 7, 10, 12, 7, 11, 13, 14, 8, 10, 15, 8, 11, 16, 17, 9, 12, 15, 9, 13, 16, 18, 14, 17, 18], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12], Int8[1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1])
angles = Array{Int64,1}[[2, 1], [1, 3], [4, 1], [3, 2], [2, 4], [4, 3], [7, 4, 5, 6], [9, 8, 4, 5], [11, 4, 5, 10], [8, 6], [9, 7], [10, 6], [7, 11], [7, 12], [8, 10], [11, 9], [9, 12], [12, 11]]

sigma =1

function get_seed_cell(ld_cellsnum, count_marks)
	s = -1
	for i in 1:ld_cellsnum
		if count_marks[i] == 0
			return i
		elseif count_marks[i] == 1 && s < 0
			s = i
		end
	end
	return s
end

function nextprev(lld::Int64, ld::Int64, norp)
	as = angles[lld]
	#ne = findfirst(as, ld)  (findfirst(isequal(v), A), 0)[1]
	ne = (findfirst(isequal(ld), as), 0)[1]
	while true
		ne += norp
		if ne > length(as)
			ne = 1
		elseif ne < 1
			ne = length(as)
		end

		if count_marks[as[ne]] < 2
			break
		end
	end
	as[ne]
end

function _minimal_cycles(V::Lar.Points,ld_bounds::Lar.ChainOp)
#@show V
#@show ld_bounds
    lld_cellsnum, ld_cellsnum = size(ld_bounds)
    count_marks = zeros(Int8, ld_cellsnum)
    dir_marks = zeros(Int8, ld_cellsnum)
    d_bounds = spzeros(Int8, ld_cellsnum, 0)

    angles = Array{Array{Int64, 1}, 1}(undef, lld_cellsnum)

    for lld in 1:lld_cellsnum
        as = []
        for ld in ld_bounds[lld, :].nzind
            push!(as, (ld, angles_fn(lld, ld)))
        end
        sort!(as, lt=(a,b)->a[2]<b[2])
        as = map(a->a[1], as)
        angles[lld] = as
    end

    while (sigma = get_seed_cell(ld_cellsnum, count_marks)) > 0
        if verbose
            print(Int(floor(50 * sum(count_marks) / ld_cellsnum)), "%\r")
        end

        c_ld = spzeros(Int8, ld_cellsnum)
        if count_marks[sigma] == 0
            c_ld[sigma] = 1
        else
            c_ld[sigma] = -dir_marks[sigma]
        end
        c_lld = ld_bounds*c_ld
        while c_lld.nzind != []
			#corolla = spzeros(Int8, ld_cellsnum)
			corolla = zeros(Int64, ld_cellsnum)
            for tau in c_lld.nzind
                b_ld = ld_bounds[tau, :]
                pivot = intersect(c_ld.nzind, b_ld.nzind)[1]
                adj = nextprev(tau, pivot, sign(-c_lld[tau]))
                corolla[adj] = c_ld[pivot]
                if b_ld[adj] == b_ld[pivot]
                    corolla[adj] *= -1
                end
@show corolla
            end
            c_ld += corolla
            c_lld = ld_bounds*c_ld
@show c_lld
        end
        map(s->count_marks[s] += 1, c_ld.nzind)
        map(s->dir_marks[s] = c_ld[s], c_ld.nzind)
        d_bounds = [d_bounds c_ld]
@show d_bounds
    end
    return d_bounds
end

function minimal_cycles(angles_fn::Function, verbose=false)
    return _minimal_cycles
end

EF = SparseArrays.sparse(ld_bounds)


# FUNCTIONS THAT DEFINE INDICES

# define the index function to get the index of an element in the array
function index(
			i1::Int64, i2::Int64,
			N1::Int64, N2::Int64
		) :: Int64
	return (i1-1)*N2 + i2
end
function index(
			i1::Int64, i2::Int64, i3::Int64,
			N1::Int64, N2::Int64, N3::Int64
		) :: Int64
	return N3*((i1-1)*N2+i2-1) + i3
end
function index(
			i1::Int64, i2::Int64, i3::Int64, i4::Int64,
			N1::Int64, N2::Int64, N3::Int64, N4::Int64
		) :: Int64
	return N4*(N3*((i1-1)*N2+i2-1) + i3 -1) + i4
end

# function to constrain an index
# returns (index_constrained, offset)
# s.t. index = index_constraint + offset*index_max
# To be replaced by ic = div(.,.) and offset = rem(.,.) ???
# apparently not faster...
function getConstrainedIndex(
		index		::Int64,
		index_max	::Int64
	) :: Tuple{Int64, Int64}
	# specify the initial offset as 0
	offset = 0 :: Int64
	# check that the index is bigger than the minimum value
	while index < 1
		index += index_max
		offset += -1
	end
	# check that the index is smaller than the maximum value
	while index > index_max
		index -= index_max
		offset += 1
	end
	# return both index and offset
	return (index, offset)
end


x = create_var(3, 4)
y = x'
test_expr(y, (x,))

x = create_var(10, 1)
y = x''
test_expr(y, (x,))

info("All transpose tests passed")


### A Pluto.jl notebook ###
# v0.15.1

using Markdown
using InteractiveUtils

# ╔═╡ 6617f01e-f252-11eb-1696-0f9f9b01245b
using MixedModels, PackageAnalyzer

# ╔═╡ 8be846d1-0872-41c0-9a97-776f8ade7185
using CairoMakie, MixedModelsMakie

# ╔═╡ ccf3aa24-756c-445a-a22c-99c748ccbc91
html"<button onclick='present()'>presentation mode</button>"

# ╔═╡ f9a85d0b-5e59-4dc1-83f1-48683dcb6acf
md"""
# Fitting mixed-models faster with MKL

Fitting a linear mixed-effects model (LMM) involves setting up a numerical representation of the model from which the objective function can be evaluated for a given value of the parameters.
The evaluation involves a considerable amount of linear algebra.

Intel's [Math Kernel Library](https://en.wikipedia.org/wiki/Math_Kernel_Library) provides an accelerated version of the Basic Linear Algebra Subroutines (BLAS) and some LAPACK subroutines.

Julia v1.7.0 will introduce a framework called `libblastrampoline` that allows for dynamic switching between BLAS libraries.
The binary [downloads](https://julialang.org/downloads) of Julia come with the [OpenBLAS](https://en.wikipedia.org/wiki/OpenBLAS) implementation, which is the default.  We will illustrate using MKL with a beta-test version of Julia v1.7.0

The active parts of this notebook use OpenBLAS.
We will simply quote the results from [lme4](https://github.com/lme4/lme4) for R and for [MixedModels](https://github.com/JuliaStats/MixedModels.jl) for Julia.
"""

# ╔═╡ 3052b69a-a9a8-4633-9df8-b1a70bbcabb7
md"""
## Linear mixed-effects models
- A linear mixed-effects (LMM) model allows for modeling several sources of variability (or *variance components*) in the response.
- A common example in Psychology or Linguistics would be a study in which each of several subjects is exposed to each of several items (e.g. words) under different experimental conditions, e.g. clear vs blurred image, primed by earlier exposure or not, and the response measured is the reaction time to, say, indicate if the image is a word or not.
- We expect an underlying variability in the response but also subject-to-subject variability and item-to-item variability.
- *Fixed-effects* are coefficients associated with repeatable conditions (e.g. clear vs blurred).
- *Random-effects* are coefficients in the linear predictor associated with *blocking factors* such as `subj` or `item` which are considered a selection from a population of possible values.
- *Mixed-effects* refers to a model with both fixed-effects parameters and random effects.
- The lme4 package for R allows for fitting models with *crossed* grouping factors for the random effects.  It is widely used because of this capability.
"""

# ╔═╡ ae102e47-1716-4861-84e5-76c19c054b6b
md"""
## An example
- Data from experiment 1 of [Masson, Rabe & Kliegl, 2017](https://doi.org/10.3758/s13421-016-0666-z) are available in [Arrow format](https://arrow.apache.org) with the [MixedModels package](https://github.com/JuliaStats/MixedModels.jl) for Julia.
- The data are stored in a directory in the `Artifacts` folder under the main Julia directory, which on my Linux system is `~/.julia/artifacts/`.
- The particular folder name is a long sequence of characters called a *hash* or *secure hash algorithm (SHA)*.  This particular SHA is in the [Artifacts.toml](https://github.com/JuliaStats/MixedModels.jl/blob/main/Artifacts.toml) file for the *MixedModels* package.
- The arrow file can be read in R using the `arrow` package or in Python/Pandas with the `pyarrow` package.  In both of these packages the `arrow` file format is called `feather` because it is also the Feather version 2 format.
"""

# ╔═╡ cf44a69e-7628-43f3-b395-05ebf62ca648
md"""
## Fitting a model using `lme4`
```
> library(lme4)
Loading required package: Matrix
> df <- read_feather("~/.julia/artifacts/6d31be16850ffb7b5c0b80cb25f85b5c10df6546/mrk17_exp1.arrow")
> str(df)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':	16409 obs. of  9 variables:
 $ subj : Factor w/ 73 levels "S01","S02","S03",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ item : Factor w/ 240 levels "CAKE","PARTY",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ trial: int  2 3 5 9 10 11 15 21 22 24 ...
 $ F    : Factor w/ 2 levels "LF","HF": 1 2 2 2 2 2 2 1 1 2 ...
 $ P    : Factor w/ 2 levels "unr","rel": 1 1 2 2 1 2 2 1 1 2 ...
 $ Q    : Factor w/ 2 levels "deg","clr": 1 2 2 1 1 2 1 1 2 2 ...
 $ lQ   : Factor w/ 2 levels "deg","clr": 1 1 1 1 1 1 1 2 1 1 ...
 $ lT   : Factor w/ 2 levels "NW","WD": 1 2 1 1 2 2 1 1 2 1 ...
 $ rt   : int  794 506 491 486 482 542 766 993 552 499 ...
> contrasts(df$F) <- contr.helmert(2)
> contrasts(df$P) <- contr.helmert(2)
> contrasts(df$Q) <- contr.helmert(2)
> contrasts(df$lQ) <- contr.helmert(2)
> contrasts(df$lT) <- contr.helmert(2)
> system.time(m6 <- lmer(1000/rt ~ 1+F*P*Q*lQ*lT+(1+P+Q+lQ+lT|item)+(1+F+P+Q+lQ+lT|subj), df, REML=FALSE))
boundary (singular) fit: see ?isSingular
   user  system elapsed
603.279   0.023 603.317
```
"""

# ╔═╡ d87d83aa-be17-4f14-b8ac-78a674db11b3
md"""
## Model summary
```
> summary(m6)
Linear mixed model fit by maximum likelihood  ['lmerMod']
Formula: 1000/rt ~ 1 + F * P * Q * lQ * lT + (1 + P + Q + lQ + lT | item) +
    (1 + F + P + Q + lQ + lT | subj)
   Data: df

     AIC      BIC   logLik deviance df.resid
  7285.8   7817.4  -3573.9   7147.8    16340

Scaled residuals:
    Min      1Q  Median      3Q     Max
-4.6350 -0.5990  0.0874  0.6620  5.5168

Random effects:
 Groups   Name        Variance  Std.Dev. Corr
 item     (Intercept) 3.202e-03 0.056583
          P1          1.250e-04 0.011179  0.05
          Q1          1.582e-04 0.012577  0.36  0.40
          lQ1         8.777e-06 0.002963  0.76  0.33 -0.10
          lT1         1.573e-04 0.012542 -0.11 -0.89  0.00 -0.60
 subj     (Intercept) 3.061e-02 0.174957
          F1          3.838e-05 0.006195  0.39
          P1          1.282e-04 0.011324  0.35  0.95
          Q1          7.899e-04 0.028105  0.41  0.50  0.72
          lQ1         1.153e-04 0.010738  0.06  0.02  0.22  0.58
          lT1         1.044e-03 0.032314  0.26 -0.14 -0.01  0.37  0.50
 Residual             8.574e-02 0.292810
Number of obs: 16409, groups:  item, 240; subj, 73

Fixed effects:
                   Estimate Std. Error t value
(Intercept)       1.637e+00  2.093e-02  78.248
F1                1.925e-02  4.375e-03   4.401
P1                1.883e-02  2.747e-03   6.856
...
```
"""

# ╔═╡ e2306a42-dcb6-40e4-811f-7c5bb26e0c20
md"## The same model fit with MixedModels.jl"

# ╔═╡ cfb22981-bb2f-43fb-8dd4-59b62f3eed9c
mrk17 = MixedModels.dataset(:mrk17_exp1) # sample data set

# ╔═╡ 27647edb-a0c6-451a-93d8-4f8415be786b
contr = Dict(              # set the contrasts
	:subj => Grouping(),
	:item => Grouping(),
	:F => HelmertCoding(),
	:P => HelmertCoding(),
	:Q => HelmertCoding(),
	:lQ => HelmertCoding(),
	:lT => HelmertCoding(),
);

# ╔═╡ 26b3f46f-4dee-4e60-99ed-892137126c93
m6frm = @formula 1000/rt ~ 1+F*P*Q*lQ*lT + (1+P+Q+lQ+lT|item) + (1+F+P+Q+lQ+lT|subj);

# ╔═╡ 9a303a89-dafc-4736-a711-ccb19b0671fd
md"## First model fit"

# ╔═╡ 71b3b7a0-2f29-4bf0-b10b-d06fc8805b34
m6 = fit(MixedModel, m6frm, mrk17; contrasts=contr)

# ╔═╡ f96dd303-e501-4343-939f-2b9ddc05ee8a
md"""
## Comparative speed
- The first fit in Julia is somewhat slow (a little over 60 seconds on my laptop) because of the JIT compilation.
- The fit with `lmer` from `lme4` took over 600 seconds on my laptop.  Various options could have been used to speed up the fit but we just used the "vanilla" version.
- A progress indicator is shown during the optimization to minimize the objective (negative twice the log-likelihood) with respect to the parameters.  It doesn't appear in the Pluto output.  In this case it was
```
Minimizing 1312  Time: 0 Time: 0:00:34 (26.29 ms/it)
      From worker 3:	  objective:  7147.682158526245
```
"""

# ╔═╡ 349652e8-39ff-466d-9eb3-bf8af4cd3e33
md"""
## Model fits after the first will be faster
- For illustration we fit the same model but, in practice, we may be fitting alternative models
"""

# ╔═╡ 41eb523c-d897-4a87-9bf5-89cc2802c29e
fit(MixedModel, m6frm, mrk17; contrasts=contr);

# ╔═╡ ecded3b9-5a1f-4f42-9f05-b29a7cf803e7
md"""
- This takes about 33 seconds on my laptop.  The progress indicator ended up at
```
Minimizing 1312  Time: 0 Time: 0:00:32 (24.82 ms/it)
      From worker 3:	  objective:  7147.682158526245
```
- The time to do the optimizing is essentially the same as before but the JIT compilation no longer occurs.
"""

# ╔═╡ 191901d3-ea42-4e5c-8582-285dd5af4652
md"""
## Julia v1.7.0 is faster, especially with MKL
```
julia> m6 = fit(MixedModel, m6frm, mrk17; contrasts=contr);
Minimizing 1506  Time: 0 Time: 0:00:18 (12.51 ms/it)

julia> m6.objective
7147.55033778133

julia> using MKL

julia> m6 = fit(MixedModel, m6frm, mrk17; contrasts=contr);
Minimizing 1316  Time: 0 Time: 0:00:05 ( 4.28 ms/it)

julia> m6.objective
7147.550374727961
```
"""

# ╔═╡ 548589e2-5299-4ad1-a0ec-22ad3936d363
md"""
## Why is the Julia code so much faster?
- It is not the optimizer per se - lme4 and MixedModels use the same optimizer (BOBYQA) and the same implementation, [NLopt](https://github.com/stevengj/nlopt)
- Method instances are compiled with the JIT compiler (even better in v1.7.0)
- The flexibility of the system allows for things like swapping in another (binary) BLAS library
- The implementation in MixedModels is similar to that in lme4 but a bit more advanced
    + finer grain control of the linear algebra b/c of Julia's [LinearAlgebra package](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/)
    + I stumbled upon a cleaner way to evaluate a certain quantity needed to evaluate the objective
    + I don't think I would have been able to do this in the R implementation. MixedModels.jl is 100% Julia whereas lme4 is a hodge-podge of R, C, C++, Rcpp, RcppEigen, etc. (my fault, entirely - don't blame my co-authors)

## Characteristics of the MixedModels package
"""

# ╔═╡ 40b0b7e3-88d7-47ea-bb46-e0dfabefc4e1
analyze("MixedModels")

# ╔═╡ 03cdeea6-5f6b-4095-8ae3-3600906df570
md"""
## Internal representation is more fine-grained
- uses a blocked matrix representation for a penalized least squares problem rather than a generic sparse matrix
"""

# ╔═╡ 61cb5943-a6e9-4022-bb01-68b86df6fe36
BlockDescription(m6)

# ╔═╡ b151e0fb-b28b-41b0-aef4-38a81a7dfa78
sparseL(m6; full=true)

# ╔═╡ ab4b74a3-8e97-48a5-8cf8-91fdea464aa3
md"""
## Diagnostic plots
- One of the strengths of R is the data and diagnostic graphics
- Graphics packages take a long time to develop.  Julia graphics are still comparatively early stage.
- We do have some diagnostic plots for mixed-effects models in the `MixedModelsMakie` package.
"""

# ╔═╡ 8781b4e9-c2f0-4a44-a29f-4cbc8eb7d298
CairoMakie.activate!(type="svg")

# ╔═╡ 81001f33-3f66-401e-815a-a46e4d4309ab
md"## Shrinkage plots"

# ╔═╡ d6aada8f-511f-4a74-a8cd-19ef88512e65
shrinkageplot(m6) # random-effects by item

# ╔═╡ adaaae43-5c43-45e1-9bd7-3f4fb9efc768
md"## Shrinkage plots by subject"

# ╔═╡ ac2f5d62-49be-4850-90f0-95c58edece02
shrinkageplot(m6, :subj)

# ╔═╡ 7ce2e0d0-b3df-4006-9b07-70b64da3b29a
md"""
## Summary of my experiences
- After adjusting to the language, development of a compute-intensive package in Julia was much easier than in R
- Julia package is 100% Julia, R package was written in several languages
- Maintenance of the Julia package is more straightforward because tools (documentation, testing, continuous integration, pull requests, issues) are native.
- Performance is generally better in Julia
- Performance tools (profiling execution, memory allocation profiling) are native.
- Changes in the overall system can bring big performance bonuses.
- I can experiment in Julia much more easily than in a static language.
- Auxillary tools (formula language, graphics packages) needed polishing but are coming along.
- See also [Kyla McConnell's experiences](https://github.com/kyla-mcconnell/juliaR)
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
MixedModels = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316"
MixedModelsMakie = "b12ae82c-6730-437f-aff9-d2c38332a376"
PackageAnalyzer = "e713c705-17e4-4cec-abe0-95bf5bf3e10c"

[compat]
CairoMakie = "~0.6.2"
MixedModels = "~4.0.0"
MixedModelsMakie = "~0.3.2"
PackageAnalyzer = "~0.1.0"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.6.2"
manifest_format = "2.0"

[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "485ee0867925449198280d4af84bdb46a2a404d0"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.0.1"

[[deps.Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[deps.Animations]]
deps = ["Colors"]
git-tree-sha1 = "e81c509d2c8e49592413bfb0bb3b08150056c79d"
uuid = "27a7e980-b3e6-11e9-2bcd-0b925532e340"
version = "0.4.1"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[deps.ArrayInterface]]
deps = ["IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"]
git-tree-sha1 = "2e004e61f76874d153979effc832ae53b56c20ee"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "3.1.22"

[[deps.Arrow]]
deps = ["ArrowTypes", "BitIntegers", "CodecLz4", "CodecZstd", "DataAPI", "Dates", "Mmap", "PooledArrays", "SentinelArrays", "Tables", "TimeZones", "UUIDs"]
git-tree-sha1 = "b00e6eaba895683867728e73af78a00218f0db10"
uuid = "69666777-d1a9-59fb-9406-91d4454c9d45"
version = "1.6.2"

[[deps.ArrowTypes]]
deps = ["UUIDs"]
git-tree-sha1 = "a0633b6d6efabf3f76dacd6eb1b3ec6c42ab0552"
uuid = "31f734f8-188a-4ce0-8406-c8a06bd891cd"
version = "1.2.1"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "a4d07a1c313392a77042855df46c5f534076fab9"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.0.0"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.BenchmarkTools]]
deps = ["JSON", "Logging", "Printf", "Statistics", "UUIDs"]
git-tree-sha1 = "c31ebabde28d102b602bada60ce8922c266d205b"
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
version = "1.1.1"

[[deps.BitIntegers]]
deps = ["Random"]
git-tree-sha1 = "f0853a9d2cf2cf4f9fbd98c6e19ff1627e65a9a7"
uuid = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1"
version = "0.2.4"

[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.6+5"

[[deps.CEnum]]
git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.1"

[[deps.Cairo]]
deps = ["Cairo_jll", "Colors", "Glib_jll", "Graphics", "Libdl", "Pango_jll"]
git-tree-sha1 = "d0b3f8b4ad16cb0a2988c6788646a5e6a17b6b1b"
uuid = "159f3aea-2a34-519c-b102-8c37f9878175"
version = "1.0.5"

[[deps.CairoMakie]]
deps = ["Base64", "Cairo", "Colors", "FFTW", "FileIO", "FreeType", "GeometryBasics", "LinearAlgebra", "Makie", "SHA", "StaticArrays"]
git-tree-sha1 = "68628add03c2c7c2235834902aad96876f07756a"
uuid = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
version = "0.6.2"

[[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "e2f47f6d8337369411569fd45ae5753ca10394c6"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.0+6"

[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "f53ca8d41e4753c41cdafa6ec5f7ce914b34be54"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "0.10.13"

[[deps.CodecBzip2]]
deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"]
git-tree-sha1 = "2e62a725210ce3c3c2e1a3080190e7ca491f18d7"
uuid = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
version = "0.7.2"

[[deps.CodecLz4]]
deps = ["Lz4_jll", "TranscodingStreams"]
git-tree-sha1 = "59fe0cb37784288d6b9f1baebddbf75457395d40"
uuid = "5ba52731-8f18-5e0d-9241-30f10d1ec561"
version = "0.4.0"

[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

[[deps.CodecZstd]]
deps = ["TranscodingStreams", "Zstd_jll"]
git-tree-sha1 = "d19cd9ae79ef31774151637492291d75194fc5fa"
uuid = "6b39b394-51ab-5f42-8807-6242bab2b4c2"
version = "0.7.0"

[[deps.ColorBrewer]]
deps = ["Colors", "JSON", "Test"]
git-tree-sha1 = "61c5334f33d91e570e1d0c3eb5465835242582c4"
uuid = "a2cac450-b92f-5266-8821-25eda20663c8"
version = "0.4.0"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random", "StaticArrays"]
git-tree-sha1 = "ed268efe58512df8c7e224d2e170afd76dd6a417"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.13.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"]
git-tree-sha1 = "42a9b08d3f2f951c9b283ea427d96ed9f1f30343"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.5"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[deps.Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "344f143fa0ec67e47917848795ab19c6a455f32c"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.32.0"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[deps.Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[deps.Crayons]]
git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.0.4"

[[deps.DataAPI]]
git-tree-sha1 = "ee400abb2298bd13bfc3df1c412ed228061a2385"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.7.0"

[[deps.DataFrames]]
deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "d785f42445b63fc86caa08bb9a9351008be9b765"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.2.2"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "4437b64df1e0adccc3e5d1adbc3ac741095e4677"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.9"

[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[deps.Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns"]
git-tree-sha1 = "3889f646423ce91dd1055a76317e9a1d3a23fff1"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.11"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "a32185f5428d3986f47c2ab78b1f216d5e6cc96f"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.5"

[[deps.Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[deps.EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "92d8f9f208637e8d2d28c664051a00569c01493d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.1.5+1"

[[deps.EllipsisNotation]]
deps = ["ArrayInterface"]
git-tree-sha1 = "8041575f021cba5a099a456b4163c9a08b566a02"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.1.0"

[[deps.Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[deps.ExprTools]]
git-tree-sha1 = "b7e3d17636b348f005f11040025ae8c6f645fe92"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.6"

[[deps.FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[deps.FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.3.1+4"

[[deps.FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "f985af3b9f4e278b1d24434cbb546d6092fca661"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.4.3"

[[deps.FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3676abafff7e4ff07bbd2c42b3d8201f31653dcc"
uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a"
version = "3.3.9+8"

[[deps.FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "256d8e6188f3f1ebfa1a5d17e072a0efafa8c5bf"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.10.1"

[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "8c8eac2af06ce35973c3eadb4ab3243076a408e7"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.12.1"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "35895cf184ceaab11fd778b4590144034a167a2f"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.1+14"

[[deps.Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[deps.FreeType]]
deps = ["CEnum", "FreeType2_jll"]
git-tree-sha1 = "cabd77ab6a6fdff49bfd24af2ebe76e6e018a2b4"
uuid = "b38be410-82b0-50bf-ab77-7b57e271db43"
version = "4.0.0"

[[deps.FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "cbd58c9deb1d304f5a245a0b7eb841a2560cfec6"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.1+5"

[[deps.FreeTypeAbstraction]]
deps = ["ColorVectorSpace", "Colors", "FreeType", "GeometryBasics", "StaticArrays"]
git-tree-sha1 = "d51e69f0a2f8a3842bca4183b700cf3d9acce626"
uuid = "663a7486-cb36-511b-a19d-713bb74d65c9"
version = "0.9.1"

[[deps.FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

[[deps.GLM]]
deps = ["Distributions", "LinearAlgebra", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "StatsModels"]
git-tree-sha1 = "f564ce4af5e79bb88ff1f4488e64363487674278"
uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
version = "1.5.1"

[[deps.GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "4136b8a5668341e58398bb472754bff4ba0456ff"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.3.12"

[[deps.Gettext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "8c14294a079216000a0bdca5ec5a447f073ddc9d"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.20.1+7"

[[deps.Git]]
deps = ["Git_jll"]
git-tree-sha1 = "d7bffc3fe097e9589145493c08c41297b457e5d0"
uuid = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2"
version = "1.2.1"

[[deps.GitHub]]
deps = ["Base64", "Dates", "HTTP", "JSON", "MbedTLS", "Sockets", "SodiumSeal"]
git-tree-sha1 = "9e62f3eae4a2514d1de65cc2ac9d1669032a4595"
uuid = "bc5e4493-9b4d-5f90-b8aa-2b2bcaad7a26"
version = "5.6.0"

[[deps.Git_jll]]
deps = ["Artifacts", "Expat_jll", "Gettext_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "Libiconv_jll", "OpenSSL_jll", "PCRE2_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "33be385f3432a5a5b7f6965af9592d4407f3167f"
uuid = "f8c6e375-362e-5223-8a59-34ff63f689eb"
version = "2.31.0+0"

[[deps.Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "04690cc5008b38ecbdfede949220bc7d9ba26397"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.59.0+4"

[[deps.Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "2c1cf4df419938ece72de17f368a021ee162762e"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.0"

[[deps.Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+0"

[[deps.GridLayoutBase]]
deps = ["GeometryBasics", "InteractiveUtils", "Match", "Observables"]
git-tree-sha1 = "d44945bdc7a462fa68bb847759294669352bd0a4"
uuid = "3955a311-db13-416c-9275-1d80ed98e5e9"
version = "0.5.7"

[[deps.Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[deps.HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "44e3b40da000eab4ccb1aecdc4801c040026aeb5"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.13"

[[deps.HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Gettext_jll", "Glib_jll", "Graphite2_jll", "ICU_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "90bed5fc61d12d10832ebf988988104888eebaca"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.6.1+10"

[[deps.ICU_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6ce9cf3c5490b045710d60ac3fd2fe48188846b3"
uuid = "a51ab1cf-af8e-5615-a023-bc2c838bba6b"
version = "67.1.0+3"

[[deps.IfElse]]
git-tree-sha1 = "28e837ff3e7a6c3cdb252ce49fb412c8eb3caeef"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.0"

[[deps.ImageCore]]
deps = ["AbstractFFTs", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Graphics", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "Reexport"]
git-tree-sha1 = "75f7fea2b3601b58f24ee83617b528e57160cbfd"
uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534"
version = "0.9.1"

[[deps.ImageIO]]
deps = ["FileIO", "Netpbm", "PNGFiles", "TiffImages", "UUIDs"]
git-tree-sha1 = "d067570b4d4870a942b19d9ceacaea4fb39b69a1"
uuid = "82e4d734-157c-48bb-816b-45c225c6df19"
version = "0.5.6"

[[deps.IndirectArrays]]
git-tree-sha1 = "c2a145a145dc03a7620af1444e0264ef907bd44f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "0.5.1"

[[deps.Inflate]]
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.2"

[[deps.IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[deps.IntelOpenMP_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d979e54b71da82f3a65b62553da4fc3d18c9004c"
uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0"
version = "2018.0.3+2"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.Interpolations]]
deps = ["AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"]
git-tree-sha1 = "1470c80592cf1f0a35566ee5e93c5f8221ebc33a"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.3"

[[deps.IntervalSets]]
deps = ["Dates", "EllipsisNotation", "Statistics"]
git-tree-sha1 = "3cc368af3f110a767ac786560045dceddfc16758"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.5.3"

[[deps.InvertedIndices]]
deps = ["Test"]
git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.0.0"

[[deps.Isoband]]
deps = ["isoband_jll"]
git-tree-sha1 = "f9b6d97355599074dc867318950adaa6f9946137"
uuid = "f1662d9f-8043-43de-a69a-05efc1cc6ff4"
version = "0.1.1"

[[deps.IterTools]]
git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.3.0"

[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[deps.JSON3]]
deps = ["Dates", "Mmap", "Parsers", "StructTypes", "UUIDs"]
git-tree-sha1 = "b3e5984da3c6c95bcf6931760387ff2e64f508f3"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.9.1"

[[deps.JSONSchema]]
deps = ["HTTP", "JSON", "ZipFile"]
git-tree-sha1 = "b84ab8139afde82c7c65ba2b792fe12e01dd7307"
uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
version = "0.3.3"

[[deps.KernelDensity]]
deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"]
git-tree-sha1 = "591e8dc09ad18386189610acafb970032c519707"
uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
version = "0.6.3"

[[deps.LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[deps.LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[deps.LibVPX_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "12ee7e23fa4d18361e7c2cde8f8337d4c3101bc7"
uuid = "dd192d2f-8180-539f-9fb4-cc70b1dcf69a"
version = "1.10.0+0"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

[[deps.Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[deps.Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[deps.Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[deps.Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[deps.Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[deps.LicenseCheck]]
deps = ["licensecheck_jll"]
git-tree-sha1 = "e98bc9e1f773123cfdb1fa3d7a4c898e1f030341"
uuid = "726dbf0d-6eb6-41af-b36c-cd770e0f00cc"
version = "0.2.2"

[[deps.LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "LinearAlgebra"]
git-tree-sha1 = "7bd5f6565d80b6bf753738d2bc40a5dfea072070"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.2.5"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Lz4_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "5d494bc6e85c4c9b626ee0cab05daa4085486ab1"
uuid = "5ced341a-0733-55b8-9ab6-a4889d929147"
version = "1.9.3+0"

[[deps.MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "c253236b0ed414624b083e6b72bfe891fbd2c7af"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2021.1.1+1"

[[deps.Makie]]
deps = ["Animations", "Artifacts", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "Contour", "Distributions", "DocStringExtensions", "FFMPEG", "FileIO", "FixedPointNumbers", "Formatting", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageIO", "IntervalSets", "Isoband", "KernelDensity", "LinearAlgebra", "MakieCore", "Markdown", "Match", "Observables", "Packing", "PlotUtils", "PolygonOps", "Printf", "Random", "Serialization", "Showoff", "SignedDistanceFields", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "UnicodeFun"]
git-tree-sha1 = "82f9d9de6892e5470372720d23913d14a08991fd"
uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
version = "0.14.2"

[[deps.MakieCore]]
deps = ["Observables"]
git-tree-sha1 = "7bcc8323fb37523a6a51ade2234eee27a11114c8"
uuid = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
version = "0.1.3"

[[deps.MappedArrays]]
git-tree-sha1 = "18d3584eebc861e311a552cbb67723af8edff5de"
uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
version = "0.4.0"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.Match]]
git-tree-sha1 = "5cf525d97caf86d29307150fcba763a64eaa9cbe"
uuid = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf"
version = "1.1.0"

[[deps.MathOptInterface]]
deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "JSON", "JSONSchema", "LinearAlgebra", "MutableArithmetics", "OrderedCollections", "SparseArrays", "Test", "Unicode"]
git-tree-sha1 = "575644e3c05b258250bb599e57cf73bbf1062901"
uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
version = "0.9.22"

[[deps.MathProgBase]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "9abbe463a1e9fc507f12a69e7f29346c2cdc472c"
uuid = "fdba3010-5040-5b88-9595-932c9decdf73"
version = "0.7.8"

[[deps.MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "4ea90bd5d3985ae1f9a908bd4500ae88921c5ce7"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.0"

[[deps.MixedModels]]
deps = ["Arrow", "DataAPI", "Distributions", "GLM", "JSON3", "LazyArtifacts", "LinearAlgebra", "Markdown", "NLopt", "PooledArrays", "ProgressMeter", "Random", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "StatsFuns", "StatsModels", "StructTypes", "Tables"]
git-tree-sha1 = "c17a2cdb285cf936920855e48e198e4f25fcef5c"
uuid = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316"
version = "4.0.0"

[[deps.MixedModelsMakie]]
deps = ["DataFrames", "LinearAlgebra", "Makie", "MixedModels", "SpecialFunctions"]
git-tree-sha1 = "126f059a16e8ae01f3199982a5062e1e98856c38"
uuid = "b12ae82c-6730-437f-aff9-d2c38332a376"
version = "0.3.2"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.Mocking]]
deps = ["ExprTools"]
git-tree-sha1 = "748f6e1e4de814b101911e64cc12d83a6af66782"
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
version = "0.7.2"

[[deps.MosaicViews]]
deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"]
git-tree-sha1 = "b34e3bc3ca7c94914418637cb10cc4d1d80d877d"
uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
version = "0.3.3"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[deps.MutableArithmetics]]
deps = ["LinearAlgebra", "SparseArrays", "Test"]
git-tree-sha1 = "3927848ccebcc165952dc0d9ac9aa274a87bfe01"
uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
version = "0.2.20"

[[deps.NLopt]]
deps = ["MathOptInterface", "MathProgBase", "NLopt_jll"]
git-tree-sha1 = "d80cb3327d1aeef0f59eacf225e000f86e4eee0a"
uuid = "76087f3c-5699-56af-9a33-bf431cd00edd"
version = "0.6.3"

[[deps.NLopt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "2b597c46900f5f811bec31f0dcc88b45744a2a09"
uuid = "079eb43e-fd8e-5478-9966-2cf3e3edb778"
version = "2.7.0+0"

[[deps.NaNMath]]
git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[deps.Netpbm]]
deps = ["FileIO", "ImageCore"]
git-tree-sha1 = "18efc06f6ec36a8b801b23f076e3c6ac7c3bf153"
uuid = "f09324ee-3d7c-5217-9330-fc30815ba969"
version = "1.0.2"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[deps.Observables]]
git-tree-sha1 = "fe29afdef3d0c4a8286128d4e45cc50621b1e43d"
uuid = "510215fc-4207-5dde-b226-833fc4488ee2"
version = "0.4.0"

[[deps.OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "5cc97a6f806ba1b36bac7078b866d4297ae8c463"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.4"

[[deps.Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[deps.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[deps.Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[deps.OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[deps.PCRE2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15"

[[deps.PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[deps.PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "4dd403333bcf0909341cfe57ec115152f937d7d8"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.1"

[[deps.PNGFiles]]
deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"]
git-tree-sha1 = "520e28d4026d16dcf7b8c8140a3041f0e20a9ca8"
uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883"
version = "0.3.7"

[[deps.PackageAnalyzer]]
deps = ["Git", "GitHub", "JSON3", "LicenseCheck", "Pkg", "TOML", "Tokei_jll", "UUIDs"]
git-tree-sha1 = "a4cb0648ddcbeb6bc161f87906a0c17c456a27dc"
uuid = "e713c705-17e4-4cec-abe0-95bf5bf3e10c"
version = "0.1.0"

[[deps.Packing]]
deps = ["GeometryBasics"]
git-tree-sha1 = "f4049d379326c2c7aa875c702ad19346ecb2b004"
uuid = "19eb6ba3-879d-56ad-ad62-d5c202156566"
version = "0.4.1"

[[deps.PaddedViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "59925f4ae6861cddc2313a47514b93b6740f9b6f"
uuid = "5432bcbf-9aad-5242-b902-cca2824c8663"
version = "0.5.9"

[[deps.Pango_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9a336dee51d20d1ed890c4a8dca636e86e2b76ca"
uuid = "36c8627f-9965-5494-a995-c6b170f724f3"
version = "1.42.4+10"

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "477bf42b4d1496b454c10cce46645bb5b8a0cf2c"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.2"

[[deps.Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[deps.PkgVersion]]
deps = ["Pkg"]
git-tree-sha1 = "a7a7e1a88853564e551e4eba8650f8c38df79b37"
uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688"
version = "0.1.1"

[[deps.PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "501c20a63a34ac1d015d5304da0e645f42d91c9f"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.11"

[[deps.PolygonOps]]
git-tree-sha1 = "c031d2332c9a8e1c90eca239385815dc271abb22"
uuid = "647866c9-e3ac-4575-94e7-e3d426903924"
version = "0.1.1"

[[deps.PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "cde4ce9d6f33219465b55162811d8de8139c0414"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.2.1"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[deps.PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
git-tree-sha1 = "0d1245a357cc61c8cd61934c07447aa569ff22e6"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.1.0"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.ProgressMeter]]
deps = ["Distributed", "Printf"]
git-tree-sha1 = "afadeba63d90ff223a6a48d2009434ecee2ec9e8"
uuid = "92933f4c-e287-5a05-a399-4b506db050ca"
version = "1.7.1"

[[deps.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "12fbe86da16df6679be7521dfb39fbc861e1dc7b"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.4.1"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.Ratios]]
git-tree-sha1 = "37d210f612d70f3f7d57d488cb3b6eff56ad4e41"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.0"

[[deps.RecipesBase]]
git-tree-sha1 = "b3fb709f3c97bfc6e948be68beeecb55a0b340ae"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.1.1"

[[deps.Reexport]]
git-tree-sha1 = "5f6c21241f0f655da3952fd60aa18477cf96c220"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.1.0"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.1.3"

[[deps.Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "bf3188feca147ce108c76ad82c2792c57abe7b1f"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.0"

[[deps.Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "68db32dff12bb6127bac73c209881191bf0efbb7"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.3.0+0"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[deps.SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "a3a337914a035b2d59c9cbe7f1a38aaba1265b02"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.6"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[deps.ShiftedArrays]]
git-tree-sha1 = "22395afdcf37d6709a5a0766cc4a5ca52cb85ea0"
uuid = "1277b4bf-5013-50f5-be3d-901d8477a67a"
version = "1.0.0"

[[deps.Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[deps.SignedDistanceFields]]
deps = ["Random", "Statistics", "Test"]
git-tree-sha1 = "d263a08ec505853a5ff1c1ebde2070419e3f28e9"
uuid = "73760f76-fbc4-59ce-8f25-708e95d2df96"
version = "0.4.0"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SodiumSeal]]
deps = ["Base64", "Libdl", "libsodium_jll"]
git-tree-sha1 = "80cef67d2953e33935b41c6ab0a178b9987b1c99"
uuid = "2133526b-2bfb-4018-ac12-889fb3908a75"
version = "0.1.1"

[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[deps.SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[deps.SpecialFunctions]]
deps = ["ChainRulesCore", "LogExpFunctions", "OpenSpecFun_jll"]
git-tree-sha1 = "508822dca004bf62e210609148511ad03ce8f1d8"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.6.0"

[[deps.StackViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c"
uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
version = "0.1.1"

[[deps.Static]]
deps = ["IfElse"]
git-tree-sha1 = "62701892d172a2fa41a1f829f66d2b0db94a9a63"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.3.0"

[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "b28f39450421d07d89ab5d126fd15e5246350e8a"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.11"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[deps.StatsAPI]]
git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.0.0"

[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "fed1ec1e65749c4d96fc20dd13bea72b55457e62"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.9"

[[deps.StatsFuns]]
deps = ["LogExpFunctions", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "30cd8c360c54081f806b1ee14d2eecbef3c04c49"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.8"

[[deps.StatsModels]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "ShiftedArrays", "SparseArrays", "StatsBase", "StatsFuns", "Tables"]
git-tree-sha1 = "a209a68f72601f8aa0d3a7c4e50ba3f67e32e6f8"
uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
version = "0.6.24"

[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "Tables"]
git-tree-sha1 = "44b3afd37b17422a62aea25f04c1f7e09ce6b07f"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.5.1"

[[deps.StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "e36adc471280e8b346ea24c5c87ba0571204be7a"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.7.2"

[[deps.SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "d0c690d37c73aeb5ca063056283fde5585a41710"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.0"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[deps.TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[deps.TiffImages]]
deps = ["ColorTypes", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "OffsetArrays", "OrderedCollections", "PkgVersion", "ProgressMeter"]
git-tree-sha1 = "03fb246ac6e6b7cb7abac3b3302447d55b43270e"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.4.1"

[[deps.TimeZones]]
deps = ["Dates", "Future", "LazyArtifacts", "Mocking", "Pkg", "Printf", "RecipesBase", "Serialization", "Unicode"]
git-tree-sha1 = "81753f400872e5074768c9a77d4c44e70d409ef0"
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
version = "1.5.6"

[[deps.Tokei_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "8ccf563fc2dd590fbc91c8634ba66b0e0ab94a5f"
uuid = "3ac119c9-1236-5556-b556-adc8150b0244"
version = "12.1.2+2"

[[deps.TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

[[deps.URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.UnicodeFun]]
deps = ["REPL"]
git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf"
uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1"
version = "0.4.1"

[[deps.WoodburyMatrices]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "59e2ad8fd1591ea019a5259bd012d7aee15f995c"
uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6"
version = "0.5.3"

[[deps.XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[deps.XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[deps.Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[deps.Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[deps.Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[deps.Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[deps.Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[deps.Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[deps.Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[deps.Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[deps.ZipFile]]
deps = ["Libdl", "Printf", "Zlib_jll"]
git-tree-sha1 = "c3a5637e27e914a7a445b8d0ad063d701931e9f7"
uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
version = "0.9.3"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[deps.Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[deps.isoband_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "a1ac99674715995a536bbce674b068ec1b7d893d"
uuid = "9a68df92-36a6-505f-a73e-abb412b6bfb4"
version = "0.2.2+0"

[[deps.libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "acc685bcf777b2202a904cdcb49ad34c2fa1880c"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.14.0+4"

[[deps.libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7a5780a0d9c6864184b3a2eeeb833a0c871f00ab"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "0.1.6+4"

[[deps.libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[deps.libsodium_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "848ab3d00fe39d6fbc2a8641048f8f272af1c51e"
uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8"
version = "1.0.20+0"

[[deps.libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[deps.licensecheck_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "36fd7569c95add047b52be1fb99c485e91f374f6"
uuid = "4ecb348a-8b88-51ea-b912-4c460483ee91"
version = "0.3.1+1"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[deps.x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d713c1ce4deac133e3334ee12f4adff07f81778f"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2020.7.14+2"

[[deps.x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "487da2f8f2f0c8ee0e83f39d13037d6bbf0a45ab"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.0.0+3"
"""

# ╔═╡ Cell order:
# ╟─ccf3aa24-756c-445a-a22c-99c748ccbc91
# ╟─f9a85d0b-5e59-4dc1-83f1-48683dcb6acf
# ╟─3052b69a-a9a8-4633-9df8-b1a70bbcabb7
# ╟─ae102e47-1716-4861-84e5-76c19c054b6b
# ╟─cf44a69e-7628-43f3-b395-05ebf62ca648
# ╟─d87d83aa-be17-4f14-b8ac-78a674db11b3
# ╟─e2306a42-dcb6-40e4-811f-7c5bb26e0c20
# ╠═6617f01e-f252-11eb-1696-0f9f9b01245b
# ╠═cfb22981-bb2f-43fb-8dd4-59b62f3eed9c
# ╠═27647edb-a0c6-451a-93d8-4f8415be786b
# ╠═26b3f46f-4dee-4e60-99ed-892137126c93
# ╟─9a303a89-dafc-4736-a711-ccb19b0671fd
# ╠═71b3b7a0-2f29-4bf0-b10b-d06fc8805b34
# ╟─f96dd303-e501-4343-939f-2b9ddc05ee8a
# ╟─349652e8-39ff-466d-9eb3-bf8af4cd3e33
# ╠═41eb523c-d897-4a87-9bf5-89cc2802c29e
# ╟─ecded3b9-5a1f-4f42-9f05-b29a7cf803e7
# ╟─191901d3-ea42-4e5c-8582-285dd5af4652
# ╟─548589e2-5299-4ad1-a0ec-22ad3936d363
# ╠═40b0b7e3-88d7-47ea-bb46-e0dfabefc4e1
# ╟─03cdeea6-5f6b-4095-8ae3-3600906df570
# ╠═61cb5943-a6e9-4022-bb01-68b86df6fe36
# ╠═b151e0fb-b28b-41b0-aef4-38a81a7dfa78
# ╟─ab4b74a3-8e97-48a5-8cf8-91fdea464aa3
# ╠═8be846d1-0872-41c0-9a97-776f8ade7185
# ╠═8781b4e9-c2f0-4a44-a29f-4cbc8eb7d298
# ╟─81001f33-3f66-401e-815a-a46e4d4309ab
# ╠═d6aada8f-511f-4a74-a8cd-19ef88512e65
# ╟─adaaae43-5c43-45e1-9bd7-3f4fb9efc768
# ╠═ac2f5d62-49be-4850-90f0-95c58edece02
# ╟─7ce2e0d0-b3df-4006-9b07-70b64da3b29a
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


@testset "Weighting" begin
  @testset "UniformWeighting" begin
    d = RegularGrid(100,100)
    s = georef((z=rand(100,100),))
    for o in [d, s]
      w = weight(o, UniformWeighting())
      @test length(w) == nelms(o)
      @test all(w .== 1)
    end
  end

  @testset "BlockWeighting" begin
    d = RegularGrid(100,100)
    s = georef((z=rand(100,100),))
    for o in [d, s]
      w = weight(o, BlockWeighting(10,10))
      @test length(unique(w)) == 1
      @test w[1] == 1 / 100
    end
  end

  @testset "DensityRatioWeighting" begin
    n = 1000; Random.seed!(123)

    r1 = Normal(0, 2)
    r2 = MixtureModel([Normal(-2,1), Normal(2,2)], [0.2, 0.8])

    z1 = sort(rand(r1, n))
    z2 = sort(rand(r2, n))

    d1 = georef(DataFrame(z=z1), PointSet(reshape(1:n,1,:)))
    d2 = georef(DataFrame(z=z2), PointSet(reshape(1:n,1,:)))

    w = weight(d1, DensityRatioWeighting(d2))

    if visualtests
      @plottest begin
        plot( z1, pdf.(r1, z1), size=(800,400), label="source")
        plot!(z1, pdf.(r2, z1), label="target")
        plot!(z1, w .* pdf.(r1, z1), label="approx")
      end joinpath(datadir,"density-ratio.png") !istravis
    end
  end
end


### A Pluto.jl notebook ###
# v0.17.3

using Markdown
using InteractiveUtils

# ╔═╡ ebaefdd0-5d91-11ec-0a21-bbe3a1de4c39
using BenchmarkTools

# ╔═╡ c6aa1933-5c9d-4a82-83c6-483ccd4b3f01
function gaxpy_line!(y,A,x)
    (m,n) = size(A)
    for i in 1:m, j in 1:n
        y[i] += A[i,j]*x[j]
    end
end

# ╔═╡ 962e5971-84b8-4186-a1bb-910020957439
function gaxpy_column!(y,A,x)
    (m,n) = size(A)
    for j in 1:n, i in 1:m
        y[i] += A[i,j]*x[j]
    end
end

# ╔═╡ 334c4eac-546e-4f79-87d7-231d85f08f85
begin
	A = rand(50,50)
	x = rand(50)
	y = rand(50)
end

# ╔═╡ bb187913-fa8e-4974-957a-ff26f6967389
@benchmark gaxpy_line!(y,A,x)

# ╔═╡ bd6cbfb1-646b-4306-8bc5-b230949317a3
@benchmark gaxpy_column!(y,A,x)

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"

[compat]
BenchmarkTools = "~1.2.2"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

[[BenchmarkTools]]
deps = ["JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"]
git-tree-sha1 = "940001114a0147b6e4d10624276d56d531dd9b49"
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
version = "1.2.2"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "ae4bbcadb2906ccc085cf52ac286dc1377dceccc"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.1.2"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[Profile]]
deps = ["Printf"]
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
"""

# ╔═╡ Cell order:
# ╠═ebaefdd0-5d91-11ec-0a21-bbe3a1de4c39
# ╠═c6aa1933-5c9d-4a82-83c6-483ccd4b3f01
# ╠═962e5971-84b8-4186-a1bb-910020957439
# ╠═334c4eac-546e-4f79-87d7-231d85f08f85
# ╠═bb187913-fa8e-4974-957a-ff26f6967389
# ╠═bd6cbfb1-646b-4306-8bc5-b230949317a3
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


#=
Using a function rand5() that returns an integer from 1 to 5 (inclusive) with uniform probability, implement a function rand7() that returns an integer from 1 to 7 (inclusive).
=#

using Test
include("Solutions/problem45_rand7_from_rand5.jl")

@test rand7() in collect(1:7)


export Map_From_VectFunc

@doc raw"""

An [`Abstract_Map`](@ref) instance that can be easily created by
providing a Julia function

# Constructor
```julia
Map_From_VectFunc(n_θ,f)
```
where ``(X,θ)->Y=f(X,θ)`` is the wrapped function.

# Example

```jldoctest
using NLS_Fit

f(X,θ) = θ[1]*X

map = Map_From_VectFunc(1,f)

X = Float64[1,2,3]

θ = Float64[4]

eval_map(map,X,θ)

# output
3-element Vector{Float64}:
  4.0
  8.0
 12.0

```

"""
struct Map_From_VectFunc{F<:Function} <: Abstract_Map
    _n_θ::Int
    _f::F
end

parameter_size(m::Map_From_VectFunc) = m._n_θ

function eval_map(m::Map_From_VectFunc,
                  X::AbstractVector,
                  θ::AbstractVector)
    @assert length(θ) == parameter_size(m)

    m._f(X,θ)
end