text:
using Test, MPI
import GaussQuadrature
using CLIMA
using CLIMA.Mesh.Topologies
using CLIMA.Mesh.Grids
using CLIMA.Mesh.Geometry
using CLIMA.Mesh.Interpolation
using StaticArrays
using GPUifyLoops

using CLIMA.VariableTemplates
#------------------------------------------------
using CLIMA.DGmethods
using CLIMA.DGmethods.NumericalFluxes
using CLIMA.MPIStateArrays
using CLIMA.ODESolvers
using CLIMA.GenericCallbacks
using CLIMA.Atmos
using CLIMA.VariableTemplates
using CLIMA.MoistThermodynamics
using CLIMA.PlanetParameters
using CLIMA.TicToc
using LinearAlgebra
using StaticArrays
using Logging, Printf, Dates
using CLIMA.VTK

using CLIMA.Atmos: vars_state, vars_aux

using Random
using Statistics
const seed = MersenneTwister(0)

const ArrayType = CLIMA.array_type()
#-------------------------------------
function Initialize_Brick_Interpolation_Test!(bl, state::Vars, aux::Vars, (x,y,z), t)
    FT         = eltype(state)
    # Dummy variables for initial condition function
    state.ρ               = FT(0)
    state.ρu              = SVector{3,FT}(0,0,0)
    state.ρe              = FT(0)
    state.moisture.ρq_tot = FT(0)
end
#------------------------------------------------
struct TestSphereSetup{DT}
    p_ground::DT
    T_initial::DT
    domain_height::DT

    function TestSphereSetup(p_ground::DT, T_initial::DT, domain_height::DT) where DT <: AbstractFloat
        return new{DT}(p_ground, T_initial, domain_height)
    end
end
#----------------------------------------------------------------------------
function (setup::TestSphereSetup)(bl, state, aux, coords, t)
    # callable to set initial conditions
    FT = eltype(state)

    r = norm(coords, 2)
    h = r - FT(planet_radius)

    scale_height = R_d * setup.T_initial / grav
    p = setup.p_ground * exp(-h / scale_height)

    state.ρ = air_density(setup.T_initial, p)
    state.ρu = SVector{3, FT}(0, 0, 0)
    state.ρe = state.ρ * (internal_energy(setup.T_initial) + aux.orientation.Φ)
    return nothing
end
#----------------------------------------------------------------------------
function run_brick_interpolation_test()
    CLIMA.init()
    ArrayType = CLIMA.array_type()
    DA = CLIMA.array_type()
    FT = Float64
    mpicomm = MPI.COMM_WORLD
    pid = MPI.Comm_rank(mpicomm)
    npr = MPI.Comm_size(mpicomm)

    xmin, ymin, zmin = 0, 0, 0                   # defining domain extent
    xmax, ymax, zmax = 2000, 400, 2000
    xres = [FT(10), FT(10), FT(10)] # resolution of interpolation grid

    Ne        = (20,4,20)

    polynomialorder = 5 #8# 5 #8 #4
    #-------------------------
    _x, _y, _z = CLIMA.Mesh.Grids.vgeoid.x1id, CLIMA.Mesh.Grids.vgeoid.x2id, CLIMA.Mesh.Grids.vgeoid.x3id
    #-------------------------

    brickrange = (range(FT(xmin); length=Ne[1]+1, stop=xmax),
                  range(FT(ymin); length=Ne[2]+1, stop=ymax),
                  range(FT(zmin); length=Ne[3]+1, stop=zmax))
    topl = StackedBrickTopology(mpicomm, brickrange, periodicity = (true, true, false))
    grid = DiscontinuousSpectralElementGrid(topl,
                                            FloatType = FT,
                                            DeviceArray = DA,
                                            polynomialorder = polynomialorder)
    model = AtmosModel{FT}(AtmosLESConfiguration;
                           ref_state=NoReferenceState(),
                          turbulence=ConstantViscosityWithDivergence(FT(0)),
                              source=(Gravity(),),
                          init_state=Initialize_Brick_Interpolation_Test!)

    dg = DGModel(model,
               grid,
               Rusanov(),
               CentralNumericalFluxDiffusive(),
               CentralNumericalFluxGradient())

    Q = init_ode_state(dg, FT(0))
    #------------------------------
    x1 = @view grid.vgeo[:,_x,:]
    x2 = @view grid.vgeo[:,_y,:]
    x3 = @view grid.vgeo[:,_z,:]

    fcn(x,y,z) = sin.(x) .* cos.(y) .* cos.(z) # sample function
    #----calling interpolation function on state variable # st_idx--------------------------
    nvars = size(Q.data,2)

    for vari in 1:nvars
        Q.data[:,vari,:] = fcn( x1 ./ xmax, x2 ./ ymax, x3 ./ zmax )
    end

    xbnd = Array{FT}(undef,2,3)

    xbnd[1,1] = FT(xmin); xbnd[2,1] = FT(xmax)
    xbnd[1,2] = FT(ymin); xbnd[2,2] = FT(ymax)
    xbnd[1,3] = FT(zmin); xbnd[2,3] = FT(zmax)
    #----------------------------------------------------------
    filename = "test.nc"
    varnames = ("ρ", "ρu", "ρv", "ρw", "e", "other")

    intrp_brck = InterpolationBrick(grid, xbnd, xres)                            # sets up the interpolation structure
    iv = DA(Array{FT}(undef, intrp_brck.Npl, nvars))                             # allocating space for the interpolation variable
    interpolate_local!(intrp_brck, Q.data, iv)                       # interpolation
    svi = write_interpolated_data(intrp_brck, iv, varnames, filename)      # write interpolation data to file
    #------------------------------

    err_inf_dom = zeros(FT, nvars)

    x1g = intrp_brck.x1g
    x2g = intrp_brck.x2g
    x3g = intrp_brck.x3g

    if pid==0
        nx1 = length(x1g); nx2 = length(x2g); nx3 = length(x3g)
        x1 = Array{FT}(undef,nx1,nx2,nx3); x2 = similar(x1); x3 = similar(x1)

        for k in 1:nx3, j in 1:nx2, i in 1:nx1
            x1[i,j,k] = x1g[i]
            x2[i,j,k] = x2g[j]
            x3[i,j,k] = x3g[k]
        end
        fex = fcn( x1 ./ xmax , x2 ./ ymax , x3 ./ zmax )

        for vari in 1:nvars
            err_inf_dom[vari] = maximum( abs.(svi[:,:,:,vari] .- fex[:,:,:]) )
        end
    end

    toler = 1.0E-9
    return maximum(err_inf_dom) < toler #1.0e-14
    #----------------
