text:
##### Beginning of file

module Common # Begin submodule RepoSnapshots.Common

__precompile__(true)

import ..Types
import ..Utils

import ArgParse
import Dates
import HTTP
import Pkg
import TimeZones

import ..delayederror

function _toml_file_to_package(
        packagetoml_file_filename::String,
        )::Types.Package
    toml_file_text::String = read(packagetoml_file_filename, String)
    toml_file_parsed::Dict{String,Any}=Pkg.TOML.parse(toml_file_text)
    pkg_name::String = toml_file_parsed["name"]
    pkg_uuid::String = toml_file_parsed["uuid"]
    pkg_source_url::String = toml_file_parsed["repo"]
    pkg::Types.Package = Types.Package(
        ;
        name=pkg_name,
        uuid=pkg_uuid,
        source_url=pkg_source_url,
        )
    return pkg
end

function _get_uuid_from_toml_file(toml_file_filename::String)::String
    toml_file_text::String = read(toml_file_filename, String)
    toml_file_parsed::Dict{String,Any}=Pkg.TOML.parse(toml_file_text)
    uuid::String = toml_file_parsed["uuid"]
    return uuid
end

function _add_trailing_spaces(x::AbstractString, n::Integer)::String
    temp::String = strip(convert(String, x))
    if length(temp) >= n
        result::String = temp
    else
        deficit::Int = n - length(temp)
        result = string(temp, repeat(" ", deficit))
    end
    return result
end

function _names_that_fall_in_interval(
        list_of_names::Vector{T},
        interval::Types.AbstractInterval,
        ) where T <: AbstractString
    stripped_list_of_names = String[]
    for i = 1:length(list_of_names)
        push!(
            stripped_list_of_names,
            strip(convert(String, list_of_names[i],)),
            )
    end
    unique!(stripped_list_of_names)
    sort!(stripped_list_of_names)
    jth_name_falls_in_interval::Vector{Bool} = Vector{Bool}(
        undef,
        length(stripped_list_of_names),
        )
    for j = 1:length(stripped_list_of_names)
        jth_name = stripped_list_of_names[j]
        jth_name_falls_in_interval[j] = _interval_contains_x(
            interval,
            jth_name,
            )
    end
    sublist::Vector{String} = list_of_names[
        jth_name_falls_in_interval
        ]
    unique!(sublist)
    sort!(sublist)
    return sublist
end

function _interval_contains_x(
        interval::Types.NoBoundsInterval,
        x::AbstractString,
        )::Bool
    result::Bool = true
    return result
end

function _interval_contains_x(
        interval::Types.LowerAndUpperBoundInterval,
        x::AbstractString,
        )::Bool
    x_stripped::String = strip(convert(String, x))
    left::String = strip(interval.left)
    right::String = strip(interval.right)
    result::Bool = (left <= x_stripped) && (x_stripped < right)
    return result
end

function _interval_contains_x(
        interval::Types.LowerBoundOnlyInterval,
        x::AbstractString,
        )::Bool
    x_stripped::String = strip(convert(String, x))
    left::String = strip(interval.left)
    result::Bool = left <= x_stripped
    return result
end

function _interval_contains_x(
        interval::Types.UpperBoundOnlyInterval,
        x::AbstractString,
        )
    x_stripped::String = strip(convert(String, x))
    right::String = strip(interval.right)
    result::Bool = x_stripped < right
    return result
end

function _snapshot_repo!!(
        repo_name;
        src_provider,
        dst_provider,
        include_branches,
        exclude_branches,
        git_user_name,
        git_user_email,
        time_zone::Dates.TimeZone,
        is_dry_run::Bool,
        )::Nothing
    original_directory = pwd()
    @debug(
        "Snapshotting repo: $(repo_name)",
        )
    git::String = Utils._get_git_binary_path()
    dst_provider(:create_repo)(
        Dict(
            :repo_name => convert(String, repo_name),
            )
        )
    dst_url_with_auth = dst_provider(:get_destination_url)(
        ;
        repo_name = convert(String, repo_name),
        credentials = :with_auth,
        )
    dst_url_with_redacted_auth = dst_provider(:get_destination_url)(
        ;
        repo_name = convert(String, repo_name),
        credentials = :with_redacted_auth,
        )
    dst_url_without_auth = dst_provider(:get_destination_url)(
        ;
        repo_name = convert(String, repo_name),
        credentials = :without_auth,
        )
    temp_initialize_dst_parent = mktempdir()
    temp_initialize_dst_dir = joinpath(
        temp_initialize_dst_parent,
        "TMP_INIT_DST_DIR",
        )
    mkpath(temp_initialize_dst_dir)
    cd(temp_initialize_dst_dir)
    run(`$(git) init`)
    touch(".gitignore")
    Utils.git_add_all!()
    Utils.git_commit!(
        ;
        message = "First commit",
        committer_name = git_user_name,
        committer_email = git_user_email,
        allow_empty = false,
        )
    run(`$(git) remote add origin $(dst_url_with_auth)`)
    try
        run(`$(git) push origin master`)
    catch e
        @warn("ignoring exception: ", e,)
    end
    cd(original_directory)
    rm(
        temp_initialize_dst_parent;
        force = true,
        recursive = true,
        )
    dst_repo_parent = mktempdir()
    dst_repo_dir = joinpath(dst_repo_parent, "DSTREPO",)
    cd(dst_repo_parent)
    dst_repo_git_clone_command = `$(git) clone $(dst_url_without_auth) DSTREPO`
    before = () -> rm(
        # joinpath(temp_dir_repo_git_clone_mirror,"GITCLONEREPOREGULAR",);
        dst_repo_dir;
        force = true,
        recursive = true,
        )
    Utils.command_ran_successfully!!(
        dst_repo_git_clone_command;
        before = before,
        )
    cd(dst_repo_dir)
    run(`$(git) remote set-url origin --push $(dst_url_with_auth)`)

    src_repo_parent = mktempdir()
    src_repo_dir = joinpath(src_repo_parent, "SRCREPO",)
    cd(src_repo_parent)
    src_url_without_auth = src_provider(:get_src_url)(
        ;
        repo_name = convert(String, repo_name),
        credentials = :without_auth,
        )
    src_repo_git_clone_command = `$(git) clone $(src_url_without_auth) SRCREPO`
    @info(
        "Attempting to run command",
        src_repo_git_clone_command,
        pwd(),
        ENV["PATH"],
        )
    when_src_cloned = Dates.now(TimeZones.localzone(),)
    before = () -> rm(
        # joinpath(temp_dir_repo_git_clone_mirror,"GITCLONEREPOREGULAR",);
        src_repo_dir;
        force = true,
        recursive = true,
        )
    Utils.command_ran_successfully!!(
        src_repo_git_clone_command;
        before = before,
        )
    mkpath(src_repo_dir)
    cd(src_repo_dir)
    if Utils.git_status_success()
        default_branch = Utils.get_current_branch()
        branches_to_snapshot::Vector{String} =
            Utils.make_list_of_branches_to_snapshot(
                ;
                default_branch = default_branch,
                include = include_branches,
                exclude = exclude_branches,
                )
        unique!(branches_to_snapshot)
        sort!(branches_to_snapshot)
        m = length(branches_to_snapshot)
        for j = 1:m
            temp_transition_parent = mktempdir()
            temp_transition_dir = joinpath(
                temp_transition_parent,
                "TEMPTRANSITIONDIR",
                )
            mkpath(temp_transition_dir)
            branch::String = branches_to_snapshot[j]
            @debug("Branch: \"$(branch)\" ($(j) of $(m))")
            cd(src_repo_dir)
            try
                Utils.checkout_branch!(branch)
            catch e
                @warn("ignoring exception: ", e,)
            end
            if lowercase(strip(Utils.get_current_branch())) ==
                    lowercase(strip(branch))
                for file_or_directory in readdir(src_repo_dir)
                    if strip(lowercase(file_or_directory)) != ".git"
                        cp(
                            joinpath(src_repo_dir, file_or_directory,),
                            joinpath(temp_transition_dir, file_or_directory,);
                            force = false,
                            )
                    end
                end
                cd(temp_transition_dir)
                Utils.delete_only_dot_git!(temp_transition_dir)
                cd(dst_repo_dir)
                Utils.checkout_branch!(
                    branch;
                    create = true
                    )
                if lowercase(strip(Utils.get_current_branch())) !=
                        lowercase(strip(branch))
                    delayederror(
                        "an error occured when trying to create branch in dst"
                        )
                end
                Utils.delete_everything_except_dot_git!(dst_repo_dir)
                for file_or_directory in readdir(temp_transition_dir)
                    if strip(lowercase(temp_transition_dir)) != ".git"
                        cp(
                            joinpath(temp_transition_dir, file_or_directory,),
                            joinpath(dst_repo_dir, file_or_directory,);
                            force = false,
                            )
                    end
                end
                _when::String = ""
                date_time_string::String = ""
                if isa(when_src_cloned, TimeZones.ZonedDateTime)
                    _when = strip(
                        string(TimeZones.astimezone(when_src_cloned,time_zone,))
                        )
                else
                    _when = strip(
                        string(when_src_cloned)
                        )
                end
                Utils.git_add_all!()
                commit_message = string(
                    "Snapshot of branch $(branch)",
                    " taken on $(_when)",
                    " from \"$(src_url_without_auth)\"",
                    )
                Utils.git_commit!(
                    ;
                    message = commit_message,
                    committer_name = git_user_name,
                    committer_email = git_user_email,
                    allow_empty = false,
                    )
                Utils.git_add_all!()
                Utils.git_commit!(
                    ;
                    message = "Snapshot commit",
                    committer_name = git_user_name,
                    committer_email = git_user_email,
                    allow_empty = false,
                    )
            end
            rm(
                temp_transition_parent;
                force = true,
                recursive = true,
                )
        end
        if is_dry_run
            @info("Skipping push, because this is a dry run.")
        else
            cd(dst_repo_dir)
            run(`$(git) push -u --all`)
            when_pushed_to_dst = Dates.now(TimeZones.localzone(),)
            args1_gen_provider_description = Dict(
                :source_url => src_url_without_auth,
                :when => when_pushed_to_dst,
                :time_zone => time_zone,
                )
            repo_description_default::String = Utils.default_repo_description(
                ;
                from = src_url_without_auth,
                when = when_pushed_to_dst,
                time_zone = time_zone,
                )
            repo_description_provider::String = try
                dst_provider(
                    :generate_new_repo_description)(
                    args1_gen_provider_description)
            catch exception
                @warn(
                    string("ignoring exception: "),
                    exception,
                    )
                ""
            end
            new_repo_description::String = ""
            if length(
                    strip(
                        repo_description_provider
                        )
                    ) == 0
                new_repo_description = strip(
                    repo_description_default
                    )
            else
                new_repo_description = strip(
                    repo_description_provider
                    )
            end
            @debug(
                string("Repo descriptions: "),
                repo_description_default,
                repo_description_provider,
                new_repo_description,
                )
            args2_update_dst_description = Dict(
                :repo_name =>
                    convert(String, repo_name),
                :new_repo_description =>
                    convert(String, new_repo_description),
                )
            @info(
                string(
                    "Attempting to update ",
                    "repo description.",
                    ),
                repo_name,
                new_repo_description,
                )
            dst_provider(:update_repo_description)(
                args2_update_dst_description
                )
        end
    else
        @warn(
            "not a git repository",
            Utils.git_status_success(),
            )
    end
    cd(original_directory)
    rm(
        src_repo_parent;
        force = true,
        recursive = true,
        )
    rm(
        dst_repo_parent;
        force = true,
        recursive = true,
        )
    return nothing
