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

using Markdown
using InteractiveUtils

# ╔═╡ a8b8a0a1-6202-4e9a-800e-a5696f893d8c
begin
	using CairoMakie
	using Makie
end

# ╔═╡ 59ab0cf8-8528-11ec-23b1-8f55636bbd90
md"""
# Survey results

This notebook generates plots for important questions for each section

## Section: Background Information

2. Roughly what percentage of your overall work time is spent **using** research software?
3. Roughly what percentage of your overall work time is spent **developing** research software?
"""

# ╔═╡ de5b448f-56f9-477e-b232-f0ee49822bec
# Plot questions 2 and 3
begin

function plot_2_3()
    x = [10, 10, 30, 30, 50, 50, 70, 70, 90, 90]
    y = [13,  8, 9,   5,  7,  9,  5,  5,  4, 11]

    dodge = [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (10:20:90, ["0-20%", "21-40%", "41-60%", "61-80%", "81-100%"]),
              yticks = 1:1:13,
              ylabel = "Responses",
              title = "Percentage of time using or developing software")

	colors = Makie.wong_colors()
    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge])

    # Legend
    labels = ["using", "developing"]
    elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = ""

    Legend(fig[1,1], elements, labels, title,
		tellheight = false,
        tellwidth = false,
        margin = (10, 10, 10, 10),
        halign = :right, valign = :top, orientation = :horizontal)

    Makie.save("BackgroundInfo.pdf", fig)
	fig
end

plot_2_3()

end

# ╔═╡ b341d6c8-09ea-4c95-b001-ec92adb279ed
md"""

## Section: Project Demographics

5. At any given moment, approximately how many developers are contributing to your research software project, including yourself?

6. Approximately how many of those developers do you interact with on at least a weekly basis?
"""

# ╔═╡ 7ceb361f-6916-4946-9101-56403d88a8b7
# Plot question 5
begin

function plot_5_6()
    x = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
    y = [ 0,  3,
		  4,  8,
		 18, 15,
		  7,  7,
		  2,  4,
		  7,  1 ]

    dodge = [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (0:1:5, ["0", "1", "2-3", "4-5", "6-10", "> 10"]),
              yticks = 0:1:20,
		      xlabel = "Number of developer",
              ylabel = "Responses",
              title = "Project developers and interactions")

	colors = Makie.wong_colors()
    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
		    tellwidth = true, tellheight = true
	        )

    # Legend
    labels = ["active", "interactive (weekly)"]
    elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = "Developer"

    Legend(fig[1,1], elements, labels, title,
		tellheight = false,
        tellwidth = false,
        margin = (10, 10, 10, 10),
        halign = :right, valign = :top, orientation = :horizontal)

    Makie.save("DevelopersInteractions.pdf", fig)
	fig
end

plot_5_6()
end

# ╔═╡ b46d2338-2179-434b-97bd-c3cb401b4519
md"""
9. Indicate the importance of the following characteristics of your research software
"""

# ╔═╡ ba87bdf3-0789-434b-84e2-93184faf18fb
# Plot question 9
begin

function plot_9()
    x = [ 1, 1, 1, 1, 1, 1,
	      2, 2, 2, 2, 2, 2,
		  3, 3, 3, 3, 3, 3,
		  4, 4, 4, 4, 4, 4
	    ]

    y = [ 0,  1,  1,  0,  0, 19,
		  1,  4,  4,  4, 14, 11,
		  4, 13, 10, 16, 11,  5,
		 33, 20, 23, 18,  9,  3
	     ]

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

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (1:1:4, ["1-Not important", "2", "3", "4-Very Important"]),
              yticks = 0:5:36,
		      xlabel = "Level of Importance",
              ylabel = "Responses",
              title = "Importance of software characteristics")

	colors = Makie.wong_colors()
    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
		    tellwidth = true, tellheight = true
	        )

    # Legend
    labels = ["Functionality", "Usability", "Sustainability",
	          "Performance", "Portability", "Security"]
    elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = "Characteristic"

	Legend(fig[1,1], elements, labels, title,
	       tellheight = false,
           tellwidth = false,
           margin = (10, 10, 10, 10),
           halign = :left, valign = :top, orientation = :vertical
	 )

  #   Legend(fig[1,1], elements, labels, title,
		# tellheight = false,
  #       tellwidth = false,
  #       margin = (10, 10, 10, 10),
  #       halign = :right, valign = :top, orientation = :horizontal)

    Makie.save("SWCharacteristics.pdf", fig)
	fig
end

plot_9()
end

# ╔═╡ 9c6234a5-9721-431f-bc95-8d7a2efd91c5
md"""

## Section: Project Technical Approach

12. Indicate the importance of the following to your research software
"""

# ╔═╡ c927a13e-82d5-402a-b330-fdecadf58764
# Plot question 12
begin
import ColorTypes

function plot_12()
    x = [ 1, 1, 1, 1, 1, 1, 1, 1,
	      2, 2, 2, 2, 2, 2, 2, 2,
		  3, 3, 3, 3, 3, 3, 3, 3,
		  4, 4, 4, 4, 4, 4, 4, 4
	    ]

    y = [ 9,  8,  9,  3, 12, 20,  5, 25,
		  8,  6, 13,  6,  9,  6,  8,  8,
		  7,  8,  5, 14,  6,  8,  6,  2,
		 14, 16, 10, 15, 11,  4, 19,  2,
	     ]

    dodge = [ 1, 2, 3, 4, 5, 6, 7, 8,
		      1, 2, 3, 4, 5, 6, 7, 8,
		      1, 2, 3, 4, 5, 6, 7, 8,
		      1, 2, 3, 4, 5, 6, 7, 8
	        ]

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (1:1:4, ["1-Not important", "2", "3", "4-Very Important"]),
              yticks = 0:5:26,
		      xlabel = "Level of Importance",
              ylabel = "Responses",
              title = "Importance of software related operation")

	colors = Makie.wong_colors()
    push!(colors, ColorTypes.RGBA{Float32}(0.5f0,0.89411765f0,0.25882354f0,1.0f0))

    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
	        )

    # Legend
    labels = ["Data storage",
		      "Data interaction (e.g. Notebooks, GUI)",
		      "Data dissemination",
	          "Continuous Integration/Deployment",
		      "Server deployment",
		      "Cloud deployment",
		      "Numerical libraries",
	          "Cloud API services"]

	elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = ""

	Legend(fig[1,1], elements, labels, title,
	       tellheight = false,
           tellwidth = false,
           margin = (10, 10, 10, 10),
           halign = :center, valign = :top, orientation = :vertical
	 )

    Makie.save("SWOperations.pdf", fig)
	fig
end

plot_12()
end

# ╔═╡ 7e97d299-86e0-4dcc-878a-5fd54b1d2a53
md"""
14. What programming languages are currently used in your project?
"""

# ╔═╡ 0bb3a38f-955f-48ec-b606-785557f16cb1
begin
function plot_14()
    x = [ 1, 2, 3, 4, 5]
	y = [ 30, 22, 6, 5, 3]

    dodge = 1:1:5

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = 0:5:40,
		      yticks = (1:1:5, ["Python", "C++", "C", "JavaScript", "Java"]),
		      xlabel = "Responses",
              title = "Programming languages used in projects")

	colors = Makie.wong_colors()

    # Plot
    barplot!(ax, x, y,
            color = colors[dodge],
		    direction = :x,
	        )

    Makie.save("ProgrammingLanguages.pdf", fig)
	fig
end

plot_14()
end

# ╔═╡ db425e20-e002-490f-bb0d-83b1fdf4d527
md"""
15. Indicate the type of computational resources targeted by your research software
"""

# ╔═╡ 4f264291-58b8-47ad-b2de-550db41c6945
begin
function plot_15()
    x = [  1,  2,  3,  4,  5, 6, 7]
	y = Array{Int32,1}([ 26, 15, 24, 13, 18, 1, 1])

    dodge = 1:1:7

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = 0:5:35,
		      yticks = (1:1:7, ["Single Computer",
				                "Single Computer with accelerator",
				                "Server or Edge System",
				                "Cloud System",
				                "HPC System",
				                "Dedicated System",
				                "Neuromorphic System"]),
		      xlabel = "Responses",
              title = "Computational hardware target")

	colors = Makie.wong_colors()

    # Plot
    barplot!(ax, x, y,
            color = colors[dodge],
		    direction = :x,
	        )

    Makie.save("HardwareTargets.pdf", fig)
	fig
end

plot_15()
end

# ╔═╡ febed389-167d-4dde-bdc4-db767ee869b2
md"""
## Section: Skills and Knowledge
17. Personal knowledge
"""

# ╔═╡ 4e47a571-d6b1-40df-bad4-3f966760f54d
# Plot question 17
begin

function plot_17()
    x = [ 1, 1, 1, 1, 1,
	      2, 2, 2, 2, 2,
		  3, 3, 3, 3, 3,
		  4, 4, 4, 4, 4,
	    ]

    y = [ 0,  0,  0,  2,  6,
		  5,  5,  7,  9,  9,
		 12, 11, 16, 11, 14,
		 20, 21, 14, 15,  8,
	     ]

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

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (1:1:4, ["1-Not important", "2", "3", "4-Very Important"]),
              yticks = 0:5:25,
		      xlabel = "Level of Importance",
              ylabel = "Responses",
              title = "Personal knowledge of software aspects")

	colors = Makie.wong_colors()
    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
		    tellwidth = true, tellheight = true
	        )

    # Legend
    labels = ["Scientific context", "Algorithms and Methods", "Library dependencies",
	          "Development best practices", "Hardware target"]
    elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = ""

	Legend(fig[1,1], elements, labels, title,
	       tellheight = false,
           tellwidth = false,
           margin = (10, 10, 10, 10),
           halign = :left, valign = :top, orientation = :vertical
	 )

    Makie.save("PersonalKnowledge.pdf", fig)
	fig
end

plot_17()
end

# ╔═╡ fb5181ae-03e4-42a8-9a34-b9c11dc2d22c
md"""
20. How you like to learn
"""

# ╔═╡ 83b092b8-3a6b-4674-89f6-2be69e2707c9
# Plot question 20
begin

