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

using Markdown
using InteractiveUtils

# ╔═╡ 0d5cd670-bdf4-11eb-3dfd-b36df6a45072
# Load Packages
begin
    using Agents
	using PlutoUI
	using Plots
	using Random
	using DataFrames
	PlutoUI.TableOfContents()
end

# ╔═╡ af61b274-831b-4fac-bc84-ab365867ddb3
md"""

# Agent-based Modeling

Agent-based Modeling (ABM) is a simulation method where the autonomous agents interacting with the environment (space) and/or each other by a set of rules.

The most obvious example of ABM is non-player characters (NPCs) in computer games (e.g. GTA V).

ABM is able to model heterogeneously, i.e. it does not require the environment to be well stirred (as opposed to ODEs), continuous (as opposed to to PDEs), nor need the characteristics of each kind of agents to be identical (as opposed to SSAs).

This makes ABM more flexible to model individual behaviors. (e.g. traffic jam, disease spread, molecular interactions)
"""

# ╔═╡ 529ac59e-5cdc-42f9-a2c3-8a36c3ef551d
md"""
## Elements of ABM

To use `Agents.jl`, we need to define:

- The [**space**](https://juliadynamics.github.io/Agents.jl/stable/api/#Available-spaces) where the agents live
- The **agents** with self-defined properties. See [`@agents`](https://juliadynamics.github.io/Agents.jl/stable/api/#@agent-macro)
- The **model** to hold the `space`, the `agent`s, and other parameters (called `properties`)
- The stepping function `step!()` to tell how the model evolve.
"""

# ╔═╡ eac86881-943f-41e9-a085-64ef2ad1554b
md"""
⚠ *WARNING*

Currently (2021-05-26) `abm_plot()` and `abm_video()` [do not work](https://discourse.julialang.org/t/error-no-backend-available-glmakie-cairomakie-wglmakie-when-calling-abm-video-in-interactivedynamics-jl/61626). There might be something wrong between `Agents.jl` and `Makie.jl`.
"""

# ╔═╡ 9668dd2f-42a0-4a1a-80f5-152af1074154
md"""
## Could I do ABM from scratch?
"""

# ╔═╡ 21a958a2-b535-4735-8b90-27ff2580858a
md"""
## Resources

- [Documentation](https://juliadynamics.github.io/Agents.jl/stable/) of `Agents.jl`.
- [sir-julia](https://github.com/epirecipes/sir-julia) : Various implementations of the classical SIR model in Julia.

"""

# ╔═╡ 0d4fd70d-892f-45d9-97a8-5e31e516ae9f
md"""

## Example 1 : Schelling's segregation model

Taken from `Agents.jl` [tutorial](https://juliadynamics.github.io/Agents.jl/stable/examples/schelling/).

- Space  : 2D grid space with a Chebyshev metric. This leads to 8 neighboring positions per position (except at the edges of the grid).
- Agents : They belong to one of two groups (0 or 1).
- Model : Each position of the grid can be occupied by at most one agent.
- For each step
  - If an agent has at least 3 neighbors belonging to the same group, then it is happy.
  - If an agent is unhappy, it keeps moving to new locations until it is happy.

"""

# ╔═╡ 51ce431e-8edf-4caa-8454-03f46bf4d9c3
md"""
To define an agent type, we should make a mutable struct derived from `AbstractAgent`

With 2 mandatory fields
- `id::Int` . The identifier number of the agent.
- `pos` . For agents on a 2D grid, the position field should be a tuple of 2 integers.

On top of that, we could define other properties for the agents.

Alternatively, we can use [`@agent`](https://juliadynamics.github.io/Agents.jl/stable/api/#@agent-macro) macro to let `Agents.jl` set up the mandatory fields for us.

```julia
@agent SchellingAgent GridAgent{2} begin
    mood::Bool
    group::Int
end
```
"""

# ╔═╡ 27dc679f-863e-45e5-b159-0135b3666463
mutable struct SchellingAgent <: AbstractAgent
    id::Int             # The identifier number of the agent
    pos::NTuple{2, Int} # The x, y location of the agent on a 2D grid
    mood::Bool          # whether the agent is happy in its position. (true = happy)
    group::Int          # The group of the agent, determines mood as it interacts with neighbors
end

# ╔═╡ 2c3940e7-7f2d-46bf-a8df-1f4ee9af25fe
md"""
It is recommeded to write a function to make ABMs so that it will be easy to recreate the model and change its parameters.
"""

# ╔═╡ 144bf87e-aac4-419f-b385-6ae853bc64ea
function make_schelling(; numagents = 320,
					  griddims = (20, 20),
		  		      min_to_be_happy = 3,
				      seed = 125)
    space = GridSpace(griddims, periodic = false)
    properties = (min_to_be_happy = 3, )

	# For demos to be reproducible
	# You don't need this in production code
    rng = Random.MersenneTwister(seed)

    model = ABM(
        SchellingAgent, space;
        properties, rng, scheduler = Schedulers.randomly
    )

    # populate the model with agents, adding equal amount of the two types of agents
    # at random positions in the model
    for n in 1:numagents
        agent = SchellingAgent(n, (1, 1), false, n < numagents / 2 ? 1 : 2)
        add_agent_single!(agent, model)
    end
    return model
end

# ╔═╡ d2d1fc91-d5b3-45f0-8237-f7acb9cbe8e4
md"""
And we define a stepping function in the format

`agent_step!(agent, model)`
"""

# ╔═╡ dc52f1f4-ac80-40c0-a3fa-afeaf11352f3
function agent_step!(agent::SchellingAgent, model)
    minhappy = model.min_to_be_happy
    count_neighbors_same_group = 0
    # For each neighbor, get group and compare to current agent's group
    # and increment count_neighbors_same_group as appropriately.
    # Here `nearby_agents` (with default arguments) will provide an iterator
    # over the nearby agents one grid point away, which are at most 8.
    for neighbor in nearby_agents(agent, model)
        if agent.group == neighbor.group
            count_neighbors_same_group += 1
        end
    end
    # After counting the neighbors, decide whether or not to move the agent.
    # If count_neighbors_same_group is at least the min_to_be_happy, set the
    # mood to true. Otherwise, move the agent to a random position.
    if count_neighbors_same_group ≥ minhappy
        agent.mood = true
    else
        move_agent_single!(agent, model)
    end
    return
end