end

end # End submodule RepoSnapshots.Common

##### End of file


text:
module DateShifting

export datetime_intervals
export sequence_and_random_date_shift

include("types.jl")

include("public.jl")

include("assert.jl")
include("compute_interval_nonrounded.jl")
include("date_shifting.jl")
include("intervals.jl")
include("sample.jl")

end

ext: jl


text:
using Test

using MathOptInterface
const MOI = MathOptInterface
const MOIT = MathOptInterface.Test
const MOIU = MathOptInterface.Utilities
const MOIB = MathOptInterface.Bridges

include("../utilities.jl")

mock = MOIU.MockOptimizer(MOIU.UniversalFallback(MOIU.Model{Float64}()))
config = MOIT.TestConfig()

@testset "NonposToNonneg" begin
    bridged_mock = MOIB.Variable.NonposToNonneg{Float64}(mock)

    @testset "lin2v" begin
        mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [-4, 3, 16, 0],
            (MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[7, 2, -4]])
        MOIT.lin2vtest(bridged_mock, config)

        @test MOI.get(mock, MOI.NumberOfVariables()) == 4
        @test MOI.get(bridged_mock, MOI.NumberOfVariables()) == 4
        vis = MOI.get(bridged_mock, MOI.ListOfVariableIndices())
        y = vis[4]
        @test y.value == -1

        @test MOI.supports(bridged_mock, MOI.VariablePrimalStart(), MOI.VariableIndex)
        MOI.set(bridged_mock, MOI.VariablePrimalStart(), y, 1.0)
        x, y_flipped, z, s = MOI.get(mock, MOI.ListOfVariableIndices())
        @test MOI.get(mock, MOI.VariablePrimalStart(), y_flipped) == -1
    end

    @testset "lin4" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
                mock, MOI.INFEASIBLE, MOI.INFEASIBLE_POINT,
                MOI.INFEASIBILITY_CERTIFICATE)
        )
        MOIT.lin4test(bridged_mock, config)

        @test MOI.get(mock, MOI.NumberOfVariables()) == 1
        @test length(MOI.get(mock, MOI.ListOfVariableIndices())) == 1
        @test first(MOI.get(mock, MOI.ListOfVariableIndices())).value ≥ 0
        @test MOI.get(bridged_mock, MOI.NumberOfVariables()) == 1
        vis = MOI.get(bridged_mock, MOI.ListOfVariableIndices())
        @test vis == [MOI.VariableIndex(-1)]
        test_delete_bridged_variable(bridged_mock, vis[1], MOI.Nonpositives, 1, (
            (MOI.VectorOfVariables, MOI.Nonnegatives, 0),
        ))
    end

    @testset "Delete in vector" begin
        MOI.empty!(bridged_mock)
        vis, ci = MOI.add_constrained_variables(bridged_mock, MOI.Nonpositives(4))
        test_delete_bridged_variable(bridged_mock, vis[2], MOI.Nonpositives, 4, (
            (MOI.VectorOfVariables, MOI.Nonnegatives, 0),
        ), used_bridges = 0, used_constraints = 0)
    end
end


text:
#---------------------------------------------------------------------#
#This code computes the global matrices using DSS
#Written by F.X. Giraldo on April 24, 2019
#           Department of Applied Mathematics
#           Naval Postgraduate School
#           Monterey; CA 93943-5216
#---------------------------------------------------------------------#
function global_matrices(Me,Le,intma,Ne,Np,Npoin,DFloat)

    #Initialize Matrices
    M=zeros(DFloat,Npoin,Npoin)
    L=zeros(DFloat,Npoin,Npoin)

    #Construct Mass and Differentiation Matrices
    for e=1:Ne
        for l=1:Np, k=1:Np
            J=intma[k,l,e]
            for j=1:Np, i=1:Np
                I=intma[i,j,e]
                M[I,J] += Me[i,j,k,l,e]
                L[I,J] += Le[i,j,k,l,e]
            end #j,i
        end #k,l
    end #e

    return (M,L)
end


text:
include("bitstrings.jl")
include("graphs.jl")
include("sats.jl")

import Base: name

name(problem::AbstractProblem) = string(problem)

function Base.show(io::IO, problem::AbstractProblem)
    show(io, string(typeof(problem)))
    first = true
    for p in deepparameters(problem)
        if first
            print(io, " with ")
            first = false
        else
            print(io, " and ")
        end

        show(io, string(p[1]))
        print(io, ":")
        show(io, p[2])
    end
end

max_stars_repo_name: DTUComputeTONIA/SDRLS

max_issues_repo_name: DTUComputeTONIA/SDRLS

max_forks_repo_name: DTUComputeTONIA/SDRLS


text:
using CartesianGeneticProgramming
using Cambrian
import Cambrian.mutate
using StatsBase
using Base.Iterators: repeated
include("../graphing/graph_utils.jl")
"""
A simple example  for calculating parity
"""

 #bitArray parity
 parity(x) = isodd(sum(x))

 function create_testcases(sz)
    train_cases = []
    for i in 0:(2^sz-1)
      bin = digits(i, base=2, pad=sz)
      push!(train_cases, (bin, parity(bin)))
      @show (bin, parity(bin))
    end
    return train_cases
 end

 NUMCLASSES = 10
 WIDTH = 8 #60

 train = create_testcases(WIDTH)
 trainX = [ x[1] for x in train ]
 trainX = hcat(trainX...)
 trainY = [ x[2] for x in train ]

X, Y = trainX, trainY

function evaluate(ind::CGPInd, X::AbstractArray, Y::AbstractArray)
    accuracy = 0.0
    for i in 1:size(X, 2)
        out = process(ind, float(X[:, i]))
        if out[1] == Int(Y[i])
            accuracy += 1
        end
    end
    [accuracy / size(X, 1)]
end

function error_count(e, X::AbstractArray, Y::AbstractArray)
   failed = 0
   for i in 1:size(X,2)
      y_hat = process(e.population[5], float(X[:,i]))
      if y_hat[1] != Int(Y[i])
           failed += 1
      end
   end
   failed
end

cfg = get_config("cfg/parity.yaml")
fit(i::CGPInd) = evaluate(i, X, Y)
mutate(i::CGPInd) = goldman_mutate(cfg, i)
e = CGPEvolution(cfg, fit)
println("run!")
run!(e)

@show e.population[end].nodes
errors = error_count(e,X,Y )
println("$errors errors out of $(size(X,2)) entries")

#generate dot file
dot_array = walk_nodes(e.population[5])
dot_file  = "parity_graph.dot"
open(dot_file, "w") do f
   for i in dot_array
      println(f, i)
   end
end
# to view from commandline:
# $ dot -Tpng parity_graph.dot -o parity_graph.png
# $ display parity_graph.png


text:
module WindingNelderMead

using LinearAlgebra

include("Vertexes.jl")
include("Simplexes.jl")

"""
    optimise(f, initial_vertex_positions; kwargs...)

Find minimum of function, `f`, first creating a Simplex from vertices at
`initial_vertex_positions`, and options passed in via kwargs.
"""
function optimise(f::T, initial_vertex_positions::U; kwargs...
   ) where {T, W<:Number, V<:AbstractVector{W}, U<:AbstractVector{V}}
  return optimise!(Simplex(f, initial_vertex_positions), f; kwargs...)
end

"""
    optimise(f, initial_positions, initial_step; kwargs...)

Find minimum of function, `f`, first creating a Simplex using a starting
vertex position, `initial_position`, and other vertices `initial_step` away from
that point in all directions, and options passed in via kwargs.
"""
function optimise(f::T, initial_position::AbstractVector{U}, initial_step;
                  kwargs...) where {T, U<:Number, V<:Number}
  return optimise(f, vertexpositions(initial_position, initial_step); kwargs...)
end