end #function run_brick_interpolation_test
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
# Cubed sphere, lat/long interpolation test
#----------------------------------------------------------------------------
function run_cubed_sphere_interpolation_test()
    CLIMA.init()
    ArrayType = CLIMA.array_type()

    DA = CLIMA.array_type()
    FT = Float64 #Float32 #Float64
    mpicomm = MPI.COMM_WORLD
    root = 0
    pid  = MPI.Comm_rank(mpicomm)
    npr  = MPI.Comm_size(mpicomm)

    ll = uppercase(get(ENV, "JULIA_LOG_LEVEL", "INFO"))
    loglevel = Dict("DEBUG" => Logging.Debug,
                    "WARN"  => Logging.Warn,
                    "ERROR" => Logging.Error,
                    "INFO"  => Logging.Info)[ll]

    logger_stream = MPI.Comm_rank(mpicomm) == 0 ? stderr : devnull
    global_logger(ConsoleLogger(logger_stream, loglevel))

    domain_height = FT(30e3)

    polynomialorder = 5
    numelem_horz = 6
    numelem_vert = 4

    #-------------------------
    _x, _y, _z = CLIMA.Mesh.Grids.vgeoid.x1id, CLIMA.Mesh.Grids.vgeoid.x2id, CLIMA.Mesh.Grids.vgeoid.x3id
    _ρ, _ρu, _ρv, _ρw = 1, 2, 3, 4
    #-------------------------
    vert_range = grid1d(FT(planet_radius), FT(planet_radius + domain_height), nelem = numelem_vert)

    lat_res  = FT(1) # 1 degree resolution
    long_res = FT(1) # 1 degree resolution
    nel_vert_grd  = 20 #100 #50 #10#50
    r_res    = FT((vert_range[end] - vert_range[1])/FT(nel_vert_grd)) #1000.00    # 1000 m vertical resolution
    #----------------------------------------------------------
    setup = TestSphereSetup(FT(MSLP),FT(255),FT(30e3))

    topology = StackedCubedSphereTopology(mpicomm, numelem_horz, vert_range)

    grid = DiscontinuousSpectralElementGrid(topology,
                                            FloatType = FT,
                                            DeviceArray = ArrayType,
                                            polynomialorder = polynomialorder,
                                            meshwarp = CLIMA.Mesh.Topologies.cubedshellwarp)

    model = AtmosModel{FT}(AtmosLESConfiguration;
                           orientation=SphericalOrientation(),
                             ref_state=NoReferenceState(),
                            turbulence=ConstantViscosityWithDivergence(FT(0)),
                              moisture=DryModel(),
                                source=nothing,
                            init_state=setup)

    dg = DGModel(model, grid, Rusanov(), CentralNumericalFluxDiffusive(), CentralNumericalFluxGradient())

    Q = init_ode_state(dg, FT(0))

    device = typeof(Q.data) <: Array ? CPU() : CUDA()
    #------------------------------
    x1 = @view grid.vgeo[:,_x,:]
    x2 = @view grid.vgeo[:,_y,:]
    x3 = @view grid.vgeo[:,_z,:]

    xmax = FT(planet_radius)
    ymax = FT(planet_radius)
    zmax = FT(planet_radius)

    fcn(x,y,z) = sin.(x) .* cos.(y) .* cos.(z) # sample function

    nvars = size(Q.data,2)

    for i in 1:nvars
        Q.data[:,i,:] .= fcn( x1 ./ xmax, x2 ./ ymax, x3 ./ zmax )
    end
    #------------------------------
    filename = "test.nc"
    varnames = ("ρ", "ρu", "ρv", "ρw", "e")

    intrp_cs = InterpolationCubedSphere(grid, collect(vert_range), numelem_horz, lat_res, long_res, r_res); # sets up the interpolation structure
    iv = DA(Array{FT}(undef, intrp_cs.Npl, nvars))                                # allocatind space for the interpolation variable
    interpolate_local!(intrp_cs, Q.data, iv)                   # interpolation
    svi = write_interpolated_data(intrp_cs, iv, varnames, filename)  # write interpolated data to file
    #----------------------------------------------------------
    # Testing
    err_inf_dom = zeros(FT, nvars)

    rad   = intrp_cs.rad_grd
    lat   = intrp_cs.lat_grd
    long  = intrp_cs.long_grd

    if pid==0
        nrad = length(rad); nlat = length(lat); nlong = length(long)
        x1g = Array{FT}(undef,nrad,nlat,nlong); x2g = similar(x1g); x3g = similar(x1g)

        for k in 1:nlong, j in 1:nlat, i in 1:nrad
            x1g[i,j,k] = rad[i] * cosd(lat[j]) * cosd(long[k]) # inclination -> latitude; azimuthal -> longitude.
            x2g[i,j,k] = rad[i] * cosd(lat[j]) * sind(long[k]) # inclination -> latitude; azimuthal -> longitude.
            x3g[i,j,k] = rad[i] * sind(lat[j])
        end
        fex = fcn( x1g ./ xmax , x2g ./ ymax , x3g ./ zmax )

        for vari in 1:nvars
            err_inf_dom[vari] = maximum( abs.(svi[:,:,:,vari] .- fex[:,:,:]) )
        end
    end

    MPI.Bcast!(err_inf_dom, root, mpicomm)

    toler = 1.0E-7
    return maximum(err_inf_dom) < toler
end
#----------------------------------------------------------------------------

@testset "Interpolation tests" begin
    @test run_brick_interpolation_test()
    @test run_cubed_sphere_interpolation_test()
end
#------------------------------------------------

max_stars_repo_name: favba/CLIMA

max_issues_repo_name: favba/CLIMA

max_forks_repo_name: favba/CLIMA


text:
export regrid2d

"""
    `regrid2d(acqData::AcquisitionData{T}, kspaceSize::NTuple{2,Int64}
              ; cgnr_iter::Int64=3, correctionMap::Array{Complex{T}}=Complex{T}[]) where (D,T)`

Regrid non-cartesian k-space data in `acqData` to a cartesian grid of size `kspaceSize`.
Uses the CGNR method to invert the non-cartesian Fourier encoding.

# Arguments:
* `acqData::AcquisitionData{T}`        - AcquisitionData
* `ksize::NTuple{2,Int64}`          - size of the cartesian k-space grid
* `cgnr_iter::Int64=3`              - number of CGNR iterations
* `correctionMao::Array{Complex{T}}`- relaxation/b0 map
"""
function regrid2d(acqData::AcquisitionData{T}, kspaceSize::NTuple{2,Int64}; cgnr_iter::Int64=3, correctionMap::Array{Complex{T}}=Complex{T}[]) where {D,T}
  dcf = samplingDensity(acqData,kspaceSize)

  nx,ny = kspaceSize
  numContr, numChan, numSl = numContrasts(acqData), numChannels(acqData), numSlices(acqData)

  kdata_cart = [zeros(Complex{T},nx*ny,numChan) for j=1:numContr, k=1:numSl, rep=1:1]
  F = sqrt(prod(kspaceSize))*FFTOp(Complex{T}, kspaceSize)
  img = zeros(Complex{T},nx*ny)
  for k = 1:numSl
    E = encodingOps_simple(acqData, kspaceSize, slice=k, correctionMap=correctionMap)
    for j = 1:numContr
      W = WeightingOp(dcf[j])
      solver = RegularizedLeastSquares.CGNR(W*E[j], iterations=cgnr_iter)
      for i = 1:numChan
        kdata = kData(acqData,j,i,k).* dcf[j]
        img .= solve(solver, kdata)
        kdata_cart[j,k,1][:,i] .= F*img
      end
    end
  end

  return AcquisitionData(CartesianTrajectory(T,ny,nx), kdata_cart, encodingSize=[nx,ny,1], fov=acqData.fov)
end

ext: jl


text:
export demo_fg, demo_fg2, random_simple_fg, random_fg
using StatsBase

function demo_fg()
    orders = [1, 3, 3, 3, 2, 4, 2]
    tensors = [randn(repeat([2], o)...) for o in orders]
    lm = zeros(Int, 7, 9)
    lm[1,1] = 1

    lm[2,1] = 1
    lm[2,2] = 2
    lm[2,3] = 3

    lm[3,2] = 1
    lm[3,4] = 2
    lm[3,5] = 3

    lm[4,3] = 1
    lm[4,6] = 2
    lm[4,7] = 3

    lm[5,4] = 1
    lm[5,8] = 2

    lm[6,5] = 1
    lm[6,6] = 2
    lm[6,8] = 3
    lm[6,9] = 4

    lm[7,7] = 1
    lm[7,9] = 2
    FGraph(tensors, lm)
end

# non-simple graph
function demo_fg2()
    orders = [2, 4, 4, 2, 2, 4, 2]
    tensors = [randn(repeat([2], o)...) for o in orders]
    lm = zeros(Int, 7, 9)
    lm[1,1] = 1

    lm[2,1] = 1
    lm[2,2] = 2
    lm[2,3] = 3
    lm[2,6] = 4

    lm[3,2] = 1
    lm[3,4] = 2
    lm[3,5] = 3
    lm[3,6] = 4

    lm[4,3] = 1
    lm[4,7] = 2

    lm[5,4] = 1
    lm[5,8] = 2

    lm[6,5] = 1
    lm[6,8] = 3
    lm[6,7] = 4

    lm[7,7] = 2
    lm[7,9] = 1
    FGraph(tensors, lm)
end

function random_simple_fg(::Type{T}, tensor_sizes::Vector{<:Tuple}, nbond::Int; bias_factor::Real=-1) where T
    n = length(tensor_sizes)
    nlegs = length.(tensor_sizes) |> sum
    nlegs < 2nbond && throw(ArgumentError("Number of bond $nbond too large."))
    lm = zeros(Int, n, nbond)
    # randomly connect tensors
    # assign tensor legs
    #lm[rand(n, nbond)<bond_density] .= 1

    # combine tensors with graph
    ts = [randn(T, size...) for size in tensor_sizes]
    fg = FGraph(ts, lm)

    for i=1:100
        try
            for ibond = 1:nbond
                legs = fg |> dangling_legs
                it, jt = sample(1:n, Weights(exp.(-bias_factor*length.(legs))), 2, replace=false)
                ileg = sample(dangling_legs(fg, it))
                jleg = sample(dangling_legs(fg, jt))
                legmap(fg)[it, ibond] = ileg
                legmap(fg)[jt, ibond] = jleg
            end
            break
        catch
            legmap(fg) .= 0
        end
        if i==100
            throw(ArgumentError("Can not construct this random simple graph with 100 tries, try decrease `bias_factor`."))
        end
    end
    fg
end

function random_fg(::Type{T}, nv::Int, ne::Int, link_density::Real=2/nv, bond_dimension::Int=2) where T
    lm = zeros(Int, nv, ne)
    # randomly connect tensors
    ks = zeros(Int, nv)
    for iv = 1:nv
        for ie = 1:ne
            if rand() < link_density
                ks[iv] += 1
                @inbounds lm[iv, ie] = ks[iv]
            end
        end
    end

    # combine tensors with graph
    ts = [randn(T, fill(bond_dimension, ndim)...) |> asarray for ndim in ks]
    FGraph(ts, lm)
end

random_fg(nv::Int, ne::Int, args...) = random_fg(Float64, nv::Int, ne::Int, args...)
random_simple_fg(tensor_sizes::Vector{<:Tuple}, nbond::Int; kwargs...) = random_simple_fg(Float64, tensor_sizes, nbond; kwargs...)