# ╔═╡ d1282e3d-3dd4-4bae-83d5-4c29d27f6c97
begin
	groupcolor(a) = a.group == 1 ? :blue : :orange
	groupmarker(a) = a.group == 1 ? :circle : :rect
	model = make_schelling(griddims = (50, 50), numagents = 1800)

	anim = @animate for i in 1:25
		step!(model, agent_step!)
		plotabm(model; ac = groupcolor, am = groupmarker, as = 5, aspect_ratio=:equal, xlims=(0.0, 50.5), ylims = (0.0, 50.5), title = "Schelling Step $i", size=(600, 600))
	end

	mp4(anim, fps = 5)
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Agents = "46ada45e-f475-11e8-01d0-f70cc89e6671"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[compat]
Agents = "~4.4.1"
DataFrames = "~1.2.0"
Plots = "~1.18.0"
PlutoUI = "~0.7.9"
"""

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

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

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

[[Agents]]
deps = ["CSV", "DataFrames", "DataStructures", "Distributed", "GraphRecipes", "JLD2", "LightGraphs", "LinearAlgebra", "OpenStreetMapX", "ProgressMeter", "Random", "RecipesBase", "Requires", "Scratch", "StatsBase"]
git-tree-sha1 = "22aeef889a072d15ec60e56ff84d1be73526f026"
uuid = "46ada45e-f475-11e8-01d0-f70cc89e6671"
version = "4.4.1"

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

[[ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "f87e559f87a45bece9c9ed97458d3afe98b1ebb9"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.1.0"

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

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

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

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

[[CSV]]
deps = ["Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"]
git-tree-sha1 = "b83aa3f513be680454437a0eee21001607e5d983"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.8.5"

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

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

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

[[ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "32a2b8af383f11cbb65803883837a149d10dfe8a"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.10.12"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+0"

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

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

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

[[GeometryTypes]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "StaticArrays"]
git-tree-sha1 = "07194161fe4e181c6bf51ef2e329ec4e7d050fc4"
uuid = "4d00f742-c7ba-57c2-abde-4428a4b178cb"
version = "0.8.4"

[[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"

[[Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "47ce50b742921377301e15005c96e979574e130b"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.1+0"

[[GraphRecipes]]
deps = ["AbstractTrees", "GeometryTypes", "InteractiveUtils", "Interpolations", "LightGraphs", "LinearAlgebra", "NaNMath", "NetworkLayout", "PlotUtils", "RecipesBase", "SparseArrays", "Statistics"]
git-tree-sha1 = "79d9dc8ab02c4e753696b0d3b1096fabb7d74da3"
uuid = "bd48cda9-67a9-57be-86fa-5b3c104eda73"
version = "0.5.6"

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

[[HTTP]]
deps = ["Base64", "Dates", "IniFile", "MbedTLS", "Sockets"]
git-tree-sha1 = "c7ec02c4c6a039a98a15f955462cd7aea5df4508"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.8.19"

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

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

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

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

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

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

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

[[JLD2]]
deps = ["DataStructures", "FileIO", "MacroTools", "Mmap", "Pkg", "Printf", "Reexport", "TranscodingStreams", "UUIDs"]
git-tree-sha1 = "4813826871754cf52607e76ad37acb36ccf52719"
uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
version = "0.4.11"

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

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

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

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

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

[[LaTeXStrings]]
git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.2.1"

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

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

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

[[LibExpat]]
deps = ["Expat_jll", "Pkg"]
git-tree-sha1 = "27dc51f94ceb107fd53b367431a638b430e01e81"
uuid = "522f3ed2-3f36-55e3-b6df-e94fee9b0c07"
version = "0.6.1"

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

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

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

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

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

[[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"

[[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"

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

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

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

[[Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

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

[[LightGraphs]]
deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "432428df5f360964040ed60418dd5601ecd240b6"
uuid = "093fc24a-ae57-5d10-9952-331d41423f4d"
version = "1.3.5"

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

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

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

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

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

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

[[Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

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

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

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

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

[[NetworkLayout]]
deps = ["GeometryBasics", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "01b5715cdd1b7c5d493c26cc05e4af663ba9a052"
uuid = "46757867-2c16-5918-afeb-47bfcb05e46a"
version = "0.3.0"

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

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "2bf78c5fd7fa56d2bbf1efbadd45c1b8789e6f57"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.2"

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

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

[[OpenStreetMapX]]
deps = ["DataStructures", "HTTP", "JSON", "LibExpat", "LightGraphs", "Random", "Serialization", "SparseArrays", "Statistics"]
git-tree-sha1 = "71fe65bce368557f5b94079ac709a9c08f46f720"
uuid = "86cd37e6-c0ff-550b-95fe-21d72c8d4fc9"
version = "0.2.3"

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

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

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

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

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

[[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"

[[PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

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

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

[[PlutoUI]]
deps = ["Base64", "Dates", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "Suppressor"]
git-tree-sha1 = "44e225d5837e2a2345e69a1d1e01ac2443ff9fcb"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.9"

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

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

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

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

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

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

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

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

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

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

[[RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "2a7a2469ed5d94a98dea0e85c46fa653d76be0cd"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.3.4"

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

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

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

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

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

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

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

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

[[SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "daf7aec3fe3acb2131388f93a4c409b8c7f62226"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.3"

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

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

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

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "896d55218776ab8f23fb7b222a5a4a946d4aafc2"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.5"

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

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

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

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

[[Suppressor]]
git-tree-sha1 = "a819d77f31f83e5792a76081eee1ea6342ab8787"
uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
version = "0.2.0"

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

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

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

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

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

[[TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "7c53c35547de1c5b9d46a4797cf6d8253807108c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.5"

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

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

[[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"

[[Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"]
git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.18.0+4"

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

[[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"

[[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"

[[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"

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

[[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"

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

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

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

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

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

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

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

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

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

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

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

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

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

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

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

[[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:
# ╠═af61b274-831b-4fac-bc84-ab365867ddb3
# ╟─529ac59e-5cdc-42f9-a2c3-8a36c3ef551d
# ╟─eac86881-943f-41e9-a085-64ef2ad1554b
# ╠═9668dd2f-42a0-4a1a-80f5-152af1074154
# ╠═21a958a2-b535-4735-8b90-27ff2580858a
# ╠═0d5cd670-bdf4-11eb-3dfd-b36df6a45072
# ╠═0d4fd70d-892f-45d9-97a8-5e31e516ae9f
# ╠═51ce431e-8edf-4caa-8454-03f46bf4d9c3
# ╠═27dc679f-863e-45e5-b159-0135b3666463
# ╟─2c3940e7-7f2d-46bf-a8df-1f4ee9af25fe
# ╠═144bf87e-aac4-419f-b385-6ae853bc64ea
# ╠═d2d1fc91-d5b3-45f0-8237-f7acb9cbe8e4
# ╠═dc52f1f4-ac80-40c0-a3fa-afeaf11352f3
# ╠═d1282e3d-3dd4-4bae-83d5-4c29d27f6c97
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
# AUTO GENERATED FILE - DO NOT EDIT

export 'feffery'_antddatepicker

"""
    'feffery'_antddatepicker(;kwargs...)

An AntdDatePicker component.

Keyword arguments:
- `id` (String; optional)
- `allowClear` (Bool; optional)
- `bordered` (Bool; optional)
- `className` (String; optional)
- `defaultPickerValue` (optional): . defaultPickerValue has the following type: lists containing elements 'value', 'format'.
Those elements have the following types:
  - `value` (String; optional)
  - `format` (String; optional)
- `loading_state` (optional): Object that holds the loading state object coming from dash-renderer. loading_state has the following type: lists containing elements 'is_loading', 'prop_name', 'component_name'.
Those elements have the following types:
  - `is_loading` (Bool; optional): Determines if the component is loading or not
  - `prop_name` (String; optional): Holds which property is loading
  - `component_name` (String; optional): Holds the name of the component that is loading