function convergenceconfig(dim::Int, T::Type; kwargs...)
  kwargs = Dict(kwargs)
  timelimit = get(kwargs, :timelimit, Inf)
  xtol_abs = get(kwargs, :xtol_abs, zero(real(T)))
  xtol_rel = get(kwargs, :xtol_rel, eps(real(T)))
  ftol_abs = get(kwargs, :ftol_abs, zero(real(T)))
  ftol_rel = get(kwargs, :ftol_rel, eps(real(T)))
  stopval = get(kwargs, :stopval, eps(real(T)))
  maxiters = get(kwargs, :maxiters, 1000)

  α = get(kwargs, :α, 1.0)
  β = get(kwargs, :β, 0.5)
  γ = get(kwargs, :γ, 2.0)
  δ = get(kwargs, :δ, 0.5)

  (α >= 0) || throw(ArgumentError("$α >= 0"))
  (0 <= β < 1) || throw(ArgumentError("0 <= $β < 1"))
  (γ > 1) || throw(ArgumentError("$γ > 1"))
  (γ > β) || throw(ArgumentError("$γ > $α"))

  vectoriser(x) = length(x) == 1 ? [x for _ ∈ 1:dim] : Vector(x)
  xtol_abs = vectoriser(xtol_abs)
  xtol_rel = vectoriser(xtol_rel)

  return (timelimit=timelimit, xtol_abs=xtol_abs, xtol_rel=xtol_rel,
          ftol_abs=ftol_abs, ftol_rel=ftol_rel, stopval=stopval,
          maxiters=maxiters, α=α, β=β, γ=γ, δ=δ)
end

function updatehistory!(history, newentry)
  returncode = any(h->isequal(h, newentry), history) ? :ENDLESS_LOOP : :CONTINUE
  for i in length(history):-1:2 # history .= circshift(history, 1)
    history[i] = history[i-1]
  end
  history[1] = newentry
  return returncode
end

"""
    optimise!(s, f; kwargs...)

Find minimum of function, `f`, starting from Simplex, `s`, with options
passed in via kwargs.

# Keyword Arguments
-  stopval (default sqrt(eps())): stopping criterion when function evaluates
equal to or less than stopval
-  xtol_abs (default zero(T) scalar or with length dimensionality(s)): stop if
the vertices of simplex get within this absolute tolerance
-  xtol_rel (default eps(T) scalar or with length dimensionality(s)): stop if
the vertices of simplex get within this relative tolerance
-  ftol_abs (default zero(real(U))): stop if function evaluations at the
vertices are close to one another by this absolute tolerance
-  ftol_rel (default 1000eps(real(U))): stop if function evaluations at the
vertices are close to one another by this relative tolerance
-  maxiters (default 1000): maximum number of iterations of the Nelder Mead
algorithm
-  timelimit (default Inf): stop if it takes longer than this in seconds
-  α (default 1): Reflection factor
-  β (default 0.5): Contraction factor
-  γ (default 2): Expansion factor
-  δ (default 0.5): Shrinkage factor
"""
function optimise!(s::Simplex{D,T}, f::F; kwargs...) where {F,D,T<:Real}

  config = convergenceconfig(dimensionality(s), T; kwargs...)

  reflect(this, other) = Vertex(newposition(this, config[:α], other), f)
  expand(this, other) = Vertex(newposition(this, -config[:γ], other), f)
  contract(this, other) = Vertex(newposition(this, -config[:β], other), f)
  shrink(this, other) = Vertex(newposition(this, config[:δ], other), f)

  function shrink!(s::Simplex)
    ignore = bestvertex(s)
    for v ∈ s
      isequal(v, ignore) || swap!(s, v, shrink(ignore, v))
    end
    return nothing
  end

  iters, totaltime = 0, 0.0
  asg = AssessConvergenceGraph()
  returncode = assessconvergence(s, config, asg)
  history = deepcopy(s.vertices)

  windings = windingnumber(s)

  while returncode == :CONTINUE && totaltime < config[:timelimit]
    totaltime += @elapsed begin
      (iters += 1) < config[:maxiters] || break

      if windings == 0
        best = bestvertex(s)
        worst = worstvertex(s)
        secondworst = secondworstvertex(s)
        reflected = reflect(centroidposition(s), worst)

        returncode = updatehistory!(history, reflected)
        returncode == :ENDLESS_LOOP && break

        if best <= reflected < secondworst
          swapworst!(s, reflected)
        else
          centroid = Vertex(centroidposition(s), f)
          if reflected < best
            expanded = expand(centroid, reflected)
            expanded < reflected && swapworst!(s, expanded)
            expanded >= reflected && swapworst!(s, reflected)
          elseif secondworst <= reflected < worst
            contracted = contract(centroid, reflected)
            contracted <= reflected ? swapworst!(s, contracted) : shrink!(s)
          elseif reflected >= worst
            contracted = contract(centroid, worst)
            contracted < worst ? swapworst!(s, contracted) : shrink!(s)
          end
        end

        windings = windingnumber(s)
      else
        keeper = closestomiddlevertex(s)
        newnodeposition = centroidposition(s, keeper)
        any(isequal(newnodeposition, position(v)) for v in s) && continue
        centroid = Vertex(newnodeposition, f)
        rootlostandsimplexunchanged = true
        for vertex ∈ s
          isequal(vertex, keeper) && continue
          swap!(s, vertex, centroid)
          windingnumber(s) == 0 || (rootlostandsimplexunchanged = false; break)
          swap!(s, centroid, vertex)
        end

        returncode = updatehistory!(history, centroid)
        returncode == :ENDLESS_LOOP && break

        windings = if rootlostandsimplexunchanged
          centroid < worstvertex(s) && swapworst!(s, centroid)
          0
        else
          windingnumber(s)
        end
      end
      returncode = assessconvergence(s, config, asg)
    end
  end

  iters == config[:maxiters] && (returncode = :MAXITERS_REACHED)

  return s, windingnumber(s), returncode, iters
end # optimise!

end


text:
#==
  C++ class style enums for Julia, written in Julia v0.7.0-DEV
  Created 10th December 2017
==#

abstract type Enumeration{T} end

function Enumerate(name::Symbol, data::Dict{T, Int})::Void where T
  enumExpression = quote
    struct $name{T} <: Enumeration{T}
      value::Int
      data::Dict{T, Int}
      function $name(x::T) where T
        value::Int = $data[x]
        new{T}(value, $data)
      end
    end
  end

   equalityExpression = quote
     import Base.==
     ==(x::$name, y::$name) = x.value == y.value
     ==(x::$name, y::Int) = x.value == y
     ==(y::Int, x::$name) = x.value == y
   end

   eval(Main, enumExpression)
   eval(Main, equalityExpression)
   return
end

#== Example:

julia> include("Enumeration.jl")

julia> Enumerate(:Fruit, Dict("apple" => 1, "orange" => 2, "pear" => 3, "guava" => 4))

julia> myFruit = Fruit("guava")
Fruit(1, Dict("guava"=>4,"orange"=>2,"pear"=>3,"apple"=>1))

julia> yourFruit = Fruit("pear")
Fruit(3, Dict("guava"=>4,"orange"=>2,"pear"=>3,"apple"=>1))

julia> yourFruit == myFruit
false

julia> myFruit == Fruit("guava")
true

julia> myFruit == 4
true

julia> myFruit == 3
false

julia> 4 == myFruit
true
==#


text:
module SimulacoesTemplate

  f(x) = 2*x

  export f

end