function plot_20()
    x = [ 1, 1, 1, 1, 1,
	      2, 2, 2, 2, 2,
		  3, 3, 3, 3, 3,
		  4, 4, 4, 4, 4,
	    ]

    y = [ 1,  3,  0,  4,  0,
		  6,  8,  5, 10,  9,
		  6, 18, 19, 11, 22,
		 24,  8, 12, 12,  6,
	     ]

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

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (1:1:4, ["1-Not preferred", "2", "3", "4-Strongly preferred"]),
              yticks = 0:5:25,
		      xlabel = "Level of preference",
              ylabel = "Responses",
              title = "Preference for learning style")

	colors = Makie.wong_colors()
    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
		    tellwidth = true, tellheight = true
	        )

    # Legend
    labels = ["Self-study", "Semi-formal or formal training", "Hands-on examples",
	          "Project specific activity", "Asking a colleague"]
    elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = ""

	Legend(fig[1,1], elements, labels, title,
	       tellheight = false,
           tellwidth = false,
           margin = (10, 10, 10, 10),
           halign = :left, valign = :top, orientation = :vertical
	 )

    Makie.save("LearningStyle.pdf", fig)
	fig
end

plot_20()
end

# ╔═╡ 5f7d0c7f-6d5f-4859-9637-2abc7f3506ee
md"""
## Section: Preparing for the Future

31. To what extent do the changes you anticipate to your project in the next five years cause you concern as a developer?
"""

# ╔═╡ 3cd83886-51b7-4c9e-84b1-4f3c1f4dbc57
# Plot question 31
begin

function plot_31()
    x = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
		  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
		  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
	    ]

    y = [  4,  10,  5,  4,  4,  2, 10,  8,  6,  9, 12, 14,
		  10,  15,  9, 12, 10, 10,  9, 13, 12, 11,  9, 10,
		   9,   8, 18, 13, 16, 16, 11, 12, 11, 11, 12, 10,
		  14,   4,  5,  8,  7,  9,  7,  4,  8,  6,  4,  3
	     ]

    dodge = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
		      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
		      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
		      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
	        ]

    # Figure and Axis
    fig = Figure()
    ax = Axis(fig[1,1],
		      xticks = (1:1:4, ["1-Not concerned", "2", "3", "4-Very concerned"]),
              yticks = 0:5:20,
		      xlabel = "Level of Concern",
              ylabel = "Responses",
              title = "Concern for anticipated project future changes")

	colors = Makie.wong_colors()
	#RGBA{Float32}(0.9411765f0,0.89411765f0,0.25882354f0,1.0f0)
    push!(colors, ColorTypes.RGBA{Float32}(0.5f0,0.89411765f0,0.25882354f0,1.0f0))
	push!(colors, ColorTypes.RGBA{Float32}(0.9411765f0,0.5f0,0.25882354f0,1.0f0))
	push!(colors,ColorTypes.RGBA{Float32}(0.9411765f0,0.89411765f0,0.5f0,1.0f0))
	push!(colors, ColorTypes.RGBA{Float32}(0.9411765f0,0.89411765f0,1.0f0,1.0f0))
	push!(colors, ColorTypes.RGBA{Float32}(0.9411765f0,0.5f0,0.5f0,1.0f0))

    # Plot
    barplot!(ax, x, y,
            dodge = dodge,
            color = colors[dodge],
	        )

    # Legend
    labels = ["Hardware",
		      "Scientific context",
		      "Functionality",
	          "Usability",
		      "Sustainability",
		      "Performance",
		      "Data storage",
	          "Numerical libraries",
		      "Data interaction",
		      "CI/CD",
		      "Cloud deployment",
		      "Cloud services"
	         ]

	elements = [PolyElement(polycolor = colors[i]) for i in 1:length(labels)]
    title = "Changes in"

	Legend(fig[1,2], elements, labels, title, labelsize=11)

    Makie.save("FutureConcerns.pdf", fig)
	fig
end

plot_31()
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"

[compat]
CairoMakie = "~0.7.2"
ColorTypes = "~0.11.0"
Makie = "~0.16.3"
"""

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

[[AbstractFFTs]]
deps = ["ChainRulesCore", "LinearAlgebra"]
git-tree-sha1 = "6f1d9bc1c08f9f4a8fa92e3ea3cb50153a1b40d4"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.1.0"

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

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

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

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

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

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

[[Automa]]
deps = ["Printf", "ScanByte", "TranscodingStreams"]
git-tree-sha1 = "d50976f217489ce799e366d9561d56a98a30d7fe"
uuid = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b"
version = "0.8.2"

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

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

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

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

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

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

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

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

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

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

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

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

[[ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"]
git-tree-sha1 = "3f1f500312161f1ae067abe07d13b40f78f32e07"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.8"

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

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

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

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

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

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

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

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

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

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[EllipsisNotation]]
deps = ["ArrayInterface"]
git-tree-sha1 = "d7ab55febfd0907b285fbf8dc0c73c0825d9d6aa"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.3.0"

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

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

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

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

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

[[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 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

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

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

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

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

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

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

[[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 = "a32d672ac2c967f3deb8a81d828afc739c838a06"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+2"

[[Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "1c5a84319923bea76fa145d49e93aa4394c73fc2"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.1"

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

[[GridLayoutBase]]
deps = ["GeometryBasics", "InteractiveUtils", "Observables"]
git-tree-sha1 = "70938436e2720e6cb8a7f2ca9f1bbdbf40d7f5d0"
uuid = "3955a311-db13-416c-9275-1d80ed98e5e9"
version = "0.6.4"

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

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

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

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

[[ImageIO]]
deps = ["FileIO", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs"]
git-tree-sha1 = "816fc866edd8307a6e79a575e6585bfab8cef27f"
uuid = "82e4d734-157c-48bb-816b-45c225c6df19"
version = "0.6.0"

[[Imath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "87f7662e03a649cffa2e05bf19c303e168732d3e"
uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1"
version = "3.1.2+0"

[[IndirectArrays]]
git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "1.0.0"

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

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

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

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

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

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

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

[[IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

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

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

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

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

[[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 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[MakieCore]]
deps = ["Observables"]
git-tree-sha1 = "c5fb1bfac781db766f9e4aef96adc19a729bc9b2"
uuid = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
version = "0.2.1"

[[MappedArrays]]
git-tree-sha1 = "e8b359ef06ec72e8c030463fe02efe5527ee5142"
uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
version = "0.4.1"

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

[[Match]]
git-tree-sha1 = "1d9bc5c1a6e7ee24effb93f175c9342f9154d97f"
uuid = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf"
version = "1.2.0"

[[MathTeXEngine]]
deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "Test"]
git-tree-sha1 = "70e733037bbf02d691e78f95171a1fa08cdc6332"
uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53"
version = "0.2.1"

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

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

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

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

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

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

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

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

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

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

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

[[OpenEXR]]
deps = ["Colors", "FileIO", "OpenEXR_jll"]
git-tree-sha1 = "327f53360fdb54df7ecd01e96ef1983536d1e633"
uuid = "52e1d378-f018-4a11-a4be-720524705ac7"
version = "0.3.2"

[[OpenEXR_jll]]
deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "923319661e9a22712f24596ce81c54fc0366f304"
uuid = "18a262bb-aa17-5467-a713-aee519bc75cb"
version = "3.1.1+0"

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

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

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

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

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

[[PNGFiles]]
deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"]
git-tree-sha1 = "2271d1c3b0103844a9f4af6cd17d70d146d5295f"
uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883"
version = "0.3.13"

[[Packing]]
deps = ["GeometryBasics"]
git-tree-sha1 = "1155f6f937fa2b94104162f01fa400e192e4272f"
uuid = "19eb6ba3-879d-56ad-ad62-d5c202156566"
version = "0.4.2"

[[PaddedViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "03a7a85b76381a3d04c7a1656039197e70eda03d"
uuid = "5432bcbf-9aad-5242-b902-cca2824c8663"
version = "0.5.11"

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

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

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

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

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

[[PolygonOps]]
git-tree-sha1 = "77b3d3605fc1cd0b42d95eba87dfcd2bf67d5ff6"
uuid = "647866c9-e3ac-4575-94e7-e3d426903924"
version = "0.1.2"

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

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

[[QOI]]
deps = ["ColorTypes", "FileIO", "FixedPointNumbers"]
git-tree-sha1 = "18e8f4d1426e965c7b532ddd260599e1510d26ce"
uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65"
version = "1.0.0"

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

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

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

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

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

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

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

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

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

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

[[SIMD]]
git-tree-sha1 = "39e3df417a0dd0c4e1f89891a281f82f5373ea3b"
uuid = "fdea26ae-647d-5447-a871-4b548cad5224"
version = "3.4.0"

[[ScanByte]]
deps = ["Libdl", "SIMD"]
git-tree-sha1 = "9cc2955f2a254b18be655a4ee70bc4031b2b189e"
uuid = "7b38b023-a4d7-4c5e-8d43-3f3097f304eb"
version = "0.3.0"

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

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

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

[[Sixel]]
deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"]
git-tree-sha1 = "8fb59825be681d451c246a795117f317ecbcaa28"
uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47"
version = "0.1.2"

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

[[SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "e6bf188613555c78062842777b116905a9f9dd49"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.1.0"

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

[[Static]]
deps = ["IfElse"]
git-tree-sha1 = "b4912cd034cdf968e06ca5f943bb54b17b97793a"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.5.1"

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

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

[[StatsAPI]]
git-tree-sha1 = "d88665adc9bcf45903013af0982e2fd05ae3d0a6"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.0"

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

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

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

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

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

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

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

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

[[TiffImages]]
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "OffsetArrays", "PkgVersion", "ProgressMeter", "UUIDs"]
git-tree-sha1 = "991d34bbff0d9125d93ba15887d6594e8e84b305"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.5.3"

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

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

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

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

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

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

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

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

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

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

[[libsixel_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "78736dab31ae7a53540a6b752efc61f77b304c5b"
uuid = "075b6546-f08a-558a-be8f-8157d0f608a5"
version = "1.8.6+1"

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

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

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

# ╔═╡ Cell order:
# ╟─59ab0cf8-8528-11ec-23b1-8f55636bbd90
# ╟─a8b8a0a1-6202-4e9a-800e-a5696f893d8c
# ╟─de5b448f-56f9-477e-b232-f0ee49822bec
# ╟─b341d6c8-09ea-4c95-b001-ec92adb279ed
# ╟─7ceb361f-6916-4946-9101-56403d88a8b7
# ╟─b46d2338-2179-434b-97bd-c3cb401b4519
# ╟─ba87bdf3-0789-434b-84e2-93184faf18fb
# ╟─9c6234a5-9721-431f-bc95-8d7a2efd91c5
# ╟─c927a13e-82d5-402a-b330-fdecadf58764
# ╟─7e97d299-86e0-4dcc-878a-5fd54b1d2a53
# ╟─0bb3a38f-955f-48ec-b606-785557f16cb1
# ╟─db425e20-e002-490f-bb0d-83b1fdf4d527
# ╟─4f264291-58b8-47ad-b2de-550db41c6945
# ╟─febed389-167d-4dde-bdc4-db767ee869b2
# ╟─4e47a571-d6b1-40df-bad4-3f966760f54d
# ╟─fb5181ae-03e4-42a8-9a34-b9c11dc2d22c
# ╟─83b092b8-3a6b-4674-89f6-2be69e2707c9
# ╟─5f7d0c7f-6d5f-4859-9637-2abc7f3506ee
# ╟─3cd83886-51b7-4c9e-84b1-4f3c1f4dbc57
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: williamfgc/PlutoNotebooks

max_issues_repo_name: williamfgc/PlutoNotebooks

max_forks_repo_name: williamfgc/PlutoNotebooks


text:
using HTTPStatus
using Test

@testset "is_information" begin
    @test is_information(100) == true
    @test is_information(11) == false
end

@testset "is_success" begin
    for pair = [(200, true), (299, true),
                         (300, false), (11, false)
                         ]
        @test is_success(pair[1]) == pair[2]
    end
end

@testset "is_redirect" begin
    for pair = [(300, true), (399, true),
                (400, false), (11, false)
                ]
        @test is_redirect(pair[1]) == pair[2]
    end
end

@testset "is_client_error" begin
    for pair = [(400, true), (499, true),
                (500, false), (11, false)
                ]
        @test is_client_error(pair[1]) == pair[2]
    end
end

@testset "is_server_error" begin
    for pair = [(500, true), (599, true),
                (400, false), (11, false)
                ]
        @test is_server_error(pair[1]) == pair[2]
    end
end

@testset "codes" begin
    @test HTTP_200_OK == 200
    @test HTTP_410_GONE == 410
    @test HTTP_418_IM_A_TEAPOT == 418
end

ext: jl

max_stars_repo_name: kracekumar/HTTPStatus

max_issues_repo_name: kracekumar/HTTPStatus

max_forks_repo_name: kracekumar/HTTPStatus


text:
struct JacobianData{T1 <: SparseMatrixCSC,T2 <: ForwardColorJacCache}
    f!::Function
    jac::T1
    jac_cache::T2
    length_jac::Int
    sparsity::SparseArrays.SparseMatrixCSC{Bool,Int64}

    function JacobianData(f!, output, input)
        # TODO Proper way to do it (currently not working)
        # Issue: https://github.com/SciML/SparsityDetection.jl/issues/41
        # sparsity = jacobian_sparsity(f!, output, input)

        # Workaround
        num_samples = 50
        jac_samples = [ForwardDiff.jacobian(f!, rand!(output), rand!(input)) for _ in 1:num_samples]
        sparsity = sparse(sum(jac_samples) .≠ 0)

        jac = convert.(Float64, sparse(sparsity))

        jac_cache = ForwardColorJacCache(f!, input, dx=output,
                                         colorvec=matrix_colors(jac),
                                         sparsity=sparsity)

        length_jac = nnz(jac)

        T1 = typeof(jac)
        T2 = typeof(jac_cache)

        new{T1,T2}(f!, jac, jac_cache, length_jac, sparsity)
    end
end

function (jd::JacobianData)(x)
    forwarddiff_color_jacobian!(jd.jac, jd.f!, x, jd.jac_cache)
end


text:
"""
The functions provided by YAXArrays are supposed to work on different types of cubes. This module defines the interface for all
Data types that
"""
module Cubes
using DiskArrays: DiskArrays, eachchunk
using Distributed: myid
using Dates: TimeType
using IntervalSets: Interval, (..)
using Base.Iterators: take, drop
using ..YAXArrays: workdir, YAXDefaults
using YAXArrayBase: YAXArrayBase, iscompressed, dimnames, iscontdimval
import YAXArrayBase: getattributes, iscontdim, dimnames, dimvals

"""
This function calculates a subset of a cube's data
"""
function subsetcube end

"Returns the axes of a Cube"
function caxes end

include("Axes.jl")
using .Axes: CubeAxis, RangeAxis, CategoricalAxis, findAxis, getAxis, axVal2Index,
  axname, axsym, axVal2Index_lb, axVal2Index_ub, renameaxis, axcopy

mutable struct CleanMe
  path::String
  persist::Bool
  function CleanMe(path::String,persist::Bool)
    c = new(path,persist)
    finalizer(clean,c)
    c
  end
end
function clean(c::CleanMe)
  if !c.persist && myid()==1
    if !isdir(c.path) && !isfile(c.path)
      @warn "Cube directory $(c.path) does not exist. Can not clean"
    else
      rm(c.path,recursive=true)
    end
  end
end

"""
    YAXArray{T,N}