text:
function checkArgumentOrder(mdp::MDP)

  statedim = length(mdp.statemap)
  actiondim = length(mdp.actionmap)

  ntransitionargs = length(mdp.transition.argnames)
  nrewardargs = length(mdp.reward.argnames)

  sadim = statedim + actiondim
  saspdim = sadim + statedim

  if sadim != nrewardargs
    @error(string(
      "the number of reward function input arguments must be the same as ",
      "the sum of the number of state and action variables"))
  elseif sadim != ntransitionargs && saspdim != ntransitionargs
    @error(string(
      "the number of transition function input arguments must be the same as ",
      "the sum of the number of state, action, and next state variables or ",
      "the sum of the number of state and action variables"))
  end

  for iarg in 1:nrewardargs
    if mdp.reward.argnames[iarg] != mdp.transition.argnames[iarg]
      @error(string(
        "transition and reward function state and action variable input arguments",
        "must be consistent in both naming and order"))
    end
  end

  if length(mdp.transition.argnames) > length(mdp.reward.argnames)
    for iarg in 1:nrewardargs - actiondim
      if mdp.transition.argnames[iarg] != mdp.transition.argnames[iarg + sadim]
        @error(string(
          "transition type T(s,a,s')'s state s and next state s' variable ",
          "input arguments must be consistent in both naming and order"))
      end
    end
  end

end

function checkTransition(mdp::MDP)
  args = randargs(mdp)
  transitionval = mdp.transition.fn(args...)

  if isa(transitionval, Real) || isa(transitionval, Vector)
    checkTransition(mdp, args, transitionval)
  else
    @error(string(
      "transition function provided is not a correctly defined ",
      "T(s,a,s') or T(s,a) type function, check the return type\n",
      "return type: ", typeof(transitionval)))
  end
end

function checkTransition(mdp::MDP, args::Vector, transitionval::Real)
  if transitionval < 0 || transitionval > 1
    @warn(string(  # warn not error because we might have sampled a non-existent state
      "transition function provided is of type T(s,a,s'), ",
      "but the value returned from a random state is not ",
      "a valid probability value bounded to [0,1]\n",
      "argument names: ", mdp.transition.argnames, "\n",
      "random state: ", args, "\n",
      "return value: ", transitionval))
  end
end

function checkTransition(mdp::MDP, args::Vector, transitionval::Vector)
  nargs = length(mdp.transition.argnames)
  sumprob = 0.0

  for returnval in transitionval  # |returnval| is a (state, prob) pair
    state = returnval[1]
    prob = returnval[2]
    sumprob += prob

    if length(state) + length(prob) != nargs || !isvalid(mdp, state)
      @error(string(
        "transition function provided is of type T(s,a), ",
        "but one of the states returned from a random state is ",
        "either not bounded by its range or not in the set of values\n",
        "argument names: ", mdp.transition.argnames, "\n",
        "random state: ", args, "\n",
        "return value: ", state, "\n",
        "probability: ", prob))
    elseif prob < 0 || prob > 1
      @error(string(
        "transition function provided is of type T(s,a), ",
        "but one of the probabilities returned from a random state is ",
        "a valid probability value bounded to [0,1]\n",
        "argument names: ", mdp.transition.argnames, "\n",
        "random state: ", args, "\n",
        "return value: ", state, "\n",
        "probability: ", prob))
    end
  end

  if sumprob != 1
    @warn(string(  # warn not error because we might have sampled a non-existent state
      "transition function provided is of type T(s,a), ",
      "but the sum of transition probabilities returned from a random state ",
      "does not sum to 1\n",
      "argument names: ", mdp.transition.argnames, "\n",
      "random state: ", args, "\n",
      "return value: ", returnval, "\n",
      "sum of transition probabilities: ", sumprob))
  end
end

function randargs(mdp::MDP)
  nargs = length(mdp.transition.argnames)
  args = Array{Any,1}(undef, nargs)
  for iarg in 1:nargs
    argname = mdp.transition.argnames[iarg]
    if haskey(mdp.statemap, argname)
      args[iarg] = lazySample(mdp.statemap[argname])
    elseif haskey(mdp.actionmap, argname)
      args[iarg] = lazySample(mdp.actionmap[argname])
    else
      @error(string("variable ", lazyvar.varname, " has not been defined"))
    end
  end
  args
end

function lazySample(lazyvar::LazyVar)
  if isa(lazyvar, RangeVar)
    return lazyvar.minval + rand() * (lazyvar.maxval - lazyvar.minval)
  elseif isa(lazyvar, ValuesVar)
    return lazyvar.values[rand(1:length(lazyvar.values))]
  else
    @error(string("variable", lazyvar.varname, " is not a valid subtype of LazyVar"))
  end
end

function isvalid(mdp::MDP, state::Vector)
  for iarg in length(mdp.statemap)
    argname = mdp.transition.argnames[iarg]
    if isa(mdp.statemap[argname], RangeVar) &&
        (state[iarg] < mdp.statemap[argname].minval ||
        state[iarg] > mdp.statemap[argname].maxval)
      return false
    elseif isa(mdp.statemap[argname], ValuesVar) &&
        !(state[iarg] in mdp.statemap[argname].values)
      return false
    end
  end
  return true
end


text:
# Juliaを使った株価のアラート通知
using JSON, Parameters, TimeZones, Logging, CSV, DataFrames, BusinessDays, Dates
# cd(raw"C:\workspace\StockPrice.jl") # for debug
include("SendGmail.jl")
include("GetStockPrice.jl")

# -----------------------------------------
# アラート設定
# -----------------------------------------
@with_kw mutable struct AlertSetting
    stock::String   # 株価ティッカー
    func::String    # アラート関数
    value::Array{Float64,1}  # アラートのしきい値とする値
    enable::Bool  # アラートの有効化フラグ
    alerted::Bool # アラートがその日に上がったことを示すフラグ
end

# 設定ファイルの作成
function initalertsetting()
    settings = Dict(
        "stock" => "SPXL",
        "func" => "checklowerlimit",
        "value" => "120.0",
        "enable" => true,
        "alerted" => false
    )
    json = JSON.json(settings)
    open("./setting/SPXL_alert_setting.json", "w") do f
        print(f, json)
    end
end

## 設定をDictで読み取りstructにマッピングする-----------------
# 参考：https://matsueushi.github.io/posts/julia-mapping-nested-dict/
# キーを文字列からシンボルに変換する関数
keytosymbol(x) = Dict(Symbol(k) => v for (k, v) in pairs(x))
# アラート設定を記載したJSONファイルを読み込みstructのインスタンスを返す
function readalertsetting(jsonfile)
    str = open(f -> read(f, String), jsonfile)
    json = JSON.parse(str)
    symbol = keytosymbol(json)
    symbol[:value] = parse.(Float64, split(symbol[:value], ","))
    setting = AlertSetting(;symbol...)
    return setting
end

# 指定したdirからkeyを含むファイル名からsettingを読み込みリスト化する．
# dir: 設定読み込み先ディレクトリ名
# key: 読み込む設定に該当するキー
function readalertsettings(;key=".json", dir="./")
    settings_json = filter(f -> contains(f, key), readdir(dir))
    settings = readalertsetting.(dir .* settings_json)
    return settings
end

# -----------------------------------------
# アラート関数：動作検証済み
# -----------------------------------------
# 設定下限値を下回った場合にアラート
function checklowerlimit(alert::AlertSetting, prices)
    message = ""
    lowerlimit = alert.value[1]
    if ( sum(prices."close" .< lowerlimit) > 0 )
        alert.alerted = true
        meet = prices[prices."close" .< lowerlimit,:] # 条件に当てはまったデータ
        price = string(round(meet[1,"close"], digits=1))
        dt = meet[1, "timestamp"]
        dtfmt = "YYYY/mm/dd HH:MM:SS"
        message = alert.stock * "の株価が下限値設定を下回りました．\r\n" *
            "下限値: " * string(lowerlimit) * "\r\n" *
            "時刻: " * Dates.format(dt, dtfmt) * "\r\n" *
            "株価: " * price * "\r\n"
    end
    return message
end

# 設定上限値を上回った場合にアラート
function checkupperlimit(alert::AlertSetting, prices)
    message = ""
    upperlimit = alert.value[1]
    if ( sum(prices."close" .> upperlimit) > 0 )
        alert.alerted = true
        meet = prices[prices."close" .> upperlimit, :] # 条件に当てはまったデータ
        price = string(round(meet[1, "close"], digits=1))
        dt = meet[1, "timestamp"]
        dtfmt = "YYYY/mm/dd HH:MM:SS"
        message = alert.stock * "の株価が上限を超過しました．\r\n" *
            "上限値: " * string(upperlimit) * "\r\n" *
            "時刻: " * Dates.format(dt, dtfmt) * "\r\n" *
            "株価: " * price * "\r\n"
    end
    return message
end