- `picker` (a value equal to: 'date', 'week', 'month', 'quarter', 'year'; optional)
- `placeholder` (String; optional)
- `selectedDate` (String; optional)
- `showTime` (Bool; optional)
- `size` (a value equal to: 'small', 'middle', 'large'; optional)
- `style` (Dict; optional)
"""
function 'feffery'_antddatepicker(; kwargs...)
        available_props = Symbol[:id, :allowClear, :bordered, :className, :defaultPickerValue, :loading_state, :picker, :placeholder, :selectedDate, :showTime, :size, :style]
        wild_props = Symbol[]
        return Component("'feffery'_antddatepicker", "AntdDatePicker", "feffery_antd_components", available_props, wild_props; kwargs...)
end

ext: jl

max_stars_repo_name: limmyforget/feffery-antd-components

max_issues_repo_name: limmyforget/feffery-antd-components

max_forks_repo_name: limmyforget/feffery-antd-components


text:
module PiAnalysis

using Plots

# Function to compute pi using the Chudnovsky algorithm
#
# chud() takes the desired precision of BigFloat as input

export chud
function chud(prcsn::Int)

  # Set the precision of BigFloat using the input

  setprecision(BigFloat,prcsn)

  # Begin the summation in the algorithm

  pInvTemp = 0

  for i in 0:ceil(28*prcsn/1024)

    pInvTemp = pInvTemp + (-1)^(i)*factorial(BigInt(6*i))*BigInt(545140134*i+13591409)/((factorial(BigInt(3*i))*((factorial(BigInt(i)))^3)*(BigInt(640320)^BigFloat(3*i+(3/2)))))

  end

  # End the summation and multiply the result by 12

  pInv = BigFloat(pInvTemp*12)

  # Invert pInv to obtain pi

  p = BigFloat(1/pInv)

  return BigFloat(p)

end

# Function to test the accuracy of Julia's pi by comparing it to
# the result of the Chudnovsky algorithm
#
# piAccurate() takes the desired precision of BigFloat as input

export piAccurate
function piAccurate(prcsn::Int)

  # Set the precision of BigFloat using the input

  setprecision(BigFloat,prcsn)

  # Compute pi using Julia's value and chud() and return
  # the absolute value of the difference

  p1 = BigFloat(pi)
  p2 = chud(prcsn)
  diff = abs(p1-p2)

  return diff

end

# Function to find the number of recurrences of each digit of pi
#
# numDig() takes the number of the first and last digit in the
# desired interval, as well as the desired precision of BigFloat,
# as input

export numDig
function numDig(a::Int,b::Int,prcsn::Int)

  # Return errors if the input interval doesn't make any sense,
  # or if the precision of the desired interval is too small.

  if a>=b
    return error("The first input cannot be greater than or equal to the second input")
  end

  if b > prcsn/3.5
    return error("The precision must be higher for this interval (Try a precision that is at least 3.5 times the end bound)")
  end

  # Set the precision of BigFloat using the third input

  setprecision(BigFloat,prcsn)

  # Compute pi

  p = BigFloat(pi)

  # Convert pi into an array of digits

  temp = p*(10^BigFloat(b))
  dig = Base.digits(trunc(BigInt,temp))

  # Create an array to hold the numbers of recurrences the
  # first column contains the digit, and the second contains
  # the number of recurrences

  numDgts = zeros(Float64, 10, 2)

  for i in 1:10
    d = i-1
    numDgts[i,1] = d
  end

  # Count the recurrences

  for i in a:b

    num = dig[b+1-i]

    if num == 0
      numDgts[1,2] = numDgts[1,2] + 1
    elseif num == 1
      numDgts[2,2] = numDgts[2,2] + 1
    elseif num == 2
      numDgts[3,2] = numDgts[3,2] + 1
    elseif num == 3
      numDgts[4,2] = numDgts[4,2] + 1
    elseif num == 4
      numDgts[5,2] = numDgts[5,2] + 1
    elseif num == 5
      numDgts[6,2] = numDgts[6,2] + 1
    elseif num == 6
      numDgts[7,2] = numDgts[7,2] + 1
    elseif num == 7
      numDgts[8,2] = numDgts[8,2] + 1
    elseif num == 8
      numDgts[9,2] = numDgts[9,2] + 1
    elseif num == 9
      numDgts[10,2] = numDgts[10,2] + 1
    end
  end

# return the array of digits

  return(numDgts)

end

# Function to compare the number of recurrences in two different
# intervals
#
# Takes the takes the number of the first and last digit in both
# desired intervals, as well as the desired precision of BigFloat,
# as input. Returns an array with the digits in the first column
# and the number of recurrences in the second column.

export digCompare
function digCompare(a::Int,b::Int,c::Int,d::Int,prcsn::Int)

  # Return errors if the intervals are not equal or overlap

  if (b-a) != (d-c)
    return error("The intervals are not equal")
  end

  if c<=a
    return error("The intervals cannot overlap")
  end

  # Use numDig() to compute the recurrences in each interval

  dig1 = numDig(a,b,prcsn)
  dig2_temp = numDig(c,d,prcsn)

  # Subtract out the first column of the second array so
  # that the first column will remain when the arrays are
  # subtracted

  dig2 = dig2_temp-[0 0;1 0;2 0;3 0;4 0;5 0;6 0;7 0;8 0;9 0]

  # Return the result of subtracting the arrays

  return dig1-dig2

end

# Function to plot the recurrences as a pie chart
#
# Takes the number of the first and last digit in the
# desired interval, as well as the desired precision of BigFloat
# as input
#
# Uses Plots and pyplot()

export piPlot
function piPlot(a::Int,b::Int,prcsn::Int)

  pyplot()

  values = numDig(a,b,prcsn) # Compute the recurrences

  # Put the values and the labels into two arrays and plot

  x = ["0","1","2","3","4","5","6","7","8","9"]

  y = values[:,2]

  pie(x,y,title="Digits in pi from $a to $b",l=0.5)

end

end # module


text:
using DirectConvolution
using Documenter

DocMeta.setdocmeta!(DirectConvolution, :DocTestSetup, :(using DirectConvolution); recursive=true)

makedocs(modules=[DirectConvolution],
#         doctest = false,
         authors="vincent-picaud <picaud.vincent@gmail.com> and contributors",
         repo="https://github.com/vincent-picaud/DirectConvolution.jl/blob/{commit}{path}#{line}",
         sitename="DirectConvolution.jl",
         format=Documenter.HTML(;
                                prettyurls=get(ENV, "CI", "false") == "true",
                                canonical="https://vincent-picaud.github.io/DirectConvolution.jl",
                                assets=String[],
                                ),
         pages=[
             "Home" => "index.md",
         ],
         )

deploydocs(
    repo="github.com/vincent-picaud/DirectConvolution.jl.git"
)

max_stars_repo_name: vincent-picaud/DirectConvolution

max_issues_repo_name: vincent-picaud/DirectConvolution

max_forks_repo_name: vincent-picaud/DirectConvolution


text:
let
    f(X) = (10 - X[1, 1])^2 + (0 - X[1, 2])^2 + (0 - X[2, 1])^2 + (5 - X[2, 2])^2

    function g!(X, S)
        S[1, 1] = -20 + 2 * X[1, 1]
        S[1, 2] = 2 * X[1, 2]
        S[2, 1] = 2 * X[2, 1]
        S[2, 2] = -10 + 2 * X[2, 2]
        return
    end

    res = optimize(f, g!, eye(2), method = GradientDescent())

    @test norm(vec(Optim.minimizer(res) - [10.0 0.0; 0.0 5.0])) < 10e-8

    # TODO: Get finite differencing to work for generic arrays as well
    # optimize(f, eye(2), method = :gradient_descent)
end


text:
#### This file should contain all state variables
#### But, early_kernelstate.jl contains things that must be defined first.

# We need to find a place to put VersionInfo
@mkapprule VersionInfo :nargs => 0:1

@sjdoc VersionInfo """
    VersionInfo()

Return the version numbers of Symata, Julia, and Python.

    VersionInfo(All)

give more verbose information.
"""

@doap function VersionInfo()
    return _versioninfo()
end

_vpad(s) = rpad(s,19)

function _versioninfo()
    println(_vpad("Symata version"), SYMATA_VERSION)
#    println(_vpad("Commit"), string(commit_hash, "*"))
    println(_vpad("Julia version"), Base.VERSION)
#    if isdefined(PyCall, :pyversion)
    if hasproperty(PyCall, :pyversion)
        println(_vpad("Python version"), pyversion)
    else
        println("no Python version available")
    end
    try
        println(_vpad("SymPy version") * sympy.__version__)
    catch
        println("SymPy version unavailable")
    end
    if @isdefined(SymataSyntax) && _init_symatasyntax()
        println(_vpad("symatasyntax ver."), SymataSyntax.SYMATASYNTAX_VERSION)
        try
            println(_vpad("mathics version") * SymataSyntax.mathics.__version__)
        catch
            println("mathics version unavailable")
        end
    end
    return nothing
end

@doap function VersionInfo(s::SJSym)
    if s == :All
        _versioninfo()
        return InteractiveUtils.versioninfo()
    else
        return mx
    end
end

"""
    type Meval

Holds flags and counters for monitoring evaluation.
"""
mutable struct Meval
    entrycount::Int             # For trace
    trace_ev_flag::Bool         # Trace()
    trace_upvalues_flag::Bool   # TraceUpValues()
    trace_downvalues_flag::Bool # TraceDownValues()
    timingon::Bool              # Time() does @time on every user input
    try_downvalue_count::Int
    try_upvalue_count::Int
    localization_counter::Int
#    is_sjinteractive::Bool
end
const MEVAL = Meval(0, false, false, false, false, 0, 0, 0)

reset_meval_count() = MEVAL.entrycount = 0
get_meval_count() = MEVAL.entrycount
increment_meval_count() = MEVAL.entrycount += 1
decrement_meval_count() = MEVAL.entrycount -= 1

set_meval_trace() = MEVAL.trace_ev_flag = true
unset_meval_trace() = MEVAL.trace_ev_flag = false
is_meval_trace() = MEVAL.trace_ev_flag

set_down_trace() = MEVAL.trace_downvalues_flag = true
unset_down_trace() = MEVAL.trace_downvalues_flag = false
is_down_trace() = MEVAL.trace_downvalues_flag

set_up_trace() = MEVAL.trace_upvalues_flag = true
unset_up_trace() = MEVAL.trace_upvalues_flag = false
is_up_trace() = MEVAL.trace_upvalues_flag

set_timing() = MEVAL.timingon = true
unset_timing() = MEVAL.timingon = false
is_timing() = MEVAL.timingon

reset_try_downvalue_count() = MEVAL.try_downvalue_count = 0
reset_try_upvalue_count() = MEVAL.try_upvalue_count = 0
get_try_downvalue_count() = MEVAL.try_downvalue_count
get_try_upvalue_count() = MEVAL.try_upvalue_count
increment_try_downvalue_count() = MEVAL.try_downvalue_count += 1
increment_try_upvalue_count() = MEVAL.try_upvalue_count += 1

get_localization_counter() = MEVAL.localization_counter
increment_localization_counter() = MEVAL.localization_counter += 1

#### Tracing evaluation

# For (possibly) improved efficiency, we don't include Trace() in the KernelOptions Dict below.
# The value is checked twice on every pass through meval.

@sjdoc Trace """
    Trace(True)