An array labelled with named axes that have values associated with them.
It can wrap normal arrays or, more typically DiskArrays.

### Fields

* `axes` a `Vector{CubeAxis}` containing the Axes of the Cube
* `data` N-D array containing the data
"""
struct YAXArray{T,N,A<:AbstractArray{T,N},AT}
  axes::AT
  data::A
  properties::Dict{String}
  cleaner::Vector{CleanMe}
  function YAXArray(axes,data,properties,cleaner)
    if ndims(data) != length(axes)
      throw(ArgumentError("Can not construct YAXArray, supplied data dimension is $(ndims(data)) while the number of axes is $(length(axes))"))
    elseif ntuple(i->length(axes[i]),ndims(data)) != size(data)
      throw(ArgumentError("Can not construct YAXArray, supplied data size is $(size(data)) while axis lenghts are $(ntuple(i->length(axes[i]),ndims(data)))"))
    else
      return new{eltype(data),ndims(data),typeof(data),typeof(axes)}(axes,data,properties,cleaner)
    end
  end
end

YAXArray(axes,data,properties=Dict{String,Any}(); cleaner=CleanMe[]) = YAXArray(axes,data,properties, cleaner)
function YAXArray(x::AbstractArray)
  ax = caxes(x)
  props = getattributes(x)
  YAXArray(ax,x,props)
end
Base.size(a::YAXArray) = size(a.data)
Base.size(a::YAXArray,i::Int) = size(a.data,i)
Base.ndims(a::YAXArray{<:Any,N}) where N = N
Base.eltype(a::YAXArray{T}) where T = T
Base.permutedims(c::YAXArray,p)=YAXArray(c.axes[collect(p)],permutedims(c.data,p),c.properties,c.cleaner)
caxes(c::YAXArray)=c.axes
function caxes(x)
  map(enumerate(dimnames(x))) do a
    i,s = a
    v = YAXArrayBase.dimvals(x,i)
    iscontdim(x,i) ? RangeAxis(s,v) : CategoricalAxis(s,v)
  end
end

"""
    readcubedata(cube)

