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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ f66e452c-97db-11eb-23fc-bd95da10e2d6
using Plots, FFTW, TestImages, PlutoUI, Images, ImageShow

# ╔═╡ adaa78fa-d805-45e6-ba5f-d91a5d4823d6
using ImageContrastAdjustment

# ╔═╡ 09fc6764-2050-4276-8a14-3596368d0c32
md"""
# How much data do we need?

One of the challenges of information representation generally is how much data do we need to represent an object/concept sufficiently. It should be noted, that "represent sufficiently" is an ill-defined term, since this judgement will be application specific.

In order to address this question, we are going to assume that a concept can be represented as a function. A concept can be quite general but in this notebook we will be using images as our concepts. That is, an image represents some function and this function can be represented as a combination of __basis functions__. So when we ask, "How much data do you need?" can be restated as "How many basis functions do you need?"

## What is a basis function?

I'll answer this later.

We will generally need an infinite number of basis functions to represent an arbitrary ???. However, in our digital world we can only use a finite number of basis functions, and with a finite number of basis functions we can only __approximate__ these functions.

### Sinusoidal Basis Functions

In this notebook we are going to look at information representation in terms of sinusoidal basis functions. The canonical information representation based on sinusoidal basis functions is the [Fourier transform](https://en.wikipedia.org/wiki/Fourier_transform). In 1822 Jean-Baptiste Joseph Fourier demonstrated that (most) continous functions can be represented as a summation of an infinite number of appropriately weighted and phased sinusoidal (sines, cosines, complex exponentials) functions. The sinusoidal functions are an example of __basis__ functions. A key concept in the Fourier transform is the need for an infinite number of basis functions.

In applications such as magnetic resonance imaging (MRI) of the human body, we can view the body region being imaged as the continuous function. The MRI technique actually measures samples from the Fourier transform of the person's body region. How we sample this signal relates to both the cost of the acquisition and the integrity (error) of our approximation.

In communications, how many basis functions we use relates to how quickly we can transmit information using a radio wave or a fiber optic cable.

In this notebook we are going to look at information representation in terms of sinusoidal basis functions, specifically, the [Discrete Cosine Transform (DCT)](https://en.wikipedia.org/wiki/Discrete_cosine_transform), which is commonly used in signal processing and image.

## Image Example

To start with, we are going to look at a public domain digital image. As the image is already digitized, we are not going to worry about how the discrete image is only an approximation of the continuous physical object.

I will refer to the inverse DCT of an image as the __spectrum__. The spectrum corresponds to the coefficients for each basis function.

I've taken the DCT of the image and then prior to taking the inverse DCT (IDCT), I've zeroed out a fraction of the spectrum. (NEED TO DEFINE SPECTRUM.) based on the slider value _kp_. _kp_ represents what fraction of the spectrum was kept (not zeroed out) starting with the DC term. So a _kp_ of zero throws out all the original data and a _kp_ of 1 keeps all the original data.

$(@bind go Button("Start/Restart"))
"""

# ╔═╡ e50c3024-140d-4312-ad8e-66b94482964b
md"""# DCT Basis Functions

DCT forms the basis of JPEG image compression. In JPEG compression the image is split into 8x8 tiles. The DCT is computed for each tile. As was demonstrated above, an image can be recognized with a high degree of certitude wihtout many of the high frequency terms. JPEG exploits this by discarding the coefficients for high frequency basis functions within the DCT for each tile.

What do these basis functions look like? For an 8x8 tile, there are 64 distinct basis functions. We can visualize these basis functions by taking the inverse DCT for a Kronecker Delta spectrum.

Plot the desired basis function by selecting the desired Kronecker Delta value δ(i,j)
"""

# ╔═╡ f90425a3-8e6f-440a-8522-5ccd5cca2797

md"""

Create a Different Kronecker Delta spectrum by changin the (i,j) vaues.

i
$(@bind i Slider(1:1:8))
j
$(@bind j Slider(1:1:8))
"""

# ╔═╡ 899a3541-9cef-48de-a03d-367223fe3100
md"""### All 64 Basis Functions"""

# ╔═╡ 99028838-babb-4d29-a400-c321c65e455d
md"""### Code cells are hidden down here"""

# ╔═╡ 85859f7b-26e2-415e-87f1-b61180449a61
images = [i for i in TestImages.remotefiles if ! contains(i, "tif") && ! contains(i, "256") && ! contains(i, "color")] ;

# ╔═╡ 0d142947-1e3c-4adc-b6ca-09c502f89f0e
begin
	go
	ind = rand(1:length(images))
	iname = popat!(images, ind)
	img = Gray.(testimage(iname));
	aimg = Float64.(img) ;
	kimg = dct(aimg) ;
	@bind kp Slider(0:0.01:1, show_value=true)
end

# ╔═╡ c4d7b864-275a-4e6f-9cc1-74138a1f07ae
function kd2(i,j)
	img = zeros((8,8))
	img[i,j] = 1
	img
end ;

# ╔═╡ 4369ef1b-4291-4b2f-8bc1-ac011080bb18
bimg = kd2(i,j) ;

# ╔═╡ 740ecf61-15d7-4b30-8ef8-e9ed339912af
md"""
### Kronecker Delta Spectrum

$(Gray.(bimg))

### Resulting Basis Function

$(Gray.(6*idct(bimg)))
"""

# ╔═╡ 6c43a6ef-41af-4343-910b-04e72fdc87fd
alg = Equalization(nbins = 256);

# ╔═╡ 2b98ae25-097e-4dd5-aa4b-01a3b06c2fc8
begin
	tmp3 = zeros(64,64) ;
	for j in 0:7
		for i in 0:7
			tmp3[i*8+1:i*8+8,j*8+1:j*8+8] =idct(kd2(i+1,j+1))
		end
	end
	imresize(adjust_histogram(Gray.(tmp3), alg), 256, 256)
end

# ╔═╡ 628877b2-6e8d-47a1-8dce-752b9d75ab56
function filter_img(kimg, p)
	sz = size(kimg)
	fsz = convert.(Int64, round.(sz .* p))
	f = zeros(sz)
	f[1:fsz[1],1:fsz[2]] .= 1
	idct(kimg .* f)
end;

# ╔═╡ 12fb095f-02a6-48c6-856a-afbc71a6ad64
fimg = filter_img(kimg, kp) ;

# ╔═╡ 48412713-7266-43dc-a49e-bab349318cce
md"""
## What do you think this image is?

Increase kp to provide more basis functions for representing the image. kp represents the fraction of the discrete cosine transform basis functions to use (extending out from the DC term. What is the minimum kp for you to recognize the image?

$(Gray.(fimg))

kp
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
ImageContrastAdjustment = "f332f351-ec65-5f6a-b3d1-319c6670881a"
ImageShow = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"

[compat]
FFTW = "~1.4.5"
ImageContrastAdjustment = "~0.3.7"
ImageShow = "~0.3.1"
Images = "~0.24.1"
Plots = "~1.22.2"
PlutoUI = "~0.7.11"
TestImages = "~1.6.1"
"""

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

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

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

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

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

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

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

[[AxisArrays]]
deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"]
git-tree-sha1 = "d127d5e4d86c7680b20c35d40b503c74b9a39b5e"
uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
version = "0.4.4"