text:
"""
    G = grid_at_sensor(fname::String, sds_name::String=""; V::Bool=false, kw...)

Read one of those netCDF files that are not regular grids but have instead the coordinates in the
LONGITUDE abd LATITUDE arrays. MODIS L2 files are a good example of this. Data in theses files are
not layed down on a regular grid and we must interpolate to get one. Normally the lon and lat arrays
are called 'longitude' and 'latitude' and these it's what is seek for by default. But files exist
that pretend to comply to CF but use other names. In this case, use the kwargs `xarray` & `yarray`
to pass in the variable names. For example: `xarray="XLONG"`, `yarray="XLAT"`
The other fundamental info to pass in is the name of the array to be read/interpolated. We do that
via the `sds_name` arg.

In simpler cases the variable to be interpolated lays down on a 2D array but it is also possible that
it is stored in a 3D array. If that is the case, use the keyword 'band' to select a band (ex: 'band=2')
Bands are numbered from 1.

The interpolation is done so far with 'nearneighbor'. Both the region (-R) and increment (-I) are estimated
from data but they can be set with `region` and `inc` kwargs as well. One can also set the 'nearneighbor'
serach radius with option `search_radius`. The defaul is to set search_radius equal to two times
the average increment.

For MODIS data we can select the quality flag to filter by data quality. By default the best quality (=0) is
used, but one can select another with the `quality=val` kwarg. Positive 'val' values select data of quality
<= quality, whilst negative 'val' values select only data with quality >= abs(val). This allows for example
to extract only the cloud coverage.

If instead of calculating a grid (returned as a GMTgrid type) user wants the x,y,z data intself, use the
keywords `dataset`, or `outxyz` and the output will be in a GMTdataset (i.e. use `dataset=true`).

To inquire just the list of available arrays use `list=true` or `gdalinfo=true` to get the full file info.

    Examples:

    G = grid_at_sensor("AQUA_MODIS.20020717T135006.L2.SST.nc", "sst", V=true);

    G = grid_at_sensor("TXx-narr-annual-timavg.nc", "T2MAX", xarray="XLONG", yarray="XLAT", V=true);
"""
function grid_at_sensor(fname::String, sds_name::String=""; quality::Int=0, V::Bool=false, kw...)

	d = KW(kw)
	!isfile(fname) && error("This file $(fname) does not exist")
	info = gdalinfo(fname)
	if (info === nothing)		# Try again after calling resetGMT because still something screws time-to-time
		GMT.resetGMT()
		info = gdalinfo(fname)
	end
	(haskey(d, :gdalinfo)) && (return println(info))
	inc = ((val = find_in_dict(d, [:inc :increment :spacing])[1]) !== nothing) ? val : [0.0, 0.0]
	(isa(inc, Tuple)) && (inc = collect(inc))
	(isa(inc, Real)) && (inc = [inc, inc])
	((ind = findfirst("Subdatasets:", info)) === nothing) && error("This file " * fame * " has no Subdatasets")
	is_MODIS = (findfirst("MODISA Level-2", info) !== nothing) ? true : false
	info = info[ind[1]+12:end]		# Chop up the long string into smaller chunk where all needed info lives
	ind = findlast("SUBDATASET_", info)
	info = info[1:ind[1]]			# Chop even last SUBDATASET_X_DESC string that we wouldn't use anyway
	ind_EOLs = findall("\n", info)

	if (haskey(d, :list))
		c = ((ind = findlast("/", info[ind_EOLs[1][1] : ind_EOLs[2][1]-1])) !== nothing) ? '/' : ':'
		println("List of bands in this file:")
		[println("\t",split(info[ind_EOLs[k-1][1] : ind_EOLs[k][1]-1], c)[end]) for k = 2:2:length(ind_EOLs)]
		return nothing
	end

	(sds_name == "") && error("Must provide the band name to process. Try grid_at_sensor(\"\", list=true) to print available bands")

	# Get the arrays  SUBDATASET names
	sds_z  = helper_find_sds(sds_name, info, ind_EOLs)		# Return the full SUBDATASET name (a string)
	x_name = ((val = find_in_dict(d, [:xarray])[1]) !== nothing) ? string(val) : "longitude"
	y_name = ((val = find_in_dict(d, [:yarray])[1]) !== nothing) ? string(val) : "latitude"
	sds_qual = (is_MODIS) ? helper_find_sds("qual_" * sds_name, info, ind_EOLs) : ""
	sds_lon = helper_find_sds(x_name, info, ind_EOLs)
	sds_lat = helper_find_sds(y_name, info, ind_EOLs)

	# Get the arrays with the data
	band = ((val = find_in_dict(d, [:band])[1]) !== nothing) ? Int(val) : 1
	lon, lat, z_vals, inc, proj4 = get_xyz_qual(sds_lon, sds_lat, sds_z, quality, sds_qual, inc, band, V)

	if ((opt_R = GMT.parse_R(d, "")[1]) == "")	# If != "" believe it makes sense as a -R option
		inc_txt = split("$(inc[1])", '.')[2]	# To count the number of decimal digits to use in rounding
		nd = length(inc_txt)
		min_lon, max_lon = extrema(lon)
		min_lat, max_lat = extrema(lat)
		west, east   = round(min_lon-inc[1]; digits=nd), round(max_lon+inc[1]; digits=nd)
		south, north = round(min_lat-inc[2]; digits=nd), round(max_lat+inc[2]; digits=nd)
		if (x_name == "longitude")			# The "inc" pad above may "overflow" geogs. Revet the padding if need.
			((east - west) > 360) && (west += inc[1];	east -= inc[1])
			(north >  90) && (north -= inc[2])
			(south < -90) && (south += inc[2])
		end
		opt_R = @sprintf("%.10g/%.10g/%.10g/%.10g", west, east, south, north)
	else
		opt_R = opt_R[4:end]		# Because it already came with " -R....." from parse_R()
	end

	if (haskey(d, :outxyz) || haskey(d, :dataset))
		O = mat2ds([lon lat z_vals])
		O[1].proj4 = proj4
	else
		s_rad = ((val = find_in_dict(d, [:S :search_radius])[1]) !== nothing) ? string(val) : (inc[1]+inc[2])
		O = nearneighbor([lon lat z_vals], I=inc, R=opt_R, S=s_rad, Vd=(V) ? 1 : 0)
		O.proj4 = proj4
	end
	return O
end

# ---------------------------------------------------------------------------------------------------
function helper_find_sds(sds::String, info::String, ind_EOLs::Vector{UnitRange{Int64}})::String
	if ((ind = findfirst("/" * sds, info)) === nothing)
		((ind = findfirst(":" * sds, info)) === nothing) && error("The band name -- " * sds * " -- does not exist")
	end
	k = 1;	while (ind_EOLs[k][1] < ind[1])  k += 1  end
	return info[ind_EOLs[k-1][1]+3:ind_EOLs[k][1]-1]	# +3 because 1 = \n and the other 2 are blanks
end

# ---------------------------------------------------------------------------------------------------
function get_xyz_qual(sds_lon::String, sds_lat::String, sds_z::String, quality::Int, sds_qual::String="",
	                  inc::Vector{Float64}=[0.,0.], band::Int=1, V::Bool=false)
	# Get a Mx3 matrix with data to feed interpolator. Filter with quality if that's the case
	# If INC != 0, also estimates a reasonable increment for interpolation
	(V) && println("Extract lon, lat, " * sds_z * " from file")
	G = gd2gmt(sds_z; band=band);		z_vals = G.z;		proj4 = G.proj4

	if (sds_qual != "")
		Gqual = gd2gmt(sds_qual)
		if (quality >= 0)  qual = (Gqual.image .< quality + 1)		# Best (0), Best+Intermediate (1) or all (2)
		else               qual = (Gqual.image .> -quality - 1)		# Pick only, Intermediate+Lousy (-1) or Lousy (-2)
		end
		qual = reshape(qual, size(qual,1), size(qual,2))
		z_vals = z_vals[qual]
		lon, lat, dx, dy = get_lon_lat_qual(sds_lon, sds_lat, qual, inc)
		(proj4 == "") && (proj4 = GMT.prj4WGS84)	# Almost for sure that's always the case
	else
		info = gdalinfo(GMT.trim_SUBDATASET_str(sds_z))
		fill_val, got_fill_val = GMT.get_FillValue(info)
		if (got_fill_val)
			qual = (z_vals .!= fill_val)
			z_vals = z_vals[qual]
			lon, lat, dx, dy = get_lon_lat_qual(sds_lon, sds_lat, qual, inc)
		else
			G = gd2gmt(sds_lon);	lon = G.z
			G = gd2gmt(sds_lat);	lat = G.z
			(inc[1] == 0.0) && (dx = diff(lon[:, round(Int, size(lon, 1)/2)]))
			(inc[2] == 0.0) && (dy = diff(lat[round(Int, size(lat, 2)/2), :]))
		end
		(proj4 == "") && (proj4 = GMT.seek_wkt_in_gdalinfo(info))
	end
	(inc[1] == 0) && (inc = guess_increment_from_coordvecs(dx, dy))
	(V) && println("Finished extraction ($(length(z_vals)) points), now intepolate")
	return lon, lat, z_vals, inc, proj4
end

function get_lon_lat_qual(sds_lon::String, sds_lat::String, qual, inc)
	# Another helper function to get only the lon, lat values that pass the 'qual' criteria
	dx, dy = Vector{Float32}(), Vector{Float32}()
	G = gd2gmt(sds_lon);
	(inc[1] == 0.0) && (dx = diff(G.z[:, round(Int, size(G.z, 1)/2)]))
	lon = G.z[qual]
	G = gd2gmt(sds_lat);
	(inc[2] == 0.0) && (dy = diff(G.z[round(Int, size(G.z,2)/2), :]))
	lat = G.z[qual]
	return lon, lat, dx, dy
end

# ---------------------------------------------------------------------------------------------------
function guess_increment_from_coordvecs(dx, dy)
	# Guess a good -I<inc> from the spacings in the x (lon), y(lat) arrays
	x_mean = abs(Float64(mean(dx)));		y_mean = abs(Float64(mean(dy)));
	#xy_std = max(Float64(std(dx)), Float64(std(dy)))
	#return (xy_std == 0) ? (x_mean + y_mean) / 2 : round((x_mean + y_mean) / 2, digits=round(Int, abs(log10(xy_std))))
	x_std, y_std = Float64(std(dx)), Float64(std(dy))
	inc_x = (x_std == 0) ? x_mean : round(x_mean, digits=round(Int, abs(log10(x_std))))
	inc_y = (y_std == 0) ? y_mean : round(y_mean, digits=round(Int, abs(log10(y_std))))
	[inc_x, inc_y]
end

max_stars_repo_name: GenericMappingTools/RemoteS

max_issues_repo_name: GenericMappingTools/RemoteS

max_forks_repo_name: GenericMappingTools/RemoteS


text:
@doc raw"""
    IsoCuboid3

An object `c` of the data type [`IsoCuboid3`](@ref) is a rectangle in the
Euclidean space ``Ε^3`` with edges parallel to the ``x``, ``y`` and ``z`` axis
of the coordinate system.

Although they are represented in a canonical form by only two vertices, namely
the lower left and the upper right vertex with respect to Cartesian ``xyz``
coordinates, we provide functions for "accessing" the other vertices as well.

Iso-oriented cuboids and bounding boxes are quite similar. The difference
however is that bounding boxes have always double coordinates, whereas the
coordinate type of an iso-oriented cuboid is chosen by the user.
"""
IsoCuboid3

"""
    IsoCuboid3(p::Point3, q::Point3)

Introduces an iso-oriented cuboid `c` with diagonal opposite vertices `p` and
`q`.

Note that the object is brought in the canonical form.
"""
IsoCuboid3(p::Point3, q::Point3)

"""
    IsoCuboid3(p::Point3, q::Point3, ::Integer)

Introduces an iso-oriented cuboid `c` with diagonal opposite vertices `p` and
`q`.

Note that the object is brought in the canonical form.
"""
IsoCuboid3(p::Point3, q::Point3, ::Integer)

@doc raw"""
    IsoCuboid3(left::Point3, right::Point3, bottom::Point3, top::Point3,
               far::Point3, close::Point3)

Introduces an iso-oriented cuboid `c` whose minimal ``x`` coordinate is the
one of `left`, the maximal ``x`` coordinate is the one of `right`, the minimal
``y`` coordinate is the one of `bottom`, the maximal ``y`` coordinate is the one
of ``top``, the minimal ``z`` coordinate is the one of ``far``, the maximal
``z`` coordinate is the one of ``close``.
"""
IsoCuboid3(left::Point3, right::Point3, bottom::Point3, top::Point3,
           far::Point3, close::Point3)