Given any array implementing the YAXArray interface it returns an in-memory [`YAXArray`](@ref) from it.
"""
function readcubedata(x)
  YAXArray(collect(CubeAxis,caxes(x)),getindex_all(x),getattributes(x))
end

cubechunks(c::YAXArray)=common_size(eachchunk(c.data))
cubechunks(x) = common_size(eachchunk(x))
common_size(a::DiskArrays.GridChunks) = a.chunksize
function common_size(a)
  ntuple(ndims(first(a))) do idim
    otherdims = setdiff(1:ndims(first(a)),idim)
    allengths = map(i->length(i.indices[idim]),a)
    for od in otherdims
      allengths = unique(allengths,dims=od)
    end
    length(allengths)<3 ? allengths[1] : allengths[2]
  end
end

getindex_all(a) = getindex(a,ntuple(_->Colon(),ndims(a))...)
Base.getindex(x::YAXArray, i...) = x.data[i...]
chunkoffset(c::YAXArray)=common_offset(eachchunk(c.data))
chunkoffset(x) = common_offset(eachchunk(x))
common_offset(a::DiskArrays.GridChunks) = a.offset
function common_offset(a)
  ntuple(ndims(a)) do idim
    otherdims = setdiff(1:ndims(a),idim)
    allengths = map(i->length(i[idim]),a)
    for od in otherdims
      allengths = unique(allengths,dims=od)
    end
    @assert length(allengths) == size(a,idim)
    length(allengths)<3 ? 0 : allengths[2]-allengths[1]
  end
end

# Implementation for YAXArrayBase interface
YAXArrayBase.dimvals(x::YAXArray, i) = x.axes[i].values

function YAXArrayBase.dimname(x::YAXArray, i)
  axsym(x.axes[i])
end

YAXArrayBase.getattributes(x::YAXArray) = x.properties

YAXArrayBase.iscontdim(x::YAXArray, i) = isa(x.axes[i], RangeAxis)

YAXArrayBase.getdata(x::YAXArray) = x.data

function YAXArrayBase.yaxcreate(::Type{YAXArray},data, dimnames, dimvals, atts)
  axlist = map(dimnames, dimvals) do dn, dv
    iscontdimval(dv) ? RangeAxis(dn,dv) : CategoricalAxis(dn,dv)
  end
  YAXArray(axlist, data, atts)
end
YAXArrayBase.iscompressed(c::YAXArray)=_iscompressed(c.data)
_iscompressed(c::DiskArrays.PermutedDiskArray) = iscompressed(c.a.parent)
_iscompressed(c::DiskArrays.SubDiskArray) = iscompressed(c.v.parent)
_iscompressed(c) = YAXArrayBase.iscompressed(c)

function renameaxis!(c::YAXArray,p::Pair)
  i = findAxis(p[1],c.axes)
  c.axes[i]=renameaxis(c.axes[i],p[2])
  c
end
function renameaxis!(c::YAXArray,p::Pair{<:Any,<:CubeAxis})
  i = findAxis(p[1],c.axes)
  i === nothing && throw(ArgumentError("$(p[1]) Axis not found"))
  length(c.axes[i].values) == length(p[2].values) || throw(ArgumentError("Length of replacement axis must equal length of old axis"))
  c.axes[i]=p[2]
  c
end

function _subsetcube end

function subsetcube(z::YAXArray{T};kwargs...) where T
  newaxes, substuple = _subsetcube(z,collect(Any,map(Base.OneTo,size(z)));kwargs...)
  newdata = view(z.data,substuple...)
  YAXArray(newaxes,newdata,z.properties,cleaner = z.cleaner)
end

sorted(x,y) = x<y ? (x,y) : (y,x)

#TODO move everything that is subset-related to its own file or to axes.jl
interpretsubset(subexpr::Union{CartesianIndices{1},LinearIndices{1}},ax) = subexpr.indices[1]
interpretsubset(subexpr::CartesianIndex{1},ax)   = subexpr.I[1]
interpretsubset(subexpr,ax)                      = axVal2Index(ax,subexpr,fuzzy=true)
function interpretsubset(subexpr::NTuple{2,Any},ax)
  x, y = sorted(subexpr...)
  Colon()(sorted(axVal2Index_lb(ax,x),axVal2Index_ub(ax,y))...)
end
interpretsubset(subexpr::NTuple{2,Int},ax::RangeAxis{T}) where T<:TimeType = interpretsubset(map(T,subexpr),ax)
interpretsubset(subexpr::UnitRange{<:Integer},ax::RangeAxis{T}) where T<:TimeType = interpretsubset(T(first(subexpr))..T(last(subexpr)+1),ax)
interpretsubset(subexpr::Interval,ax)       = interpretsubset((subexpr.left,subexpr.right),ax)
interpretsubset(subexpr::AbstractVector,ax::CategoricalAxis)      = axVal2Index.(Ref(ax),subexpr,fuzzy=true)

function _subsetcube(z, subs;kwargs...)
  kwargs = Dict{Any,Any}(kwargs)
  for f in YAXDefaults.subsetextensions
    f(kwargs)
  end
  newaxes = deepcopy(collect(caxes(z)))
  foreach(kwargs) do kw
    axdes,subexpr = kw
    axdes = string(axdes)
    iax = findAxis(axdes,caxes(z))
    if isa(iax,Nothing)
      throw(ArgumentError("Axis $axdes not found in cube"))
    else
      oldax = newaxes[iax]
      subinds = interpretsubset(subexpr,oldax)
      subs2 = subs[iax][subinds]
      subs[iax] = subs2
      if !isa(subinds,AbstractVector) && !isa(subinds,AbstractRange)
        newaxes[iax] = axcopy(oldax,oldax.values[subinds:subinds])
      else
        newaxes[iax] = axcopy(oldax,oldax.values[subinds])
      end
    end
  end
  substuple = ntuple(i->subs[i],length(subs))
  inewaxes = findall(i->isa(i,AbstractVector),substuple)
  newaxes = newaxes[inewaxes]
  @assert length.(newaxes) == map(length,filter(i->isa(i,AbstractVector),collect(substuple)))
  newaxes, substuple
end

Base.getindex(a::YAXArray;kwargs...) = subsetcube(a;kwargs...)

Base.read(d::YAXArray) = getindex_all(d)

function formatbytes(x)
  exts=["bytes","KB","MB","GB","TB"]
  i=1
  while x>=1024
    i=i+1
    x=x/1024
  end
  return string(round(x, digits=2)," ",exts[i])
end
cubesize(c::YAXArray{T}) where {T}=(sizeof(T))*prod(map(length,caxes(c)))
cubesize(::YAXArray{T,0}) where T=sizeof(T)

getCubeDes(::CubeAxis)="Cube axis"
getCubeDes(::YAXArray)="YAXArray"
getCubeDes(::Type{T}) where T = string(T)
Base.show(io::IO,c::YAXArray) = show_yax(io,c)

function show_yax(io::IO,c)
    println(io,getCubeDes(c), " with the following dimensions")
    for a in caxes(c)
        println(io,a)
    end

    foreach(getattributes(c)) do p
      if p[1] in ("labels","name","units")
        println(io,p[1],": ",p[2])
      end
    end
    println(io,"Total size: ",formatbytes(cubesize(c)))
end

include("TransformedCubes.jl")
include("Slices.jl")
end


text:
# https://fenicsproject.org/docs/dolfin/latest/python/demos/maxwell-eigenvalues/demo_maxwell-eigenvalues.py.html

module maxwell_eigenvalues

using FenicsPy

@assert has_linear_algebra_backend("PETSc") "DOLFIN has not been configured with PETSc. "
@assert has_slepc() "DOLFIN has not been configured with SLEPc. "

function eigenvalues(V, bcs)
    # Define the bilinear forms on the right- and left-hand sides
    u = TrialFunction(V)
    v = TestFunction(V)
    a = inner(curl(u), curl(v))*dx
    b = inner(u, v)*dx

    # Assemble into PETSc matrices
    dummy = v[1]*dx
    A = PETScMatrix()
    assemble_system(a, dummy, bcs, A_tensor=A)
    B = PETScMatrix()
    assemble_system(b, dummy, bcs, A_tensor=B)

    [bc.zero(B) for bc in bcs]

    solver = SLEPcEigenSolver(A, B)
    solver.parameters["solver"] = "krylov-schur"
    solver.parameters["problem_type"] = "gen_hermitian"

    solver.parameters["spectrum"] = "target magnitude"
    solver.parameters["spectral_transform"] = "shift-and-invert"
    solver.parameters["spectral_shift"] = 5.5
    neigs = 12
    solver.solve(neigs)

    # Return the computed eigenvalues in a sorted array
    computed_eigenvalues = []
    for i in 1:min(neigs, solver.get_number_converged())
        r, _ = solver.get_eigenvalue(i-1) # ignore the imaginary part
        push!(computed_eigenvalues, r)
    end
    return sort(computed_eigenvalues)
end

function print_eigenvalues(mesh)
    nedelec_V   = FunctionSpace(mesh, "N1curl", 1)
    nedelec_bcs = [DirichletBC(nedelec_V, Constant((0.0, 0.0)), DomainBoundary())]
    nedelec_eig = eigenvalues(nedelec_V, nedelec_bcs)

    lagrange_V   = VectorFunctionSpace(mesh, "Lagrange", 1)
    lagrange_bcs = [DirichletBC(lagrange_V.sub(1), 0, "near(x[0], 0) || near(x[0], pi)"),
		                         DirichletBC(lagrange_V.sub(0), 0, "near(x[1], 0) || near(x[1], pi)")]
    lagrange_eig = eigenvalues(lagrange_V, lagrange_bcs)

    true_eig = sort([float((m-1)^2 + (n-1)^2) for m in 1:6 for n in 1:6])[1:13]

    println("Nedelec:  $nedelec_eig")
    println("Lagrange: $lagrange_eig")
    println("Exact:    $true_eig")
end

mesh = RectangleMesh(Point(0, 0), Point(pi, pi), 40, 40)
println("\ndiagonal mesh")
print_eigenvalues(mesh)

mesh = RectangleMesh(Point(0, 0), Point(pi, pi), 40, 40, "crossed")
println("\ncrossed mesh")
print_eigenvalues(mesh)

end # module maxwell_eigenvalues


text:
using ApproxFun, SingularIntegralEquations, LinearAlgebra, Test
    import ApproxFunBase: ∞, testbandedoperator, testblockbandedoperator, testfunctional

@testset "Curve" begin
    @testset "quadratic" begin
        a=1+10*im;b=2-6*im
        d=Curve(Fun(x->1+a*x+b*x^2))

        x=Fun(d)
        w=sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x))

        @test cauchy(w,2.) ≈ (-4.722196879007759+2.347910413861846im)
        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π

        w=1/(sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x)))

        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π

        testbandedoperator(SingularIntegral(space(w),0))
        testbandedoperator(Hilbert(space(w)))

        @test (SingularIntegral(0)*w)(fromcanonical(d,0.1)) ≈ logkernel(w,fromcanonical(d,0.1))
        @test (Hilbert()*w)(fromcanonical(d,0.1)) ≈ hilbert(w,fromcanonical(d,0.1)) ≈
            im*(cauchy(w,fromcanonical(d,0.1)+eps())+cauchy(w,fromcanonical(d,0.1)-eps()))

        f=real(exp(x))
        @test logkernel(f,2) ≈ linesum(f*logabs(x-2.))/π

        w=abs(leftendpoint(d)-x)^0.1*abs(rightendpoint(d)-x)^0.2
        @test logkernel(f*w,2+2im) ≈ linesum(f*w*logabs(2+2im-x))/π
    end

    @testset "cubic" begin
        a=1+10*im;b=2-6*im
        d=Curve(Fun(x->1+a*x+x^2+b*x^3))

        x=Fun(d)
        w=sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x))

        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π

        w=1/(sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x)))

        testbandedoperator(SingularIntegral(space(w),0))
        testbandedoperator(Hilbert(space(w)))

        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π
        @test (SingularIntegral(0)*w)(fromcanonical(d,0.1)) ≈ logkernel(w,fromcanonical(d,0.1))
        @test (Hilbert()*w)(fromcanonical(d,0.1)) ≈ hilbert(w,fromcanonical(d,0.1))

        f=Fun(d,[1.,2.,3.])
        @test logkernel(f,2) ≈ linesum(f*logabs(x-2.))/π

        w=abs(leftendpoint(d)-x)^0.1*abs(rightendpoint(d)-x)^0.2
        @test logkernel(f*w,2+2im) ≈ linesum(f*w*logabs(2+2im-x))/π
    end

    @testset "quartic" begin

        a=1+10*im;b=2-6*im
        d=Curve(Fun(x->1+a*x+x^2+x^3+b*x^4))

        x=Fun(d)
        w=sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x))

        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π

        testbandedoperator(SingularIntegral(space(w),0))
        testbandedoperator(Hilbert(space(w)))
        testblockbandedoperator(SingularIntegral(space(w),0))
        testblockbandedoperator(Hilbert(space(w)))

        w=1/(sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x)))

        testbandedoperator(SingularIntegral(space(w),0))
        testbandedoperator(Hilbert(space(w)))

        @test cauchy(w,2.) ≈ sum(w/(x-2.))/(2π*im)
        @test logkernel(w,2.) ≈ linesum(w*logabs(x-2.))/π
        @test (SingularIntegral(0)*w)(fromcanonical(d,0.1)) ≈ logkernel(w,fromcanonical(d,0.1))
        @test (Hilbert()*w)(fromcanonical(d,0.1)) ≈ hilbert(w,fromcanonical(d,0.1))
    end

    @testset "Arc" begin
        d=exp(im*Segment(0.1,0.2))
        x=Fun(d)
        w=sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x))

        testbandedoperator(SingularIntegral(space(w),0))
        testbandedoperator(Hilbert(space(w)))

        z=10.;
        @test sum(w/(x-z))/(2π*im) ≈ cauchy(w,z)
        @test sum(w*log(z-x))/(-2π*im) ≈ cauchyintegral(w,z)
        @test linesum(w*logabs(z-x))/π ≈ logkernel(w,z)

        w=1/(sqrt(abs(leftendpoint(d)-x))*sqrt(abs(rightendpoint(d)-x)))

        testbandedoperator(SingularIntegral(space(w),0))

        @test sum(w/(x-z))/(2π*im) ≈ cauchy(w,z)
        @test sum(w*log(z-x))/(-2π*im) ≈ cauchyintegral(w,z)
        @test linesum(w*logabs(z-x))/π ≈ logkernel(w,z)
        @test (SingularIntegral(0)*w)(fromcanonical(d,0.1)) ≈ logkernel(w,fromcanonical(d,0.1))
        @test (Hilbert()*w)(fromcanonical(d,0.1)) ≈ hilbert(w,fromcanonical(d,0.1)) ≈
            im*(cauchy(w,fromcanonical(d,0.1)-eps())+cauchy(w,fromcanonical(d,0.1)+eps()))
    end

    @testset "Legendre singularities" begin
        Γ=Curve(Fun(x->x^2+im*x))
        x=Fun(Γ)
        f=exp(x)

        @test cauchy(f,1.0) ≈ sum(f/(x-1.0))/(2π*im)
    end
end


text:
function foo()
    lines = readlines(open("data/3.txt", "r"))
    claims = zeros(Int, 1000, 1000)
    for line in lines
        a, b, c, d = split(line, ' ')
        x, y = parse.(Int, split(c[1:end-1], ',')) .+ 1
        w, h = parse.(Int, split(d, 'x')) .- 1
        claims[x:x+w, y:y+h] .+= 1
    end
    return sum(claims .> 1)
end

println(foo())


text:
n, p = 500, 5
((X, y, θ), (X1, y1, θ1)) = generate_continuous(n, p; seed=525)

# NOTE: in these cases, if available, θ_newton is used as reference.
# so if the others are not far, it's assumed all have converged to the
# same (correct) minimizer. The reference J(θ) or J(θ1) is the objective
# at the generating θ; it should usually be >
# these are tests that should be considered as "sanity check" and are not
# stress tests testing corner cases.

@testset "HuberReg" begin
    # No intercept
    δ = 0.01
    λ = 3.0
    hr = HuberRegression(δ, λ; fit_intercept=false)
    J = objective(hr, X, y)
    o = RobustLoss(Huber(δ)) + λ * L2Penalty()
    @test J(θ) == o(y, X*θ, θ)
    θ_newton   = fit(hr, X, y, solver=Newton())
    θ_newtoncg = fit(hr, X, y, solver=NewtonCG())
    θ_lbfgs    = fit(hr, X, y, solver=LBFGS())
    θ_iwls     = fit(hr, X, y, solver=IWLSCG())
    @test (J(θ)          - 10.60971) ≤ 1e-5
    @test (J(θ_newton)   -  7.70113) ≤ 1e-5
    @test (J(θ_newtoncg) -  7.70113) ≤ 1e-5
    @test (J(θ_lbfgs)    -  7.70113) ≤ 1e-5
    @test (J(θ_iwls)     -  7.70113) ≤ 1e-5

    δ = 0.01
    λ = 3.0
    hr = HuberRegression(δ, λ; penalize_intercept=true)
    J = objective(hr, X, y1)
    o = RobustLoss(Huber(δ)) + λ * L2Penalty()
    @test J(θ1) == o(y1, X1*θ1, θ1)
    θ_newton   = fit(hr, X, y1, solver=Newton())
    θ_newtoncg = fit(hr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(hr, X, y1, solver=LBFGS())
    θ_iwls     = fit(hr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 16.36661) ≤ 1e-5
    @test (J(θ_newton)   - 10.51384) ≤ 1e-5
    @test (J(θ_newtoncg) - 10.51384) ≤ 1e-5
    @test (J(θ_lbfgs)    - 10.51384) ≤ 1e-5
    @test (J(θ_iwls)     - 10.51384) ≤ 1e-5

    # don't penalize intercept
    δ = 0.01
    λ = 3.0
    hr = HuberRegression(δ, λ)
    J = objective(hr, X, y1)
    θ_newton   = fit(hr, X, y1, solver=Newton())
    θ_newtoncg = fit(hr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(hr, X, y1, solver=LBFGS())
    θ_iwls     = fit(hr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 8.994865) ≤ 1e-5
    @test (J(θ_newton)   - 6.810135) ≤ 1e-5
    @test (J(θ_newtoncg) - 6.810135) ≤ 1e-5
    @test (J(θ_lbfgs)    - 6.810135) ≤ 1e-5
    @test (J(θ_iwls)     - 6.810135) ≤ 1e-5
end

# NOTE: small difference obtained with NCG and IWLS, might just be
# that the algorithm stops a bit earlier, negligible relative tol anyway.
@testset "AndrewsReg" begin
    δ = 0.1
    λ = 3.0
    rr = RobustRegression(rho=Andrews(δ), lambda=λ; penalize_intercept=true)
    J = objective(rr, X, y1)
    o = RobustLoss(AndrewsRho(δ)) + λ * L2Penalty()
    @test J(θ1) == o(y1, X1*θ1, θ1)
    θ_newton   = fit(rr, X, y1, solver=Newton())
    θ_newtoncg = fit(rr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(rr, X, y1, solver=LBFGS())
    θ_iwls     = fit(rr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 16.11921) ≤ 1e-5
    @test (J(θ_newton)   -  0.49078) ≤ 1e-5
    @test (J(θ_newtoncg) -  0.49078) ≤ 1e-3
    @test (J(θ_lbfgs)    -  0.49078) ≤ 1e-5
    @test (J(θ_iwls)     -  0.49078) ≤ 1e-3
end

@testset "BisquareReg" begin
    δ = 0.1
    λ = 3.0
    rr = RobustRegression(rho=Bisquare(δ), lambda=λ; penalize_intercept=true)
    J = objective(rr, X, y1)
    o = RobustLoss(BisquareRho(δ)) + λ * L2Penalty()
    @test J(θ1) == o(y1, X1*θ1, θ1)
    θ_newton   = fit(rr, X, y1, solver=Newton())
    θ_newtoncg = fit(rr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(rr, X, y1, solver=LBFGS())
    θ_iwls     = fit(rr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 16.54073) ≤ 1e-5
    @test (J(θ_newton)   -  0.82180) ≤ 1e-5
    @test (J(θ_newtoncg) -  0.82180) ≤ 1e-5
    @test (J(θ_lbfgs)    -  0.82180) ≤ 1e-5
    @test (J(θ_iwls)     -  0.82180) ≤ 1e-5
end

@testset "LogisticRReg" begin
    δ = 1.5
    λ = 1.0
    rr = RobustRegression(rho=Logistic(delta=δ), lambda=λ, penalize_intercept=true)
    J = objective(rr, X, y1)
    o = RobustLoss(LogisticRho(δ)) + λ * L2Penalty()
    @test J(θ1) ≈ o(y1, X1*θ1, θ1)
    θ_newton = fit(rr, X, y1, solver=Newton())
    θ_newtoncg = fit(rr, X, y1, solver=NewtonCG())
    θ_lbfgs = fit(rr, X, y1, solver=LBFGS())
    θ_iwls  = fit(rr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 7.69833) ≤ 1e-5
    @test (J(θ_newton)   - 7.66289) ≤ 1e-5
    @test (J(θ_newtoncg) - 7.66289) ≤ 1e-5
    @test (J(θ_lbfgs)    - 7.66289) ≤ 1e-5
    @test (J(θ_iwls)     - 7.66289) ≤ 1e-5
end

@testset "FairReg" begin
    δ = 0.1
    λ = 3.0
    rr = RobustRegression(rho=Fair(δ), lambda=λ, penalize_intercept=true)
    J = objective(rr, X, y1)
    o = RobustLoss(Fair(δ)) + λ * L2Penalty()
    @test J(θ1) ≈ o(y1, X1*θ1, θ1)
    θ_newton   = fit(rr, X, y1, solver=Newton())
    θ_newtoncg = fit(rr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(rr, X, y1, solver=LBFGS())
    θ_iwls     = fit(rr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 17.26553) ≤ 1e-5
    @test (J(θ_newton)   - 16.96553) ≤ 1e-5
    @test (J(θ_newtoncg) - 16.96553) ≤ 1e-5
    @test (J(θ_lbfgs)    - 16.96553) ≤ 1e-5
    @test (J(θ_iwls)     - 16.96553) ≤ 1e-5
end

# NOTE: small difference obtained with NCG and IWLS, might just be
# that the algorithm stops a bit earlier, negligible relative tol anyway.
@testset "TalwarReg" begin
    δ = 0.1
    λ = 3.0
    rr = RobustRegression(rho=Talwar(δ), lambda=λ, penalize_intercept=true)
    J = objective(rr, X, y1)
    o = RobustLoss(Talwar(δ)) + λ * L2Penalty()
    @test J(θ1) == o(y1, X1*θ1, θ1)
    θ_newton   = fit(rr, X, y1, solver=Newton())
    θ_newtoncg = fit(rr, X, y1, solver=NewtonCG())
    θ_lbfgs    = fit(rr, X, y1, solver=LBFGS())
    θ_iwls     = fit(rr, X, y1, solver=IWLSCG())
    @test (J(θ1)         - 17.25562) ≤ 1e-5
    @test (J(θ_newton)   -  2.44343) ≤ 1e-5
    @test (J(θ_newtoncg) -  2.44343) ≤ 2e-3
    @test (J(θ_lbfgs)    -  2.44343) ≤ 1e-5
    @test (J(θ_iwls)     -  2.44343) ≤ 2e-3
end

###########################
## With Sparsity penalty ##
###########################

n, p = 500, 100
((X, y, θ), (X1, y1, θ1)) = generate_continuous(n, p;  seed=51112, sparse=0.1)
# pepper with outliers
y1a  = outlify(y1, 0.1)

@testset "Robust+L1" begin
    δ  = 0.1
    λ  = 5.0
    γ  = 10.0

    # this is a nice case where the robust is actually smooth
    rr = RobustRegression(rho=Huber(δ), lambda=λ, gamma=γ, penalize_intercept=true)
    J  = objective(rr, X, y1a)
    θ_ls    = X1 \ y1a
    θ_fista = fit(rr, X, y1a, solver=FISTA())
    θ_ista  = fit(rr, X, y1a, solver=ISTA())
    @test isapprox(J(θ_ls),    391.66463, rtol=1e-5)
    @test isapprox(J(θ_fista),  99.10028, rtol=1e-5) # <- ref value
    @test isapprox(J(θ_ista),   99.10028, rtol=1e-5) # ista stops a bit early?
    @test nnz(θ_ls)    == 101
    @test nnz(θ_fista) == 6
    @test nnz(θ_ista)  == 6
end


text:
#=
Lightweight implementation of forward-mode second-degree autodiff.
=#
module Jets

import SpecialFunctions: erf, erfc, erfcinv, dawson
import Base: convert, promote_rule, +, -, *, /, inv, cos, sin, tan, cot, sec, csc, exp, cosh, sinh, tanh, coth, sech, csch, log, sqrt, one, zero, isnan, isinf, conj, real, imag

const erfinf=2/sqrt(pi)
const ierfinf=sqrt(pi)/2

#a+be+ce^2 with e^3=0
struct Jet{T<:Number} <: Number
  a::T
  b::T
  c::T
end

Standard=Union{Real,Complex{<:Real}}

Jet(x::T) where T<:Number = Jet{T}(x, zero(T), zero(T))

function Jet(x::T1,y::T2) where {T1<:Number,T2<:Number}
    T = promote_type(T1,T2)
    Jet{T}(promote(x,y)..., zero(T))
end

function Jet(x::T1,y::T2,z::T3) where {T1<:Number,T2<:Number,T3<:Number}
    T = promote_type(T1,T2,T3)
    Jet{T}(promote(x,y,z)...)
end

convert(::Type{Jet},x::Standard)=Jet(x)
convert(::Type{Jet{T}},x::Standard) where T<:Number = Jet(convert(T,x))
convert(T::Type{<:Standard},x::Jet)=convert(T,x.a)

promote_rule(::Type{Jet{T1}}, ::Type{T2}) where {T1<:Number,T2<:Standard} = Jet{promote_type(T1,T2)}
promote_rule(::Type{Jet{T1}}, ::Type{Jet{T2}}) where {T1<:Number,T2<:Number} = Jet{promote_type(T1,T2)}

function (+)(x::Jet,y::Jet)
  Jet(x.a+y.a,x.b+y.b,x.c+y.c)
end

function (-)(x::Jet,y::Jet)
  Jet(x.a-y.a,x.b-y.b,x.c-y.c)
end

function (-)(y::Jet)
  Jet(-y.a,-y.b,-y.c)
end

function (+)(x::Jet,y::Standard)
  Jet(x.a+y,x.b,x.c)
end

function (-)(x::Jet,y::Standard)
  Jet(x.a-y,x.b,x.c)
end

function (+)(x::Standard,y::Jet)
  Jet(x+y.a,y.b,y.c)
end

function (-)(x::Standard,y::Jet)
  Jet(x-y.a,-y.b,-y.c)
end

function (*)(x::Standard,y::Jet)
  Jet(x*y.a,x*y.b,x*y.c)
end

function (*)(y::Jet,x::Standard)
  Jet(y.a*x,y.b*x,y.c*x)
end

function (/)(x::Jet,y::Standard)
  x*inv(y)
end

function (*)(x::Jet,y::Jet)
  Jet(x.a*y.a,x.a*y.b+x.b*y.a,x.a*y.c+x.b*y.b+x.c*y.a)
end

#x=z/y only if x*y=z
function (/)(z::Jet,y::Jet)
  r=inv(y.a)
  xa=r*z.a
  xb=r*(z.b-xa*y.b)
  xc=r*(z.c-xa*y.c-xb*y.b)
  Jet(xa,xb,xc)
end

function inv(y::Jet)
  xa=inv(y.a)
  xb=-xa*xa*y.b
  xc=-xa*(xa*y.c + xb*y.b)
  Jet(xa,xb,xc)
end

function (/)(z::Standard,y::Jet)
  r=inv(y.a)
  xa=r*z
  xb=-r*xa*y.b
  xc=-r*(xa*y.c + xb*y.b)
  Jet(xa,xb,xc)
end

#f(a+e)=f(a)+ef'(a)+e^2f''(a)/2
function taylorcoeffs(func, pt::Standard)
  func(Jet(pt,one(pt)))
end

function taylorapprox(taylor::Jet,x::Standard)
  taylor.a+x*(taylor.b+x*taylor.c)
end

#computes f(x::Jet) from x and
#f,df,ddf=f(x.a),f'(x.a),f''(x.a)
function derivschain(x::Jet,
                     f::Standard,
                     df::Standard,
                     ddf::Standard)
  #f(a+be+ce^2)=f(a)+bef'(a)+e^2(cf'(a)+b^2f''(a)/2)
  Jet(f, x.b*df, x.c*df + x.b*x.b*ddf/2)
end

cos(x::Jet,si::Standard,co::Standard) = Jet(co, -x.b*si, -x.c*si - x.b*x.b*co/2)
sin(x::Jet,si::Standard,co::Standard) = Jet(si, x.b*co, x.c*co - x.b*x.b*si/2)
tan(x::Jet,si::Standard,co::Standard) = sin(x,si,co) / cos(x,si,co)
cot(x::Jet,si::Standard,co::Standard) = cos(x,si,co) / sin(x,si,co)
sec(x::Jet,si::Standard,co::Standard) = inv(cos(x,si,co))
csc(x::Jet,si::Standard,co::Standard) = inv(sin(x,si,co))

cos(x::Jet)=cos(x,sincos(x.a)...)
sin(x::Jet)=sin(x,sincos(x.a)...)
tan(x::Jet)=tan(x,sincos(x.a)...)
cot(x::Jet)=cot(x,sincos(x.a)...)
sec(x::Jet)=sec(x,sincos(x.a)...)
csc(x::Jet)=csc(x,sincos(x.a)...)

function exp(x::Jet)
  ex=exp(x.a)
  Jet(ex, ex*x.b, ex*(x.c + x.b*x.b/2))
end

function log(x::Jet)
    f=log(x.a)
    df=inv(x.a)
    ddf=-df^2
    derivschain(x,f,df,ddf)
end

function sqrt(x::Jet)
  f=sqrt(x.a)
  r=inv(2x.a)
  df=f*r
  ddf=-df*r
  derivschain(x,f,df,ddf)
end

function dawson(x::Jet)
  f=dawson(x.a)
  df=1-2*x.a*f
  ddf=2*(f*(2*x.a*x.a-1)-x.a)
  derivschain(x,f,df,ddf)
end

function erf(x::Jet)
  f=erf(x.a)
  df=erfinf*exp(-x.a*x.a)
  ddf=-2*x.a*df
  derivschain(x,f,df,ddf)
end

function erfc(x::Jet)
  f=erfc(x.a)
  df=-erfinf*exp(-x.a*x.a)
  ddf=-2*x.a*df
  derivschain(x,f,df,ddf)
end

function erfcinv(x::Jet)
  #erfcinv only defined on (0,2)
  f=erfcinv(real(x.a))
  df=-ierfinf*exp(f*f)
  ddf=2*f*df*df
  derivschain(x,f,df,ddf)
end

function cosh(x::Jet)
    p=exp(x)
    m=inv(p)
    (p+m)/2
end
function sinh(x::Jet)
    p=exp(x)
    m=inv(p)
    (p-m)/2
end
function tanh(x::Jet)
    p=exp(x)
    m=inv(p)
    (p-m)/(p+m)
end
function coth(x::Jet)
    p=exp(x)
    m=inv(p)
    (p+m)/(p-m)
end
function sech(x::Jet)
    p=exp(x)
    m=inv(p)
    2/(p+m)
end
function csch(x::Jet)
    p=exp(x)
    m=inv(p)
    2/(p-m)
end

function real(x::Jet)
  Jet(real(x.a),real(x.b),real(x.c))
end

function imag(x::Jet)
  Jet(imag(x.a),imag(x.b),imag(x.c))
end

function conj(x::Jet)
  Jet(conj(x.a),conj(x.b),conj(x.c))
end

one(::Jet{T}) where T<:Number = Jet(one(T))
zero(::Jet{T}) where T<:Number = Jet(zero(T))

isnan(x::Jet)=isnan(x.a) || isnan(x.b) || isnan(x.c)
isinf(x::Jet)=isinf(x.a) || isinf(x.b) || isinf(x.c)

#input: 2nd-order Taylor polynomial of function f at some point
#output: quadratic and linear coefficients of Taylor polynomial of arg(f) at that point
phasepoly(z::Jet)=complex(0.,phase_acceleration(z)),complex(0.,phase_velocity(z))

phase_velocity(z::Jet)=imag(z.b/z.a)
phase_acceleration(z::Jet)=imag((z.c*z.a-0.5*z.b*z.b)/(z.a*z.a))

end #module


text:
using Distributed
addprocs(6)
@everywhere include("reproducibility.jl")
using Random
Random.seed!(42)
##

@everywhere using QSWalk
@everywhere using LightGraphs
@everywhere using NPZ
@everywhere using LinearAlgebra, SparseArrays
data_folder_name = "convergence_qsw"

## graph_generators

@everywhere function multi_sink_condensation(n::Int, p::Float64)
    g = erdos_renyi(n, p, is_directed=true)
    h = condensation(g)
    while length(filter(v->outdegree(h, v) == 0 , 1:nv(h))) <= 1 || !is_weakly_connected(g)
        g = erdos_renyi(n, p, is_directed=true)
        h = condensation(g)
    end
    g
end

@everywhere function single_sink_condensation(n::Int, p::Float64)
    g = erdos_renyi(n, p, is_directed=true)
    h = condensation(g)
    while length(filter(v->outdegree(h, v) == 0 , 1:nv(h))) > 1
        g = erdos_renyi(n, p, is_directed=true)
        h = condensation(g)
    end
    g
end

@everywhere function random_oriented_tree(n::Int)
    g = DiGraph(n)
    for i=2:n
        if rand() < 0.5
            add_edge!(g, i, rand(1:(i-1)))
        else
            add_edge!(g, rand(1:(i-1)), i)
        end
    end
    g
end

@everywhere function random_orientation(g::Graph)
    digraph = DiGraph(nv(g))
    for e = edges(g)
        i, j = e.src, e.dst
        if rand() < 0.5
            add_edge!(digraph, i, j)
        else
            add_edge!(digraph, j, i)
        end
    end
    digraph
end

@everywhere function random_multi_sink_orientation(n::Int, p::Float64)
    g = random_orientation(erdos_renyi(n, p))
    h = condensation(g)
    while length(filter(v->outdegree(h, v) == 0 , 1:nv(h))) <= 1 || !is_weakly_connected(g)
        g = random_orientation(erdos_renyi(n, p))
        h = condensation(g)
    end
    g
end

@everywhere function multi_sink_condensation_ba(n::Int, k::Int)
    g = random_orientation(barabasi_albert(n, k, complete=true))
    h = condensation(g)
    while length(filter(v->outdegree(h, v) == 0 , 1:nv(h))) <= 1
        g = random_orientation(barabasi_albert(n, k, complete=true))
        h = condensation(g)
    end
    g
end
@everywhere function multi_sink_condensation_tree(n::Int)
    g = random_oriented_tree(n)
    h = condensation(g)
    while length(filter(v->outdegree(h, v) == 0 , 1:nv(h))) <= 1
        g = random_oriented_tree(n)
        h = condensation(g)
    end
    g
end

@everywhere function connected_ER(n::Int, p::Float64; is_directed::Bool)
    g = erdos_renyi(n, p, is_directed=is_directed)
    while !is_weakly_connected(g)
        g = erdos_renyi(n, p, is_directed=is_directed)
    end
    g
end

## #########################################################################
# ############################# GQSW #######################################
# ##########################################################################

gens = [("ba_3", n -> barabasi_albert(n, 3, complete=true, is_directed=true)),
        ("er_0.4", n -> connected_ER(n, 0.4, is_directed=true)),
        ("ba_1", n -> barabasi_albert(n, 1, complete=true, is_directed=true))]

for (gen_lab, gen) = gens, n = 10:10:50
    println("$gen_lab $n")
    filename = "$data_folder_name/global_gaps_$gen_lab-$n.npz"
    if isfile(filename)
        println("File exists - computation skipped")
        continue
    end
    gaps = @sync @distributed (hcat) for m = 1:500
        println("$m")
        g = gen(n)
        l = Matrix(adjacency_matrix(g, dir=:in))
        h = adjacency_matrix(Graph(g))
        s = Matrix(evolve_generator(h, [l]))
        v = eigvals(s)
        second_minimal_abs = sort(abs.(v))[2]
        list_imaginary = sort(imag.(collect(filter(x->abs(real(x)) < 1e-10 && abs(imag(x)) > 1e-10 , v))), by = x->abs(x))
        second_minimal_imag = -1
        if length(list_imaginary) > 0
            second_minimal_imag = abs(first(list_imaginary))
        end
        [second_minimal_abs, second_minimal_imag]
    end
    npzwrite(filename, gaps)
end

###########################################################################
############################## LQSW #######################################
###########################################################################

gens = [("ba_3", n -> multi_sink_condensation_ba(n, 3)),
        ("er_0.4", n -> random_multi_sink_orientation(n, 0.4)),
        ("ba_1", n -> multi_sink_condensation_ba(n, 1))]

for (gen_lab, gen) = gens, n = 10:10:50
    println("$gen_lab $n")
    if n > 30 && gen_lab == "er_0.4"
        println("continue")
        continue
    end
    filename = "$data_folder_name/local_gaps_$gen_lab-$n.npz"
    if isfile(filename)
        println("File exists - computation skipped")
        continue
    end
    gaps = @sync @distributed (hcat) for m = 1:500
        println("$m")
        @time g = gen(n)
        println("found")
        l = Matrix(adjacency_matrix(g, dir=:in))
        h = adjacency_matrix(Graph(g))
        s = Matrix(evolve_generator(h, local_lind(l)))
        v = eigvals(s)
        second_minimal_abs = sort(abs.(v))[2]
        list_imaginary = sort(imag.(collect(filter(x->abs(real(x)) < 1e-10 && abs(imag(x)) > 1e-10 , v))), by = x->abs(x))
        second_minimal_imag = -1
        if length(list_imaginary) > 0
            second_minimal_imag = abs(first(list_imaginary))
        end
        [second_minimal_abs, second_minimal_imag]
    end
    npzwrite(filename, gaps)
end

## #########################################################################
# ############################# NGQSW ######################################
# ##########################################################################

models = []
push!(models, (n -> barabasi_albert(n, 1), "ba_1"))
push!(models, (n -> barabasi_albert(n, 3, complete=true, is_directed=true), "ba_3_directed"))
push!(models, (n -> connected_ER(n, 0.4, is_directed=true), "er_0.4_directed"))

for n = 5:5:20, (generator, generator_label) = models
    println("$generator_label $n")
    filename = "$data_folder_name/nonmoral_gaps_$generator_label-$n.npz"
    if isfile(filename)
        println("File exists - computation skipped")
        continue
    end
    gaps = @sync @distributed (hcat) for m = 1:500
        println("$m")
        @time g = generator(n)
        a = adjacency_matrix(g, dir=:in)
        l, vset = nm_lind(a)
        h = nm_glob_ham(a)
        hrot = nm_loc_ham(vset)
        s = Matrix(evolve_generator(h, [l], hrot))
        v = eigvals(s)
        second_minimal_abs = sort(abs.(v))[2]
        list_imaginary = sort(imag.(collect(filter(x->abs(real(x)) < 1e-10 && abs(imag(x)) > 1e-10 , v))), by = x->abs(x))
        second_minimal_imag = -1
        if length(list_imaginary) > 0
            second_minimal_imag = abs(first(list_imaginary))
        end
        [second_minimal_abs, second_minimal_imag]
    end
    npzwrite(filename, gaps)
end


text:
using Test

using Blind

using FileIO, CSVFiles

function test_output(path_key)
    @test isfile(path_key)

    # Check key file.
    for (original, blind) in CSVFiles.getiterator(load(path_key))

        # Check file record.
        @test isfile(blind)

        # Check file extensions.
        @test splitext(original)[2] == splitext(blind)[2]
    end
end

@testset "Blind" begin

    @testset "Name Generation" begin
        n = 4
        num_sets = 3
        num_numerics = 4

        strs = Blind.generate_names(n, num_sets, num_numerics)

        @show strs
        @test length(strs) == n
        @test length(unique(strs)) == n
        @test all((str)-> length(str) == num_sets * num_numerics + num_sets -1, strs)
    end #testset Name Generation

    files_original = [
        "f1.tif",
        "f2.tif",
        "f3.tif",
        "f4.tif",
    ]

    dir_input = abspath(joinpath(@__DIR__, "input"))

    mkpath(dir_input)
    paths_original = joinpath.(dir_input, files_original)
    touch.(paths_original)

    path_key = joinpath(dir_input, "key.csv")

    @testset "Procedure" begin

        dir_output = joinpath(@__DIR__, "output")

        blind(dir_input, dir_output, path_key)

        @test isdir(dir_output)

        test_output(path_key)

        # Clean up.
        rm(dir_output, recursive = true)
        rm(path_key)

    end # testset Procedure

    @testset "Script" begin
        script = joinpath(@__DIR__, "..", "blind.sh")

        if Sys.iswindows()
            run(`julia $script $dir_input`)
        else
            run(`bash $script $dir_input`)
        end

        dir_output = joinpath(@__DIR__, "input-blind")

        @test isdir(dir_output)

        test_output(path_key)

        # Clean up
        rm(dir_output, recursive = true)

    end #testset Script

    # Clean up
    rm(dir_input, recursive = true)

end # testset Blind


text:
# ------------------------------------------------------------------
# Licensed under the ISC License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    GeoDataFrame(data, coordnames)

A dataframe object `data` with additional metadata for tracking
the columns `coordnames` that represent spatial coordinates.

## Examples

If the data was already loaded in a normal DataFrame `data`,
and there exists columns named `x`, `y` and `z`, wrap the
data and specify the column names:

```julia
julia> GeoDataFrame(data, [:x,:y,:z])
```

Alternatively, load the data directly into a `GeoDataFrame` object
by using the method [`readgeotable`](@ref).

### Notes

This type is a lightweight wrapper over Julia's DataFrame types.
No additional storage is required other than a vector of symbols
with the columns names representing spatial coordinates.

"""
struct GeoDataFrame{T,N,DF<:AbstractDataFrame} <: AbstractData{T,N}
  data::DF
  coordnames::Vector{Symbol}

  function GeoDataFrame{T,N,DF}(data, coordnames) where {T,N,DF<:AbstractDataFrame}
    new(data, coordnames)
  end