enable tracing the evaluation loop.

    Trace(False)

disable tracing the evaluation loop.

The previous value is returned. `Trace()` returns the current value.
"""

@mkapprule Trace :nargs => 0:1

@doap Trace() = is_meval_trace()

@doap function Trace(v::Bool)
    oldval = is_meval_trace()
    v ? set_meval_trace() : unset_meval_trace()
    return oldval
end

#### Time  turn timing on and off

@sjdoc Time """
    Time(True)

enable printing CPU time consumed and memory allocated after each evaluation of command line input.

    Time(False)

disable printing CPU time consumed and memory allocated.

    Time()

Return the current value.
"""

@mkapprule Time  :nargs => 0:1

@doap Time() = is_timing()

@doap function Time(v::Bool)
    oldval = is_timing()
    v ? set_timing() : unset_timing()
    return oldval
end

#### Tracing Up and Down value evaluation

@sjdoc TraceDownValues """
    TraceDownValues(True)

enable tracing attempted applications of `DownRules`.

    TraceDownValues(False)

disable tracing attempted applications of `DownRules`.
"""

@mkapprule TraceDownValues  :nargs => 0:1

@doap TraceDownValues() = is_down_trace()

@doap function TraceDownValues(v::Bool)
    oldval = is_down_trace()
    v ? set_down_trace() : unset_down_trace()
    return oldval
end

@sjdoc TraceUpValues """
    TraceUpValues(True)

enable tracing attempted applications of `UpRules`.

    TraceUpValues(False)

disable tracing attempted applications of `UpRules`.
"""

@mkapprule TraceUpValues  :nargs => 0:1

@doap TraceUpValues() = is_up_trace()

@doap function TraceUpValues(v::Bool)
    oldval = is_up_trace()
    v ? set_up_trace() : unset_up_trace()
    return oldval
end

##### More evaluation things

mutable struct SavedOutput
    expr::Any
end

function clear_all_output()
    for i in 1:length(Output)
        Output[i].expr = :Null   # temporary solutions
    end
    return nothing
end

const LineNumber = Int[1]
get_line_number() = LineNumber[1]
set_line_number(n::Integer) =  (LineNumber[1] = n)
increment_line_number() = LineNumber[1] += 1

const Output = SavedOutput[]

function get_saved_output_by_index(n::Integer)
    if n > 0 && n <= length(Output)
        return Output[n].expr
    end
    return nothing
end

function push_output(expr)
    n0 = getkerneloptions(:history_length)
    while length(Output) >= n0
        popfirst!(Output)
    end
    push!(Output, SavedOutput(expr))
    return nothing
end

get_output_by_line() = get_output_by_line(-1)

function get_output_by_line(lineno::Integer)
    if lineno < 0 lineno = length(Output) + lineno + 1 end
    idx = length(Output) - (get_line_number() - lineno) + 1
    if idx <= length(Output) && idx > 0
        return get_saved_output_by_index(idx)
    else
        return Null
    end
end

global do_we_print_Out_label = true

##### Break

mutable struct FlowFlags
    breakflag::Bool
    throwflag::Bool
end

const FLOWFLAGS = FlowFlags(false, false)

# const FLOWFLAGS = Dict{Symbol, Bool}()
# FLOWFLAGS[:Break] = false

function is_break()
    return FLOWFLAGS.breakflag
#    return FLOWFLAGS[:Break]
end

function clear_break()
    return FLOWFLAGS.breakflag = false
#    FLOWFLAGS[:Break] = false
end

function set_break()
    return FLOWFLAGS.breakflag = true
#    FLOWFLAGS[:Break] = true
end

is_throw()  = FLOWFLAGS.throwflag
clear_throw() = FLOWFLAGS.throwflag = false
set_throw() = FLOWFLAGS.throwflag = true

##### User options and info

"""
    Kerneloptions

Global options for the Symata kernel.
"""
const Kerneloptions = Dict{Any,Any}(
    :unicode_output => false,
    :ijulia_latex_output => false,
    :show_sympy_docs => true,
    :return_sympy => false,
    :sympy_error => nothing,
    :compact_output => true,
    :history_length => 100,
    :bigint_input => false,
    :bigfloat_input => false,
    :isymata_inited => false,
    #:isymata_mode => false, # this state now stored in ./IJulia/handlers.jl
    :isymata_mma_mode => false,
    :output_style => :InputForm,
    :float_format => "",
    :bigfloat_format => ""
)

function getkerneloptions(sym::Symbol)
    return Kerneloptions[sym]
end

"""
    setkerneloptions(sym::Symbol, val)

Set the Symata kernel option `sym` to `val`.
"""
function setkerneloptions(sym::Symbol, val)
    oval = Kerneloptions[sym]
    Kerneloptions[sym] = val
    return oval
end

#### UnicodeOutput

@mkapprule UnicodeOutput :nargs => 0:1  :nodefault => true

@sjdoc UnicodeOutput """
    UnicodeOutput()

is obsolete. See `OutputStyle()`.
"""

@doap UnicodeOutput(args...) = println("UnicodeOutput() is obsolete. See OutputStyle()")

#### ShowSymPyDocs

@mkapprule ShowSymPyDocs  :nargs => 0:1

@sjdoc ShowSymPyDocs """
    ShowSymPyDocs(True)

(default) enable printing SymPy document strings.

    ShowSymPyDocs(False)

disable printing SymPy document strings.

    ShowSymPyDocs()

Return the current state.
"""

#### ReturnSymPy

@mkapprule ReturnSymPy  :nargs => 0:1

@sjdoc ReturnSymPy """
    ReturnSymPy(True)

disable conversion of expressions computed by SymPy to Symata.

    ReturnSympy(False)

(default) enable conversion to Symata.

    ReturnSympy()

Return the current state.
"""

#### SymPyError

@mkapprule SymPyError :nargs => 0

@sjdoc SymPyError """
    SymPyError()

Return the most recent SymPy error message. If you see a message warning that
a SymPy error has occurred, you can find the detailed error message.
"""

#### CompactOutput

@mkapprule CompactOutput  :nargs => 0:1

@sjdoc CompactOutput """
    CompactOutput(True)

(default) enable printing fewer spaces between operators.

    Compact()

Return the current state.

`CompactOutput` has an effect in `InputForm` and `UnicodeForm` output styles, but not in `JupyterForm` output style.
"""

#### BigIntInput

@mkapprule BigIntInput  :nargs => 0:1

@sjdoc BigIntInput """
    BigIntInput(True)

enable interpreting all integers as arbitrary precision `BigInt`s.

    BigIntInput(False)

(default) disable interpreting all integers as arbitrary precision `BigInts`.

    BigIntInput()

Return the current state.

You can always specify that an integer should be a `BigInt` by giving `BI(n)`.
"""

"""
    bigintinput()

Return true if the "kernel option" for converting input integers to BigInt is set.
"""
bigintinput() = getkerneloptions(:bigint_input)

#### BigFloatInput

@mkapprule BigFloatInput  :nargs => 0:1

@sjdoc BigFloatInput """
    BigFloatInput(True)

enable interpreting all floating point numbers as arbitrary precision `BigFloats`.

    BigFloatInput(False)

(default) disable interpreting all floating point numbers as arbitrary precision `BigFloat`s.

    BigFloatInput()

Return the current state.

You can always specify that a float should be a BigFloat by using BF(n).
"""

@sjseealso_group(BI, BigIntInput, BF, BigFloatInput)

for (fn, sym) in ((:ShowSymPyDocs, :show_sympy_docs), (:ReturnSymPy, :return_sympy),
                 (:CompactOutput, :compact_output), (:BigIntInput, :bigint_input),(:BigFloatInput, :bigfloat_input))
    fnf = Symbol("do_", fn)
    fns = string(fn)
    ssym = string(sym)
    @eval begin
        ($fnf)(mx::Mxpr{Symbol($fns)}, v::Bool) = v ? setkerneloptions(Symbol($ssym), true) : setkerneloptions(Symbol($ssym), false)
        ($fnf)(mx::Mxpr{Symbol($fns)}) = getkerneloptions(Symbol($ssym))
    end
end

for (fn, sym) in ((:SymPyError, :sympy_error),)
    fnf = Symbol("do_", fn)
    fns = string(fn)
    ssym = string(sym)
    @eval begin
        ($fnf)(mx::Mxpr{Symbol($fns)}) = getkerneloptions(Symbol($ssym))
    end
end

@mkapprule HistoryLength  :nargs => 0:1

@sjdoc HistoryLength """
    HistoryLength(n)