[[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_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 = "f2202b55d816427cd385a9a4f3ffb226bee80f99"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+0"

[[CatIndices]]
deps = ["CustomUnitRanges", "OffsetArrays"]
git-tree-sha1 = "a0f80a09780eed9b1d106a1bf62041c2efc995bc"
uuid = "aafaddc9-749c-510e-ac4f-586e18779b91"
version = "0.2.2"

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

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "a851fec56cb73cfdf43762999ec72eff5b86882a"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.15.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 = "45efb332df2e86f2cb2e992239b6267d97c9e0b6"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.7"

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

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

[[ComputationalResources]]
git-tree-sha1 = "52cb3ec90e8a8bea0e62e275ba577ad0f74821f7"
uuid = "ed09eef8-17a6-5b46-8889-db040fac31e3"
version = "0.3.2"

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

[[CoordinateTransformations]]
deps = ["LinearAlgebra", "StaticArrays"]
git-tree-sha1 = "6d1c23e740a586955645500bbec662476204a52c"
uuid = "150eb455-5306-5404-9cee-2592286d6298"
version = "0.6.1"

[[CustomUnitRanges]]
git-tree-sha1 = "1a3f97f907e6dd8983b744d2642651bb162a3f7a"
uuid = "dc8bdbbb-1ca9-579f-8c36-e416f6a65cce"
version = "1.0.2"

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

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

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

[[Distances]]
deps = ["LinearAlgebra", "Statistics", "StatsAPI"]
git-tree-sha1 = "9f46deb4d4ee4494ffb5a40a27a2aced67bdd838"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.4"

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

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

[[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 = "8041575f021cba5a099a456b4163c9a08b566a02"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.1.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"

[[FFTViews]]
deps = ["CustomUnitRanges", "FFTW"]
git-tree-sha1 = "70a0cfd9b1c86b0209e38fbfe6d8231fd606eeaf"
uuid = "4f61f5a4-77b1-5117-aa51-3ab5ef4ef0cd"
version = "0.3.1"

[[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 = "3c041d2ac0a52a12a27af2782b34900d9c3ee68c"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.11.1"

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

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "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"

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

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

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

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

[[GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "ef49a187604f865f4708c90e3f431890724e9012"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.59.0+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 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

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

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

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

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

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

[[HypertextLiteral]]
git-tree-sha1 = "72053798e1be56026b81d4e2682dbe58922e5ec9"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.0"

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

[[IdentityRanges]]
deps = ["OffsetArrays"]
git-tree-sha1 = "be8fcd695c4da16a1d6d0cd213cb88090a150e3b"
uuid = "bbac6d45-d8f3-5730-bfe4-7a449cd117ca"
version = "0.3.1"

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

[[ImageAxes]]
deps = ["AxisArrays", "ImageCore", "Reexport", "SimpleTraits"]
git-tree-sha1 = "794ad1d922c432082bc1aaa9fa8ffbd1fe74e621"
uuid = "2803e5a7-5153-5ecf-9a86-9b4c37f5f5ac"
version = "0.6.9"

[[ImageContrastAdjustment]]
deps = ["ColorVectorSpace", "ImageCore", "ImageTransformations", "Parameters"]
git-tree-sha1 = "2e6084db6cccab11fe0bc3e4130bd3d117092ed9"
uuid = "f332f351-ec65-5f6a-b3d1-319c6670881a"
version = "0.3.7"

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

[[ImageDistances]]
deps = ["ColorVectorSpace", "Distances", "ImageCore", "ImageMorphology", "LinearAlgebra", "Statistics"]
git-tree-sha1 = "6378c34a3c3a216235210d19b9f495ecfff2f85f"
uuid = "51556ac3-7006-55f5-8cb3-34580c88182d"
version = "0.2.13"

[[ImageFiltering]]
deps = ["CatIndices", "ColorVectorSpace", "ComputationalResources", "DataStructures", "FFTViews", "FFTW", "ImageCore", "LinearAlgebra", "OffsetArrays", "Requires", "SparseArrays", "StaticArrays", "Statistics", "TiledIteration"]
git-tree-sha1 = "bf96839133212d3eff4a1c3a80c57abc7cfbf0ce"
uuid = "6a3955dd-da59-5b1f-98d4-e7296123deb5"
version = "0.6.21"

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

[[ImageMagick]]
deps = ["FileIO", "ImageCore", "ImageMagick_jll", "InteractiveUtils", "Libdl", "Pkg", "Random"]
git-tree-sha1 = "5bc1cb62e0c5f1005868358db0692c994c3a13c6"
uuid = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
version = "1.2.1"

[[ImageMagick_jll]]
deps = ["JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "1c0a2295cca535fabaf2029062912591e9b61987"
uuid = "c73af94c-d91f-53ed-93a7-00f77d67a9d7"
version = "6.9.10-12+3"

[[ImageMetadata]]
deps = ["AxisArrays", "ColorVectorSpace", "ImageAxes", "ImageCore", "IndirectArrays"]
git-tree-sha1 = "ae76038347dc4edcdb06b541595268fca65b6a42"
uuid = "bc367c6b-8a6b-528e-b4bd-a4b897500b49"
version = "0.9.5"

[[ImageMorphology]]
deps = ["ColorVectorSpace", "ImageCore", "LinearAlgebra", "TiledIteration"]
git-tree-sha1 = "68e7cbcd7dfaa3c2f74b0a8ab3066f5de8f2b71d"
uuid = "787d08f9-d448-5407-9aad-5290dd7ab264"
version = "0.2.11"

[[ImageQualityIndexes]]
deps = ["ColorVectorSpace", "ImageCore", "ImageDistances", "ImageFiltering", "OffsetArrays", "Statistics"]
git-tree-sha1 = "1198f85fa2481a3bb94bf937495ba1916f12b533"
uuid = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9"
version = "0.2.2"

[[ImageShow]]
deps = ["Base64", "FileIO", "ImageCore", "OffsetArrays", "Requires", "StackViews"]
git-tree-sha1 = "832abfd709fa436a562db47fd8e81377f72b01f9"
uuid = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
version = "0.3.1"

[[ImageTransformations]]
deps = ["AxisAlgorithms", "ColorVectorSpace", "CoordinateTransformations", "IdentityRanges", "ImageCore", "Interpolations", "OffsetArrays", "Rotations", "StaticArrays"]
git-tree-sha1 = "e4cc551e4295a5c96545bb3083058c24b78d4cf0"
uuid = "02fcd773-0e25-5acc-982a-7f6622650795"
version = "0.8.13"

[[Images]]
deps = ["AxisArrays", "Base64", "ColorVectorSpace", "FileIO", "Graphics", "ImageAxes", "ImageContrastAdjustment", "ImageCore", "ImageDistances", "ImageFiltering", "ImageIO", "ImageMagick", "ImageMetadata", "ImageMorphology", "ImageQualityIndexes", "ImageShow", "ImageTransformations", "IndirectArrays", "OffsetArrays", "Random", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "TiledIteration"]
git-tree-sha1 = "8b714d5e11c91a0d945717430ec20f9251af4bd2"
uuid = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
version = "0.24.1"

[[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 = "c2a145a145dc03a7620af1444e0264ef907bd44f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "0.5.1"

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

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

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

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

[[IrrationalConstants]]
git-tree-sha1 = "f76424439413893a832026ca355fe273e93bce94"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.0"

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

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

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

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

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

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

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

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

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

[[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 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

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

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

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

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

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

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

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

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

[[LogExpFunctions]]
deps = ["ChainRulesCore", "DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "34dc30f868e368f8a17b728a1238f3fcda43931a"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.3"

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

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

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

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

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

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

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

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "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 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[Netpbm]]
deps = ["ColorVectorSpace", "FileIO", "ImageCore"]
git-tree-sha1 = "09589171688f0039f13ebe0fdcc7288f50228b52"
uuid = "f09324ee-3d7c-5217-9330-fc30815ba969"
version = "1.0.1"

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

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

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

[[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 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+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"

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

[[PaddedViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "646eed6f6a5d8df6708f15ea7e02a7a2c4fe4800"
uuid = "5432bcbf-9aad-5242-b902-cca2824c8663"
version = "0.5.10"

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

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

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

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

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

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

[[PlutoUI]]
deps = ["Base64", "Dates", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "0c3e067931708fa5641247affc1a1aceb53fff06"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.11"

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

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

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

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

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

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

[[RangeArrays]]
git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5"
uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d"
version = "0.3.2"

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

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

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

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

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

[[Rotations]]
deps = ["LinearAlgebra", "StaticArrays", "Statistics"]
git-tree-sha1 = "2ed8d8a16d703f900168822d83699b8c3c1a5cd8"
uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc"
version = "1.0.2"

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

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

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

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

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

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

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

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

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

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

[[StringDistances]]
deps = ["Distances"]
git-tree-sha1 = "a4c05337dfe6c4963253939d2acbdfa5946e8e31"
uuid = "88034a9c-02f8-509d-84a9-84ec65e18404"
version = "0.10.0"

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

[[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 = "1162ce4a6c4b7e31e0e6b14486a6986951c73be9"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.2"

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

[[TestImages]]
deps = ["AxisArrays", "ColorTypes", "FileIO", "OffsetArrays", "Pkg", "StringDistances"]
git-tree-sha1 = "db28237376a6b7ae9c9fe05880ece0ab8bb90b75"
uuid = "5e47fb64-e119-507b-a336-dd2b206d9990"
version = "1.6.1"

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

[[TiledIteration]]
deps = ["OffsetArrays"]
git-tree-sha1 = "5683455224ba92ef59db72d10690690f4a8dc297"
uuid = "06e1c1a7-607b-532d-9fad-de7d9aa2abac"
version = "0.3.1"

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

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

[[UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

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

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

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

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

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

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

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

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

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

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

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

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

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

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

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

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

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

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

[[Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

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

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

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

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

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

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

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

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

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

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

[[libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "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"

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

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

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

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "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"

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

# ╔═╡ Cell order:
# ╟─09fc6764-2050-4276-8a14-3596368d0c32
# ╟─48412713-7266-43dc-a49e-bab349318cce
# ╟─0d142947-1e3c-4adc-b6ca-09c502f89f0e
# ╟─e50c3024-140d-4312-ad8e-66b94482964b
# ╟─f90425a3-8e6f-440a-8522-5ccd5cca2797
# ╟─740ecf61-15d7-4b30-8ef8-e9ed339912af
# ╟─899a3541-9cef-48de-a03d-367223fe3100
# ╟─2b98ae25-097e-4dd5-aa4b-01a3b06c2fc8
# ╟─99028838-babb-4d29-a400-c321c65e455d
# ╟─85859f7b-26e2-415e-87f1-b61180449a61
# ╟─12fb095f-02a6-48c6-856a-afbc71a6ad64
# ╟─f66e452c-97db-11eb-23fc-bd95da10e2d6
# ╟─4369ef1b-4291-4b2f-8bc1-ac011080bb18
# ╟─c4d7b864-275a-4e6f-9cc1-74138a1f07ae
# ╟─adaa78fa-d805-45e6-ba5f-d91a5d4823d6
# ╟─6c43a6ef-41af-4343-910b-04e72fdc87fd
# ╟─628877b2-6e8d-47a1-8dce-752b9d75ab56
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
module ChainRulesCore
using Base.Broadcast: broadcasted, Broadcasted, broadcastable, materialize, materialize!

export frule, rrule
export @scalar_rule, @thunk
export canonicalize, extern, unthunk
export Composite, DoesNotExist, InplaceableThunk, One, Thunk, Zero, AbstractZero, AbstractThunk
export NO_FIELDS

include("compat.jl")
include("debug_mode.jl")

include("differentials/abstract_differential.jl")
include("differentials/abstract_zero.jl")
include("differentials/one.jl")
include("differentials/thunks.jl")
include("differentials/composite.jl")

include("differential_arithmetic.jl")

include("rules.jl")
include("rule_definition_tools.jl")

end # module

ext: jl


text:
# Clayton, N. S. and Dickinson, A. (1999), Memory for the Content of Caches by
# Scrub Jays (Aphelocoma coerulescens), Journal of Experimental Psychology:
# Animal Behavior Processes, 1: 82 - 91

function _summarize(::Experiment{:Clayton99A_exp1}, data)
    combine(groupby(data, [:trial, :tray, :action]),
       df -> DataFrame(μ = mean(df.counts),
                       sem = sem(df.counts),
                       n = length(df.counts)))
end
function statistical_tests(exp::Experiment{:Clayton99A_exp1}, data)
    tests = Test[]
    id = "4h overall cache"
    push!(tests, Test(id,
                      splitplotanova(@where(data, :trial .== 4, :action .== "cache"),
                                     exp.tests[id].locals,
                                     betweenfactors = [:order, :foodtype, :pilfering],
                                     withinfactors = [:tray],
                                     id = :id, data = :counts),
                      exp.tests))
    id = "4h overall inspect"
    push!(tests, Test(id,
                      splitplotanova(@where(data, :trial .== 4, :action .== "inspect"),
                                     exp.tests[id].locals,
                                     betweenfactors = [:order, :foodtype, :pilfering],
                                     withinfactors = [:tray],
                                     id = :id, data = :counts),
                      exp.tests))
    id = "172h overall cache"
    push!(tests, Test(id,
                      splitplotanova(@where(data, :trial .== 172, :action .== "cache"),
                                     exp.tests[id].locals,
                                     betweenfactors = [:order, :foodtype],
                                     withinfactors = [:tray],
                                     id = :id, data = :counts),
                      exp.tests))
    id = "172h overall inspect"
    push!(tests, Test(id,
                      splitplotanova(@where(data, :trial .== 172, :action .== "inspect"),
                                     exp.tests[id].locals,
                                     betweenfactors = [:order, :foodtype],
                                     withinfactors = [:tray],
                                     id = :id, data = :counts),
                      exp.tests))
    TestCollection(tests)
end
function run!(::Experiment{:Clayton99A_exp1}, models)
    results = DataFrame(trial = Int[], tray = String[],
                        action = String[], foodtype = String[],
                        order = String[], pilfering = Bool[],
                        id = Int[], counts = Int[])
    traylabel = (foodtype, id) -> foodtype == Peanut && id > 8 ||
                                  foodtype == Kibble && id <= 8 ? "same" : "different"
    for trial in 1:2
        for id in 1:14 # 2 excluded in trial 1
        m = models[id]
            remove!(m, Any)     # 10:00
            wait!(m, 4u"hr")
            trays = [Tray(i) for i in 1:2]
            foodtypes = [Peanut, Kibble]
            id % 4 < 2 && reverse!(foodtypes)
            ispilfer = (trial == 2 || id % 2 == 0)
            prefed = id > 8 ? PowderedPeanut : PowderedKibble
            for (i, foodtype) in enumerate(foodtypes)
                add!(m, trays[i])
                add!(m, foodtype, 50)
                wait!(m, 15u"minute")
                remove!(m, Any)
                push!(results, [trial == 1 ? 4 : 172,
                                traylabel(foodtype, id), "cache",
                                string(prefed), string(foodtypes[1]),
                                ispilfer,
                                id, countcache(trays[i], foodtype)])
            end
            if trial == 1
                wait!(m, 3.5u"hr")
            else
                add!(m, MaintenanceDiet)
                wait!(m, 167.5u"hr")
                remove!(m, Any)
                wait!(m, 4u"hr")
            end
            add!(m, prefed, 50)
            wait!(m, 30u"minute")
            (trial == 2 || id % 2 == 0) && pilfer!.(trays)
            remove!(m, Any)
            for i in 1:2 add!(m, trays[i]) end
            inspectionobserver = InspectionObserver()
            add!(m, inspectionobserver)
            wait!(m, 15u"minute")
            for (i, foodtype) in enumerate(foodtypes)
                push!(results, [trial == 1 ? 4 : 172,
                                traylabel(foodtype, id), "inspect",
                                string(prefed), string(foodtypes[1]),
                                ispilfer,
                                id, countinspections(inspectionobserver, trays[i])])
            end
            remove!(m, Any)
            add!(m, MaintenanceDiet)
            wait!(m, 15u"minute" + 15u"hr" + 6u"d")
        end
    end
    results
end

function _summarize(::Experiment{:Clayton99A_exp2}, data)
    combine(groupby(data, [:side, :action, :tray]),
       df -> DataFrame(μ = mean(df.counts),
                       sem = sem(df.counts),
                       n = length(df.counts)))
end
function statistical_tests(exp::Experiment{:Clayton99A_exp2}, data)
    tests = Test[]
    id = "inspect"
    push!(tests, Test(id,
                      splitplotanova(data,
                                     exp.tests[id].locals,
                                     betweenfactors = [:foodtype],
                                     withinfactors = [:tray, :side],
                                     id = :id, data = :counts),
                      exp.tests))
    for g in groupby(data, :side)
        id = "inspect $(g.side[1])"
        push!(tests, Test(id,
                          splitplotanova(g,
                                         exp.tests[id].locals,
                                         betweenfactors = :foodtype,
                                         withinfactors = :tray,
                                         id = :id, data = :counts),
                         exp.tests))
    end
    for g in groupby(data, :tray)
        id = "inspect $(g.tray[1])"
        push!(tests, Test(id,
                          splitplotanova(g,
                                         exp.tests[id].locals,
                                         betweenfactors = :foodtype,
                                         withinfactors = :side,
                                         id = :id, data = :counts),
                         exp.tests))
    end
    TestCollection(tests)
end
function run!(::Experiment{:Clayton99A_exp2}, models)
    results = DataFrame(tray = String[], action = String[],
                        foodtype = String[],
                        side = String[],
                        id = Int[], counts = Int[])
    for id in 1:18
        m = models[id]
        remove!(m, Any)
        wait!(m, 4u"hr")
        trays = [Tray(i) for i in 1:4] # left and right hand side of a tray are treated as different trays.
        for i in 1:4
            add!(m, trays[i])
            if i <= 2
                add!(m, Peanut, 50)
            else
                add!(m, Kibble, 50)
            end
            wait!(m, 15u"minute", m -> (countcache(trays[i]) >= 3))
            remove!(m, Any)
        end
        # if sum(countcache.(trays)) < 12 continue end # drop bird
        wait!(m, 3u"hr")
        if id <= 9
            first = 2; second = 3
        else
            first = 3; second = 2
        end
        add!(m, trays[first]) # tray B Peanuts
        wait!(m, 15u"minute")
        add!(m, trays[second]) # tray A Kibble
        wait!(m, 15u"minute")
        remove!(m, Any)
        if id % 2 == 0
            add!(m, PowderedPeanut, 50)
        else
            add!(m, PowderedKibble, 50)
        end
        wait!(m, 30u"minute")
        remove!(m, Any)
        add!(m, trays)
        inspectionobserver = InspectionObserver()
        add!(m, inspectionobserver)
        wait!(m, 15u"minute")
        for i in 1:4
            push!(results, [(id % 2 == 0 && i <= 2 || id % 2 == 1 && i > 2 ? "same" : "different"),
                            "inspect",
                            id % 2 == 0 ? "Peanut" : "Kibble", # prefed
                            (i == 1 || i == 4 ? "intact" : "recovered"),
                            id,
                            countinspections(inspectionobserver, trays[i])])
        end
    end
    results
end


text:
struct RelaxAllInOne
    max_width::Int
    merge
    sort_by  # TODO: add default implementation (distance)
end

function Diderot.process(
    relax::RelaxAllInOne, layer::Layer{S,D,V}
) where {S,D,V}
    if length(layer) <= relax.max_width
        return layer
    end

    # Sort states (best ones first).
    candidates = collect(layer)
    sort!(candidates, by=relax.sort_by)

    # Keep first (width - 1) unchanged.
    new_layer = Layer{S,D,V}(Dict(candidates[1:(relax.max_width - 1)]), false)

    # Merge the remaining states into a single relaxed state.
    rest = @view candidates[relax.max_width:end]
    merged_state = foldl(relax.merge, first.(rest))

    # Use predecessor for longest distance of any merged state.
    index = argmax(map(pair -> pair.second.distance, rest))
    merged_node = rest[index].second
    new_node = Node{S,D,V}(merged_node.distance, merged_node.inarc, false)
    new_layer[merged_state] = new_node

    return new_layer
end


text:
module FunctionalControlFlow

export @functionalize

using MacroTools: @capture, prewalk, postwalk, isexpr, rmlines, unblock, block

function vars(ex; callables=false, types=false)
    isexpr(ex, Number, QuoteNode) && return Symbol[]
    isexpr(ex, Symbol) && return ex == :nothing ? Symbol[] : [ex]
    ex = ex |> rmlines |> unblock
    @capture(ex, a_.b_) && return vars(a)
    params = Symbol[]
    args = !callables && isexpr(ex, :call) ||
               !types && isexpr(ex, :curly) ? ex.args[2:end] : ex.args
    for x in args
        append!(params, vars(x))
    end
    return params
end
function vars(ex1, ex2; callables=false, types=false)
    params = vars(ex1; callables=callables, types=types)
    append!(params, vars(ex2; callables=callables, types=types))
    unique!(params)
    return params
end

defined(param::Symbol) = :($(Expr(:isdefined, param)) ? $param : nothing)
defined(params::Expr) = Expr(:tuple, (defined(p) for p in params.args)...)

function func(ex, params; mut=true)
    params = :(ret, $(params...))
    ex = block(ex)
    if mut
        ex.args[end] = :(ret = $(ex.args[end]))
        push!(ex.args, :(return $params))
    end
    return Expr(:(->), params, ex)
end
func(ex; mut=true) = func(ex, unique(vars(ex)); mut=mut)

function _while(cond, body, params)
    while cond(params...)
        params = body(params...)
    end
    return params
end

function _if(cond, body, params)
    if cond
        return body(params...)
    end
    return params
end
# TODO consider allowing params1 and params2
function _if(cond, body1, body2, params)
    if cond
        return body1(params...)
    else
        return body2(params...)
    end
end

macro functionalize(ex)
    #TODO break, continue, return
    #continue requires adding conditionals
    #break is continue plus setting an &&-ed while condition to false
    #return from a while is break plus setting a return expr
    postwalk(ex) do x
        isexpr(x, :elseif) && (x.head = :if)
        return if @capture(x, while c_ b_ end |
                              for i_ in v_ b_ end | for i_ = v_ b_ end)
            if isexpr(x, :for)
                c = :(next !== nothing)
                b.args = [:(($i, state) = next), b.args...,
                          :(next = iterate(it, state))]
            end
            params = vars(c, b)
            cf, bf = func(c, params; mut=false), func(b, params)
            ret = quote
                $(bf.args[1]) = _while($cf, $bf, $(defined(bf.args[1])))
                $(bf.args[1].args[1])
            end
            if isexpr(x, :for)
                pushfirst!(ret.args, :(it = $v), :(next = iterate(it)))
            end
            ret
        elseif @capture(x, if c_ b1_ else b2_ end)
            params = vars(b1, b2)
            f1, f2 = func(b1, params), func(b2, params)
            quote
                $(f1.args[1]) = _if($c, $f1, $f2, $(defined(f1.args[1])))
                $(f1.args[1].args[1])
            end
        elseif @capture(x, if c_ b_ end | c_ && b_)
            f = func(b)
            quote
                $(f.args[1]) = _if($c, $f, $(defined(f.args[1])))
                $(f.args[1].args[1])
            end
        elseif @capture(x, a_ && b_)
            f = func(b)
            quote
                c = $a
                $(f.args[1]) = _if(c, $f, $(defined(f.args[1])))
                c ? $(f.args[1].args[1]) : false
            end
        elseif @capture(x, a_ || b_)
            f = func(b)
            quote
                c = !$a
                $(f.args[1]) = _if(c, $f, $(defined(f.args[1])))
                c ? $(f.args[1].args[1]) : true
            end
        elseif isexpr(x, :function)
            x.args[1].args[1] = esc(x.args[1].args[1])
            x
        else
            x
        end
    end
end

end #module


text:
# Extract the matrix diagonal
Base.diag{T}(dm::DataMatrix{T}) = DataArray(diag(dm.data), diag(dm.na))


text:
import Base: showerror
import .ExpressionExplorer: FunctionName, join_funcname_parts

abstract type ReactivityError <: Exception end

struct CyclicReferenceError <: ReactivityError
	syms::Set{Symbol}
end

function CyclicReferenceError(topology::NotebookTopology, cycle::AbstractVector{Cell})
	CyclicReferenceError(cyclic_variables(topology, cycle))
end

struct MultipleDefinitionsError <: ReactivityError
	syms::Set{Symbol}
end

function MultipleDefinitionsError(topology::NotebookTopology, cell::Cell, all_definers)
	competitors = setdiff(all_definers, [cell])
	defs(c) = topology.nodes[c].funcdefs_without_signatures ∪ topology.nodes[c].definitions
	MultipleDefinitionsError(
		union((defs(cell) ∩ defs(c) for c in competitors)...)
	)
end

hint1 = "Combine all definitions into a single reactive cell using a `begin ... end` block."
hint2 = "Wrap all code in a `begin ... end` block."

# TODO: handle case when cells are in cycle, but variables aren't
function showerror(io::IO, cre::CyclicReferenceError)
	print(io, "Cyclic references among $(join(cre.syms, ", ", " and ")).\n$hint1")
end

function showerror(io::IO, mde::MultipleDefinitionsError)
	print(io, "Multiple definitions for $(join(mde.syms, ", ", " and ")).\n$hint1") # TODO: hint about mutable globals
end

"Send `error` to the frontend without backtrace. Runtime errors are handled by `WorkspaceManager.eval_format_fetch_in_workspace` - this function is for Reactivity errors."
function relay_reactivity_error!(cell::Cell, error::Exception)
	body, mime = PlutoRunner.format_output(CapturedException(error, []))
	cell.output = CellOutput(
		body=body,
		mime=mime,
		rootassignee=nothing,
		last_run_timestamp=time(),
		persist_js_state=false,
	)
	cell.published_objects = Dict{String,Any}()
	cell.runtime = nothing
	cell.errored = true
end


text:
# Tests that trait dispatch for the BaseTraits does not incur a
# overhead.

# Dict with base-traits to check using value[1] as type and value[2]
# as number of lines allowed in llvm code
cutoff = 5
basetrs = [:IsConcrete=>:Int,
           :IsBits=>:Int,
           :IsImmutable=>:Int,
           :IsContiguous=>:(SubArray{Int64,1,Array{Int64,1},Tuple{Array{Int64,1}},false}),
           :IsIndexLinear=>:(Vector{Int}),
           :IsAnything=>:Int,
           :IsNothing=>:Int,
           :IsCallable=>:(typeof(sin))]

for (bt, tp) in basetrs
    @test @eval @check_fast_traitdispatch $bt $tp true
end

# IsIterator used dynamic dispatch as hasmethod is not inferable,
# see https://github.com/mauro3/SimpleTraits.jl/issues/40.
println("""One statement of "Number of llvm code lines X but should be Y." is expected:""")
@test !(@eval @check_fast_traitdispatch IsIterator Dict{Int,Int} true)


text:
struct Womack <: DiscreteMultivariateDistribution
    D::Int
    ζ::Float64
    p::Vector{Float64}
    punnormalized::Vector{Float64}
    function Womack(D::Int, ζ::Float64)
        p = big.([zeros(D); 1.0])
        for d1 in (D - 1):-1:0
            for d2 in 1:(D - d1)
                p[1 + d1] += ζ * p[1 + d1 + d2] * binomial(big(d1 + d2), big(d1))
            end
        end
        p /= sum(p)
        punnormalized = copy(p)
        for d1 in 1:D
            p[d1] /= binomial(big(D), big(d1 - 1))
        end
        return new(D, ζ, p, punnormalized)
    end
end

function pdf(d::Womack, γ::Vector{Bool})
    return d.p[sum(γ) + 1]
end

function logpdf(d::Womack, γ::Vector{Bool})
    return log(pdf(d, γ))
end


text:
function vertesi_nodes(n::S,domain = [1.0,-1.0]) where {S <: Integer}

  if n <= 0
    error("The number of nodes must be positive.")
  end

  nodes = zeros(n)

  if isodd(n)
    nodes[Int((n-1)/2)+1] = (domain[1]+domain[2])/2.0
  end

  if n == 1

    return nodes

  elseif n == 2

    nodes[1] = domain[2]
    nodes[n] = domain[1]

    return nodes

  else

    nodes[1] = domain[2]
    nodes[n] = domain[1]

    for i = 2:div(n,2)
      x = -cos((pi/2)*(2(i-1)+1.0)/(n))/cos((pi/(2*(n)))*(1.0+1/(4*log(n))))*(domain[1]-domain[2])/2.0
      nodes[i]     = (domain[1]+domain[2])/2.0 + x
      nodes[n-i+1] = (domain[1]+domain[2])/2.0 - x
    end

    return nodes

  end

end

max_stars_repo_name: RJDennis/ChebyshevApprox

max_issues_repo_name: RJDennis/ChebyshevApprox

max_forks_repo_name: RJDennis/ChebyshevApprox


text:
# the packages we need
include("CostumeFunctions.jl")

using Gtk, Graphics, Logging, Printf

# the main window
win = GtkWindow("SO(3)")

render_scale = 50

function init_canvas(h,w)
    # create the drawing canvas
    c = @GtkCanvas(h,w)
    # create the initial drawing inside a try/catch loop
    @guarded draw(c) do widget
        #  draw the background with the canvas drawing context
        # the code for this comes later
        draw_the_canvas(c)
    end

    show(c)
    return c
end

# make the canvas
the_canvas = init_canvas(800,800)

# --------- part 2 -------------
# define all the widgets

# a widget for status messages that we define at the beginning so we can use it from the callback
msg_label = GtkLabel("No message at this time")

rotation_matrix = [0 0 0; 0 0 0; 0 0 0]

# defaults
default_value = Dict("phi" => 0, "v_x" => 1, "v_y" => 0, "v_z" => 0, "alpha" => 70, "q_s" => 0,  "q_x" => 0,  "q_y" => 0,  "q_z" => 0)

# an array to store the entry boxes
entry_list = []

# an array to store sliders (same functionality as entry_list)
slider_list = []

# an array of labels that we use to display normalized inputs,
# and which also gets modified from the callback
normalized_labels = []

#Coordinates origin
origin3D = [600 600 600]

function find_by_name(list, name)
    for item in list
        if get_gtk_property(item, :name, String) == name
            return item
        end
    end
    @warn name, "not found in list"
    @warn "available names are"
    for item in list
        @warn get_gtk_property(item, :name, String)
    end
end

function output_normalized(label, value)
    GAccessor.text(find_by_name(normalized_labels, label), @sprintf("%3.2f", value))
end

function output_normalized_string(label, value)
    GAccessor.text(find_by_name(normalized_labels, label), value)
end

function normalize_v()
    v_x = read_original_box("v_x")
    v_y = read_original_box("v_y")
    v_z = read_original_box("v_z")

    norm = sqrt(v_x*v_x + v_y*v_y + v_z*v_z)

    output_normalized("v_x_normalized", v_x / norm)
    output_normalized("v_y_normalized", v_y / norm)
    output_normalized("v_z_normalized", v_z / norm)
end

function normalize_quat()

    # Read the current quaternion
    q_s = read_original_box("q_s")
    q_x = read_original_box("q_x")
    q_y = read_original_box("q_y")
    q_z = read_original_box("q_z")

    q = Quaternions.Quaternion(q_s, q_x, q_y, q_z, false)

    # Normalize the current quaternion
    q = q/abs(q)

    # Update normalized labels
    output_normalized("q_s_normalized", q.s)
    output_normalized("q_x_normalized", q.v1)
    output_normalized("q_y_normalized", q.v2)
    output_normalized("q_z_normalized", q.v3)
end

function normalize_alpha()
    output_normalized("alpha_normalized", read_slider_box("alpha"))
end

# Updates both the quaternion and rotation matrix based on the current axis and angle
function update_quat_rotation_matrix()

    # Read the current axis and angle
    vx = read_normalized_label("v_x_normalized")
    vy = read_normalized_label("v_y_normalized")
    vz = read_normalized_label("v_z_normalized")
    a = read_normalized_label("alpha_normalized")

    # Update normalized quaternion labels based on the current axis and angle
    q = axis_angle_to_quat(EulerAngleAxis(a, [vx; vy; vz]))
    output_normalized("q_s_normalized", q.s)
    output_normalized("q_x_normalized", q.v1)
    output_normalized("q_y_normalized", q.v2)
    output_normalized("q_z_normalized", q.v3)

    matrix_from_quat = quat_to_mat(q)

    variable_values = ["x", "y", "z"]

    # Update current rotation matrix based on the normalized quaternion
    for i = 1:3
        for j = 1:3
            item_n = string(variable_values[i]) * string(j)
            output_normalized("matrix_" * item_n ,matrix_from_quat[i, j])
        end
    end

end

# Updates both the rotation angle, the axis and the angle based on the current quaternion
function update_rotation_matrix_axis_angle()
    # Read current normalized quaternion
    q_s = read_normalized_label("q_s_normalized")
    q_x = read_normalized_label("q_x_normalized")
    q_y = read_normalized_label("q_y_normalized")
    q_z = read_normalized_label("q_z_normalized")

    q = Quaternions.Quaternion(q_s, q_x, q_y, q_z, false)

    matrix_from_quat = quat_to_mat(q)

    variable_values = ["x", "y", "z"]

    # Update current rotation matrix
    for i = 1:3
        for j = 1:3
            item_n = string(variable_values[i]) * string(j)
            output_normalized("matrix_" * item_n ,matrix_from_quat[i, j])
        end
    end
    # Update current axis angle normalized values
    vector_angle = quat_to_axis_angle(q)
    v = [vector_angle.v[1] vector_angle.v[2] vector_angle.v[3]]
    output_normalized("v_x_normalized", v[1])
    output_normalized("v_y_normalized", v[2])
    output_normalized("v_z_normalized", v[3])
    output_normalized("alpha_normalized", rad2deg(vector_angle.a))

    # Draw changes on canvas
    draw_the_canvas(the_canvas)
    reveal(the_canvas)
end

# Callback function for slider_boxes
function slider_box_callback(widget)
    # who called us?
    name = get_gtk_property(widget, :name, String)

    # If we are updating alpha...
    if name[1] == 'a'
        # ... save current value as noramlized alpha...
        normalize_alpha()
        # ... and update quaternion and rotation matrix to current alpha value
        update_quat_rotation_matrix()
    end
    # actually draw the changes
    draw_the_canvas(the_canvas)
    reveal(the_canvas)
end

function entry_box_callback(widget)
    # who called us?
    name = get_gtk_property(widget, :name, String)
    text = get_gtk_property(widget, :text, String)

    # trumpet this out to the world
    GAccessor.text(msg_label, name * " changed to " * text)

    # change the correct normalized output
    if name[1] == 'v'
        normalize_v()
        # Update quaternion and rotation matrix values based on the axis values
        update_quat_rotation_matrix()
    elseif name[1] == 'q'
        normalize_quat()
        # Update rotation matrix, axis and angle values based on current quaternion
        update_rotation_matrix_axis_angle()
    end

    # actually draw the changes
    draw_the_canvas(the_canvas)
    reveal(the_canvas)
end

function slider_box(label_string, min, max)
    # set up the entry
    entry = GtkScale(false, min:max)
    set_gtk_property!(entry,:name, label_string)

    push!(slider_list, entry)

    # make it communicate changes
    signal_connect(slider_box_callback, entry, "value-changed")

    # make and return the containing box
    hbox = GtkButtonBox(:h)
    push!(hbox, entry)

    return hbox
end

function entry_box(label_string)
    # set up the entry
    entry = GtkEntry()
    set_gtk_property!(entry,:width_chars, 5)
    set_gtk_property!(entry,:max_length, 5)
    set_gtk_property!(entry,:name, label_string)

    default_text = string(default_value[label_string])
    GAccessor.text(entry,default_text)
    push!(entry_list, entry)

    # make it communicate changes
    signal_connect(entry_box_callback, entry, "changed")

    # set up the label and normalized output
    label = GtkLabel(label_string)
    normalized_output = GtkLabel(default_text)
    set_gtk_property!(normalized_output, :name, label_string * "_normalized")

    # make and return the containing box
    hbox = GtkButtonBox(:h)
    push!(hbox, label)
    push!(hbox, entry)
    push!(hbox, normalized_output)

    # export the normalized output for further use
    push!(normalized_labels, normalized_output)

    return hbox
end

function bold_label(label_string)
    label = GtkLabel("")
    GAccessor.markup(label, """<b>""" * label_string * """</b>""")
    return label
end

function phi_box()
    vbox = GtkBox(:v)
    hbox = GtkBox(:h)
    push!(vbox, bold_label("Coordinate rotation"))
    push!(hbox, GtkLabel("\t   phi"))
    push!(hbox, GtkLabel("\t"))
    push!(hbox, slider_box("phi", 0, 360))
    push!(vbox, hbox)
    return vbox
end

function quat_box()
    vbox = GtkBox(:v)

    push!(vbox, bold_label("Rotation Quaternion"))

    for label in ["q_s", "q_x", "q_y", "q_z"]
        push!(vbox, entry_box(label))
    end

    return vbox
end

function vector_angle_box()
    vbox = GtkBox(:v)
    hbox = GtkBox(:h)
    push!(vbox, bold_label("Axis"))

    for label in ["v_x", "v_y", "v_z"]
        push!(vbox, entry_box(label))
    end

    push!(vbox, GtkLabel(""))

    push!(vbox, bold_label("Angle"))

    push!(hbox, GtkLabel("\t alpha"))
    push!(hbox, GtkLabel("\t"))
    push!(hbox, slider_box("alpha", 0, 180))
    # set up the label and normalized output
    label = GtkLabel("alpha")
    normalized_output = GtkLabel("0")
    set_gtk_property!(normalized_output, :name, "alpha_normalized")

    # export the normalized output for further use
    push!(normalized_labels, normalized_output)

    push!(hbox, normalized_output)

    push!(vbox, hbox)

    return vbox
end

function rotation_matrix_label()
    vbox = GtkBox(:v)

    hbox = GtkBox(:h)

    push!(vbox, bold_label("Rotation Matrix"))

    variable_name = ["x", "y", "z"]

    # Set up rotation matrix label
    for i = 1:3
        separation = GtkLabel("\t\t")
        columnBox = GtkBox(:v)
        push!(columnBox, GtkLabel(variable_name[i]))
        push!(hbox, separation)
        push!(hbox, columnBox)
        for j = 1:3
            # Set labels with name "matrix_xj", "matrix_yj", "matrix_zj"
            item = GtkLabel("0.00")
            item_num = string(variable_name[i]) * string(j)
            # Set property to find later
            set_gtk_property!(item, :name, "matrix_" * item_num)
            push!(normalized_labels, item)
            push!(columnBox, item)
        end
    end

    push!(vbox, hbox)

    return vbox

end

# Now put everything into the window,
# including the canvas

function init_window(win, canvas)

    # make a vertically stacked box for the data entry widgets
    control_box = GtkBox(:v)
    push!(control_box, phi_box())
    push!(control_box, GtkLabel(""))
    push!(control_box, vector_angle_box())
    push!(control_box, GtkLabel(""))
    push!(control_box, quat_box())
    push!(control_box, GtkLabel(""))
    push!(control_box, rotation_matrix_label())
    push!(control_box, GtkLabel(""))
    push!(control_box, msg_label)

    # make another box for the drawing canvas
    canvas_box = GtkBox(:v)
    push!(canvas_box, canvas)

    # make a containing box that will stack the widgets and the canvas side by side
    global_box = GtkBox(:h)
    push!(global_box, control_box)
    push!(global_box, GtkLabel("   ")) # a very basic separator
    push!(global_box, canvas_box)

    # put it all inside the window
    push!(win, global_box)

end

# --------- part 3 -------------
# now we make the canvas interactive

function read_box(name, from_which_list, what)
    the_box = find_by_name(from_which_list, name)
    result = parse(Float64, get_gtk_property(the_box, what, String))
    return result
end

function read_original_box(name)
    return read_box(name, entry_list, :text)
end

function read_normalized_label(name)
    return read_box(name, normalized_labels, :label)
end

function read_slider_box(name)
    # Read slider box searching on slider_list
    the_box = find_by_name(slider_list, name)
    result = Gtk.GAccessor.value(the_box)
    return result
end

# Draw the axis at the end of the current vector
function draw_vector_axis(origin2D, position, R1, R2, R3, alpha, ctx, scale)
    #Transfrom alpha to radians
    alpha = deg2rad(alpha)

    # Rescale the three axis
    R1 = rescale_transalte_vector(R1, position*alpha, scale)
    R2 = rescale_transalte_vector(R2, position*alpha, scale)
    R3 = rescale_transalte_vector(R3, position*alpha, scale)

    # Rotate them on current alpha properties
    R1 = rotate_phi(R1, rad2deg(alpha), position)
    R2 = rotate_phi(R2, rad2deg(alpha), position)
    R3 = rotate_phi(R3, rad2deg(alpha), position)

    # Convert them to 2D
    R1 = to_2d(R1)
    R2 = to_2d(R2)
    R3 = to_2d(R3)

    position = to_2d(position)

    #Draw the entire axis
    # Set line
    set_line_width(ctx, 3)
    set_source_rgb(ctx, 0, 0, 1)
    # Move to Origin
    move_to(ctx, origin2D[1] + position[1] *alpha * render_scale, origin2D[2] - position[2]*alpha  * render_scale)
    line_to(ctx, origin2D[1] + R1[1] * render_scale, origin2D[2] - R1[2] * render_scale)
    stroke(ctx)
    # Circle to determine direction
    circle(ctx, origin2D[1] + R1[1] * render_scale, origin2D[2] - R1[2] * render_scale,3)
    fill(ctx)

    # Repeat on the other two vectors
    set_line_width(ctx, 3)
    set_source_rgb(ctx, 1, 0, 0)
    move_to(ctx , origin2D[1] + position[1]*alpha * render_scale, origin2D[2] - position[2] *alpha* render_scale)
    line_to(ctx, origin2D[1] + R2[1] * render_scale, origin2D[2] - R2[2] * render_scale)
    stroke(ctx)

    circle(ctx, origin2D[1] + R2[1] * render_scale, origin2D[2] - R2[2] * render_scale, 3)
    fill(ctx)

    set_line_width(ctx, 3)
    set_source_rgb(ctx, 0, 1, 0)
    move_to(ctx, origin2D[1] + position[1]*alpha  * render_scale, origin2D[2] - position[2]*alpha * render_scale)
    line_to(ctx, origin2D[1] + R3[1] * render_scale, origin2D[2] - R3[2] * render_scale)
    stroke(ctx)

    circle(ctx, origin2D[1] + R3[1] * render_scale, origin2D[2] - R3[2] * render_scale, 3)
    fill(ctx)

end

# Draw the axis vectors of the axonometry
function draw_axis(origin2D, R1, R2, R3, ctx)
    # Set line
    set_line_width(ctx, 5)
    set_source_rgb(ctx, 0, 0, 1)
    # Move to Origin
    move_to(ctx, origin2D[1], origin2D[2])
    line_to(ctx, origin2D[1] + R1[1] * render_scale, origin2D[2] - R1[2] * render_scale)
    stroke(ctx)
    # Circle to determine direction
    circle(ctx, origin2D[1] + R1[1] * render_scale, origin2D[2] - R1[2] * render_scale, 5)
    fill(ctx)

    # Repeat on the other two vectors
    set_line_width(ctx, 5)
    set_source_rgb(ctx, 1, 0, 0)
    move_to(ctx , origin2D[1], origin2D[2])
    line_to(ctx, origin2D[1] + R2[1] * render_scale, origin2D[2] - R2[2] * render_scale)
    stroke(ctx)

    circle(ctx, origin2D[1] + R2[1] * render_scale, origin2D[2] - R2[2] * render_scale, 5)
    fill(ctx)

    set_line_width(ctx, 5)
    set_source_rgb(ctx, 0, 1, 0)
    move_to(ctx, origin2D[1], origin2D[2])
    line_to(ctx, origin2D[1] + R3[1] * render_scale, origin2D[2] - R3[2] * render_scale)
    stroke(ctx)

    circle(ctx, origin2D[1] + R3[1] * render_scale, origin2D[2] - R3[2] * render_scale, 5)
    fill(ctx)

end

function draw_sphere(origin2D, R1, R2, R3, ctx)
    #Create 3 circles, two around R1 using R2 and R3 as axis
    # And the third using R2 or R3 using R1 as axis

    for i = 0:+2:358
        pointR = to_2d(rotate_phi(R1, i, R2))
        set_source_rgb(ctx, 1, 0, 0)
        circle(ctx, origin2D[1] + pointR[1] * render_scale * pi,  origin2D[2] - pointR[2] * render_scale * pi, 1)
        fill(ctx)

        pointG = to_2d(rotate_phi(R1, i, R3))
        set_source_rgb(ctx, 0, 1, 0)
        circle(ctx, origin2D[1] + pointG[1] * render_scale * pi,  origin2D[2] - pointG[2] * render_scale * pi, 1)
        fill(ctx)

        pointB = to_2d(rotate_phi(R2, i, R1))
        set_source_rgb(ctx, 0, 0 , 1)
        circle(ctx, origin2D[1] + pointB[1] * render_scale * pi,  origin2D[2] - pointB[2] * render_scale * pi, 1)
        fill(ctx)
    end

end

function draw_vector(origin2D, V, alpha, ctx)

    #Transfrom alpha to radians
    alpha = deg2rad(alpha)

    # Get line
    set_line_width(ctx, 5)
    set_source_rgb(ctx, 0, 0, 0)
    # Create circle to indicate direction
    circle(ctx, origin2D[1] + V[1] * alpha * render_scale, origin2D[2] - V[2] * alpha * render_scale, 5)
    fill(ctx)
    # Create line
    move_to(ctx, origin2D[1], origin2D[2])
    line_to(ctx, origin2D[1] + V[1] * alpha * render_scale, origin2D[2] - V[2] * alpha * render_scale)
    stroke(ctx)

    # Repeat
    set_line_width(ctx, 2)
    set_source_rgb(ctx, 1, 1, 1)

    circle(ctx, origin2D[1] + V[1] * alpha * render_scale, origin2D[2] - V[2] * alpha * render_scale, 2)
    fill(ctx)

    println("Vector:")
    println(origin2D)
    println(V)
    println(alpha)
    println(render_scale)

    move_to(ctx, origin2D[1], origin2D[2])
    line_to(ctx, origin2D[1] + V[1] * alpha * render_scale, origin2D[2] - V[2] * alpha * render_scale)
    stroke(ctx)

end

# the background drawing
function draw_the_canvas(canvas)
    h   = height(canvas)
    w   =  width(canvas)
    ctx =  getgc(canvas)
    # clear the canvas
    rectangle(ctx, 0, 0, w, h)
    set_source_rgb(ctx, 1, 1, 1)
    fill(ctx)

    # read some normalized boxes and draw a line
    #phi = read_normalized_label("phi_normalized")
    phi = read_slider_box("phi")
    v_x = read_normalized_label("v_x_normalized")
    v_y = read_normalized_label("v_y_normalized")
    v_z = read_normalized_label("v_z_normalized")
    alpha = read_slider_box("alpha")

    #Define origin
    #origin = [250 250]

    origin2D = to_2d(origin3D)

    #Get base vectors on the current phi rotation and pass them to 2d
    R1 = [1 0 0]
    R2 = [0 1 0]
    R3 = [0 0 1]

    R1 = rotate_phi_z(R1, phi)
    R2 = rotate_phi_z(R2, phi)
    R3 = rotate_phi_z(R3, phi)

    draw_sphere(origin2D, R1, R2, R3, ctx)

    R1 = to_2d(R1)
    R2 = to_2d(R2)
    R3 = to_2d(R3)

    draw_axis(origin2D, R1, R2, R3, ctx)

    # Get current vector, rotate on phi and transform to 2d
    V = [v_x v_y v_z]

    V = rotate_phi_z(V, phi)

    # Declare axis on the vector
    R4 = [1 0 0]
    R5 = [0 1 0]
    R6 = [0 0 1]

    # Rotate to current phi value
    R4 = rotate_phi_z(R4, phi)
    R5 = rotate_phi_z(R5, phi)
    R6 = rotate_phi_z(R6, phi)

    # Get axis 3D position
    pos = V

    V = to_2d(V)

    # Draw vector and vector axis on screen
    draw_vector(origin2D, V, alpha, ctx)
    draw_vector_axis(origin2D, pos, R4, R5, R6, alpha, ctx, 0.5)

end
# -------- initialize everything ---------

# prepare and  the initial widgets
init_window(win, the_canvas)
showall(win)


text:
# Tracing charged particle in the Harris current sheet.
# This example shows how to trace protons in a stationary magnetic field that
# corresponds to the 1D Harris current sheet.
# Reference: https://en.wikipedia.org/wiki/Current_sheet
#
# Hongyang Zhou, hyzhou@umich.edu

using TestParticle
using TestParticle: getB_CS_harris
using OrdinaryDiffEq
using StaticArrays
using PyPlot
using Statistics: mean

## Obtain field

# Harris current sheet parameters in SI units
const B₀, L = 20e-9, 0.4TestParticle.Rₑ

function getB(xu)
   SVector{3}(getB_CS_harris(xu[1:3], B₀, L))
end

function getE(xu)
   SA[0.0, 0.0, 0.0]
end

## Initialize particles

m = TestParticle.mᵢ
q = TestParticle.qᵢ
c = TestParticle.c
Rₑ = TestParticle.Rₑ

Ek = 5e7 # [eV]

# initial velocity, [m/s]
v₀ = [c*√(1-1/(1+Ek*q/(m*c^2))^2), 0.0, 0.0]
# initial position, [m]
r₀ = [-5.0Rₑ, 0.0, 0.0]
stateinit = [r₀..., v₀...]

param = prepare(getE, getB)
tspan = (0.0, 10.0)

prob = ODEProblem(trace_analytic!, stateinit, tspan, param)

sol = solve(prob, Tsit5(); save_idxs=[1,2,3])

## Visualization

using3D()
fig = plt.figure(figsize=(10,6))
ax = fig.gca(projection="3d")

n = 100 # number of timepoints
ts = range(tspan..., length=n)
ax.plot(sol(ts, idxs=1)./Rₑ,sol(ts, idxs=2)./Rₑ, sol(ts, idxs=3)./Rₑ,
   label="50 MeV proton, B0 = 20 nT")

ax.legend()
title("Particle trajectory near the Harris current sheet")
xlabel("x [Re]")
ylabel("y [Re]")
zlabel("z [Re]")

x = range(-8, 8, length=20)

X = collect(Float32, x)
Y = zeros(Float32, size(X)...)
Z = zeros(Float32, size(X)...)

B = zeros(Float32, 3, size(X)...)

i = 1
for (x,y) in zip(X,Y)
   B[1+3*(i-1):3*i] = getB_CS_harris([x,0.0,0.0], 4e-2, 1.0)
   global i += 1
end

for s = 1:3
   ax.quiver(X, Y, Z, vec(B[1,:,:]), vec(B[2,:,:]), vec(B[3,:,:]),
      color="k", alpha=0.6)
   @. Y -= 15
end

ax.set_box_aspect([2,5,1])
TestParticle.set_axes_equal(ax)

#savefig("test.png", bbox_inches="tight")


text:
"
    Protocol buffer data reader in Julia

    author: Atsushi Sakai
"

using ProtoBuf

include("tutorial.jl")
include("addressbook_pb.jl")

function main()
    println(PROGRAM_FILE," start!!")

    stream = UInt8[]
    # open( "pbdata_julia.dat", "r" ) do fp
    # open( "../cpp/pbdata_cpp.dat", "r" ) do fp
    open( "../python/pbdata_py.dat", "r" ) do fp
        stream = read( fp )
    end
    iob = PipeBuffer(stream)
    address_book = readproto(iob, AddressBook())

    println(address_book)  # Human readable print

    println(PROGRAM_FILE," Done!!")
end

main()


text:
@testset "Sampling" begin
  @testset "UniformSampler" begin
    d = RegularGrid(100,100)
    s = sample(d, UniformSampler(100))
    μ = mean(coordinates(s), dims=2)
    @test nelms(s) == 100
    @test isapprox(μ, [50.,50.], atol=10.)
  end

  @testset "BallSampler" begin
    d = RegularGrid(100,100)
    s = sample(d, BallSampler(10.))
    n = nelms(s)
    X = coordinates(s, sample(1:n, 2, replace=false))
    x, y = X[:,1], X[:,2]
    @test n < 100
    @test sqrt(sum((x - y).^2)) ≥ 10.

    d = RegularGrid(100,100)
    s = sample(d, BallSampler(20.))
    n = nelms(s)
    X = coordinates(s, sample(1:n, 2, replace=false))
    x, y = X[:,1], X[:,2]
    @test n < 50
    @test sqrt(sum((x - y).^2)) ≥ 20.
  end

  @testset "WeightedSampler" begin
    # uniform weights => uniform sampler
    d = RegularGrid(100,100)
    s = sample(d, WeightedSampler(100))
    μ = mean(coordinates(s), dims=2)
    @test nelms(s) == 100
    @test isapprox(μ, [50.,50.], atol=10.)
  end
end


text:
using Random, Statistics, StatsBase
struct FunnelDistribution{T<:Real,U<:Integer} <: Distribution{Multivariate,Continuous}
    "Variance of the dominant normal distribution."
    a::T

    "Variance of the supporting normal distributions."
    b::T

    "Number of dimensions."
    n::U
end

function FunnelDistribution(; a::Real = 1.0, b::Real = 0.5, n::Integer = 3)
    a_pr, b_pr = promote(a, b)
    FunnelDistribution(a_pr, b_pr, n)
end

Base.length(d::FunnelDistribution) = d.n
Base.eltype(d::FunnelDistribution) = Base.eltype(d.a)

Statistics.mean(d::FunnelDistribution) = zeros(d.n)

function Statistics.cov(dist::FunnelDistribution)
    cov(nestedview(rand(rng, sampler(dist), 10^5)))
end

StatsBase.params(d::FunnelDistribution) = (d.a, d.b, d.n)

function Distributions._logpdf(d::FunnelDistribution, x::AbstractArray)
    idxs = eachindex(x)
    s = logpdf(Normal(0, d.a^2), x[idxs[1]])
    @inbounds for i in idxs[2:end]
        s += logpdf(Normal(0, exp(2 * d.b * x[1])), x[i])
    end
    s
end

function Distributions.gradlogpdf(d::FunnelDistribution{T, U}, x::AbstractVector{T}) where {T<:Real, U<:Integer}
    FillArrays.Zeros(length(d))
end

function Distributions._rand!(rng::AbstractRNG, d::FunnelDistribution, x::AbstractVector)
    idxs = eachindex(x)
    x[idxs[1]] = rand(rng, Normal(0, d.a^2))
    @inbounds for i in idxs[2:end]
        x[i] = rand(rng, Normal(0, exp(2 * d.b * x[1])))
    end
    return x
end
#
#
# dist = FunnelDistribution(1.0, 0.5, 2)
#
# s=rand(dist,200)
#
# scatter(s[1,:],s[2,:])

max_stars_repo_name: cmerkatas/HMC

max_issues_repo_name: cmerkatas/HMC

max_forks_repo_name: cmerkatas/HMC