end

function GeoDataFrame(data::DF, coordnames::AbstractVector{Symbol}) where {DF<:AbstractDataFrame}
  @assert coordnames ⊆ names(data) "invalid column names"

  Ts = eltypes(data[coordnames])
  T  = promote_type(Ts...)
  N  = length(coordnames)

  @assert !(Missing <: T) "coordinates cannot be missing"

  GeoDataFrame{T,N,DF}(data, coordnames)
end

domain(geodata::GeoDataFrame) = PointSet(coordinates(geodata))

function coordnames(geodata::GeoDataFrame)
  rawdata = geodata.data
  cnames = geodata.coordnames

  Tuple(cnames)
end

function variables(geodata::GeoDataFrame)
  rawdata = geodata.data
  cnames = geodata.coordnames
  vnames = [var for var in names(rawdata) if var ∉ cnames]
  vtypes = Base.nonmissingtype.(eltypes(rawdata[vnames]))

  Dict(var => T for (var,T) in zip(vnames,vtypes))
end

npoints(geodata::GeoDataFrame) = nrow(geodata.data)

function coordinates!(buff::AbstractVector, geodata::GeoDataFrame, ind::Int)
  rawdata = geodata.data
  cnames = geodata.coordnames

  for (i, cname) in enumerate(cnames)
    @inbounds buff[i] = rawdata[ind,cname]
  end