# -----------------------------------------
# アラート実行
# -----------------------------------------
# 指定されたalertsリストのアラートをチェックして，条件を満たせばアラートメールを発信する
# alerts Array{AlertSetting, 1}
function exealert(alerts)

    for alert in alerts
        # 開場時間判定
        if( contains(alert.stock, ".T") )
            now_tk = now() # 日本時間
            open_tk = (Time(now_tk) >= Time(9, 00)) && (Time(now_tk) <= Time(15, 0)) # 東京証券取引所
            market_open = open_tk && isbday("JPTSE", Date(now_tk))
        else
            now_ny = now(tz"America/New_York") # 米国東部時間
            open_ny = (Time(now_ny) >= Time(9, 30)) && (Time(now_ny) <= Time(16, 0)) # NY証券取引所
            market_open =  open_ny && isbday("USNYSE", Date(now_ny))
        end

        # 開場時にアラート有効かつアラート未発報
        if market_open && alert.enable && !alert.alerted
            info("株価を確認します: " * alert.stock)
            prices = getstockprice(alert.stock)
            info("price: " * string(prices[end,:].close))
            message = eval(:( $(Symbol(alert.func))($alert, $prices) )) # 文字列で与えた関数の評価
            if alert.alerted
                title = "【株価アラート通知】" * alert.stock
                info("アラートメールを発信します．\n" * message)
                resp = sendmail(title, message) # アラートメールの発信
                info("アラートメールを発信しました．\n"*string(resp))
            end
        end
    end

end

# 東京証券取引所の祝日を追加定義
struct JPTSE <: BusinessDays.HolidayCalendar end
function BusinessDays.isholiday(::JPTSE, dt::Dates.Date)
    # [東証の祝日](https://www.jpx.co.jp/corporate/about-jpx/calendar/index.html)
    # 上記は取得しにくいので内閣府からCSVをダウンロード．ただし 1/2, 1/3, 12/31が不足しているので追記必須．年1回程度確認する
    # download("https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv", filename)
    filename = "./data/holidays_JPTSE.csv"
    dfmt = dateformat"yyyy/mm/dd"
    df = DataFrame(CSV.File(filename, dateformat=dfmt))
    return sum(df[:,1] .== Date(dt)) > 0
end

# settingリストからアラートを1つずつ3時まで定期実行する
# それぞれのアラートを個別チェックし，最大日に1回ずつアラートするようにする
function managealerts()
    # アラート定義の取得
    global alerts = readalertsettings(key="alert_setting.json", dir="./setting/")
    [info(alert) for alert in alerts] # アラートの内容出力

    # アラートを9時に起動して翌6時まで10分おき想定で実行
    int = 60 * 10 # アラートチェック間隔=10分の秒数
    period = 21 * 3600 # 朝9時～翌6時の秒数
    info("株価を" * string(int / 60) * "分間隔で" * string(period / 60 / 60) * "時間監視します．")
    cb(timer) = (exealert(alerts))
    t = Timer(cb, 0, interval=int)
    wait(t)
    sleep(period)
    close(t)
end

# ConsoleLoggerに時刻出力を追加
function timed_metafmt(level, _module, group, id, file, line)
    color, prefix, suffix = Logging.default_metafmt(level, _module, group, id, file, line)
    timestamp = Dates.now()
    prefix2 = "$timestamp : $prefix"
    return color, prefix2, suffix
end

# flushを付加
function info(x)
    @info x
    flush(io)
end
function warn(x)
    @warn x
    flush(io)
end

function main()
    # Loggingの設定: log.txtに追加書き込みでInfo以上のログを書き出し．debug, info, warn, errorがあり．
    global io = open("log.txt", "a+")
    logger = Logging.ConsoleLogger(io, Logging.Info, meta_formatter=timed_metafmt)
    Logging.global_logger(logger)
    info(logger)

    managealerts()

    close(io) # close log file
end

main()


text:
"""
An explicit representation of the normalized B-spline.
"""
function normalized_bspline(i::Integer, kp1::Integer, λ::Vector{T}, x::T) where {T <: Real}
    total = zero(T)
    for j = 0:kp1
        denom = one(T)
        for l = 0:(j - 1)
            denom *= λ[i + j] - λ[i + l]
        end
        for l = (j + 1):kp1
            denom *= λ[i + j] - λ[i + l]
        end
        total += truncated(λ[i + j], k, x) / denom
    end
    (λ[i + kp1] - λ[i]) * total
end


text:
export AbstractStateSpace

"""
Abstract type for FSP state space. This is the supertype of all concrete FSP state space implementations.
"""
abstract type AbstractStateSpace end

include("sparse/sparsestatespace.jl")


text:
push!(LOAD_PATH,"../src/")
using Documenter, Epi

makedocs(
    modules = [Epi],
    sitename="Epi.jl",
    pages = ["Home" => "index.md"]
)

deploydocs(
    repo = "github.com/kklot/Epi.jl.git",
    julia = "1.0",
    osname = "linux"
)


text:
using chitchat

trie = Trie()
add_to_trie(trie, "watch movies", Dict("action" => "BROWSE"))
add_to_trie(trie, "show me movies", Dict("action" => "BROWSE"))
add_to_trie(trie, "watch <genre> movies", Dict("action" => "BROWSE"))
sz_kb = Base.summarysize(trie) / 1024
"$sz_kb KB"


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

using Markdown
using InteractiveUtils

# ╔═╡ 2f67f6bf-832e-4bb7-bdda-576ea37e98c8
begin
	# setup: we need to specify the paths where we can find our project resources
    _PATH_TO_ROOT = pwd()
    _PATH_TO_SRC = joinpath(_PATH_TO_ROOT, "src")
    _PATH_TO_DATA = joinpath(_PATH_TO_ROOT, "data")
    _PATH_TO_CONFIG = joinpath(_PATH_TO_ROOT, "configuration")

    # what packages are we going to use?
    using DataFrames
    using CSV
    using HTTP
    using TOML
    using Dates
    using StatsPlots
    using Statistics
    using Distributions
    using PlutoUI
	using HypothesisTests
	using PrettyTables
	using Colors
	using Optim
	using Convex
	using SCS
	using MathOptInterface

    # alias the AlphaVantage URL -
    DATASTORE_URL_STRING = "https://www.alphavantage.co/query?"

    # What we have here is a classic good news, bad news situation ...
    # Bad news: We don't check in our AlphaVantage API key to GitHub (sorry).
    # Good news: AlphaVantage API keys are free.
    # check out: https://www.alphavantage.co/support/#api-key
    configuration_dictionary = TOML.parsefile(joinpath(_PATH_TO_CONFIG, "Configuration.toml"))

    # get some stuff from the configuration dictionary -
    ALPHAVANTAGE_API_KEY = configuration_dictionary["API"]["alphavantage_api_key"]

	# List of colors -
	WHITE = RGB(1.0, 1.0, 1.0)
	BACKGROUND = RGB(0.99, 0.98, 0.96)
	BLUE = RGB(68 / 255, 119 / 255, 170 / 255)
	LBLUE = RGB(102 / 255, 204 / 255, 238 / 255)
	GRAY = RGB(187 / 255, 187 / 255, 187 / 255)
	RED = RGB(238 / 255, 102 / 255, 119 / 255)

    # show -
    nothing
end

# ╔═╡ a0e130f0-fe63-4c2b-9250-3a22b1dd6be4
md"""
## Classical Portfolio Management: Markowitz Mean-Variance Portfolio Theory
"""

# ╔═╡ 530772fd-e03e-466f-a095-74e3ca89cef8
md"""
### Introduction

Portfolio allocation is a classic problem in mathematical finance. Suppose we have a basket of $i=1,2,\dots,\mathcal{P}$ risky assets e.g., individual stocks or exchange-traded funds (ETFs) and we must estimate the relative proportion $\omega_{i}$ of each asset in the basket so that we achieve some objective, for example, a specified minimum growth rate (return).

The [Markowitz Mean-Variance Portfolio Theory](https://en.wikipedia.org/wiki/Modern_portfolio_theory) is the classical approach for computing the portfolio asset allocations $\omega_{i},i=1,2,\dots\mathcal{P}$ first published in 1952:

* [Markowitz, H. (1952). Portfolio Selection. The Journal of Finance, 7(1), 77–91. https://doi.org/10.2307/2975974](https://www.jstor.org/stable/2975974)

Mean-variance portfolio theory assumes that investors are rational and risk-averse. Thus, when given two portfolios that offer the same expected return, a _rational investor_ prefers the _less risky_ portfolio. Further, an investor will take on increased risk only if they are compensated by higher expected returns. On the other hand, investors who want higher expected returns must assume more risk to achieve these desired returns. Individual investors evaluate the trade-off between risk and reward differently based upon their own risk aversion characteristics.
"""

# ╔═╡ 68a3dce4-2a89-4cf4-ae3d-0230abe179fb
md"""
### Materials and Methods
"""

# ╔═╡ c0b2f1ac-90a6-4d5a-ba55-2e679a1a982f

# ╔═╡ ee1a82c2-a485-4e9a-8b08-323f174bedd5
md"""
### Results and Discussion
"""

# ╔═╡ 9bc330e1-0353-44f2-967a-2f825fb11eae
ticker_symbol_array = [
	"SPY", "SPYD", "SPYG", "SPYV", "SPYX", "VOO", "VTI", "VEA", "VWO", "VNQ", "VGK", "AAPL", "ALLY"
];