"""
    IsoCuboid3(min_hx::Real, min_hy::Real, min_hz::Real,
               max_hx::Real, max_hy::Real, max_hz::Real, hw::Real = 1)

Introduces an iso-oriented cuboid `c` with diagonal opposite vertices
`(min_hx/hw, min_hy/hw, min_hz/hw)` and `(max_hx/hw, max_hy/hw, max_hz/hw)`.

!!! info "Precondition"

    `hw` ``≠`` `0`.
"""
IsoCuboid3(min_hx::Real, min_hy::Real, min_hz::Real,
           max_hx::Real, max_hy::Real, max_hz::Real, hw::Real = 1) =
    IsoCuboid3(convert.(FT, (min_hx, min_hy, min_hz,
                             max_hx, max_hy, max_hz, hw))...)

"""
    IsoCuboid3(bbox::Bbox3)

If [`RT`](@ref) is constructible from `Float64`, introduces an iso-oriented
cuboid from `bbox`.
"""
IsoCuboid3(bbox::Bbox3)

"""
    ==(c₁::IsoCuboid3, c₂::IsoCuboid3)

Test for equality: two iso-oriented cuboids are equal, iff their lower left and
upper right vertices are equal.
"""
==(c₁::IsoCuboid3, c₂::IsoCuboid3)

"""
    vertex(r::IsoCuboid3, i::Integer)

Returns the `i`ᵗʰ vertex modulo 8 of `c`.
"""
vertex(c::IsoCuboid3, i::Integer)

"""
    min(c::IsoCuboid3)

Returns the smallest vertex of `c` (= `vertex(c, 0)`).
"""
min(c::IsoCuboid3)

"""
    max(c::IsoCuboid3)

Returns the largest vertex of `c` (= `vertex(c, 7)`).
"""
max(c::IsoCuboid3)

"""
    xmin(c::IsoCuboid3)

Returns smallest Cartesian ``x``-coordinate in `c`.
"""
xmin(c::IsoCuboid3)

"""
    ymin(c::IsoCuboid3)

Returns smallest Cartesian ``y``-coordinate in `c`.
"""
ymin(c::IsoCuboid3)

"""
    zmin(c::IsoCuboid3)

Returns smallest Cartesian ``z``-coordinate in `c`.
"""
zmin(c::IsoCuboid3)

"""
    xmax(c::IsoCuboid3)

Returns largest Cartesian ``x``-coordinate in `c`.
"""
xmax(c::IsoCuboid3)

"""
    ymax(c::IsoCuboid3)

Returns largest Cartesian ``y``-coordinate in `c`.
"""
ymax(c::IsoCuboid3)

"""
    zmax(c::IsoCuboid3)

Returns largest Cartesian ``z``-coordinate in `c`.
"""
zmax(c::IsoCuboid3)

"""
    min_coord(c::IsoCuboid3, i::Integer)

Returns `i`ᵗʰ Cartesian coordinate of the smallest vertex of `c`.

!!! info "Precondition"

    ``0 ≤ i ≤ 2``
"""
min_coord(c::IsoCuboid3, i::Integer)

"""
    max_coord(c::IsoCuboid3, i::Integer)

Returns `i`ᵗʰ Cartesian coordinate of the largest vertex of `c`.

!!! info "Precondition"

    ``0 ≤ i ≤ 2``
"""
max_coord(r::IsoCuboid3, i::Integer)

"""
    is_degenerate(c::IsoCuboid3)

`c` is degenerate, if all vertices are coplanar.
"""
is_degenerate(c::IsoCuboid3)

"""
    bounded_side(c::IsoCuboid3, p::Point3)

Returns either [`ON_UNBOUNDED_SIDE`](@ref), [`ON_BOUNDED_SIDE`](@ref), or the
constant [`ON_BOUNDARY`](@ref), depending on where point `p` is.
"""
bounded_side(c::IsoCuboid3, p::Point3)

"""
    has_on_boundary(c::IsoCuboid3, p::Point3)

Returns `true`, iff `p` lies on the boundary of `r`.
"""
has_on_boundary(c::IsoCuboid3, p::Point3)

"""
    has_on_bounded_side(c::IsoCuboid3, p::Point3)

Returns `true`, iff `p` lies properly inside of `r`.
"""
has_on_bounded_side(c::IsoCuboid3, p::Point3)

"""
    has_on_unbounded_side(c::IsoCuboid3, p::Point3)

Returns `true`, iff `p` lies properly outside of `r`.
"""
has_on_unbounded_side(c::IsoCuboid3, p::Point3)

"""
    volume(c::IsoCuboid3)

Returns the volume of `c`.
"""
volume(c::IsoCuboid3)

"""
    bbox(c::IsoCuboid3)

Returns a bounding box containing `c`.
"""
bbox(c::IsoCuboid3)

@doc raw"""
    transform(c::IsoCuboid3, t::AffTransformation2)

Returns the iso-oriented cuboid obtained by applying `t` on the smallets
and largest corner of `c`.

!!! info "Precondition"

    The angle at a rotation must be a multiple of ``π \over 2``, otherwise the
    resulting cuboid does not have the same size. Note that rotating about an
    arbitrary angle can even result in a degenerate iso-oriented cuboid.
"""
transform(c::IsoCuboid3, t::AffTransformation2)


text:
using ModelingToolkit
using LinearAlgebra
using Test

A = [
     0  1   1   2   2  1  1   2  1   2
     0  1  -1  -3  -2  2  1  -5  0  -5
     0  1   2   2   1  1  2   1  1   2
     0  1   1   1   2  1  1   2  2   1
     0  2   1   2   2  2  2   1  1   1
     0  1   1   1   2  2  1   1  2   1
     0  2   1   2   2  1  2   1  1   2
     0  1   7  17  14  2  1  19  4  23
     0  1  -1  -3  -2  1  1  -4  0  -5
     0  1   1   2   2  1  1   2  2   2
    ]
N = ModelingToolkit.nullspace(A)
@test size(N, 2) == 3
@test rank(N) == 3
@test iszero(A * N)

A = [0 1 2 0 1 0;
     0 0 0 0 0 1;
     0 0 0 0 0 1;
     1 0 1 2 0 1;
     0 0 0 2 1 0]
col_order = Int[]
N = ModelingToolkit.nullspace(A; col_order)
colspan = A[:,col_order[1:4]]   # rank is 4
@test iszero(ModelingToolkit.nullspace(colspan))
@test !iszero(ModelingToolkit.nullspace(A[:,col_order[1:5]]))
@test !iszero(ModelingToolkit.nullspace(A[:,[col_order[1:4]...,col_order[6]]]))


text:
using ResearchBooks; @openbook

# ===================================================================
@new_document!
@set_title!("")

@set_author!("__AUTHOR__")
@set_doi!("__DOI__")
@set_year!("__YEAR__")
@set_bibkey!("__BIBKEY__")
@set_abstract!(
    "__ABSTRACT__"
)
@set_ctime!("__READ__")
@add_tag!("__KEYWORDS__")

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


text:
using Pkg , Printf
Pkg.add("JuMP")
Pkg.add("GLPK")
#Pkg.add("GLPKMathProgInterface")
Pkg.add("Plots")
Pkg.add("Distributions")
Pkg.add("SpecialFunctions")
using GLPK
using JuMP, GLPKMathProgInterface, Plots, Distributions, SpecialFunctions
include("../src/OT_sampler.jl")
plot_flag = 1
savedata_flag = 0
a = @time OT_sampler(plot_flag,savedata_flag)
# write your own tests here
# @test 1 == 1

max_stars_repo_name: niladridas/UKF

max_issues_repo_name: niladridas/UKF

max_forks_repo_name: niladridas/UKF


text:
using Distributions
using RmathDist

import Distributions: zval

distlist = [
            Normal(0,1),
            Normal(1e10,1e10),
            Normal(1e-10,1e-10)
            ]

for d in distlist
    for x in [-logspace(-300,300,1_000_000),logspace(-300,300,1_000_000)]
        z = zval(d,x)

        test_rmath(pdf,d,x)
        if !(1e154 < abs(z) < 1e155)
            # dist.jl overflow: only a small gap, so probably not worth worrying about
            test_rmath(logpdf,d,x)
        end

        if !(37 < abs(z) < 39) # rmath underflow
            test_rmath(cdf,d,x,1e5)
            test_rmath(ccdf,d,x,1e5)
        end
        if !(1e154 < abs(z) < 1e155) # rmath overflow
            test_rmath(logcdf,d,x,1e5)
            test_rmath(logccdf,d,x,1e5)
        end
    end

    for p in logspace(-300,0,1_000_000)
        test_rmath(quantile,d,p,1e5)
        test_rmath(cquantile,d,p,1e5)
    end

    for lp in -logspace(-300,300,1_000_000)
        test_rmath(invlogcdf,d,lp)
        test_rmath(invlogccdf,d,lp)
    end
end


text:
using StochasticDiffEq, Test

SRIW1_tab = constructSRIW1()
@test minimum(checkSRIOrder(SRIW1_tab))

SRA1_tab = constructSRA1()
@test minimum(checkSRAOrder(SRA1_tab))

DRI1_tab = constructDRI1()
@test minimum(checkRIOrder(DRI1_tab))

RI1_tab = constructRI1()
@test minimum(checkRIOrder(RI1_tab))


text:
# Run FlowSeed on the full body MRI graph, refining PPR outputs

include("../algorithms/FlowSeed-0.6.jl")
using MAT

mat = matread("data/MRI_Graph.mat")
A = mat["mri_A"]
Target = mat["cavity"]
Target = round.(Int64,Target)
volA = mat["mri_vol"]
d = sum(A,1)'
n = size(A,1)

# Output stats about the target atrial cavity
TarSize = length(Target)
TargetStats = set_stats(A,vec(Target),volA)
Tcond = round(TargetStats[4],3)
Tsize = length(Target)
println("Target Cavity has $Tsize nodes and a conductance of $Tcond ")

mat = matread("data/cavity_100_nodes.mat")
seed_start = mat["seed_start"] # Seed100

alpha = .6
epsilon = .1

# These 100 nodes we know to be in the atrial cavity
R0 = vec(round.(Int64,seed_start))

# One-hop neighborhood
R1 = neighborhood(A,R0,1)