end

# ------------
# IO methods
# ------------
function Base.show(io::IO, geodata::GeoDataFrame)
  dims = join(size(geodata.data), "×")
  cnames = join(geodata.coordnames, ", ", " and ")
  print(io, "$dims GeoDataFrame ($cnames)")
end

function Base.show(io::IO, ::MIME"text/plain", geodata::GeoDataFrame)
  println(io, geodata)
  show(io, geodata.data, allcols=true, summary=false)
end

function Base.show(io::IO, ::MIME"text/html", geodata::GeoDataFrame)
  println(io, geodata)
  show(io, MIME"text/html"(), geodata.data, summary=false)
end


text:
# -*- coding: utf-8 -*-
# ---
# jupyter:
#   jupytext:
#     formats: ipynb,jl:hydrogen
#     text_representation:
#       extension: .jl
#       format_name: hydrogen
#       format_version: '1.3'
#       jupytext_version: 1.11.2
#   kernelspec:
#     display_name: Julia 1.7.0-DEV
#     language: julia
#     name: julia-1.7
# ---

# %%
VERSION

# %% [markdown]
# Wave equaiton: $\displaystyle
# \frac{\partial^2 u}{\partial t^2} =
# \frac{\partial^2 u}{\partial x^2} +
# \frac{\partial^2 u}{\partial y^2}
# $