enable storing the `n` most recent output expressions.

    HistoryLength()

Return the current value.
"""

function _set_historylength(n::Integer)
    oldn = getkerneloptions(:history_length)
    setkerneloptions(:history_length, n)
    for i in 1:(length(Output)-n)
        popfirst!(Output)
    end
    oldn
end

@doap function HistoryLength(n::Integer)
    _set_historylength(n)
end

@doap HistoryLength() = getkerneloptions(:history_length)

@sjdoc FloatFormat """
    FloatFormat()

get the floating point output format

    FloatFormat(fmt)

set the floating point output format to `fmt`.

If `fmt` is `Full` or `""`, then default output format is used.

If `fmt` is `Short` or `"%.6g"`, then fewer digits are printed.

If `fmt` is `n` or `"%.ng"`, then `n` digits after the decimal are printed.
"""
@mkapprule FloatFormat
@doap FloatFormat() = getkerneloptions(:float_format)
@doap FloatFormat(s) = setkerneloptions(:float_format,_float_format(s))

_float_format(s::String) = s

function _float_format(s::Symbol)
    if s == :Full
        return ""
    elseif s == :Short
        return "%g"
    else
        symerror("Unrecognized number format")
    end
end

function _float_format(s::Integer)
    "%.$(s)g"
end

@sjdoc BigFloatFormat """
    BigFloatFormat()

get the output format for arbitrary-precision, floating-point numbers.

    BigFloatFormat(fmt::String)

set the output format for arbitrary-precision, floating-point numbers to `fmt`.

If `fmt=""`, then default output format is used

`fmt="%.6g"` is a common choice.
"""
@mkapprule BigFloatFormat
@doap BigFloatFormat() = getkerneloptions(:bigfloat_format)
@doap BigFloatFormat(s) = setkerneloptions(:bigfloat_format,_float_format(s))

#### isymata_inited

"""
    isymata_inited()
    isymata_inited(v::Bool)

true if IJulia has been configured to run Symata during this
session. This configuration is done by `init_isymata` the first time `isymata()`
is called during a session.
"""
isymata_inited() = getkerneloptions(:isymata_inited)
isymata_inited(v::Bool) = (ov = getkerneloptions(:isymata_inited); setkerneloptions(:isymata_inited,v); ov)

# """
#     isymata_mode()
#     isymata_mode(v::Bool)

# get or set the flag signifying that IJulia input should be interpreted as Symata rather than Julia.
# """
# isymata_mode() = getkerneloptions(:isymata_mode)
# isymata_mode(v::Bool) = (ov = getkerneloptions(:isymata_mode); setkerneloptions(:isymata_mode,v); ov)

"""
    isymata_mma_mode()
    isymata_mma_mode(v::Bool)

get or set the flag signifying that IJulia input should be interpreted as Symata with Mathematica syntax rather than Julia or Symata.
"""
isymata_mma_mode() = getkerneloptions(:isymata_mma_mode)
isymata_mma_mode(v::Bool) = (ov = getkerneloptions(:isymata_mma_mode); setkerneloptions(:isymata_mma_mode,v); ov)

@mkapprule OutputStyle :nargs => 0:1
@sjdoc OutputStyle """
    OutputStyle(InputForm)

print plain 1d text output.

    OutputStyle(UnicodeForm)

print 1d text output with pretty unicode characters.

    OutputStyle(JupyterForm)

in a Jupyter notebook, print in typeset mathematics style using latex.

    OutputStyle()

Return the current output style.

`InputForm` and `UnicodeForm` give output that is valid `Symata` input for the same expression.
"""

function _set_output_style(st::Symbol)
    if st != :InputForm && st != :UnicodeForm  && st != :JupyterForm
        error("OutputStyle: style must be one of InputForm, UnicodeForm, JupyterForm")
    end
    oldst = getkerneloptions(:output_style)
    setkerneloptions(:output_style, st)
    return st
end

@doap function OutputStyle(st::Symbol)
    _set_output_style(st)
end

@doap OutputStyle() = getkerneloptions(:output_style)

@sjseealso_group(OutputStyle, CompactOutput)

"""
    using_unicode_output()

Return true if unicode output style is selected. This is mutually exclusive with InputForm output and
JupyterForm output styles.
"""
using_unicode_output() = getkerneloptions(:output_style) == :UnicodeForm

# This means we are using LaTeX
using_ijulia_output() = getkerneloptions(:output_style) == :JupyterForm

### Julia

@sjdoc Julia """
    Julia()

Exit Symata mode and returns to Julia mode from within Jupyter.
Use `isymata()` from Julia to enter Symata mode again.
"""

@mkapprule Julia :nargs => 0

@doap function Julia()
    Jupyter.set_julia_mode()
    nothing
#    set_jupyter_input_prompt_color("green") # This used to apply to single cells.
end


text:
module ApproxFunBase
    using Base, BlockArrays, BandedMatrices, BlockBandedMatrices, DomainSets, IntervalSets,
            SpecialFunctions, AbstractFFTs, FFTW, SpecialFunctions, DSP, DualNumbers,
            LinearAlgebra, SparseArrays, LowRankApprox, FillArrays, InfiniteArrays #, Arpack
import StaticArrays, Calculus

import DomainSets: Domain, indomain, UnionDomain, ProductDomain, FullSpace, Point, elements, DifferenceDomain,
            Interval, ChebyshevInterval, boundary, ∂, rightendpoint, leftendpoint,
            dimension, WrappedDomain

import AbstractFFTs: Plan, fft, ifft
import FFTW: plan_r2r!, fftwNumber, REDFT10, REDFT01, REDFT00, RODFT00, R2HC, HC2R,
                r2r!, r2r,  plan_fft, plan_ifft, plan_ifft!, plan_fft!

import Base: values, convert, getindex, setindex!, *, +, -, ==, <, <=, >, |, !, !=, eltype, iterate,
                >=, /, ^, \, ∪, transpose, size, tail, broadcast, broadcast!, copyto!, copy, to_index, (:),
                similar, map, vcat, hcat, hvcat, show, summary, stride, sum, cumsum, sign, imag, conj, inv,
                complex, reverse, exp, sqrt, abs, abs2, sign, issubset, values, in, first, last, rand, intersect, setdiff,
                isless, union, angle, join, isnan, isapprox, isempty, sort, merge, promote_rule,
                minimum, maximum, extrema, argmax, argmin, findmax, findmin, isfinite,
                zeros, zero, one, promote_rule, repeat, length, resize!, isinf,
                getproperty, findfirst, unsafe_getindex, fld, cld, div, real, imag,
                @_inline_meta, eachindex, firstindex, lastindex, keys, isreal, OneTo,
                Array, Vector, Matrix, view, ones, @propagate_inbounds, print_array,
                split, iszero

import Base.Broadcast: BroadcastStyle, Broadcasted, AbstractArrayStyle, broadcastable,
                        DefaultArrayStyle, broadcasted

import Statistics: mean

import LinearAlgebra: BlasInt, BlasFloat, norm, ldiv!, mul!, det, eigvals, dot, cross,
                        qr, qr!, rank, isdiag, istril, istriu, issymmetric, ishermitian,
                        Tridiagonal, diagm, diagm_container, factorize, nullspace,
                        Hermitian, Symmetric, adjoint, transpose, char_uplo

import SparseArrays: blockdiag

# import Arpack: eigs

# we need to import all special functions to use Calculus.symbolic_derivatives_1arg
# we can't do importall Base as we replace some Base definitions
import SpecialFunctions: sinpi, cospi, airy, besselh,
                    asinh, acosh,atanh, erfcx, dawson, erf, erfi,
                    sin, cos, sinh, cosh, airyai, airybi, airyaiprime, airybiprime,
                    hankelh1, hankelh2, besselj, besselj0, bessely, besseli, besselk,
                    besselkx, hankelh1x, hankelh2x, exp2, exp10, log2, log10,
                    tan, tanh, csc, asin, acsc, sec, acos, asec,
                    cot, atan, acot, sinh, csch, asinh, acsch,
                    sech, acosh, asech, tanh, coth, atanh, acoth,
                    expm1, log1p, lfact, sinc, cosc, erfinv, erfcinv, beta, lbeta,
                    eta, zeta, gamma,  lgamma, polygamma, invdigamma, digamma, trigamma,
                    abs, sign, log, expm1, tan, abs2, sqrt, angle, max, min, cbrt, log,
                    atan, acos, asin, erfc, inv