# ╔═╡ 4c417596-f5c5-445b-9806-00ea4fbc4c9c
# How many tickers do we have?
𝒫 = length(ticker_symbol_array);

# ╔═╡ 96fb3275-7be3-4611-96ab-46b805477ad4
# what is my budget?
budget_total = 2750.0; # USD

# ╔═╡ 57e56bcf-59a1-4ef9-9394-636d4ecaac96

# ╔═╡ 7cc32583-0ece-4319-b0b1-33583ceae14b
md"""
### Conclusions
"""

# ╔═╡ e7ef9b22-aee2-442d-9021-218e10cf9e30
function ingredients(path::String)

	# this is from the Julia source code (evalfile in base/loading.jl)
	# but with the modification that it returns the module instead of the last object
	name = Symbol("Serenity")
	m = Module(name)
	Core.eval(m,
        Expr(:toplevel,
             :(eval(x) = $(Expr(:core, :eval))($name, x)),
             :(include(x) = $(Expr(:top, :include))($name, x)),
             :(include(mapexpr::Function, x) = $(Expr(:top, :include))(mapexpr, $name, x)),
             :(include($path))))
	m
end

# ╔═╡ d8309e86-d613-4987-a87b-0314a7f4ddad
Serenity = ingredients(joinpath(_PATH_TO_SRC, "Include.jl"));

# ╔═╡ 49f6a628-a7cf-4f56-883f-0715f569abca
function download_ticker_data(ticker_symbol_array::Array{String,1})::Dict{String,DataFrame}

    # initialize some storage -
    price_data_dictionary = Dict{String,DataFrame}() # Dict key => ticker symbol and value = price DataFrame

    # setup: specify the query parameters for the call to Alphavantage -
    # check out the API documentation: https://www.alphavantage.co/documentation/
    query_parameters = Dict{String,String}()
    query_parameters["function"] = "TIME_SERIES_DAILY_ADJUSTED" # get the daily close price adjusted
    query_parameters["apikey"] = ALPHAVANTAGE_API_KEY # your alphavantage API key goes here (config block below)
    query_parameters["datatype"] = "csv" # download in CSV (the other option is JSON) format
    query_parameters["outputsize"] = "full" # compact -vs- full: last 100 trading days -vs- up to 20 years of data

    # data type: sub dir where we save the data
    data_type_flag = "daily"
    training_prediction_flag = "training"

    # main download loop -
    for ticker_symbol in ticker_symbol_array

        # check -> have we downloaded this data already?
        data_file_path = joinpath(_PATH_TO_DATA, "$(training_prediction_flag)", "$(data_type_flag)",
            "$(ticker_symbol).csv")
        if (ispath(data_file_path) == false || Serenity.does_data_file_exist(data_file_path) == false)

            # let use know what is going on ...
            with_terminal() do
                println("Starting $(ticker_symbol) download ...")
            end

            # We do NOT have this data file -> download from Alphavantage.co
            # execute API call -> check to see if error -> turn into DataFrame
            query_parameters["symbol"] = ticker_symbol
            url_string = Serenity.build_url_query_string(DATASTORE_URL_STRING, query_parameters)
            data_table = Serenity.http_get_call_with_url(url_string) |> Serenity.check |>
				Serenity.process_csv_api_data

            # sleep -
            sleep(10) # to avoid issue w/API limits

            # make the dir to save the data (if we don't have it already) -
            mkpath(joinpath(_PATH_TO_DATA, "$(training_prediction_flag)", "$(data_type_flag)"))

            # dump data table to disk -
            CSV.write(data_file_path, data_table)

            # put the price DataFrame into the price_data_dictionary -
            price_data_dictionary[ticker_symbol] = data_table

        else

            # we already have this ticker downloaded. load the existing file from disk -
            data_table = CSV.read(data_file_path, DataFrame)

            # put the price DataFrame into the price_data_dictionary -
            price_data_dictionary[ticker_symbol] = data_table
        end
    end

    # show -
    return price_data_dictionary
end

# ╔═╡ 4975330e-565f-4419-9aa4-33bbd2ebdcbc
# load the historical price data from disk (if not saved, then download new data)
historical_price_dictionary = download_ticker_data(ticker_symbol_array);

# ╔═╡ 31740764-d1e0-4228-a045-ebf785987e71
historical_return_dictionary = Serenity.compute_fractional_return_array(ticker_symbol_array,
	historical_price_dictionary, :timestamp=>:adjusted_close, multiplier=100.0);

# ╔═╡ 0b85225d-e6f1-4f68-94ac-76e8a79a1a02
begin

	# what date range are we interested in?
	start = Date(2020,12,17);
	stop = Date(2021,12,17);

	# compute the average return and Σ -
	(μ_bar, Σ) = Serenity.compute_average_fractional_return_and_covariance(ticker_symbol_array, historical_return_dictionary,
		start, stop);

	# show -
	nothing
end

# ╔═╡ b11ff814-ecde-4a5c-b185-a8abd87a49fc
# compute the minvar portfolio -
result = Serenity.compute_minvar_portfolio_allocation(μ_bar,Σ, 0.01; w_lower=0.0,w_upper=1.0);

# ╔═╡ 99055948-b794-4f05-a31d-b3a2875ac857
ω = max.(0.0,result[2])

# ╔═╡ 1204dfc0-5e46-4c72-bafe-f126c9a2365f
expected_return = (1+(result[4]/100))^(252) - 1

# ╔═╡ 6b7af0b9-65a4-4dc3-a4a4-ef165dcb3959
md"""
__Table XX__: Markowitz allocation table for 𝒫 = $(𝒫) assets in the ticker array (a mixture of different ETFs).
This allocation has variance = $(round(result[3], sigdigits=4)) with a projected daily return = $(round(result[4], sigdigits=2))% (or an $(round(expected_return*100,sigdigits=4))% average return per year).
"""

# ╔═╡ fdc668ac-ece6-4edb-aba8-77a2a51e6817
with_terminal() do

	# make a table with the allocation -
	optimal_flag = result[1] # type MathOptInterface
	w = result[2]

	if (optimal_flag == MathOptInterface.OPTIMAL)

		state_table = Array{Any,2}(undef, 𝒫, 3)
		for (index, ticker) ∈ enumerate(ticker_symbol_array)
			state_table[index,1] = ticker
			state_table[index,2] = abs(w[index]) < 1e-4 ? 0.0 : round(w[index],sigdigits=2)
			state_table[index,3] = budget_total*state_table[index,2]
		end

		state_table_header = (
			["ticker","wᵢ","USD"],["","","USD"]
		)

		pretty_table(state_table, header=state_table_header)
	else
		println("No optimal solution found. Solver returned: $(optimal_flag)")
	end
end

# ╔═╡ aea955b7-dd61-4056-8a24-bf973b841c00
# compute the cybere
u_variable = Serenity.compute_cybernetic_portfolio_allocation(μ_bar, Σ);

# ╔═╡ 832354e4-52f8-4ba2-9086-80da857b82c3
with_terminal() do
	state_table = Array{Any,2}(undef, 𝒫, 3)
	for (index, ticker) ∈ enumerate(ticker_symbol_array)
		state_table[index,1] = ticker
		state_table[index,2] = abs(u_variable[index]) < 1e-4 ? 0.0 : round(u_variable[index],sigdigits=2)
		state_table[index,3] = budget_total*state_table[index,2]
	end

	state_table_header = (
		["ticker","uᵢ","USD"],["","","USD"]
	)

	pretty_table(state_table, header=state_table_header)
end

# ╔═╡ 1b43142b-de39-43d4-aeea-e9fd4a9f7a6c
WA_cybernetic = Serenity.simulate_insample_portfolio_allocation(ticker_symbol_array,historical_return_dictionary, u_variable,
	budget_total, Date(2021,1,17), stop; multiplier=(1.0/100.0));

# ╔═╡ 8cc221da-cb6b-4897-97a5-5376df98342e
WA_markowitz = Serenity.simulate_insample_portfolio_allocation(ticker_symbol_array,historical_return_dictionary, ω,
	budget_total, Date(2021,1,17), stop; multiplier=(1.0/100.0));

# ╔═╡ 3459367f-24e1-46b0-89b6-5165d5ebc00d
begin
	plot(sum(WA_cybernetic, dims=2), legend=:topleft, c=RED, lw=2, label="Cybernetic")
	plot!(sum(WA_markowitz,dims=2),lw=2,c=BLUE, label="Markowitz")
	xlabel!("Time step index (AU)", fontsize=18)
	ylabel!("Wealth (USD)", fontsize=18)
end