# %%
@time using DifferentialEquations
@time using Plots
@time using ProgressMeter
# Please do pkg> add https://github.com/bicycle1885/Fmt.jl
@time using Fmt

# %%
# The wave equation on the square with free boundary condition

#f!(du, v, u, p, t) = @. du = v

function g!(dv, v, u, p, t)
    h⁻² = p[1]
    @. @views dv[2:end-1,2:end-1] = h⁻²*(
        u[1:end-2,2:end-1] + u[3:end,2:end-1] + u[2:end-1,1:end-2] + u[2:end-1,3:end] - 4u[2:end-1,2:end-1])
    @. @views dv[1  ,2:end-1] = h⁻²*(u[2,    2:end-1] + u[1,  1:end-2] + u[1,  3:end] - 3u[1,  2:end-1])
    @. @views dv[end,2:end-1] = h⁻²*(u[end-1,2:end-1] + u[end,1:end-2] + u[end,3:end] - 3u[end,2:end-1])
    @. @views dv[2:end-1,1  ] = h⁻²*(u[2:end-1,2    ] + u[1:end-2,1  ] + u[3:end,1  ] - 3u[2:end-1,1  ])
    @. @views dv[2:end-1,end] = h⁻²*(u[2:end-1,end-1] + u[1:end-2,end] + u[3:end,end] - 3u[2:end-1,end])
    dv[1  ,1  ] = h⁻²*(u[1  ,2    ] + u[2    ,1  ] - 2u[1  ,1  ])
    dv[end,1  ] = h⁻²*(u[end,2    ] + u[end-1,1  ] - 2u[end,1  ])
    dv[1  ,end] = h⁻²*(u[1  ,end-1] + u[2    ,end] - 2u[1  ,end])
    dv[end,end] = h⁻²*(u[end,end-1] + u[end-1,end] - 2u[end,end])