import StaticArrays: SVector

import BlockArrays: nblocks, blocksize, global2blockindex, globalrange, BlockSizes

import BandedMatrices: bandrange, bandshift,
                        inbands_getindex, inbands_setindex!, bandwidth, AbstractBandedMatrix,
                        colstart, colstop, colrange, rowstart, rowstop, rowrange,
                        bandwidths, _BandedMatrix, BandedMatrix

import BlockBandedMatrices: blockbandwidth, blockbandwidths, blockcolstop, blockcolrange,
                            blockcolstart, blockrowstop, blockrowstart, blockrowrange,
                            subblockbandwidth, subblockbandwidths, _BlockBandedMatrix,
                            _BandedBlockBandedMatrix, BandedBlockBandedMatrix, BlockBandedMatrix,
                            isblockbanded, isbandedblockbanded, bb_numentries, BlockBandedSizes,
                            BandedBlockBandedSizes

import FillArrays: AbstractFill, getindex_value
import LazyArrays: cache
import InfiniteArrays: Infinity, InfRanges, AbstractInfUnitRange, OneToInf

# convenience for 1-d block ranges
const BlockRange1 = BlockRange{1,Tuple{UnitRange{Int}}}

import Base: view

import StaticArrays: StaticArray, SVector

import IntervalSets: (..), endpoints

const Vec{d,T} = SVector{d,T}

export pad!, pad, chop!, sample,
       complexroots, roots, svfft, isvfft,
       reverseorientation, jumplocations

export .., Interval, ChebyshevInterval, leftendpoint, rightendpoint, endpoints, cache

include("LinearAlgebra/LinearAlgebra.jl")
include("Fun.jl")
include("Domains/Domains.jl")
include("Multivariate/Multivariate.jl")
include("Operators/Operator.jl")
include("Caching/caching.jl")
include("PDE/PDE.jl")
include("Spaces/Spaces.jl")
include("hacks.jl")
include("testing.jl")
include("specialfunctions.jl")

end #module


text:
export all_states, local_basis
export gibbs_tensor
export brute_force, full_spectrum, energy
export Spectrum

"""
$(TYPEDSIGNATURES)

Calculates Gibbs state of a classical Ising Hamiltonian

# Details

Calculates matrix elements (probabilities) of \$\\rho\$
```math
\$\\bra{\\σ}\\rho\\ket{\\sigma}\$
```
for all possible configurations \$\\σ\$.
"""
function gibbs_tensor(ig::IsingGraph, β=Float64=1.0)
    states = collect.(all_states(rank_vec(ig)))
    ρ = exp.(-β .* energy.(states, Ref(ig)))
    ρ ./ sum(ρ)
end

"""
$(TYPEDSIGNATURES)

Calculate the Ising energy
```math
E = -\\sum_<i,j> s_i J_{ij} * s_j - \\sum_j h_i s_j.
```
"""
energy(σ::Vector, J::Matrix, η::Vector=σ) = dot(σ, J, η)
energy(σ::Vector, h::Vector) = dot(h, σ)
energy(σ::Vector, ig::IsingGraph) = energy(σ, couplings(ig)) + energy(σ, biases(ig))

"""
$(TYPEDSIGNATURES)

Return the low energy spectrum

# Details

Calculates \$k\$ lowest energy states
together with the coresponding energies
of a classical Ising Hamiltonian
"""

function brute_force(ig::IsingGraph; sorted=true, num_states::Int=1)
    if nv(ig) == 0 return Spectrum(zeros(1), []) end
    ig_rank = rank_vec(ig)
    num_states = min(num_states, prod(ig_rank))

    σ = collect.(all_states(ig_rank))
    energies = energy.(σ, Ref(ig))
    if sorted
        perm = partialsortperm(vec(energies), 1:num_states)
        return Spectrum(energies[perm], σ[perm])
    else
        return Spectrum(energies[1:num_states], σ[1:num_states])
    end
end

full_spectrum(ig::IsingGraph; num_states::Int=1) = brute_force(ig, sorted=false, num_states=num_states)

struct Spectrum
    energies::Vector{Float64}
    states::Vector{Vector{Int}}
end

# Please don't make the below another energy method.
# There is already so much mess going on :)
function inter_cluster_energy(cl1_states, J::Matrix, cl2_states)
    hcat(collect.(cl1_states)...)' * J * hcat(collect.(cl2_states)...)
end


text:
using Swalbe, Plots

"""
    run_drop_coal()

Simulation of two droplets in close contact to study their coalesence behaviour.
"""
function run_drop_coal(
    sys::Swalbe.SysConst_1D;                # System relevant constants
    r₁=500,                                 # First droplets radius
    r₂=500,                                 # Second droplets radius
    θ₀=1/9,                                 # Contact angle
    centers=(sys.L/3, 2*sys.L/3),           # Drople centers
    dump = 100,                             # Data dumping interval
    fluid=zeros(sys.Tmax÷dump, sys.L),      # Data
    verbos=true                             # Simulation updates about the bridge height in consol
)
    println("Simulating droplet coalecense")
    state = Swalbe.Sys(sys)
    state.height .= Swalbe.two_droplets(sys, r₁=r₁, r₂=r₂, θ₁=θ₀, θ₂=θ₀, center=centers)
    Swalbe.equilibrium!(state)
    println("Starting the lattice Boltzmann time loop")
    for t in 1:sys.Tmax
        if t % sys.tdump == 0
            mass = 0.0
            mass = sum(state.height)
            if verbos
                println("Time step $t bridge height is $(round(state.height[Int(sys.L/2)], digits=3))")
            end
        end
        Swalbe.filmpressure!(state, sys)
        Swalbe.h∇p!(state)
        Swalbe.slippage!(state, sys)
        state.F .= -state.h∇p .- state.slip
        Swalbe.equilibrium!(state)
        Swalbe.BGKandStream!(state)
        Swalbe.moments!(state)
        # Make a snaphot of the configuration
        Swalbe.snapshot!(fluid, state.height, t, dumping = dump)
    end
    return fluid
end

"""
    bridge_height(data)

Compuation of the bridge height between two droplets based on input `data`.
"""
function bridge_height(data; t1=100, t_dur=size(data)[1], pos=size(data)[2]÷2)
    bridge_h = []
    for i in 1:t_dur
        push!(bridge_h, data[i, pos])
    end
    return bridge_h
end

"""
	τν(γ, R, η)

Computes the viscous time.

# Mathematics

``t_c = \\sqrt{\\frac{\\rho R^3}{\\gamma}}``
"""
function τν(γ; R=500, η=1/6)
	time_c = 0.0
	time_c = R*η/γ
	return time_c
end

# Different surface tension values
γs = [0.00001, 0.00005, 0.0001, 0.0005]
# Large array that contains the simulation data
data_merge = zeros(20000, 1024, length(γs))
# Drop radii
sphere_rad = 500.0
# Loop different surface tension values
for γ in enumerate(γs)
    sys = Swalbe.SysConst_1D(L=1024, Tmax=2000000, δ=50.0, γ=γ[2])
    data_merge[:,:,γ[1]] = run_drop_coal(sys, r₁=sphere_rad, r₂=sphere_rad)
end
# Compute the bridge heights for the data collect and store it in a single array
bridges = zeros(20000, length(γs))
for i in 1:length(γs)
	bridges[:, i] = bridge_height(data_merge[:,:,i])
end
# Actual LBM time, time steps without (physical) meaning
time_lbm = 100:100:2000000
p1 = plot(time_lbm,                                                 # x-data
		  bridges,                                                  # y-data
		  xlabel="t [Δt]",                                          # axis label
		  ylabel="h₀",                                              # axis label
		  label=["γ=0.00001" "γ=0.00005" "γ=0.0001" "γ=0.0005"],    # labels for the curves
		  xticks=([0:1000000:2000000;], ["0", "1×10⁶", "2×10⁶"]),   # ticks and labels
		  xlims=(0,2100000),                                        # well limits of display
		  ylims=(0, 40),                                            # well limits of display
		  w = 3, 							                        # line width
		  marker = (8, :auto, 0.6),			                        # marker size
		  legend=:bottomright,                                      # legend position
		  legendfontsize = lf,			                            # legend font size
          tickfont = (14),	                                        # tick font and size
          guidefont = (15),	                                        # label font and size
		  grid=:none                                                # no gird, was asked once by PRE to remove the grid
)
# Now to collapse the curves we non-dimensionalize the time with the visous time scale τν and the height with the sphere radius R₀
time_norm = zeros(length(time_lbm), length(γs))
for i in enumerate(γs)
	time_norm[:, i[1]] .= time_lbm ./ τν(i[2])