# Load the output from PPR
mat = matread("PPR_Output/alpha_"*string(round(Int64,100*alpha))*"sets_stats.mat")

sets = mat["sets"]
stats = mat["stats"]

outputstring = "FlowSeed_refine_PPR_alpha_"*string(alpha)*"_epsilon_"*string(epsilon)*".txt"
outputmat = "FlowSeed_refine_PPR_alpha_"*string(alpha)*"_epsilon_"*string(epsilon)*".mat"

open(outputstring,"w") do f
    write(f,"Running FlowSeed on the PPR push algorithm output.\n")
end

sets1 = spzeros(n,4)
stats1 = zeros(7,4)
sets2 = spzeros(n,4)
stats2 = zeros(7,4)

# Refine the output of PPR for a subset of the PPR tolerances used
for t = 2:size(sets,2)-3

    tol = t-1

    # Output from PPR
    Rppr = find(sets[:,t])
    prf = PRF(Target,Rppr)
    pr = round(prf[1],3)
    re = round(prf[2],3)
    f1 = round(prf[3],3)

    # The seed set for FlowSeed will be the output from PPR, plus
    # the original 100 nodes from the atrial cavity, and their neighbors
    R = unique([R0;R1;Rppr])
    Rn = neighborhood(A,R,1)    # get the immediate neighbors of R...
    Rn = setdiff(Rn,R)          # ...but we exclude R itself
    inRc = ones(n)
    inRc[R] = 0
    Rc = find(inRc)             # complement of R

    pprSize = length(Rppr)
    open(outputstring,"a") do f
        write(f,"\nPPR tolerance Number $tol in [1e-9, 1e-10, 1e-11]\n")
        write(f,"PPR output: $pprSize nodes, PR = $pr, RE = $re, F1 = $f1 \n")
    end

    numR = length(R)
    prf = PRF(Target,R)
    pr = round(prf[1],3)
    re = round(prf[2],3)
    f1 = round(prf[3],3)
    println("Seed set: \tPR = $pr \t RE = $re \t F1 = $f1, Size = $numR")
    open(outputstring,"a") do f
        write(f,"Seed set: $numR nodes, PR = $pr, RE = $re, F1 = $f1 \n")
    end

    println("Penalty \t _Size_ \t _Time_ \t _Cond_ \t R-cond \t precision \t recall \t F1-score")
    open(outputstring,"a") do f
         write(f,"Penalty \t _Size_ \t _Time_ \t _Cond_ \t R-cond \t precision \t recall \t F1-score  \n")
    end

    # Type 1 seed exclusion penalties
    RinS = zeros(numR,1)
    pR = zeros(numR,1)
    # Hard constraint on the starter seed nodes.
    # Soft penalty on the 1st neighborhood
    for r = 1:numR
        if in(R[r],R0)
            RinS[r] = 1
        end
        if in(R[r],R1)
            pR[r] = 1
        end
    end

    # FlowSeed
    volR = sum(d[R])

    tic()
    S, Rcond = FlowSeed(A,R,Rn,Rc,epsilon,pR,RinS,d,volA,volR,true)
    timerfull = toq()
    timer = round(timerfull,3)
    Sstats = set_stats(A,S,volA)
    condS = round(Sstats[4],4)
    RcondS = round(Rcond,4)
    Ssize = length(S)
    prf = PRF(Target,S)
    pr = round(prf[1],4)
    re = round(prf[2],4)
    f1 = round(prf[3],4)
    println("Type 1 \t $Ssize\t$timer\t $condS \t $RcondS \t $pr \t $re \t $f1 ")
    open(outputstring,"a") do f
         write(f,"Type 1 \t $Ssize\t$timer\t $condS \t $RcondS \t $pr \t $re \t $f1 \n")
    end

    sets1[S,tol] = 1
    stats1[:,tol] = [Ssize;timerfull;Sstats[4];Rcond;pr;re;f1]

    # Type 2 seed exclusion penalties, more strict
    RinS = zeros(numR,1)
    pR = zeros(numR,1)
    # Hard constraint on the starter seed nodes.
    # Soft penalty on the 1st neighborhood
    # Softer penalty on ppr output
    for r = 1:numR
        if in(R[r],R0)
            RinS[r] = 1
        end
        if in(R[r],R1)
            pR[r] = 1
        end
        if in(R[r],Rppr)
            pR[r] = .5
        end
    end

    tic()
    S, Rcond = FlowSeed(A,R,Rn,Rc,epsilon,pR,RinS,d,volA,volR,true)
    timerfull = toq()
    timer = round(timerfull,3)
    Sstats = set_stats(A,S,volA)
    condS = round(Sstats[4],4)
    RcondS = round(Rcond,4)
    Ssize = length(S)
    prf = PRF(Target,S)
    pr = round(prf[1],4)
    re = round(prf[2],4)
    f1 = round(prf[3],4)
    println("Type 2 \t $Ssize\t$timer\t $condS \t $RcondS \t $pr \t $re \t $f1 ")
    open(outputstring,"a") do f
         write(f,"Type 2 \t $Ssize\t$timer\t $condS \t $RcondS \t $pr \t $re \t $f1 \n")
    end
    sets2[S,tol] = 1
    stats2[:,tol] = [Ssize;timerfull;Sstats[4];Rcond;pr;re;f1]

end

matwrite(outputmat, Dict( "sets1" => sets1, "stats1" => stats1,
"sets2" => sets2, "stats2" => stats2))

max_stars_repo_name: nveldt/FlowSeed

max_issues_repo_name: nveldt/FlowSeed

max_forks_repo_name: nveldt/FlowSeed


text:
for p in ("Knet","ArgParse","ImageMagick","MAT")
    Pkg.installed(p) == nothing && Pkg.add(p)
end

"""

julia vgg.jl image-file-or-url

This example implements the VGG model from `Very Deep Convolutional
Networks for Large-Scale Image Recognition', Karen Simonyan and Andrew
Zisserman, arXiv technical report 1409.1556, 2014.  In particular we
use the 16 layer network, denoted as configuration D in the technical
report.

* Paper url: https://arxiv.org/abs/1409.1556
* Project page: http://www.robots.ox.ac.uk/~vgg/research/very_deep
* MatConvNet weights used here: http://www.vlfeat.org/matconvnet/pretrained

"""
module VGG
using Knet,ArgParse,Images,MAT
const imgurl = "https://github.com/BVLC/caffe/raw/master/examples/images/cat.jpg"
const vggurl = "http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-16.mat"

function main(args=ARGS)
    s = ArgParseSettings()
    s.description="vgg.jl (c) Deniz Yuret, 2016. Classifying images with the VGG model from http://www.robots.ox.ac.uk/~vgg/research/very_deep."
    # s.exc_handler=ArgParse.debug_handler
    @add_arg_table s begin
        ("image"; required=true; help="Image file or URL.")
        ("--model"; default=Knet.dir("data","imagenet-vgg-verydeep-16.mat"); help="Location of the model file")
        ("--top"; default=5; arg_type=Int; help="Display the top N classes")
    end
    println(s.description)
    isa(args, AbstractString) && (args=split(args))
    o = parse_args(args, s; as_symbols=true)
    println("opts=",[(k,v) for (k,v) in o]...)
    gpu() >= 0 || error("VGG only works on GPU machines.")
    if !isfile(o[:model])
        println("Should I download the VGG model (492MB)? Enter 'y' to download, anything else to quit.")
        readline() == "y\n" || return
        download(vggurl,o[:model])
    end
    info("Reading $(o[:model])")
    vgg = matread(o[:model])
    w = weights(vgg["layers"])
    averageImage = convert(Array{Float32},vgg["meta"]["normalization"]["averageImage"])
    description = vgg["meta"]["classes"]["description"]
    info("Reading $(o[:image])")
    x1 = data(o[:image], averageImage)
    info("Classifying")
    @time y1 = predict(w,x1)
    z1 = vec(Array(y1))
    s1 = sortperm(z1,rev=true)
    p1 = exp(logp(z1))
    display(hcat(p1[s1[1:o[:top]]], description[s1[1:o[:top]]]))
    println()
end

function data(img, averageImage)
    if contains(img,"://")
        info("Downloading $img")
        img = download(img)
    end
    a0 = load(img)
    new_size = ntuple(i->div(size(a0,i)*224,minimum(size(a0))),2)
    a1 = Images.imresize(a0, new_size)
    i1 = div(size(a1,1)-224,2)
    j1 = div(size(a1,2)-224,2)
    b1 = a1[i1+1:i1+224,j1+1:j1+224]
    c1 = separate(b1)
    d1 = convert(Array{Float32}, c1)
    e1 = reshape(d1[:,:,1:3], (224,224,3,1))
    f1 = (255 * e1 .- averageImage)
    g1 = permutedims(f1, [2,1,3,4])
    x1 = KnetArray(g1)
end

function weights(layers)
    w = Any[]
    for l in layers
        haskey(l,"weights") && !isempty(l["weights"]) && push!(w, l["weights"]...)
    end
    for i in 2:2:26
        w[i] = reshape(w[i], (1,1,length(w[i]),1))
    end
    for i in 27:2:32
        w[i] = mat(w[i])'
    end
    w = map(KnetArray,w)
end

const op = [1,2,1,2,1,1,2,1,1,2,1,1,2,3,3,4]

convx(w,x)=conv4(w,x;padding=1,mode=1)

function predict(w,x)
    for k=1:div(length(w),2)
        if op[k] == 1
            x = relu(convx(w[2k-1],x) .+ w[2k])
        elseif op[k] == 2
            x = pool(relu(convx(w[2k-1],x) .+ w[2k]))
        elseif op[k] == 3
            x = relu(w[2k-1]*mat(x) .+ w[2k])
        else
            x = w[2k-1]*mat(x) .+ w[2k]
        end
    end
    return x
end

# This allows both non-interactive (shell command) and interactive calls like:
# $ julia vgg.jl cat.jpg
# julia> VGG.main("cat.jpg")
!isinteractive() && (!isdefined(Main,:load_only) || !Main.load_only) && main(ARGS)