# ╔═╡ c3647093-c7d8-4ce6-95f3-85d2517b4bfd
begin

	# monthly reallocation -
	number_of_test_months = 12
	wealth_array = Array{Array{Float64,2},1}()
	b = 2750.0
	UA = Array{Float64,2}(undef, number_of_test_months-1, 𝒫)
	base_month = Date(2020,12,17);

	for month_index ∈ 2:number_of_test_months

		if (month_index > 2)
			W = last(wealth_array)
			b = last(sum(W,dims=2))
		end

		# what is the next month -
		previous_month = Date(2021,(month_index - 1),17);
		next_month = Date(2021,month_index,17);

		# compute the average return and cov for base -> next_month -
		(μ_bar_month, Σ_month) = Serenity.compute_average_fractional_return_and_covariance(ticker_symbol_array,
			historical_return_dictionary, base_month, next_month);

		# compute u-var -
		u_variable_month = Serenity.compute_cybernetic_portfolio_allocation(μ_bar_month, Σ_month);

		# update UA -
		for (i,u) ∈ enumerate(u_variable_month)
			UA[month_index-1,i] = u
		end

		# compute cybernetic allocation -
		WA_cybernetic_month = Serenity.simulate_insample_portfolio_allocation(ticker_symbol_array,historical_return_dictionary,
				u_variable_month, b, previous_month, next_month; multiplier=(1.0/100.0));

		# grab this month -
		push!(wealth_array,WA_cybernetic_month);
	end
end

# ╔═╡ 4ae85196-b25a-4dbf-b4ff-1c910d7ea392
with_terminal() do

	(nr,nc) = size(UA)
	state_table = Array{Any,2}(undef,𝒫, nr+1)
	for (index,ticker) ∈ enumerate(ticker_symbol_array)
		state_table[index,1] = ticker

		for tmp = 1:nr
			state_table[index,tmp + 1] = UA[tmp,index]
		end
	end

	pretty_table(state_table)
end

# ╔═╡ 3f488680-fd2b-4d3d-9eac-e64ff6d725c7
WC = vcat(wealth_array...)

# ╔═╡ 79e92731-b9e5-4518-a09a-2b0181a37359
begin

	# monthly reallocation -
	wealth_array_m = Array{Array{Float64,2},1}()
	total_row_count_m = 0
	b_m = 2750.0

	for month_index ∈ 2:number_of_test_months

		if (month_index > 2)
			W = last(wealth_array_m)
			b_m = last(sum(W,dims=2))
		end

		# what is the next month -
		previous_month = Date(2021,(month_index - 1),17);
		next_month = Date(2021,month_index,17);

		# compute the average return and cov for base -> next_month -
		(μ_bar_month, Σ_month) = Serenity.compute_average_fractional_return_and_covariance(ticker_symbol_array,
			historical_return_dictionary, base_month, next_month);

		# compute u-var -
		result = Serenity.compute_minvar_portfolio_allocation(μ_bar_month,Σ_month, 0.04; w_lower=0.0,w_upper=1.0);
		ω_variable_month = max.(0.0,result[2])

		# compute cybernetic allocation -
		WA_markowitz_m = Serenity.simulate_insample_portfolio_allocation(ticker_symbol_array,historical_return_dictionary,
			ω_variable_month, b_m, previous_month, next_month; multiplier=(1.0/100.0));

		# grab this month -
		push!(wealth_array_m,WA_markowitz_m);
	end
end

# ╔═╡ 338c1f4d-a85c-4bf2-8bc0-f099fa345824
WM = vcat(wealth_array_m...)

# ╔═╡ 87913c8b-4cf5-4f92-9992-d5cc94cd138d
begin
	plot(sum(WA_cybernetic, dims=2), legend=:topleft, c=GRAY, label="Cybernetic (annual)")
	plot!(sum(WA_markowitz, dims=2), legend=:topleft, c=LBLUE, label="Markowitz (annual)")
	plot!(sum(WC,dims=2), c=RED, label="Cybernetic", lw=2)
	plot!(sum(WM,dims=2),lw=2,c=BLUE, label="Markowitz")
end

# ╔═╡ 1d6818a0-5ffe-11ec-393e-5bcad6dcfdab
html"""
<style>
main {
    max-width: 1200px;
    width: 75%;
    margin: auto;
    font-family: "Roboto, monospace";
}

a {
    color: blue;
    text-decoration: none;
}

.H1 {
    padding: 0px 30px;
}
</style>"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Convex = "f65535da-76fb-5f13-bab9-19810c17039a"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
HypothesisTests = "09f84164-cd44-5f33-b23f-e6b0d136a0d5"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
SCS = "c946c3f1-0d1f-5ce8-9dea-7daa1f7e2d13"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[compat]
CSV = "~0.9.11"
Colors = "~0.12.8"
Convex = "~0.14.18"
DataFrames = "~1.3.0"
Distributions = "~0.25.36"
HTTP = "~0.9.17"
HypothesisTests = "~0.10.6"
MathOptInterface = "~0.10.6"
Optim = "~1.5.0"
PlutoUI = "~0.7.24"
PrettyTables = "~1.2.3"
SCS = "~0.8.1"
StatsPlots = "~0.14.29"
"""

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

julia_version = "1.7.0"
manifest_format = "2.0"

[[deps.AMD]]
deps = ["Libdl", "LinearAlgebra", "SparseArrays", "Test"]
git-tree-sha1 = "fc66ffc5cff568936649445f58a55b81eaf9592c"
uuid = "14f7f29c-3bd6-536c-9a0b-7339e30b5a3e"
version = "0.4.0"

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

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "abb72771fd8895a7ebd83d5632dc4b989b022b5b"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.2"

[[deps.AbstractTrees]]
git-tree-sha1 = "03e0550477d86222521d254b741d470ba17ea0b5"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
version = "0.3.4"

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

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

[[deps.Arpack]]
deps = ["Arpack_jll", "Libdl", "LinearAlgebra"]
git-tree-sha1 = "2ff92b71ba1747c5fdd541f8fc87736d82f40ec9"
uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97"
version = "0.4.0"

[[deps.Arpack_jll]]
deps = ["Libdl", "OpenBLAS_jll", "Pkg"]
git-tree-sha1 = "e214a9b9bd1b4e1b4f15b22c0994862b66af7ff7"
uuid = "68821587-b530-5797-8361-c406ea357684"
version = "3.5.0+3"

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

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

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

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

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

[[deps.BinaryProvider]]
deps = ["Libdl", "Logging", "SHA"]
git-tree-sha1 = "ecdec412a9abc8db54c0efc5548c64dfce072058"
uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
version = "0.5.10"

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

[[deps.CSV]]
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings"]
git-tree-sha1 = "49f14b6c56a2da47608fe30aed711b5882264d7a"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.9.11"