end
# And plot it again
p2 = plot(time_norm,                                                # x-data
		  bridges ./ 500.0,                                         # y-data
		  xlabel="t [Δt]",                                          # axis label
		  ylabel="h₀",                                              # axis label
		  label=["γ=0.00001" "γ=0.00005" "γ=0.0001" "γ=0.0005"],    # labels for the curves
		  xticks=([0:1000000:2000000;], ["0", "1×10⁶", "2×10⁶"]),   # ticks and labels
		  xlims=(0,2100000),                                        # well limits of display
		  ylims=(0, 40),                                            # well limits of display
		  w = 3, 							                        # line width
		  marker = (8, :auto, 0.6),			                        # marker size
		  legend=:bottomright,                                      # legend position
		  legendfontsize = lf,			                            # legend font size
          tickfont = (14),	                                        # tick font and size
          guidefont = (15),	                                        # label font and size
		  grid=:none                                                # no gird, was asked once by PRE to remove the grid
)
# In the inertial regime we assume that the bridge height grows as time to the power of 2/3, we can check it by simply adding this curve
t_scaling = collect(1e-5:1e-5:10)                                       # Finer time scale for the power law
plot!(t_scaling, 0.024 .* t_scaling.^(2/3), c=:black, w=4, l=:dash, label="t^(2/3)")


text:
using PyCall
using FileIO
import MAT
import JSON

function load_rgb(filename)
    py"""
    import numpy as np
    import imageio
    def get_depth(depth_path):
        depth = imageio.imread(depth_path)
        depth = depth.astype(np.float)
        return depth
    def get_rgb(rgb_path):
        rgb = imageio.imread(rgb_path)
        return rgb
    """
    py"get_rgb"(filename)
end

function load_depth(filename)
    py"""
    import numpy as np
    import imageio
    def get_depth(depth_path):
        depth = imageio.imread(depth_path)
        depth = depth.astype(np.float)
        return depth
    def get_rgb(rgb_path):
        rgb = imageio.imread(rgb_path)
        return rgb
    """
    py"get_depth"(filename)
end

export load_rgb, load_depth

function load_ycb_model_list(YCB_DIR)
    model_list = readlines(joinpath(YCB_DIR, "model_list.txt"))
end

function load_ycbv_models(YCB_DIR)
    model_list = load_ycb_model_list(YCB_DIR)
    id_to_cloud = Dict()
    for (i,model_name) in enumerate(model_list)
        model_xyz = load(joinpath(YCB_DIR, "models",model_name,"textured_simple.obj"));
        model_xyz = transpose([i[j] for i in model_xyz.position, j in 1:3])
        id_to_cloud[i] = Matrix(model_xyz)
    end
    id_to_cloud
end

function load_ycbv_point_xyz(YCB_DIR)
    model_list = readlines(joinpath(YCB_DIR, "model_list.txt"))
    id_to_cloud = Dict()
    for (i,model_name) in enumerate(model_list)
        model_xyz = readlines(joinpath(YCB_DIR, "models",model_name,"points.xyz"))
        model_xyz = hcat(map(x->map(y->parse(Float64,y), split(x," ")), model_xyz)...)
        id_to_cloud[i] = Matrix(model_xyz)
    end
    id_to_cloud
end

function load_ycb_model_obj_file_paths(YCB_DIR)
    model_list = readlines(joinpath(YCB_DIR, "model_list.txt"))
    paths = []
    for (i,model_name) in enumerate(model_list)
        path = joinpath(YCB_DIR, "models",model_name,"textured_simple.obj")
        push!(paths, path)
    end
    paths
end

function load_ycb_model_texture_file_paths(YCB_DIR)
    model_list = readlines(joinpath(YCB_DIR, "model_list.txt"))
    paths = []
    for (i,model_name) in enumerate(model_list)
        path = joinpath(YCB_DIR, "models",model_name,"texture_map.png")
        push!(paths, path)
    end
    paths
end

function get_ycb_scene_frame_id_from_idx(YCB_DIR, IDX)
    # Keyframes
    keyframes = readlines(joinpath(YCB_DIR, "keyframe.txt"))
    scene_t = map(u->map(x->parse(Int,x), split(u,"/")), keyframes);

    SCENE, T = scene_t[IDX];
    SCENE,T
end

function load_ycbv_scene(YCB_DIR, IDX)
    # Keyframes
    keyframes = readlines(joinpath(YCB_DIR, "keyframe.txt"))
    scene_t = map(u->map(x->parse(Int,x), split(u,"/")), keyframes);

    SCENE, T = scene_t[IDX];
    load_ycbv_scene(YCB_DIR, SCENE, T)
end

function load_ycbv_scene(YCB_DIR, SCENE, T)
    # Load relevant files
    py"""
    import numpy as np
    import imageio

    def get_depth(depth_path):
        depth = imageio.imread(depth_path)
        depth = depth.astype(np.float)
        return depth

    def get_rgb(rgb_path):
        rgb = imageio.imread(rgb_path)
        return rgb
    """

    rgb_image = py"get_rgb"(joinpath(YCB_DIR,lpad(SCENE,4,"0"),lpad(T,6,"0")*"-color.png"))
    depth_image = py"get_depth"(joinpath(YCB_DIR,lpad(SCENE,4,"0"),lpad(T,6,"0")*"-depth.png"));

    mat = MAT.matopen(joinpath(YCB_DIR,lpad(SCENE,4,"0"),lpad(T,6,"0")*"-meta.mat"));
    keys(mat)

    Rt_mat_to_pose(mat) = Pose(mat[1:3,end],R.RotMatrix3{Float64}(mat[1:3,1:3]));

    cam_Rt = read(mat,"rotation_translation_matrix")
    cam_pose = inverse_pose(Rt_mat_to_pose(cam_Rt))

    depth_scaling_factor = read(mat,"factor_depth")
    # @show depth_scaling_factor

    K = read(mat,"intrinsic_matrix")
    camera = GL.CameraIntrinsics(
        width=640, height=480,
        fx=K[1,1], fy=K[2,2], cx=K[1,3], cy=K[2,3],
        near=1.0, far=50000.0)

    ids = map(Int,[
        read(mat,"cls_indexes")
    ][1][:])

    poses = read(mat,"poses")
    poses = [Rt_mat_to_pose(poses[:,:,i]) for i in 1:(size(poses)[3])];

    poses, ids, rgb_image, depth_image ./ depth_scaling_factor, cam_pose, camera
end

function load_ycbv_dense_fusion_predictions(YCB_DIR, IDX)
    # Load dense fusion results
    json_file = joinpath(YCB_DIR,"densefusion/dense_results",lpad(IDX-1,6,"0")*".json")
    json_data = JSON.parsefile(json_file)
    densefusion_ids = [Int.(x[2]) for x in json_data["rois"]]

    mat_file = joinpath(YCB_DIR,"densefusion/dense_results/Densefusion_iterative_result",lpad(IDX-1,4,"0")*".mat")
    mat_data = MAT.matopen(mat_file)
    densefusion_poses = [
        let
            pos = p[5:7]
            rot = p[1:4]
            if all(pos .== 0.0) && all(rot .== 0.0)
                Pose(zeros(3), IDENTITY_ORIENTATION)
            else
                Pose(p[5:7], Rotations.UnitQuaternion(p[1:4]...))
            end
        end
        for p in eachrow(read(mat_data,"poses"))
    ];
    densefusion_poses, densefusion_ids
end

function load_ycbv_models_adjusted(YCB_DIR, world_scaling_factor)
    original_id_to_cloud = load_ycbv_models(YCB_DIR);

    id_to_cloud = Dict()
    id_to_shift = Dict()
    # id_to_mesh = Dict()
    id_to_box = Dict()
    for id in keys(original_id_to_cloud)
        scaled_cloud = copy(original_id_to_cloud[id]) * world_scaling_factor
        mins,maxs = min_max(scaled_cloud)
        shift = ((maxs .+ mins) ./ 2 )
        id_to_shift[id] = shift
        scaled_cloud .-= shift
        id_to_cloud[id] = scaled_cloud
        # id_to_mesh[id] = voxelized_cloud_to_mesh(
            # voxelize(id_to_cloud[id], resolution), resolution)
    #     register_mesh!(renderer, id_to_mesh[id])
        mins,maxs = min_max(id_to_cloud[id])
        id_to_box[id] = S.Box((maxs .- mins)...)
    end
    id_to_cloud, id_to_shift, id_to_box