end

x = y = range(-1, 1; length=501)
h = step(x)
p = (1/h^2,)

F(a, b, c, x, y) = exp(-((x-a)^2+(y-b)^2)/(2c^2))
f(x, y) = F(0.7, 0, 0.01, x, y) + F(-0.4, 0.6, 0.01, x, y) + F(-0.4, -0.6, 0.01, x, y)
u0 = f.(x', y)
v0 = zero(u0)
tspan = (0.0, 2.0)

#prob = DynamicalODEProblem(g!, f!, v0, u0, tspan, p)
prob = SecondOrderODEProblem(g!, v0, u0, tspan, p)
sol = nothing; GC.gc()
@time sol = solve(prob; saveat=0.01)
sol = nothing; GC.gc()
@time sol = solve(prob; saveat=0.01)

umin = minimum(minimum.(u.x[2] for u in sol.u))
umax = maximum(maximum.(u.x[2] for u in sol.u))
umin, umax

# %%
L = 201
ts = range(tspan...; length=L) |> r -> [fill(r[1], 20); r; fill(r[end], 20)]
prog = Progress(length(ts), 0)
@gif for t in ts
    z = sol(t).x[2]'
    @views heatmap(
        x, y, z;
        #x[begin:2:end], y[begin:2:end], z[begin:2:end, begin:2:end];
        clim=(-0.03, 0.03), colorbar=false, c=:bwr)
    title!(f"t = {$t:4.2f}"; titlefontsize=12, aspectratio=1)
    plot!(size=(420, 440), xlim=extrema(x), ylim=extrema(y))
    next!(prog)
end

# %%
function plot_sol(sol, x, y, t; color=:bwr)
    z = sol(t).x[2]'
    surface(
        x, y, z;
        #x[begin:2:end], y[begin:2:end], z[begin:2:end, begin:2:end];
        zlim=(-0.03, 0.03), colorbar=false, color, camera=(30, 85))
    title!(f"t = {$t:4.2f}"; titlefontsize=12)
    plot!(bg=:lightgrey, size=(640, 500))
end

plot_sol(sol, x, y, 0.6)

# %%
L = 201
ts = range(tspan...; length=L) |> r -> [fill(r[1], 20); r; fill(r[end], 20)]
prog = Progress(length(ts), 0)
@gif for t in ts
    plot_sol(sol, x, y, t)
    next!(prog)
end

# %%
function g_dirichlet!(dv, v, u, p, t)
    h⁻² = p[1]
    @. @views dv[2:end-1,2:end-1] = h⁻²*(
        u[1:end-2,2:end-1] + u[3:end,2:end-1] + u[2:end-1,1:end-2] + u[2:end-1,3:end] - 4u[2:end-1,2:end-1])
    @. @views dv[1  ,2:end-1] = h⁻²*(u[2,    2:end-1] + u[1,  1:end-2] + u[1,  3:end] - 4u[1,  2:end-1])
    @. @views dv[end,2:end-1] = h⁻²*(u[end-1,2:end-1] + u[end,1:end-2] + u[end,3:end] - 4u[end,2:end-1])
    @. @views dv[2:end-1,1  ] = h⁻²*(u[2:end-1,2    ] + u[1:end-2,1  ] + u[3:end,1  ] - 4u[2:end-1,1  ])
    @. @views dv[2:end-1,end] = h⁻²*(u[2:end-1,end-1] + u[1:end-2,end] + u[3:end,end] - 4u[2:end-1,end])
    dv[1  ,1  ] = h⁻²*(u[1  ,2    ] + u[2    ,1  ] - 4u[1  ,1  ])
    dv[end,1  ] = h⁻²*(u[end,2    ] + u[end-1,1  ] - 4u[end,1  ])
    dv[1  ,end] = h⁻²*(u[1  ,end-1] + u[2    ,end] - 4u[1  ,end])
    dv[end,end] = h⁻²*(u[end,end-1] + u[end-1,end] - 4u[end,end])
end

x = y = range(-1, 1; length=501)
h = step(x)
p = (1/h^2,)

F(a, b, c, x, y) = exp(-((x-a)^2+(y-b)^2)/(2c^2))
f(x, y) = F(0.7, 0, 0.01, x, y) + F(-0.4, 0.6, 0.01, x, y) + F(-0.4, -0.6, 0.01, x, y)
u0 = f.(x', y)
v0 = zero(u0)
tspan = (0.0, 2.0)

prob = SecondOrderODEProblem(g_dirichlet!, v0, u0, tspan, p)
sol = nothing; GC.gc()
@time sol = solve(prob; saveat=0.01)

umin = minimum(minimum.(u.x[2] for u in sol.u))
umax = maximum(maximum.(u.x[2] for u in sol.u))
umin, umax

# %%
L = 201
ts = range(tspan...; length=L) |> r -> [fill(r[1], 20); r; fill(r[end], 20)]
prog = Progress(length(ts), 0)
@gif for t in ts
    heatmap(x, y, sol(t).x[2]';
        clim=(-0.03, 0.03), colorbar=false, c=:bwr)
    title!(f"t = {$t:4.2f}"; titlefontsize=12, aspectratio=1)
    plot!(size=(420, 440), xlim=extrema(x), ylim=extrema(y))
    next!(prog)
end

# %%
plot_sol(sol, x, y, 0.6)

# %%
L = 201
ts = range(tspan...; length=L) |> r -> [fill(r[1], 20); r; fill(r[end], 20)]
prog = Progress(length(ts), 0)
@gif for t in ts
    plot_sol(sol, x, y, t)
    next!(prog)
end

# %%

max_stars_repo_path: 0003/Wave equation on the square 2021-06-09 Part 2.jl

max_stars_repo_name: genkuroki/public

max_issues_repo_name: genkuroki/public

max_forks_repo_name: genkuroki/public