[[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 = "4b859a208b2397a7a623a03449e4636bdb17bcf2"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+1"

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

[[deps.ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

[[deps.Clustering]]
deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "75479b7df4167267d75294d14b58244695beb2ac"
uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"
version = "0.14.2"

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

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

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

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

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

[[deps.Combinatorics]]
git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
version = "1.0.2"

[[deps.CommonSolve]]
git-tree-sha1 = "68a0743f578349ada8bc911a5cbd5a2ef6ed6d1f"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.0"

[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"

[[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 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.0"

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

[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f74e9d5388b8620b4cee35d4c5a618dd4dc547f4"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.3.0"

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

[[deps.Convex]]
deps = ["AbstractTrees", "BenchmarkTools", "LDLFactorizations", "LinearAlgebra", "MathOptInterface", "OrderedCollections", "SparseArrays", "Test"]
git-tree-sha1 = "145c5e0b3ea3c9dd3bba134a58bab4112aa250c8"
uuid = "f65535da-76fb-5f13-bab9-19810c17039a"
version = "0.14.18"

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

[[deps.DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.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 = "2e993336a3f68216be91eb8ee4625ebbaba19147"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.3.0"

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

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

[[deps.DataValues]]
deps = ["DataValueInterfaces", "Dates"]
git-tree-sha1 = "d88a19299eba280a6d062e135a43f00323ae70bf"
uuid = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5"
version = "0.4.13"

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

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

[[deps.DensityInterface]]
deps = ["InverseFunctions", "Test"]
git-tree-sha1 = "80c3e8639e3353e5d2912fb3a1916b8455e2494b"
uuid = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
version = "0.4.0"

[[deps.DiffResults]]
deps = ["StaticArrays"]
git-tree-sha1 = "c18e98cba888c6c25d1c3b048e4b3380ca956805"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.0.3"

[[deps.DiffRules]]
deps = ["LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "9bc5dac3c8b6706b58ad5ce24cffd9861f07c94f"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.9.0"

[[deps.Distances]]
deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "3258d0659f812acde79e8a74b11f17ac06d0ca04"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.7"

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

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

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

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

[[deps.EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+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.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", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "d8a578692e3077ac998b50c0217dfd67f21d1e5f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.4.0+0"

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

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

[[deps.FilePathsBase]]
deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
git-tree-sha1 = "04d13bfa8ef11720c24e4d840c0033d145537df7"
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
version = "0.9.17"

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

[[deps.FiniteDiff]]
deps = ["ArrayInterface", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays"]
git-tree-sha1 = "8b3c09b56acaf3c0e581c66638b85c8650ee9dca"
uuid = "6a86dc24-6348-571c-b903-95158fe2bd41"
version = "2.8.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 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

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

[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions", "StaticArrays"]
git-tree-sha1 = "2b72a5624e289ee18256111657663721d59c143e"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.24"

[[deps.FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

[[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.GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "0c603255764a1fa0b61752d2bec14cfbd18f7fe8"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+1"

[[deps.GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "30f2b340c2fff8410d89bfcdc9c0a6dd661ac5f7"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.62.1"

[[deps.GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "fd75fa3a2080109a2c0ec9864a6e14c60cca3866"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.62.0+0"

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

[[deps.Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.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 = "a32d672ac2c967f3deb8a81d828afc739c838a06"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+2"

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

[[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 = "0fa77022fe4b511826b39c894c90daf5fce3334a"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.17"

[[deps.HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "129acf094d168394e80ee1dc4bc06ec835e510a3"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+1"

[[deps.Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[deps.HypertextLiteral]]
git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.3"

[[deps.HypothesisTests]]
deps = ["Combinatorics", "Distributions", "LinearAlgebra", "Random", "Rmath", "Roots", "Statistics", "StatsBase"]
git-tree-sha1 = "dc9bb7abfa265e0cf030635315184a476a2dd5f3"
uuid = "09f84164-cd44-5f33-b23f-e6b0d136a0d5"
version = "0.10.6"

[[deps.IOCapture]]
deps = ["Logging", "Random"]
git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a"
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
version = "0.2.2"

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

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

[[deps.InlineStrings]]
deps = ["Parsers"]
git-tree-sha1 = "8d70835a3759cdd75881426fced1508bb7b7e1b6"
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
version = "1.1.1"

[[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 = "b15fc0a95c564ca2e0a7ae12c1f095ca848ceb31"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.5"

[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[deps.InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

[[deps.IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[deps.IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.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.JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[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.LDLFactorizations]]
deps = ["AMD", "LinearAlgebra", "SparseArrays", "Test"]
git-tree-sha1 = "399bbe845e06e1c2d44ebb241f554d45eaf66788"
uuid = "40e66cde-538c-5869-a4ad-c39174c6795b"
version = "0.8.1"

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

[[deps.LaTeXStrings]]
git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

[[deps.Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a8f4f279b6fa3c3c4f1adadd78a621b13a506bce"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.9"

[[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.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

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

[[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.Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[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.Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.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.LineSearches]]
deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"]
git-tree-sha1 = "f27132e551e959b3667d8c93eae90973225032dd"
uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
version = "7.1.1"

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

[[deps.LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

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

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

[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "3d3e902b31198a27340d0bf00d6ac452866021cf"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.9"

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

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

[[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.Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

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

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

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

[[deps.MultivariateStats]]
deps = ["Arpack", "LinearAlgebra", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "8d958ff1854b166003238fe191ec34b9d592860a"
uuid = "6f286f6a-111f-5878-ab1e-185364afe411"
version = "0.8.0"

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

[[deps.NLSolversBase]]
deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"]
git-tree-sha1 = "50310f934e55e5ca3912fb941dec199b49ca9b68"
uuid = "d41bc354-129a-5804-8e4c-c37616107c6c"
version = "7.8.2"

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

[[deps.NearestNeighbors]]
deps = ["Distances", "StaticArrays"]
git-tree-sha1 = "16baacfdc8758bc374882566c9187e785e85c2f0"
uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
version = "0.4.9"

[[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 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

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

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[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.Optim]]
deps = ["Compat", "FillArrays", "ForwardDiff", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"]
git-tree-sha1 = "35d435b512fbab1d1a29138b5229279925eba369"
uuid = "429524aa-4258-5aef-a3af-852621145aeb"
version = "1.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.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 = "ee26b350276c51697c9c2d88a072b339f9f03d73"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.5"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

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

[[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.PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

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

[[deps.Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs", "UnicodeFun"]
git-tree-sha1 = "65ebc27d8c00c84276f14aaf4ff63cbe12016c70"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.25.2"

[[deps.PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "6c9fa3e4880242c666dafa4901a34d8e1cd1b243"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.24"

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

[[deps.PositiveFactorizations]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "17275485f373e6673f7e7f97051f703ed5b15b20"
uuid = "85a6dd25-e78a-55b7-8502-1745935b8125"
version = "0.2.4"

[[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 = "d940010be611ee9d67064fe559edbb305f8cc0eb"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.2.3"

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

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

[[deps.Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+0"

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

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

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

[[deps.Ratios]]
deps = ["Requires"]
git-tree-sha1 = "01d341f502250e81f6fec0afe662aa861392a3aa"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.2"

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

[[deps.RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "7ad0dfa8d03b7bcf8c597f59f5292801730c55b8"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.1"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "8f82019e525f4d5c669692772a6f4b0a58b06a6a"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.2.0"

[[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.Roots]]
deps = ["CommonSolve", "Printf", "Setfield"]
git-tree-sha1 = "5f69d1e2173de445c2f1c374dab9c6b3af5275a5"
uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
version = "1.3.12"

[[deps.SCS]]
deps = ["BinaryProvider", "Libdl", "LinearAlgebra", "MathOptInterface", "Requires", "SCS_GPU_jll", "SCS_jll", "SparseArrays"]
git-tree-sha1 = "c819d023621358f3c08f08d41bd9354cf1357d35"
uuid = "c946c3f1-0d1f-5ce8-9dea-7daa1f7e2d13"
version = "0.8.1"

[[deps.SCS_GPU_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "OpenBLAS_jll", "Pkg"]
git-tree-sha1 = "a96402e3b494a8bbec61b1adb86d4be04112c646"
uuid = "af6e375f-46ec-5fa0-b791-491b0dfa44a4"
version = "2.1.4+0"

[[deps.SCS_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "OpenBLAS_jll", "Pkg"]
git-tree-sha1 = "6cdaccb5e6a69455f960de1ae445ba1de5db9d0d"
uuid = "f4f2fc5b-1d94-523c-97ea-2ab488bedf4b"
version = "2.1.2+1"

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

[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

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

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

[[deps.Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "Requires"]
git-tree-sha1 = "0afd9e6c623e379f593da01f20590bacc26d1d14"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "0.8.1"

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

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

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

[[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", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "e08890d19787ec25029113e88c34ec20cac1c91e"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.0.0"

[[deps.Static]]
deps = ["IfElse"]
git-tree-sha1 = "7f5a513baec6f122401abfc8e9c074fdac54f6c1"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.4.1"

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

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

[[deps.StatsAPI]]
git-tree-sha1 = "0f2aa8e32d511f758a2ce49208181f7733a0936a"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.1.0"

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

[[deps.StatsFuns]]
deps = ["ChainRulesCore", "InverseFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "bedb3e17cc1d94ce0e6e66d3afa47157978ba404"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.14"

[[deps.StatsPlots]]
deps = ["Clustering", "DataStructures", "DataValues", "Distributions", "Interpolations", "KernelDensity", "LinearAlgebra", "MultivariateStats", "Observables", "Plots", "RecipesBase", "RecipesPipeline", "Reexport", "StatsBase", "TableOperations", "Tables", "Widgets"]
git-tree-sha1 = "d6956cefe3766a8eb5caae9226118bb0ac61c8ac"
uuid = "f3b207a7-027a-5e70-b257-86293d7955fd"
version = "0.14.29"

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

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

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

[[deps.TableOperations]]
deps = ["SentinelArrays", "Tables", "Test"]
git-tree-sha1 = "e383c87cf2a1dc41fa30c093b2a19877c83e1bc1"
uuid = "ab02a1b2-a7df-11e8-156e-fb1833f50b87"
version = "1.2.0"

[[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 = "bb1064c9a84c52e277f1096cf41434b675cd368b"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.6.1"

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

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

[[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.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[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.Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[deps.Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.0+0"

[[deps.WeakRefStrings]]
deps = ["DataAPI", "InlineStrings", "Parsers"]
git-tree-sha1 = "c69f9da3ff2f4f02e811c3323c22e5dfcb584cfa"
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
version = "1.4.1"

[[deps.Widgets]]
deps = ["Colors", "Dates", "Observables", "OrderedCollections"]
git-tree-sha1 = "80661f59d28714632132c73779f8becc19a113f2"
uuid = "cc8bc4a8-27d6-5769-a93b-9d913e69aa62"
version = "0.6.4"

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

[[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_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+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_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[deps.Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[deps.Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[deps.Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+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_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[deps.Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[deps.Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[deps.Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[deps.Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[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.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.libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.15.1+0"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

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

[[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.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.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 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[deps.x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"

[[deps.xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╟─a0e130f0-fe63-4c2b-9250-3a22b1dd6be4
# ╟─530772fd-e03e-466f-a095-74e3ca89cef8
# ╟─68a3dce4-2a89-4cf4-ae3d-0230abe179fb
# ╠═c0b2f1ac-90a6-4d5a-ba55-2e679a1a982f
# ╟─ee1a82c2-a485-4e9a-8b08-323f174bedd5
# ╠═9bc330e1-0353-44f2-967a-2f825fb11eae
# ╠═4c417596-f5c5-445b-9806-00ea4fbc4c9c
# ╠═4975330e-565f-4419-9aa4-33bbd2ebdcbc
# ╠═31740764-d1e0-4228-a045-ebf785987e71
# ╠═0b85225d-e6f1-4f68-94ac-76e8a79a1a02
# ╠═b11ff814-ecde-4a5c-b185-a8abd87a49fc
# ╠═96fb3275-7be3-4611-96ab-46b805477ad4
# ╠═99055948-b794-4f05-a31d-b3a2875ac857
# ╠═1204dfc0-5e46-4c72-bafe-f126c9a2365f
# ╟─6b7af0b9-65a4-4dc3-a4a4-ef165dcb3959
# ╟─fdc668ac-ece6-4edb-aba8-77a2a51e6817
# ╠═aea955b7-dd61-4056-8a24-bf973b841c00
# ╠═832354e4-52f8-4ba2-9086-80da857b82c3
# ╠═1b43142b-de39-43d4-aeea-e9fd4a9f7a6c
# ╠═8cc221da-cb6b-4897-97a5-5376df98342e
# ╠═57e56bcf-59a1-4ef9-9394-636d4ecaac96
# ╠═3459367f-24e1-46b0-89b6-5165d5ebc00d
# ╠═c3647093-c7d8-4ce6-95f3-85d2517b4bfd
# ╠═4ae85196-b25a-4dbf-b4ff-1c910d7ea392
# ╠═79e92731-b9e5-4518-a09a-2b0181a37359
# ╠═338c1f4d-a85c-4bf2-8bc0-f099fa345824
# ╠═3f488680-fd2b-4d3d-9eac-e64ff6d725c7
# ╠═87913c8b-4cf5-4f92-9992-d5cc94cd138d
# ╟─7cc32583-0ece-4319-b0b1-33583ceae14b
# ╠═2f67f6bf-832e-4bb7-bdda-576ea37e98c8
# ╠═d8309e86-d613-4987-a87b-0314a7f4ddad
# ╠═49f6a628-a7cf-4f56-883f-0715f569abca
# ╟─e7ef9b22-aee2-442d-9021-218e10cf9e30
# ╟─1d6818a0-5ffe-11ec-393e-5bcad6dcfdab
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: Pooksoft/Serenity

max_issues_repo_name: Alba-Intelligence/Serenity

max_forks_repo_name: Alba-Intelligence/Serenity


text:
using Documenter
using FoldsCUDA
using FLoops
using Literate
using LiterateTest
using LoadAllPackages

LoadAllPackages.loadall(joinpath((@__DIR__), "Project.toml"))

PAGES = [
    "index.md",
    "Examples" => [
        "`findminmax`" => "examples/findminmax.md",
        "Histogram of MSD" => "examples/histogram_msd.md",
        "Monte-Carlo π" => "examples/monte_carlo_pi.md",
        "In-place mutation with Referenceables.jl" =>
            "examples/inplace_mutation_with_referenceables.md",
        "Partition reduce" => "examples/reduce_partition_by.md",
    ],
    hide("deprecated.md"),
]

let example_dir = joinpath(dirname(@__DIR__), "examples")
    examples = Pair{String,String}[]

    for subpages in PAGES
        subpages isa Pair || continue
        subpages[1] == "Examples" || continue
        for (_, mdpath) in subpages[2]::Vector
            stem, _ = splitext(basename(mdpath))
            jlpath = joinpath(example_dir, "$stem.jl")
            if !isfile(jlpath)
                @info "`$jlpath` does not exist. Skipping..."
                continue
            end
            push!(examples, jlpath => joinpath(@__DIR__, "src", dirname(mdpath)))
        end
    end

    @info "Compiling example files" examples
    for (jlpath, dest) in examples
        Literate.markdown(jlpath, dest; config = LiterateTest.config(), documenter = true)
    end
end

write(
    joinpath(@__DIR__, "src", "examples.md"),
    """
    # [Examples](@id examples-toc)
    ```@contents
    Pages = $(repr(last.(only(p for p in PAGES if p isa Pair && p[1] == "Examples")[2])))
    Depth = 3
    ```
    """,
)

makedocs(
    # See:
    # https://juliadocs.github.io/Documenter.jl/stable/lib/public/#Documenter.makedocs
    sitename = "FoldsCUDA",
    format = Documenter.HTML(),
    modules = [FoldsCUDA],
    pages = PAGES,
    doctest = false,
    strict = true,
)

deploydocs(
    # See:
    # https://juliadocs.github.io/Documenter.jl/stable/lib/public/#Documenter.deploydocs
    repo = "github.com/JuliaFolds/FoldsCUDA.jl",
    push_preview = true,
)


text:
export ncores, nphysicalcores, systemload, normload, setnumworkers, @timedone

@static if is_apple() ncores() = asint(readall(`sysctl -n hw.ncpu`)) end
@static if is_apple() nphysicalcores() = asint(readall(`sysctl -n hw.physicalcpu`)) end
@static if is_linux() ncores() = asint(readall(`nproc --all`)) end
@static if is_linux() nphysicalcores() = div(ncores(),2) end

rmcomma(a) = a[end]==',' ? a[1:end-1] : a
systemload() = parsefloat(rmcomma(split(readall(`uptime`))[end-2]))
normload() = systemload()/ncores()

function setnumworkers(n)
    oldn = nprocs()-1
    if n>oldn
        return addprocs(n-oldn)
    elseif n<oldn
        rmthese = workers()[end-(oldn-n)+1:end]
    end
end

macro timedone(a, ex)
    quote
        local t = time()
        println($a, " ... ")
        flush(STDOUT)
        r = $ex
        local elapsed = round((time()-t)*100)/100
        println("    done, $elapsed sec!")
        flush(STDOUT)
        r
    end
end


text:
using TabularMakie
using ReTest

retest(TabularMakie)

@testset "TabularMakie.jl" begin
    include(joinpath("..", "nb", "notebook.jl"))
end

max_stars_repo_name: greimel/TabularMakie

max_issues_repo_name: greimel/TabularMakie

max_forks_repo_name: greimel/TabularMakie


text:
module ESDC
import YAXArrays.Datasets: Dataset, Cube, open_dataset
using Zarr: S3Store, zopen, AWS
using Dates: Dates, now
export esdc, esdd
global cubesdict

function __init__()
  global cubesdict
  cubesdict = Dict(
    ("low","ts","global") => ("esdl-esdc-v2.1.1","esdc-8d-0.25deg-184x90x90-2.1.1.zarr"),
    ("low","map","global") => ("esdl-esdc-v2.1.1","esdc-8d-0.25deg-1x720x1440-2.1.1.zarr"),
    ("high","ts","global") => ("esdl-esdc-v2.1.1","esdc-8d-0.083deg-184x270x270-2.1.1.zarr"),
    ("high","map","global") => ("esdl-esdc-v2.1.1","esdc-8d-0.083deg-1x2160x4320-2.1.1.zarr"),
    ("low","ts","Colombia") => ("esdl-esdc-v2.0.1","Cube_2019lowColombiaCube_184x60x60.zarr"),
    ("low","map","Colombia") => ("esdl-esdc-v2.0.1","Cube_2019lowColombiaCube_1x336x276.zarr/"),
    ("high","ts","Colombia") => ("esdl-esdc-v2.0.1","Cube_2019highColombiaCube_184x120x120.zarr"),
    ("high","map","Colombia") => ("esdl-esdc-v2.0.1","Cube_2019highColombiaCube_1x3360x2760.zarr"),
  )
end

"""
    function esdd(;kwargs...)

Opens a datacube from the AWS as a Dataset. This works on any system, but
might involve some latency depending on connection speed. One can either specify a `bucket`
and `store` or pick a resolution, chunking and cube region.

### Keyword arguments

  * `bucket=nothing` specify an OBS bucket for example "obs-esdc-v2.0.0"
  * `store=""` specify the root path of the cube, for example "esdc-8d-0.25deg-184x90x90-2.0.0.zarr"
  * `res="low"` pick a datacube resolution (`"low"` or `"high"`)
  * `chunks="ts"` choose a chunking (`"ts"` for time series access or `"map"` for spatial analyses)
  * `region="global"` choose a datacube (either `"global"` or `"Colombia"`)
"""
function esdd(;bucket=nothing, store="", res="low", chunks="ts", region="global")
  if bucket===nothing
    bucket, store = cubesdict[(res,chunks,region)]
  end
  path = "https://s3.bgc-jena.mpg.de:9000/" * bucket * "/" * store
  open_dataset(zopen(path,consolidated=true))
end

"""
    function esdc(;kwargs...)

Opens a datacube from the AWS as a Dataset. This works on any system, but
might involve some latency depending on connection speed. One can either specify a `bucket`
and `store` or pick a resolution, chunking and cube region.

### Keyword arguments

  * `bucket=nothing` specify an OBS bucket for example "obs-esdc-v2.0.0"
  * `store=""` specify the root path of the cube, for example "esdc-8d-0.25deg-184x90x90-2.0.0.zarr"
  * `res="low"` pick a datacube resolution (`"low"` or `"high"`)
  * `chunks="ts"` choose a chunking (`"ts"` for time series access or `"map"` for spatial analyses)
  * `region="global"` choose a datacube (either `"global"` or `"Colombia"`)

"""
esdc(;kwargs...) = Cube(esdd(;kwargs...))

end # module