end # module


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

using Markdown
using InteractiveUtils

# ╔═╡ 0810c98f-2526-4ab4-9cd5-a662434e332d
begin
	using Statistics
	using StatsBase
	using Plots
end

# ╔═╡ a4283cac-c253-11ec-1d76-495287bbab72
md"""
# Bootstrap Method Notes

I'm working through Lorna Yen's article [An Introduction to the Bootstrap Method](https://towardsdatascience.com/an-introduction-to-the-bootstrap-method-58bcb51b4d60). The Bootstrap Method was introduced by Bradley Efron in 1979.

Date: 2022 April 22

## The Bootstrap Sampling Method

We need to make an inference about an estimate (e.g. sample mean) for a population parameter $$\theta$$ (e.g. population mean).

Basic Steps in a bootstrap method:

1. Start with a sample of size $$n$$.
2. Create $$B$$ Bootstrap Samples of size $$n$$ by drawing from the original sample with replacement.
3. Evaluate the statistic $$\theta$$ on each sample, giving us $$B$$ estimates.
4. Constrtuct a sampling distribution with these bootstrap statistics and use it to make further statistical inference, such as estimating the standard error for $$\theta$$ or obtaining a confidence interval for $$\theta$$.
"""

# ╔═╡ c33fde47-ac17-4194-973b-cdb277907b60
md"""
## Motivation - The Esimator's Standard Error

How can we evaluate the accuracy of an estimator?

Example: We want to esimate the number of times your 100 student pick up their phones in a day. 30 students installed an app which tells you how many times they picked up their phones. We will calculate the mean of these 30 students and get an estimate for pickups.
"""

# ╔═╡ e42b8dfb-1a75-448c-acc1-3255c87a0edf
pickups = rand(0:500, 100)

# ╔═╡ 0e14ff27-5d05-4367-947e-d97e96ddfa8e
md"""

The population mean is **$(mean(pickups))** pickups. Now, let's get our sample of 30 students. Note that this is performed without replacement.

"""

# ╔═╡ fbbc6413-0afb-4531-8113-bb85afd2710d
responses = sample(pickups, 30)

# ╔═╡ 0ed657f2-8f2b-4e8f-a375-9c8986448340
md"""

Our sample mean is **$(round(mean(responses); digits=2))** with standard deviation **$(round(std(responses); digits=2))**.

This is called a point estimate, but what we want is the true number of pickups in the whole lab.

An **estimator** is a rule for calculating an estimate. In this case, we are using sample mean, denoted $$\bar{X}$$. A **population parameter** is a numeric summary about a population. In this case, this is the average time of phone pickups per day, denoted $$\mu$$.

But how accurate is the estimate result? (How far is $$\bar{X}$$ from $$\mu$$?) The common measure is the standard error.
"""

# ╔═╡ c30c49a1-2821-4ada-ab10-5cac70a99e87
md"""
## Standard Error

**The standard error of an estimator is it's standard deviation.** Often times we do not know the parameters, and must use an estimated standard error.

### Standard Error of Sample Mean

$$\sigma_{\bar{x}} = \frac{\sigma}{\sqrt{n}}$$

where $$\sigma$$ is the standard deviation of the population and $$n$$ is the size of the sample. However, we do not know the standard devation of the population. Thus, we use estimated standard error, where we use the sample standard deviation $$S$$ in place of $$\sigma$$.

$$\sigma_{\bar{x}} \approx \frac{S}{\sqrt{n}}$$

where

$$S = \sum_{i=1}^n\frac{(x_i-\bar{x})^2}{n-1}$$

This means that for us, **$$S=$$ $(round(std(responses);digits=2))** and **$$\sigma_{\bar{x}}\approx$$ $(round(std(responses) / sqrt(length(responses));digits=2))**.

With the assumption that the estimator as a normal distribution, then we expect our estimate to be within $$\bar{x}\pm\sigma_{\bar{x}}$$ 68% of the time and within $$\bar{x}\pm2\sigma_{\bar{x}}$$ 95% of the time.
"""

# ╔═╡ 520524ab-53ef-4edb-bc58-f6a86620a126
md"""
### The Real World

Assumptions we have used so far:

 - We can easily estimate the standard error of our statistic of interest.
 - We assume the estimator follows a normal distribution.

But in the real world:

 - It is hard to know information about the population or it's distribution.
 - The standard error is hard to evaluate standard error in general. For instance, the standard error of the median is hard to know.

The bootstrap method helps us in these cases.
"""

# ╔═╡ fda6b303-a082-4f44-8341-49446b100609
md"""
## The Bootstrap Method Explained

### Scenario

Assume want to estimate the standard error of a statistic to make an inference about a population parameter, such as for construction the corresponding confidence interval. Assume further that:

 - We don't know anything about the population.
 - There is no precise formula for estimating the standard error of the statistic.

Let $$X_1, X_2, \dots, X_n$$ be a random sample from a population $$P$$ with distribution function $$F$$ Let $$M=g(X_1, X_2, \dots, X_n)$$ be our statistic for the parameter of interest. We want to know the variance of $$M$$,denoted $$Var(M)$$.

Challenges:

 - We can't determine the variance of the population since we don't know it. Thus, we need to estimate the variance and estimate the standard error.
 - In the real world, we don't always have a simple formula for evaluting the estimated variance or than sample means.

Before we get to esimating the variance, we'll introduce a common practical way, through simulation, assuming we know $$P$$.
"""

# ╔═╡ 4453da4c-12fc-427d-9f9c-89476bf65541
md"""
### Simulation

If we know $$P$$, we can generate $$B$$ random samples of size $$n$$, and calculate the statistic on each. Using these $$B$$ measurements, we can get a mean and a variance. The law of large numbers tells us the sample mean and variance of these $$B$$ statistics converges to the true variance as more samples are taken.

Below, we will use $$B=100000$$ for the phone problem above. First we'll look at  the distribution of the sample means, and then we will look at what the average mean converges to.
"""

# ╔═╡ f9153c34-d26b-4e54-847e-c3bae8cdb4df
sims = [mean(sample(pickups, 30; replace=false)) for x in 1:100000]

# ╔═╡ d273d1b8-e66c-4461-ab55-b2a4fe578d0c
histogram(sims, fillcolor=:black, plot_title="Histogram of Sample Means", legend = false)

# ╔═╡ 14b9e9b0-d67b-4376-80a5-cb0b76602174
convergence = [mean(sims[1:i]) for i in 1:100000]

# ╔═╡ ceb8a078-4c55-40e7-a1bf-41bc357eaf86
plot(convergence,
	linecolor=:black,
	plottitle="Convergence of Sample Means",
	xlabel="Number of Simulations",
	ylabel="Mean of first N Simulations",
	legend=false)

# ╔═╡ 3c1f21fb-be76-446d-b27f-54119ee4835a
md"""
In the distribution chart, we see that the means are normally distributed, and centered just below 250.

In the bottom chart, after running 1000000 experiments, we see that the mean quickly approaches a stable value. The final value is $(round(convergence[100000]; digits=2)) which is very close to the true value of $(round(mean(pickups);digits=2)).
"""

# ╔═╡ 1e05bcbc-cf0a-47ba-a1be-cb2e9bafff78
md"""
### The Empirical Distribution Function and Plug-in Principle

But we can't use simulation because we don't know $$P$$.

We will use the empirical distribution function to approximate the distribution function of the population and will apply the plug-in principle to get an estimate for Var(M), which is the plug-in estimator.

#### The Empirical Distribution Function

We'll build a CDF from data. The EDF is a discrete distribution that weights each point equally. It forms a step function that increases by $$1/n$$ at each data point. (The data points are placed on the x-axis and the y-value incrases by $$1/n$$ at each.)

#### The Statistical Functional

The bootstram method uses the EDF as an estimator for the CDF of the population. However, to apply the EDF as an estimator for our statistic $$M$$, we need to formulate M as a function of a CDF. Functions of CDFs are known as **statistical functionals**.

Examples:
If a random variable $$X$$ has CDF $$F$$ and PDF $$p(x)$$,

$$E(x) = \int x dF(x) = \int xp(x)dx,$$

noting that $$dF(x) = p(x)dx$$.

When $$X$$ is discrete, we instead have

$$E(X) = \int xdF(x) = \sum_x P(x)$$

How about Variance?

$$\sigma^2 = \int x^2dF(x) - (\int xdF(x))^2$$

What we're doing is rewriting statistics as functions of their CDFs. Thus we can rewrite our statistic as $$M=g(F)$$ for population with CDF $$F$$.

#### The Plug-In Principle

Combining the EDF and the Statistical Functional gives us the Plug-In Principle.

Simply plug in the EDF for the true CDF $$F$$, enabling us to evaluate $$M=g(F).$$

Formally, we say that for a parameter of interest $$\theta=g(F)$$, if $$\hat{F}$$ is an estimator for $$F$$, the plug-in estimator for $$\theta$$ is defined to be $$\hat{\theta} = g(\hat{F})$$.
"""

# ╔═╡ 56116619-fd06-4af1-9e6c-d78b8f166542
md"""
#### Plugging in the EDF for an unknown distribution
Say we have some statistic defined as follows

$$g(F) = \int r(x)dF(x)$$.

The EDF for our data is

$$\hat{F} = \frac{1}{n}\sum_{i=1}^n1(x_i\leq x)$$

Its PMF is

$$f(x) = \frac{1}{n}, x\in {\{x_1, \dots, x_n\}}$$

Thus, the esimator for $$M$$ is

$$\hat{M} = g(\hat{F}) = \int r(x)d\hat{F}(x).$$

Using our knowledge of the PDF (I guess), we can translate this into:

$$\hat{M} = \frac{1}{n}\sum_{i=1}^n r(x_i)$$.

Note that if we let $$r(x)=x$$, we get the plug-in estimator for the population mean, which is just the sample mean.

---
Ok, so we're almost there, but we still can't use this method to compute $$Var(\hat{M})$$, I assume because we can't make the jump to discrete like we did above. So we're returning to simulation.
"""