end

function load_ycbv_scene_adjusted(YCB_DIR, IDX, world_scaling_factor, id_to_shift)
    gt_poses, ids, rgb_image, depth_image, cam_pose, camera = load_ycbv_scene(YCB_DIR, IDX)
    gt_poses = [get_c_relative_to_a(
        Pose(p.pos * world_scaling_factor, p.orientation),
        Pose(id_to_shift[id]...))
    for (id,p) in zip(ids,gt_poses)]
    cam_pose = Pose(cam_pose.pos * world_scaling_factor, cam_pose.orientation)
    depth_image = depth_image * world_scaling_factor;
    return gt_poses, ids, rgb_image, depth_image, cam_pose, camera
end

function load_ycbv_scene_adjusted(YCB_DIR, SCENE, T, world_scaling_factor, id_to_shift)
    gt_poses, ids, rgb_image, depth_image, cam_pose, camera = load_ycbv_scene(YCB_DIR, SCENE, T)
    gt_poses = [get_c_relative_to_a(
        Pose(p.pos * world_scaling_factor, p.orientation),
        Pose(id_to_shift[id]...))
    for (id,p) in zip(ids,gt_poses)]
    cam_pose = Pose(cam_pose.pos * world_scaling_factor, cam_pose.orientation)
    depth_image = depth_image * world_scaling_factor;
    return gt_poses, ids, rgb_image, depth_image, cam_pose, camera
end

function load_synthetic_scene_adjusted(SYNTHETIC_DIR, T, world_scaling_factor, id_to_shift)
    depth_image = load_depth(joinpath(SYNTHETIC_DIR,"data",lpad(T,6,"0")*"-depth.png")) ./ 10000.0;
    rgb_image = load(joinpath(SYNTHETIC_DIR,"data",lpad(T,6,"0")*"-color.png"))
    metadata = deserialize(joinpath(SYNTHETIC_DIR,"data",lpad(T,6,"0")*"-meta.data"))
    camera = metadata.camera
    cam_pose = metadata.camera_pose
    ids = metadata.ids
    gt_poses = metadata.object_poses
    gt_poses = [get_c_relative_to_a(
        Pose(p.pos * world_scaling_factor, p.orientation),
        Pose(id_to_shift[id]...))
    for (id,p) in zip(ids,gt_poses)]
    cam_pose = Pose(cam_pose.pos * world_scaling_factor, cam_pose.orientation)
    depth_image = depth_image * world_scaling_factor;
    return gt_poses, ids, rgb_image, depth_image, cam_pose, camera
end

function adjust_poses(poses, ids, world_scaling_factor, id_to_shift)
    new_poses = [get_c_relative_to_a(
        Pose(p.pos * world_scaling_factor, p.orientation),
        Pose(id_to_shift[id]...))
        for (id,p) in zip(ids,poses)]
    return new_poses
end

function load_ycbv_dense_fusion_predictions_adjusted(YCB_DIR, IDX, world_scaling_factor, id_to_shift)
    dense_poses, dense_ids = load_ycbv_dense_fusion_predictions(YCB_DIR, IDX);
    dense_poses_adjusted = adjust_poses(dense_poses, dense_ids, world_scaling_factor, id_to_shift)
    dense_poses_adjusted, dense_ids
end

export load_ycb_model_list, load_ycbv_scene_adjusted, load_ycbv_dense_fusion_predictions_adjusted, load_ycbv_models_adjusted

"""
This is the directory structure we assume for the above code:

├── ycbv_2
│   ├── 0048
│   ├── 0049
│   ├── 0050
│   ├── 0051
│   ├── 0052
│   ├── 0053
│   ├── 0054
│   ├── 0055
│   ├── 0056
│   ├── 0057
│   ├── 0058
│   ├── 0059
│   ├── densefusion
│   │    ├── dense_results
│   │    └── results_PoseCNN_RSS2018
│   ├── keyframe.txt
│   ├── model_list.txt
│   └── models
"""

function load_synthetic_dense_fusion_predictions(SYTH_DIR, T)
    # Load dense fusion results
    json_file = joinpath(SYTH_DIR,"dense_results",lpad(T,6,"0")*".json")
    json_data = JSON.parsefile(json_file)
    densefusion_ids = [Int.(x[2]) for x in json_data["rois"]]

    mat_file = joinpath(SYTH_DIR,"dense_results/Densefusion_iterative_result",lpad(T,4,"0")*".mat")
    mat_data = MAT.matopen(mat_file)
    densefusion_poses = [
        Pose(p[5:7], Rotations.UnitQuaternion(p[1:4]...))
        for p in eachrow(read(mat_data,"poses"))
    ];
    densefusion_poses, densefusion_ids
end

function load_synthetic_objposenet_fusion_predictions(SYTH_DIR, T)
    # Load dense fusion results
    json_file = joinpath(SYTH_DIR,"dense_results",lpad(T,6,"0")*".json")
    json_data = JSON.parsefile(json_file)
    densefusion_ids = [Int.(x[2]) for x in json_data["rois"]]

    mat_file = joinpath(SYTH_DIR,"objposenet_results",lpad(T,4,"0")*".mat")
    mat_data = MAT.matopen(mat_file)
    densefusion_poses = [
        Pose(p[5:7], Rotations.UnitQuaternion(p[1:4]...))
        for p in eachrow(read(mat_data,"poses"))
    ];
    densefusion_poses, densefusion_ids
end

export load_bop_scene, load_bop_object_ply, load_rgb, load_depth, load_ycbv_models, load_ycbv_scene, load_ycbv_dense_fusion_predictions, load_ycbv_point_xyz, load_ycb_model_obj_file_paths,
            load_synthetic_dense_fusion_predictions, load_synthetic_objposenet_fusion_predictions, get_ycb_scene_frame_id_from_idx, load_synthetic_scene_adjusted


text:
struct ClusterData{V<:AbstractVector,A<:AbstractArray}
    assignments::V
    centers::A
end

"""
    function GenerateClusterData(data::AbstractMatrix, η::Weights, config::NamedTuple)

Performs the preclustering step of the AHPQ; given a number of clusters `config[:a]` and performs Vector Quantization
using the main quantization function, using `n_codebooks=1` `n_centers=config[:a]` using the input loss function `η`.
Can be set to L2_loss. The loss function is configured with the `T_preclustering` configuration before this function.
"""
function GenerateClusterData(data::AbstractMatrix, η::Weights, config::NamedTuple)
    cd = quantizer(data, η, 0, merge(config, (; n_codebooks=1, n_centers=config[:a],
                                            verbose=false)))
    codebook = deepcopy(cd.C)
    cd = GenerateQuantizerData(data, 1, config.a)
    cd.C .= codebook
    assignment_step!(data, cd, InvertedIndex(), SingleThreaded())
    centers = reshape(cd.C, (size(data)[1], config[:a]))
    return ClusterData(cd.I.IVF[1], centers)
end


text:
handle("ping") do
  "pong"
end

handle("args") do args
  append!(ARGS, args)
end

handle("echo") do data
  data
end

handle("cd") do path
  cd(path)
end

handle("evalsimple") do code
  Core.eval(Main, Meta.parse(code))
end

handle("exit") do
  exit()
end

const PlotPaneEnabled = Ref(true)

handle("enableplotpane") do enable
  if enable
    Media.setdisplay(Media.Graphical, PlotPane())
    PlotPaneEnabled[] = true
  else
    Media.unsetdisplay(Media.Graphical)
    PlotPaneEnabled[] = false
  end
  nothing
end

handle("cancelCallback") do args...
  # TODO: Do something sensible here.
  # Until then it's better to silently fail than spam the REPL with "unrecognised
  # message" warnings.
end


text:
# Here is the code to install packages.
# See readme
using Pkg
Pkg.add(
    ["Parameters", "RecursiveArrayTools", "Statistics", "DifferentialEquations",
    "PyPlot", "ForwardDiff", "LinearAlgebra", "QuadGK", "NLsolve", "FileIO", "JLD2"]
)

max_stars_repo_name: McCannLab/Labmnivory

max_issues_repo_name: McCannLab/Labmnivory

max_forks_repo_name: McCannLab/Labmnivory