# ╔═╡ 06fef3c2-21cf-41d4-b645-6d3dbb75450c
md"""

#### Bootstrap Variance Estimation

Let's use simulation to approximate the variance of our estimator. The original procedure has us draw a sample from $$F$$, $$B$$ times. We don't have $$F$$, we'll use the EDF instead.

Steps for simulation:

1. Draw a sample from the EDF.
2. Obtain a plug-in statistic $$\hat{M} = g(\hat{F})$$
3. Replicate the two procedures $$B$$ times.
4. Get the variance in these $$B$$ statistics and use it to **approximate the true variance of the plug-in statistic**.
"""

# ╔═╡ a2a3d276-f33e-40e3-bf66-bfeeb0c99f95
md"""

**Drawing from the EDF**

By defintion of the EDF, each point is equally weighted. Thus, sampling from the EDF is just drawing n observations with replacement, as introduced at the beginning.
"""

# ╔═╡ 58ac0581-bde8-4940-9020-a738f695a2fd
md"""

## Assumptions, Applicability

Questions:

1. Will the variance result obtained from this process, $$S^2$$, be a good estimator for $$Var(\hat{M})$$?
2. Will $$Var(\hat{M})$$ be a good approximation of $$Var(M)$$?

$$S^2 = \frac{1}{B}\sum_{j=1}^B(\hat{M_j})^2 - (\frac{1}{B}\sum_{j=1}^B\hat{M_j})^2 \approx Var(\hat{M};\hat{F}) \approx Var(M;F)$$.

These are two distinct types of error. The difference between $$S^2$$ and $$Var(\hat{M})$$ is **simulation error** (the first approximate equality sign above). The difference between $$Var(\hat{M})$$ and $$Var(M)$$ is **approximation error** (the second approximate equality sign above).

Simulation error is improved with larger $$B$$.

Approximation error will be small if the following conditions are met:
1. The EDF must use enough data to approximate $$F$$ well.
2. There are some smoothness conditions on the statistic g.

1 is easy but 2 is concerning. The important thing is that variance does in fact meet these smoothness conditions so the bootstrap method can be used to estimate it.

## Implementation

Let's actually do the thing on the original problem.
"""

# ╔═╡ dd9e01ed-64c6-43cf-bde2-add77d470770
bootmeans = [mean(sample(responses, 30; replace=true)) for x in 1:100000]

# ╔═╡ 38c6b0b4-08a9-49ed-8268-1cdfd3861d2a
bootmean = mean(bootmeans)

# ╔═╡ fddd7c16-90b7-45dc-bcd0-8fbae1b64bb4
truemean = mean(pickups)

# ╔═╡ cb88575d-719b-44d6-aebe-e071e5a90069
bootmeanstd = sqrt(var(bootmeans))

# ╔═╡ 57c0deb6-feb6-4e79-bc1d-a57a6e678eda
truestderror = std(pickups) / (30^(.5))

# ╔═╡ 5b9bc0f6-c43d-4ea5-9ce6-2aa41d0ec74a
md"""
And that's it, we're done. We see that we have calculated an estimate for the standard deviation. The bootstrap simulation gave us **$(round(bootmeanstd;digits=2))** and the true standerd error for a sample size of 30 was **$(round(truestderror;digits=2))**.

Before, we needed to assume that the standard error of the sample was a good estimate for the standard deviation of the population, but we had to assume our estimator followed a normal distribution and that it was easy to calculate the standard error for our statistic. The bootstrap method let us sidestep that, and we only needed the following assumtions:
1. We need a smooth measure of error, formulated as a statistical functional (we used variance)
2. We needed a good estimate of $$F$$

**How can we reduce the error in our error estimate?**

With higher a higher sample size, (we used 30) we will have a better EDF and less approximation error. With more simulations, we will have less simulation error. This will give us a better estimate of the error.
"""

# ╔═╡ d9166184-8705-49c4-a7e9-0bba61adcaae
md"""

### Oh and one more thing...

Did we get a better mean? We had only one sample, which had a mean of $(mean(responses)). The bootstrap method provided us with $(round(bootmean;digits=2)), which is nearly identical. So we didn't use this to get a better mean, merely to to an estimate of the error in that measurement. Perhaps however, this would not be true with a different statistic. I don't know, this was just my own observation.
"""

# ╔═╡ e41995a5-1591-4404-b585-3c4e9aac49bf
md"""

## Thoughts

- How do we know if we have a good enough estimate of $$F$$?
- How do we apply this to statistical simulation of computer architecture?
  - Can we use this to get estimates on the error for our Markov models?
- How do we use this in an online fashion?

"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[compat]
Plots = "~1.27.6"
StatsBase = "~0.33.16"
"""

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

julia_version = "1.7.1"
manifest_format = "2.0"

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

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

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

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

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

[[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 = "9950387274246d08af38f6eef8cb5480862a435f"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.14.0"

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

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

[[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.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 = "b153278a25dd42c65abbf4e62344f9d22e59191b"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.43.0"

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

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

[[deps.DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.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.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

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

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

[[deps.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 = "bad72f730e9e91c08d9427d5e8db95478a3c323d"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.4.8+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.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.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.GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "51d2dfe8e590fbd74e7a842cf6d13d8a2f45dc01"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.6+0"

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

[[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 = "cd6efcf9dc746b06709df14e462f0a3fe0786b1e"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.64.2+0"

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

[[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.IniFile]]
git-tree-sha1 = "f550e6e32074c939295eb5ea6de31849ac2c9625"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.1"

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

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

[[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 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"

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

[[deps.JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b53380851c6e6664204efb2e62cd24fa5c47e4ba"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.2+0"

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

[[deps.LERC_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434"
uuid = "88015f11-f218-50d7-93a8-a6af411a945d"
version = "3.0.0+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 = "6f14549f7760d84b2db7a9b10b88cd3cc3025730"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.14"

[[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", "LERC_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "c9551dd26e31ab17b86cbd00c2ede019c08758eb"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+1"

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

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

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

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

[[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.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.NaNMath]]
git-tree-sha1 = "737a5957f387b17e74d4ad2f440eb330b39a62c5"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.0"

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

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

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

[[deps.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ab05aa4cc89736e95915b01e7279e61b1bfe33b8"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.14+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.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "3b429f37de37f1fc603cc1de4a799dc7fbe4c0b6"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.3.0"

[[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", "Statistics"]
git-tree-sha1 = "8162b2f8547bc23876edd0c5181b27702ae58dce"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "3.0.0"

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

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

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.3.0"

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

[[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 = "c6c0f690d0cc7caddb74cef7aa847b824a16b256"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+1"

[[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.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 = "dc1e451e15d90347a7decc4221842a022b011714"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.5.2"

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

[[deps.RelocatableFolders]]
deps = ["SHA", "Scratch"]
git-tree-sha1 = "cdbd3b1338c72ce29d9584fdbe9e9b70eeb5adca"
uuid = "05181044-ff0b-4ac5-8273-598c1e38db00"
version = "0.1.3"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[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.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[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.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "cd56bf18ed715e8b09f06ef8c6b781e6cdc49911"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.4.4"

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

[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "c82aaa13b44ea00134f8c9c89819477bd3986ecd"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.3.0"

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

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

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

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

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

[[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.URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

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

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

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

[[deps.Unzip]]
git-tree-sha1 = "34db80951901073501137bdbc3d5a8e7bbd06670"
uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d"
version = "0.1.2"

[[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 = "4528479aa01ee1b3b4cd0e6faef0e04cf16466da"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.25.0+0"

[[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 = "e45044cd873ded54b6a5bac0eb5c971392cf1927"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.2+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 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+1"

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

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

[[deps.x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "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:
# ╟─0810c98f-2526-4ab4-9cd5-a662434e332d
# ╟─a4283cac-c253-11ec-1d76-495287bbab72
# ╟─c33fde47-ac17-4194-973b-cdb277907b60
# ╟─e42b8dfb-1a75-448c-acc1-3255c87a0edf
# ╟─0e14ff27-5d05-4367-947e-d97e96ddfa8e
# ╠═fbbc6413-0afb-4531-8113-bb85afd2710d
# ╟─0ed657f2-8f2b-4e8f-a375-9c8986448340
# ╟─c30c49a1-2821-4ada-ab10-5cac70a99e87
# ╟─520524ab-53ef-4edb-bc58-f6a86620a126
# ╟─fda6b303-a082-4f44-8341-49446b100609
# ╟─4453da4c-12fc-427d-9f9c-89476bf65541
# ╟─f9153c34-d26b-4e54-847e-c3bae8cdb4df
# ╟─d273d1b8-e66c-4461-ab55-b2a4fe578d0c
# ╟─14b9e9b0-d67b-4376-80a5-cb0b76602174
# ╟─ceb8a078-4c55-40e7-a1bf-41bc357eaf86
# ╟─3c1f21fb-be76-446d-b27f-54119ee4835a
# ╟─1e05bcbc-cf0a-47ba-a1be-cb2e9bafff78
# ╟─56116619-fd06-4af1-9e6c-d78b8f166542
# ╟─06fef3c2-21cf-41d4-b645-6d3dbb75450c
# ╟─a2a3d276-f33e-40e3-bf66-bfeeb0c99f95
# ╟─58ac0581-bde8-4940-9020-a738f695a2fd
# ╠═dd9e01ed-64c6-43cf-bde2-add77d470770
# ╠═38c6b0b4-08a9-49ed-8268-1cdfd3861d2a
# ╠═fddd7c16-90b7-45dc-bcd0-8fbae1b64bb4
# ╠═cb88575d-719b-44d6-aebe-e071e5a90069
# ╠═57c0deb6-feb6-4e79-bc1d-a57a6e678eda
# ╟─5b9bc0f6-c43d-4ea5-9ce6-2aa41d0ec74a
# ╟─d9166184-8705-49c4-a7e9-0bba61adcaae
# ╟─e41995a5-1591-4404-b585-3c4e9aac49bf
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002