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

using Markdown
using InteractiveUtils

# ╔═╡ 14900210-d014-4485-9e6a-2bb97cafefd1
begin
	using PortAudio, SampledSignals, VideoIO
	using FileIO: load, save, loadstreaming, savestreaming, query
	import LibSndFile
	# using QuadGK
end

# ╔═╡ 123494fb-da41-40b3-a6da-d2dd3956bbcf
# Pogledajmo signal
using Plots

# ╔═╡ 4cda92ed-f045-4347-8a01-7d8326beeb24
md"""
# Fourierov integral

Primjer snimanja signala, numeričkog računanja Fourierovog integrala, i rekonstrukcije
signala nakon rezanja frekvencija.
"""

# ╔═╡ 36e78570-81d2-11eb-2124-0189bee238eb
# pkg> add https://github.com/JuliaAudio/PortAudio.jl.git

# ╔═╡ 5807a089-0963-47bf-b31c-9f6cb673a29a
PortAudio.devices()

# ╔═╡ 83d73bd5-adc6-4e05-8490-41cbe52d285d
md"""
Nakon što ste pronašli vaše uređaje, možete otkomentirati sljedeću
ćeliju u kojoj se ulaz s mikrofona direktno prenosi na zvučnik.
Nakon toga treba ponovo pokrenuti jezgru.
"""

# ╔═╡ 71da3573-43e1-4ddf-baaa-f00c6635506d
#=
stream = PortAudioStream(2, 2)
try
    # cancel with Ctrl-C
    write(stream, stream)
finally
    close(stream)
end
=#

# ╔═╡ 949fb68b-bde5-4f8e-8303-d941b00bd8c0
md"""
Ukoliko želite snimiti svoj tekst, zamijenite mikrofon i izlaz s vašim uređajima, i izvedite sljedeće četiri čelije.
"""

# ╔═╡ a5c7fcc5-5c53-471b-a5ee-482c6e81c17b
# stream = PortAudioStream("Microphone (BRIO 4K Stream Edit","Microsoft Sound Mapper - Output")

# ╔═╡ 16383cd6-bfd9-4b7c-9ada-90f0a06e2b00
# Namjestite duljinu snimke (nemojte pretjerivati)
# buf = read(stream, 3s)

# ╔═╡ da37b3c9-45eb-4731-b05d-dcb49a669fb7
# Zatvorite stream
# close(stream)

# ╔═╡ 33589e1a-6034-4039-b3e6-b7baca5373da
# Spremite vašu snimku
# save("myvoice.wav", buf)

# ╔═╡ 00909270-823e-11eb-209e-516ff567c9d2
glas=load("myvoice.wav")

# ╔═╡ 38c5b377-2c9e-4f2c-a4b1-e172e474da7d
length(glas)

# ╔═╡ 7ff572d4-1248-431c-a3f8-a4cdf3feeab2
glas.samplerate

# ╔═╡ 37431d3c-80b0-41e5-b181-b4e2121ea2f2
typeof(glas)

# ╔═╡ 75f49ac0-823e-11eb-38a5-5b86cc07e9ad
glas.data

# ╔═╡ d728dfd5-c51c-4008-8a0c-33a1ff7622c5
# Napravimo mono snimku
glas_mono=similar(glas);

# ╔═╡ cc609b6c-5f95-4c52-939b-46f1ea142641
begin
	glas_mono.data=sum(glas.data,dims=2)
	glas_mono.samplerate=glas.samplerate
end

# ╔═╡ 457e98b3-a7c6-4aa1-916c-dbdf9e587ec8
save("myvoice_mono.wav", glas_mono)

# ╔═╡ cf1fdcf6-acfd-494f-a545-c5935700b4b6
glas_mono.data

# ╔═╡ 12b84c10-8273-11eb-3f9b-0db8fcf7fd75
glas_mono

# ╔═╡ e3660516-58d8-4cd2-99c2-e999d6dd7dc7
begin
	S=glas_mono.data
	plot(S,label="Originalni signal")
end

# ╔═╡ 01ebedfb-66c3-4fc0-b967-69a67af812ad
# Vrijeme
T=range(0,3,length=length(S))

# ╔═╡ ccff6cf5-d60f-4294-8396-b894c1b0e673
begin
	# Trapezna formula, približno. Računamo kosinusni i sinusni spektar
	using LinearAlgebra
	A(λ::Float64)=(cos.(λ*T)⋅S)*((T[end]-T[1])/(length(T)*π))
	B(λ::Float64)=(sin.(λ*T)⋅S)*((T[end]-T[1])/(length(T)*π))
end

# ╔═╡ d588d827-a9c1-45ff-972a-30580055b38c
# Plot u vremenu
plot(T,S,xlabel="t (sec)",label="Originalni signal")

# ╔═╡ 2eff8044-d700-4a5f-9d46-9009a9e280eb
# Nacrtajmo kosinusni i sinusni spektar i odlučimo koje frekvencije ćemo zadržati
plot([A B],300,5000,layout=(2,1),label=["Kosinusni spektar" "Sinusni spektar"])

# ╔═╡ d636f56b-ffad-4ff8-8590-c6d0772438cf
begin
	# Ograničimo spektar, opet koristimo približnu formulu
	λ₀=600.0
	λ₁=4500.0
	step=0.5
	Λ=range(λ₀,λ₁,step=step)
	# Ovo traje cca 1 minutu, ali se računa samo jednom
	Aλ=A.(Λ)
	Bλ=B.(Λ)
end

# ╔═╡ dec5475f-8064-42fe-934f-b7519920b508
# Rekonstruirajmo signal s odrezanim frekvencijama
g(x::Float64)=(Aλ⋅cos.(x*Λ)+Bλ⋅sin.(x*Λ))*step

# ╔═╡ 45fb4bd1-eccf-4307-aec2-0b52353dc0db
G=g.(T)

# ╔═╡ ef9657d8-4290-4d73-bc95-f1fba9c91000
# Usporedimo grafički
plot(T,[S G],layout=(2,1),label=["Originalni mono signal" "Odrezani mono signal"])

# ╔═╡ f3f5f234-bb67-4cfe-822d-6148593c6554
begin
	# Spremimo signal s odrezanim frekvencijama i poslušajmo
	glas_mono_odrezan=deepcopy(glas_mono)
	glas_mono_odrezan.data[:,1]=map(Float32,G)
	save("myvoice_odrezan.wav", glas_mono_odrezan)
end

# ╔═╡ 9d4dc1ae-ab06-48e1-92df-b0973f8552bd
glas_mono_odrezan

# ╔═╡ e7a96973-2dda-49f5-a4c9-014fafc6e44c

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
LibSndFile = "b13ce0c6-77b0-50c6-a2db-140568b8d1a5"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PortAudio = "80ea8bcb-4634-5cb3-8ee8-a132660d1d2d"
SampledSignals = "bd7594eb-a658-542f-9e75-4c4d8908c167"
VideoIO = "d6d074c3-1acf-5d4c-9a43-ef38773959a2"

[compat]
FileIO = "~1.11.1"
LibSndFile = "~2.4.0"
Plots = "~1.22.3"
PortAudio = "~1.1.2"
SampledSignals = "~2.1.2"
VideoIO = "~0.9.4"
"""

# ╔═╡ 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"

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

[[BerkeleyDB_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "OpenSSL_jll", "Pkg"]
git-tree-sha1 = "f48d60e42490ce5516a52b2963254a4732ba9942"
uuid = "cd00e070-8fe2-570d-8212-aefc8f89bd06"
version = "18.1.40+0"

[[BlueZ_jll]]
deps = ["Artifacts", "Dbus_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libical_jll", "Pkg", "Readline_jll", "eudev_jll"]
git-tree-sha1 = "d4c413db1759fa113135800ff2993ee01206126b"
uuid = "471b5b61-da80-5748-8755-67d5084d21f2"
version = "5.54.0+1"

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

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

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

[[Check_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b5d7d180125b8d0f24bc4196f7fd53b7a0f48ea9"
uuid = "491db154-c145-5abe-9c32-446728d60cce"
version = "0.15.2+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"

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

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

[[DSP]]
deps = ["FFTW", "IterTools", "LinearAlgebra", "Polynomials", "Random", "Reexport", "SpecialFunctions", "Statistics"]
git-tree-sha1 = "2a63cb5fc0e8c1f0f139475ef94228c7441dc7d0"
uuid = "717857b8-e6f2-59f4-9121-6e50c889abd2"
version = "0.6.10"

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

[[Dbus_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "97f1325c10bd02b1cc1882e9c2bf6407ba630ace"
uuid = "ee1fde0b-3d02-5ea6-8484-8dfef6360eab"
version = "1.12.16+3"

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

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

[[Elfutils_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "XZ_jll", "Zlib_jll", "argp_standalone_jll", "fts_jll", "obstack_jll"]
git-tree-sha1 = "8f9fcde6d89b0a3ca51cb2028beab462705c5436"
uuid = "ab5a07f8-06af-567f-a878-e8bb879eba5a"
version = "0.182.0+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"

[[ExprTools]]
git-tree-sha1 = "b7e3d17636b348f005f11040025ae8c6f645fe92"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.6"

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

[[FLAC_jll]]
deps = ["Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "cd528d5083a589aab69dc6de73a901efa9d69586"
uuid = "1d38b3a6-207b-531b-80e8-c83f48dafa73"
version = "1.3.3+2"

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

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

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

[[GMP_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "781609d7-10c4-51f6-84f2-b8444358ff6d"

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

[[GSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9a6d2b6c33aa7061654d2f1b31d9f7e1c2bd2dbc"
uuid = "1b77fbbe-d8ee-58f0-85f9-836ddc23a7a4"
version = "2.7.1+0"

[[GStreamer_jll]]
deps = ["Artifacts", "Elfutils_jll", "GMP_jll", "GSL_jll", "Glib_jll", "JLLWrappers", "LibUnwind_jll", "Libdl", "Pkg", "libcap_jll"]
git-tree-sha1 = "a1d35530fb854beac4efa219c1987fb99fd3ff77"
uuid = "aaaaf01e-2457-52c6-9fe8-886f7267d736"
version = "1.18.3+0"

[[Gdbm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Readline_jll"]
git-tree-sha1 = "0f2a7b90790988ed644f28ae0e1d9069b1f345f4"
uuid = "54ca2031-c8dd-5cab-9ed4-295edde1660f"
version = "1.18.1+1"

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

[[Glob]]
git-tree-sha1 = "4df9f7e06108728ebf00a0a11edee4b29a482bb2"
uuid = "c27321d9-0574-5035-807b-f59d2c89b15c"
version = "1.3.0"

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

[[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 = "14eece7a3308b4d8be910e265c724a6ba51a9798"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.16"

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

[[ICU_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6b1e49820922eca7bfc862442da6e54173a075b4"
uuid = "a51ab1cf-af8e-5615-a023-bc2c838bba6b"
version = "68.2.0+0"

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

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

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

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

[[Intervals]]
deps = ["Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"]
git-tree-sha1 = "323a38ed1952d30586d0fe03412cde9399d3618b"
uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
version = "1.5.0"

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

[[LibSndFile]]
deps = ["FileIO", "Libdl", "LinearAlgebra", "Printf", "SampledSignals", "libsndfile_jll"]
git-tree-sha1 = "955515227165d2a276abb017bafd0b4e93d0eded"
uuid = "b13ce0c6-77b0-50c6-a2db-140568b8d1a5"
version = "2.4.0"

[[LibUnwind_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "745a5e78-f969-53e9-954f-d19f2f74f4e3"

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

[[Libical_jll]]
deps = ["Artifacts", "BerkeleyDB_jll", "Glib_jll", "ICU_jll", "JLLWrappers", "Libdl", "Pkg", "XML2_jll"]
git-tree-sha1 = "c61ffd9e8faf24c19a88f369f1966d53967824d1"
uuid = "bce108ef-3f60-5dd0-bcd6-e13a096cb796"
version = "3.0.9+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"

[[Libtool_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "e5651a50cdb27262ad368cded3130f11edbfc9de"
uuid = "a76c16ae-fb8f-5ff0-8826-da3b7a640f0b"
version = "2.4.6+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"

[[Mocking]]
deps = ["Compat", "ExprTools"]
git-tree-sha1 = "29714d0a7a8083bba8427a4fbfb00a540c681ce7"
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
version = "0.7.3"

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

[[Ncurses_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e3fb71f3c971fdc8523f9ef3906691124f3048a2"
uuid = "68e3532b-a499-55ff-9963-d1c0c0748b3a"
version = "6.2.0+0"

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

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

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

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

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

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

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

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

[[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 = "cfbd033def161db9494f86c5d18fbf874e09e514"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.22.3"

[[Polynomials]]
deps = ["Intervals", "LinearAlgebra", "OffsetArrays", "RecipesBase"]
git-tree-sha1 = "0b15f3597b01eb76764dd03c3c23d6679a3c32c8"
uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
version = "1.2.1"

[[PortAudio]]
deps = ["LinearAlgebra", "SampledSignals", "Suppressor", "alsa_plugins_jll", "libportaudio_jll"]
git-tree-sha1 = "52e590ceebf17a8ef1b51a0cbe0fd54c9678878a"
uuid = "80ea8bcb-4634-5cb3-8ee8-a132660d1d2d"
version = "1.1.2"

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

[[PulseAudio_jll]]
deps = ["Artifacts", "BlueZ_jll", "Check_jll", "Dbus_jll", "FFTW_jll", "GStreamer_jll", "Gdbm_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Libtool_jll", "OpenSSL_jll", "Pkg", "SBC_jll", "SoXResampler_jll", "SpeexDSP_jll", "alsa_jll", "eudev_jll", "libasyncns_jll", "libcap_jll", "libsndfile_jll"]
git-tree-sha1 = "6554e7e66f37a699c2f53d9d6622969272b90408"
uuid = "02771fc1-bdb7-5db5-8d11-300768e00fbd"
version = "15.0.0+0"

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

[[Readline_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ncurses_jll", "Pkg"]
git-tree-sha1 = "6efe4f1ed54a4300cd9418faf77988049203afa9"
uuid = "05236dd9-4125-5232-aa7c-9ec0c9b2c25a"
version = "8.1.1+0"

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

[[SBC_jll]]
deps = ["Libdl", "Pkg", "libsndfile_jll"]
git-tree-sha1 = "34755bff50b6b08988cdfe5fee69c1c1b24ff810"
uuid = "da37f231-8920-5702-a09a-bdd970cb6ddc"
version = "1.4.0+0"

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

[[SampledSignals]]
deps = ["Base64", "Compat", "DSP", "FFTW", "FixedPointNumbers", "IntervalSets", "LinearAlgebra", "Random", "TreeViews", "Unitful"]
git-tree-sha1 = "4b7e413f20fa56fa47b8433c96f96a1acfe372a6"
uuid = "bd7594eb-a658-542f-9e75-4c4d8908c167"
version = "2.1.2"

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

[[SoXResampler_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "a95ff1842456719a727e23fe28712eb26f7818b8"
uuid = "fbe68eb6-6641-54c6-99e3-f7c7c4d73a57"
version = "0.1.3+0"

[[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 = "793793f1df98e3d7d554b65a107e9c9a6399a6ed"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.7.0"

[[SpeexDSP_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "ecc65cb4a4e77f624deae8d881787c789af6deaf"
uuid = "f2f9631b-9a4e-5b48-9975-88f638ec36a7"
version = "1.2.0+0"

[[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 = "3c76dde64d03699e074ac02eb2e8ba8254d428da"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.13"

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

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

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

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

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

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

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

[[TimeZones]]
deps = ["Dates", "Future", "LazyArtifacts", "Mocking", "Pkg", "Printf", "RecipesBase", "Serialization", "Unicode"]
git-tree-sha1 = "6c9040665b2da00d30143261aea22c7427aada1c"
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
version = "1.5.7"

[[TreeViews]]
deps = ["Test"]
git-tree-sha1 = "8d0d7a3fe2f30d6a7f833a5f19f7c7a5b396eae6"
uuid = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7"
version = "0.3.0"

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

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

[[Unitful]]
deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"]
git-tree-sha1 = "a981a8ef8714cba2fd9780b22fd7a469e7aaf56d"
uuid = "1986cc42-f94f-5a68-af5c-568840ba703d"
version = "1.9.0"

[[VideoIO]]
deps = ["ColorTypes", "Dates", "Downloads", "FFMPEG", "FileIO", "Glob", "ImageCore", "Libdl", "ProgressMeter", "Requires"]
git-tree-sha1 = "aeca804b0335293cabcef6193b81c265175d8bbf"
uuid = "d6d074c3-1acf-5d4c-9a43-ef38773959a2"
version = "0.9.4"

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

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

[[XZ_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "a921669cd9a45c23031fd4eb904f5cc3d20de415"
uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800"
version = "5.2.5+2"

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

[[alsa_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "69859a01e7735ce5b49b1328827f6e3f4cdd7d19"
uuid = "45378030-f8ea-5b20-a7c7-1a9d95efb90e"
version = "1.2.5+0"

[[alsa_plugins_jll]]
deps = ["Artifacts", "FFMPEG_jll", "JLLWrappers", "Libdl", "Pkg", "PulseAudio_jll", "alsa_jll", "libsamplerate_jll"]
git-tree-sha1 = "a43b5bcdfadfbe06c42cd6b007572c4806f2c0f7"
uuid = "5ac2f6bb-493e-5871-9171-112d4c21a6e7"
version = "1.2.2+0"

[[argp_standalone_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "feaf9f6293003c2bf53056fd6930d677ed340b34"
uuid = "c53206cc-00f7-50bf-ad1e-3ae1f6e49bc3"
version = "1.3.1+0"

[[eudev_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "gperf_jll"]
git-tree-sha1 = "431b678a28ebb559d224c0b6b6d01afce87c51ba"
uuid = "35ca27e7-8b34-5b7f-bca9-bdc33f59eb06"
version = "3.2.9+0"

[[fts_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "78732b942383d2cb521df8a1a0814911144e663d"
uuid = "d65627f6-89bd-53e8-8ab5-8b75ff535eee"
version = "1.2.7+1"

[[gperf_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "9a7e727603ef936433110ee68b78dcdc3576ee79"
uuid = "1a1c6b14-54f6-533d-8383-74cd7377aa70"
version = "3.1.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"

[[libasyncns_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "38a54b0ebad9bc225a38106ff66b7827fac5bd9e"
uuid = "ed080073-db63-57db-a029-74e11ae80737"
version = "0.8.0+0"

[[libcap_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "c6816cb55afe6639d776f438a74193f5694268c6"
uuid = "eef66a8b-8d7a-5724-a8d2-7c31ae1e29ed"
version = "2.27.0+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"

[[libportaudio_jll]]
deps = ["Libdl", "Pkg", "alsa_jll"]
git-tree-sha1 = "7a5bcc2dcdce9ff8565768761ab3331a8a73b104"
uuid = "2d7b7beb-0762-5160-978e-1ab83a1e8a31"
version = "19.6.0+2"

[[libsamplerate_jll]]
deps = ["Libdl", "Pkg"]
git-tree-sha1 = "45ba80d9b0a208fd5165d159d93a3725fab0d76b"
uuid = "9427e74d-4e05-59c1-8ff3-7d74b6e52ac8"
version = "0.1.9+0"

[[libsndfile_jll]]
deps = ["Artifacts", "FLAC_jll", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg", "alsa_jll", "libvorbis_jll"]
git-tree-sha1 = "546f784fc1d6f6ac673eaf8a8001c9c2b96b1a9c"
uuid = "5bf562c0-5a39-5b4f-b979-f64ac885830c"
version = "1.0.31+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"

[[obstack_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "1c4a6b66e934fc6db4649cb2910c72f53bbfea7e"
uuid = "c88a4935-d25e-5644-aacc-5db6f1b8ef79"
version = "1.2.2+0"

[[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:
# ╟─4cda92ed-f045-4347-8a01-7d8326beeb24
# ╠═14900210-d014-4485-9e6a-2bb97cafefd1
# ╠═36e78570-81d2-11eb-2124-0189bee238eb
# ╠═5807a089-0963-47bf-b31c-9f6cb673a29a
# ╟─83d73bd5-adc6-4e05-8490-41cbe52d285d
# ╠═71da3573-43e1-4ddf-baaa-f00c6635506d
# ╟─949fb68b-bde5-4f8e-8303-d941b00bd8c0
# ╠═a5c7fcc5-5c53-471b-a5ee-482c6e81c17b
# ╠═16383cd6-bfd9-4b7c-9ada-90f0a06e2b00
# ╠═da37b3c9-45eb-4731-b05d-dcb49a669fb7
# ╠═33589e1a-6034-4039-b3e6-b7baca5373da
# ╠═00909270-823e-11eb-209e-516ff567c9d2
# ╠═38c5b377-2c9e-4f2c-a4b1-e172e474da7d
# ╠═7ff572d4-1248-431c-a3f8-a4cdf3feeab2
# ╠═37431d3c-80b0-41e5-b181-b4e2121ea2f2
# ╠═75f49ac0-823e-11eb-38a5-5b86cc07e9ad
# ╠═d728dfd5-c51c-4008-8a0c-33a1ff7622c5
# ╠═cc609b6c-5f95-4c52-939b-46f1ea142641
# ╠═457e98b3-a7c6-4aa1-916c-dbdf9e587ec8
# ╠═cf1fdcf6-acfd-494f-a545-c5935700b4b6
# ╠═12b84c10-8273-11eb-3f9b-0db8fcf7fd75
# ╠═123494fb-da41-40b3-a6da-d2dd3956bbcf
# ╠═e3660516-58d8-4cd2-99c2-e999d6dd7dc7
# ╠═01ebedfb-66c3-4fc0-b967-69a67af812ad
# ╠═d588d827-a9c1-45ff-972a-30580055b38c
# ╠═ccff6cf5-d60f-4294-8396-b894c1b0e673
# ╠═2eff8044-d700-4a5f-9d46-9009a9e280eb
# ╠═d636f56b-ffad-4ff8-8590-c6d0772438cf
# ╠═dec5475f-8064-42fe-934f-b7519920b508
# ╠═45fb4bd1-eccf-4307-aec2-0b52353dc0db
# ╠═ef9657d8-4290-4d73-bc95-f1fba9c91000
# ╠═f3f5f234-bb67-4cfe-822d-6148593c6554
# ╠═9d4dc1ae-ab06-48e1-92df-b0973f8552bd
# ╠═e7a96973-2dda-49f5-a4c9-014fafc6e44c
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: ivanslapnicar/Matematika

max_issues_repo_name: ivanslapnicar/Matematika

max_forks_repo_name: ivanslapnicar/Matematika


text:
using Luxor, Colors
using Printf
using JSON
using ArgParse

include("strange.jl")

function parse_commandline()
    settings = ArgParseSettings()

    @add_arg_table settings begin
        "--basename"
            help = "strange image and json basename"
            default = "strange"
	"--a"
	    help = "a control point range"
	    arg_type = Float64
	    default = 5.0
	"--b"
	    help = "b control point range"
	    arg_type = Float64
	    default = 10.0
	"--c"
	    help = "c control point range"
	    arg_type = Float64
	    default = 5.0
	"--d"
	    help = "d control point range"
	    arg_type = Float64
	    default = 10.0
	"--e"
	    help = "e control point range"
	    arg_type = Float64
	    default = 5.0
	"--n"
	    help = "number of images to generate"
	    arg_type = Int64
	    default = 1
	"--res"
	    help = "image w x w res"
	    arg_type = Int64
	    default = 1_000
	"--rc"
	    help = "rgb r  color weight"
	    arg_type = Float64
	    default = 2.13
	"--gc"
	    help = "rgb g color weight"
	    arg_type = Float64
	    default = .13
	"--bc"
	    help = "rgb b color weight"
	    arg_type = Float64
	    default = 2.83
	"--dot_max"
	    help = "max dotsize"
	    arg_type = Float64
	    default = .65
	"--dot_min"
	    help = "min dotsize"
	    arg_type = Float64
	    default = .35
	"--flip"
	    help = "flip sin and cos in the calculations"
	    arg_type = Bool
	    default = false
	"--cmode"
	    help = "color mode: rgb, clamp, grey"
	    arg_type = String
	    default = "rgb"
    end

    return parse_args(settings)
end

function main()

	parsed_args = parse_commandline()

	# parameters controls
	a_range = parsed_args["a"]
	b_range = parsed_args["b"]
	c_range = parsed_args["c"]
	d_range = parsed_args["d"]
	e_range = parsed_args["e"]

	# image size:res x res
	res = parsed_args["res"]

	# number of images to generate
	n = parsed_args["n"]

	basename = parsed_args["basename"]

	# rgb color profile
	color_profile = Dict([
			     :r=>parsed_args["rc"],
			     :g=>parsed_args["gc"],
			    :b=>parsed_args["bc"]
			    ])

	# toggle trig functions
	flip = parsed_args["flip"]

	# cmode
	cmode = parsed_args["cmode"]

	# generate n png images
	for i in 1:n
		a = b = c = d = ev = 0
		while (a==0 || b == 0 || c == 0 || d == 0 || ev == 0)
			a = rs()*rand()*a_range
			b = rs()*rand()*b_range
			c = rs()*rand()*c_range
			d = rs()*rand()*d_range
			ev = rs()*rand()*e_range
		end

		dotsize = rand()
		if dotsize > parsed_args["dot_max"]
			dotsize = parsed_args["dot_max"]
		elseif dotsize < parsed_args["dot_min"]
			dotsize = parsed_args["dot_min"]
		end

		fn = @sprintf("%s_%-2.2d.png", basename, i)
		fn_ctrl = @sprintf("%s_%-2.2d.json", basename, i)

		cf = open(fn_ctrl, "w")
		sset = StrangeSet(Dict([:a=>a, :b=>b, :c=>c, :d=>d, :e=>ev]), dotsize, res, color_profile, fn, flip, cmode)
		JSON.print(cf, JSON.parse(JSON.json(sset)), 4)
		close(cf)

		params = @sprintf("Params: a=%-2.16f, b=%-2.16f, c=%-2.16f, d=%-2.16f, e=%-2.16f, res=%-2.2d, dotsize = %-2.16f, flip = %d, cmode = %s\n",
		   a, b, c, d, ev, res, dotsize, flip, cmode)

		println("$params")

		strange(fn, flip, cmode, dotsize, res, Dict([:a=>a,:b=>b, :c=>c, :d=>d, :e=>ev]), color_profile)
		println("finished generating $fn")
	end
end

main()

ext: jl


text:
import PhysicsEngine

@testset "Particle" begin

end

max_stars_repo_name: jonathanbuchanan/PhysicsEngine

max_issues_repo_name: jonathanbuchanan/PhysicsEngine

max_forks_repo_name: jonathanbuchanan/PhysicsEngine


text:
using Revise
using LibPQ
using DataKnots: DataKnot
using FunSQL:
    FunSQL, SQLTable, From, Select, Define, Where, Join, Group, Order, Limit,
    Window, Distinct, Append, As, Bind, Agg, Fun, Get, to_sql, normalize
using PostgresCatalog

FunSQL.SQLTable(tbl::PostgresCatalog.PGTable) =
    SQLTable(Symbol(tbl.schema.name), Symbol(tbl.name), Symbol[Symbol(col.name) for col in tbl])

conn = LibPQ.Connection("postgresql:///synpuf-5pct?host=/var/run/postgresql")
#conn = LibPQ.Connection("postgresql:///synpuf-10p?host=/var/run/postgresql")

function run(q)
    sql = to_sql(normalize(q))
    #println(sql, ";")
    #println()
    result = execute(conn, sql)
    println(convert(DataKnot, result))
    println('-'^80)
end

cat = PostgresCatalog.introspect(conn)
for tbl in cat["public"]
    @eval $(Symbol(tbl.name)) = SQLTable($tbl)
end

SNOMED(code) =
    (codesystem = "SNOMED", code = code)

SNOMED(codes...) =
    [SNOMED(code) for code in codes]

VISIT(code) =
    (codesystem = "Visit", code = code)

VISIT(codes...) =
    [VISIT(code) for code in codes]

const myocardial_infarction = SNOMED("22298006")

const old_myocardial_infarction = SNOMED("1755008")

const inpatient_or_er = VISIT("ERIP", "ER", "IP")

IsCoded(t) =
    Fun.And(Get.vocabulary_id .== t.codesystem,
            Get.concept_code .== t.code)

IsCoded(ts::AbstractVector) =
    Fun.Or((IsCoded(t) for t in ts)...)

FromConcept() =
    From(concept) |>
    Where(ismissing.(Get.invalid_reason))

FromConceptOnly(t) =
    FromConcept() |> Where(IsCoded(t))

FromConcept(t) =
    FromConceptOnly(t) |>
    Append(
        FromConcept() |>
        Join(concept_ancestor,
             Get.concept_id .== Get.descendant_concept_id) |>
        Join(:ancestor => FromConceptOnly(t),
             Get.ancestor_concept_id .== Get.ancestor.concept_id)) |>
    ((t isa AbstractVector) ? Distinct(Get.concept_id) : identity)

FromConcept(t, et) =
    FromConcept(t) |>
    Join(:excluded => FromConcept(et),
         Get.concept_id .== Get.excluded.concept_id,
         is_left=true) |>
    Where(ismissing.(Get.excluded.concept_id))

QInfarctions =
    FromConcept(myocardial_infarction,
                old_myocardial_infarction)
run(QInfarctions)

QInpatientOrER =
    FromConcept(inpatient_or_er)
run(QInpatientOrER)

#=
    @define candidate_events = begin
        condition
        keep(index_date => start_date)
        filter(concept.is_myocardial_infarction)
    end

    @query sp10 begin
        candidate_events
        { person, index_date }
    end
=#

QInfarctionConditions =
    From(condition_occurrence) |>
    Join(:infarction_concept => QInfarctions,
         Get.condition_concept_id .== Get.infarction_concept.concept_id) |>
    Define(:index_date => Get.condition_start_date)
run(QInfarctionConditions |> Select(Get.person_id, Get.index_date))

QInfarctionConditionsInOP =
    QInfarctionConditions |>
    Join(:OP => observation_period,
         Fun.And(Get.person_id .== Get.OP.person_id,
                 Get.OP.observation_period_start_date .<= Get.index_date,
                 Get.index_date .<= Get.OP.observation_period_end_date))
run(QInfarctionConditionsInOP |>
    Select(Get.person_id,
           Get.OP.observation_period_start_date,
           :start_date => Get.index_date,
           :end_date => Get.index_date .+ 7,
           Get.OP.observation_period_end_date))

QAcuteVisits =
    From(visit_occurrence) |>
    Join(:inpatient_or_er_concept => QInpatientOrER,
         Get.visit_concept_id .== Get.inpatient_or_er_concept.concept_id)
run(QAcuteVisits)

QInfarctionConditionsInOPDuringAcuteVisit =
    QInfarctionConditionsInOP |>
    Join(:acute_visit => QAcuteVisits,
         Fun.And(Get.person_id
                    .== Get.acute_visit.person_id,
                 Get.OP.observation_period_start_date
                    .<= Get.acute_visit.visit_start_date,
                 Get.acute_visit.visit_end_date
                    .<= Get.OP.observation_period_end_date,
                 Get.acute_visit.visit_start_date
                    .<= Get.index_date,
                 Get.index_date
                    .<= Get.acute_visit.visit_end_date))
run(QInfarctionConditionsInOPDuringAcuteVisit)

QCorrelatedAcuteVisit(person_id, index_date, op_start_date, op_end_date) =
    QAcuteVisits |>
    As(:acute_visit) |>
    Where(Fun.And(Fun."="(Get.person_id, Get.acute_visit.person_id),
                  Fun."<="(Get.op_start_date,
                           Get.acute_visit.visit_start_date),
                  Fun."<="(Get.acute_visit.visit_end_date,
                           Get.op_end_date),
                  Fun."<="(Get.acute_visit.visit_start_date,
                           Get.index_date),
                  Fun."<="(Get.index_date,
                           Get.acute_visit.visit_end_date))) |>
    Bind(:person_id => person_id,
         :index_date => index_date,
         :op_start_date => op_start_date,
         :op_end_date => op_end_date)

QInfarctionConditionsInOPDuringAcuteVisit =
    QInfarctionConditionsInOP |>
    Where(
        Fun.Exists(
            QCorrelatedAcuteVisit(Get.person_id,
                                  Get.index_date,
                                  Get.OP.observation_period_start_date,
                                  Get.OP.observation_period_end_date)))
run(QInfarctionConditionsInOPDuringAcuteVisit)

run(QInfarctionConditionsInOPDuringAcuteVisit |>
    Group(Get.person_id) |>
    Where(Agg.Count(Get.index_date, distinct=true) .> 3))

run(person |>
    Window(Get.gender_concept_id) |>
    Select(Get.person_id, Agg.Count(), Agg.Row_Number()))

const selected_person_id = 42891

CollapseIndexDate(days) =
    Define(:end_date => Get.index_date .+ days) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:boundary => Agg.Lag(Get.end_date)) |>
    Define(:bump => Fun.Case(Get.index_date .<= Get.boundary, 0, 1)) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:group => Agg.Sum(Get.bump)) |>
    Group(Get.person_id, Get.group) |>
    Define(:min_date => Agg.Min(Get.index_date),
           :max_date => Agg.Max(Get.index_date))

q = QInfarctionConditionsInOPDuringAcuteVisit |>
    Where(Get.person_id .== selected_person_id) |>
    CollapseIndexDate(180) |>
    Select(Get.person_id, Get.min_date, Get.max_date);
run(q)

QInfarctionConditionsInOPDuringAcuteVisitCollapsedExplanation =
    QInfarctionConditionsInOPDuringAcuteVisit |>
    Where(Get.person_id .== selected_person_id) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:boundary => Agg.Lag(Get.index_date) .+ 180) |>
    Define(:bump => Fun.Case(Get.index_date .<= Get.boundary, 0, 1)) |>
    Select(Get.person_id, Get.index_date, Get.boundary, Get.bump)
run(QInfarctionConditionsInOPDuringAcuteVisitCollapsedExplanation)

QInfarctionConditionsInOPDuringAcuteVisitCollapsedExplanation2 =
    QInfarctionConditionsInOPDuringAcuteVisit |>
    Where(Get.person_id .== selected_person_id) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:boundary => Agg.Lag(Get.index_date) .+ 180) |>
    Define(:bump => Fun.Case(Get.index_date .<= Get.boundary, 0, 1)) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:group => Agg.Sum(Get.bump)) |>
    Select(Get.person_id, Get.index_date, Get.boundary, Get.bump, Get.group)
run(QInfarctionConditionsInOPDuringAcuteVisitCollapsedExplanation2)

QInfarctionConditionsInOPDuringAcuteVisitCollapsed =
    QInfarctionConditionsInOPDuringAcuteVisit |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:boundary => Agg.Lag(Get.index_date) .+ 180) |>
    Define(:bump => Fun.Case(Get.index_date .<= Get.boundary, 0, 1)) |>
    Window(Get.person_id, order=[Get.index_date]) |>
    Define(:group => Agg.Sum(Get.bump)) |>
    Group(Get.person_id, Get.group) |>
    Select(Get.person_id, Agg.Min(Get.index_date), Agg.Max(Get.index_date))
run(QInfarctionConditionsInOPDuringAcuteVisitCollapsed)


text:
immutable MultivariateTestFunction{T <: Function}
    f::T
    name::String
    x1s::Vector{Float64}
    x2s::Vector{Float64}
end

# Test cases generating as follows
# using Distributions
# repr(rand(Cauchy(0, 10), 5))

test_funcs = (
    MultivariateTestFunction(
        x -> sin(x[1]) + cos(x[2]),
        "x -> sin(x[1]) + cos(x[2])",
        [62.1908, 7.19278, 32.4944, -10.0597, 1.23525],
        [1.91818, -96.7718, -54.5914, 105.894, -2.74696],
    ),
    MultivariateTestFunction(
        x -> sin(x[1]) + 2 * sin(x[2]),
        "x -> sin(x[1]) + 2 * sin(x[2])",
        [-3.54442, 7.14114, -50.0388 , -5.73865, -8.88167],
        [-5.33968, -5.38714, -24.4391, -16.1525, -18.9814],
    ),
    MultivariateTestFunction(
        x -> x[1]^2 + x[2]^2,
        "x -> x[1]^2 + x[2]^2",
        [5.50783, -3.14069, 5.6383, 188.917, 98.7357],
        [6.71689, -15.1161, -19.7469, -2.62965, -14.9729],
    ),
    MultivariateTestFunction(
        x -> (1.0 - x[1])^2 + (2.0 - x[2])^2,
        "x -> (1.0 - x[1])^2 + (2.0 - x[2])^2",
        [5.66663, 22.7718, -13.5606, 9.80007, 0.0533083],
        [-11.0918, 1.55486, -133.914, -45.432, -19.3287],
    ),
    MultivariateTestFunction(
        x -> (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2,
        "x -> (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2",
        [25.9188, 35.6369, -17.8868, 47.76, 18.5091],
        [19.2642, -0.886276, 9.51653, 47.9309, -3.34237],
    ),
    MultivariateTestFunction(
        x -> 1 / (1 + exp(-(x[1] + x[2]))),
        "x -> 1 / (1 + exp(-(x[1] + x[2])))",
        [7.88823, -98.6984, 3.51154, -39.7024, 6.60017],
        [-55.2978, -212.439, 5.52012, 44.009, -10.9622],
    ),
    MultivariateTestFunction(
        x -> log(x[1]) + log(x[2]),
        "x -> log(x[1]) + log(x[2])",
        [7.88823, 98.6984, 3.51154, 39.7024, 6.60017],
        [55.2978, 212.439, 5.52012, 44.009, 10.9622],
    ),
)


text:
using Logging

global_logger(ConsoleLogger(stdout, Logging.Info))

"""

Checkout `oil_data` and place it in one of the locations as shown below.
"""
function data_dir()

    #@info "pwd(): $(pwd())"
    # if basename(path) == "OilData"
    #     path = joinpath(path, "test")
    # end
    name = "oil_data"

    path = joinpath(pwd(), name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "test", name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "..", name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "..", "..", name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "..", "..", "..", name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "..", "..", "..", "..", name)
    if isdir(path)
        return abspath(path)
    end

    path = joinpath(pwd(), "..", "..", "..", "..", "..", name)
    if isdir(path)
        return abspath(path)
    end

    #@warn "Data directory not found: $name"

    return nothing
    # throw(
    #     ErrorException("No data/ found")
    # )
end

# Check if `oil_data` is available
if isnothing(data_dir())
    @warn "Data directory not found"
    @warn "Some tests will be skipped"
else
    @info "Found data directory: $(data_dir())"
end


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

using Markdown
using InteractiveUtils

# ╔═╡ 80b0b83e-757f-11eb-1512-4b62350fb830
using Revise

# ╔═╡ 8374fde4-757f-11eb-2e1c-abe5ecf25d02
using OmegaIMCMC

# ╔═╡ 86ae4f9e-757f-11eb-07fd-9daa27aae41a
using Plots

# ╔═╡ 30e3b7d8-7580-11eb-26e4-4913ed8ba40c
using Random

# ╔═╡ 36475d28-7581-11eb-20a2-55d445b832f3
using Distributions

# ╔═╡ 6e9dbc6c-757f-11eb-0a43-1b6a3f01f1aa
md"#Involutive MCMC"

# ╔═╡ 89e816f4-757f-11eb-06b3-1d1094d9a25b
md"Involutive MCMC is a mechanism to construct markov chains that compute samples from some target distribution.  Similarly to Metropolis Hastings, it is parameterized by a number of different choices."

# ╔═╡ bf704d84-757f-11eb-26a1-cd7a733b6ac0
rng = Random.MersenneTwister(0)

# ╔═╡ 3884d3b4-7580-11eb-3549-8bbbdd4c0ff7
md"Let's' first construct the target density"

# ╔═╡ 0ab7717a-7581-11eb-3dc8-35536853f805
μ1, μ2 = [2.0, 0.0], [-2.0, 0.0]

# ╔═╡ 1aa926e6-7581-11eb-08ed-2911a3dfb0a8
σ1 = σ2 = [0.5 0
	       0 0.5]

# ╔═╡ d1389aaa-7580-11eb-1338-af09627a4cda
target_dist = MixtureModel([MvNormal(μ1, σ1), MvNormal(μ2, σ2)], [0.5, 0.5]);

# ╔═╡ 4b235bfe-7581-11eb-2a19-092b27730c90
xyrng = -5:0.1:5

# ╔═╡ 4029729a-7581-11eb-2639-51a448011a48
Plots.surface(xyrng, xyrng, (x, y) -> pdf(target_dist, [x, y]))

# ╔═╡ 7519366c-7580-11eb-3b9e-edc42831b839
target(x) = pdf(target_dist, x)

# ╔═╡ cd7804ea-7581-11eb-20b0-8de7d6371441
logtarget(x) = logpdf(target_dist, x)

# ╔═╡ 909b419a-7581-11eb-2381-93c6f4ee6f38
target([2.0, 0.0])

# ╔═╡ 7e20ee3a-7580-11eb-3acf-5906a2c6374a
md"Involution MCMC requires that we define an auxiliary distribution $p(v|x)$"

# ╔═╡ 5e4a80c4-7582-11eb-0694-2d1d9418b6b6
x0 = rand(target_dist)

# ╔═╡ 76dca6f4-7586-11eb-0b9e-f78d1b47240c
p_vₓ(v, x) = pdf(MvNormal(x, 1), v)

# ╔═╡ 39e5449e-75aa-11eb-0831-1986962d0bee
logp_vₓ(v, x) = logpdf(MvNormal(x, 1), v)

# ╔═╡ 662c766e-7582-11eb-3150-513857e0213f
function Vₓ(rng, x)
	v = rand(MvNormal(x, 1))
	# (v, pdf(MvNormal(x, 1), v))
end

# ╔═╡ 9c92e826-7582-11eb-34a2-979d09caac22
involution(x, v) = (v, x)

# ╔═╡ 925c225c-7580-11eb-1e20-85f296118996
samples = imcmc(rng, logtarget,  Vₓ, logp_vₓ, involution, x0; n = 100000)

# ╔═╡ e435a728-7586-11eb-1f1c-e5ff17b67e31
unpact(samples) = [[sample[i] for sample in samples] for i = 1:2]

# ╔═╡ d5607b06-7586-11eb-313e-d5acfad97d7d
Plots.histogram2d(unpact(samples)..., nbins = 100)

# ╔═╡ Cell order:
# ╠═6e9dbc6c-757f-11eb-0a43-1b6a3f01f1aa
# ╠═80b0b83e-757f-11eb-1512-4b62350fb830
# ╠═8374fde4-757f-11eb-2e1c-abe5ecf25d02
# ╠═86ae4f9e-757f-11eb-07fd-9daa27aae41a
# ╠═30e3b7d8-7580-11eb-26e4-4913ed8ba40c
# ╠═36475d28-7581-11eb-20a2-55d445b832f3
# ╠═89e816f4-757f-11eb-06b3-1d1094d9a25b
# ╠═bf704d84-757f-11eb-26a1-cd7a733b6ac0
# ╠═3884d3b4-7580-11eb-3549-8bbbdd4c0ff7
# ╠═0ab7717a-7581-11eb-3dc8-35536853f805
# ╠═1aa926e6-7581-11eb-08ed-2911a3dfb0a8
# ╠═d1389aaa-7580-11eb-1338-af09627a4cda
# ╠═4b235bfe-7581-11eb-2a19-092b27730c90
# ╠═4029729a-7581-11eb-2639-51a448011a48
# ╠═7519366c-7580-11eb-3b9e-edc42831b839
# ╠═cd7804ea-7581-11eb-20b0-8de7d6371441
# ╠═909b419a-7581-11eb-2381-93c6f4ee6f38
# ╠═7e20ee3a-7580-11eb-3acf-5906a2c6374a
# ╠═5e4a80c4-7582-11eb-0694-2d1d9418b6b6
# ╠═76dca6f4-7586-11eb-0b9e-f78d1b47240c
# ╠═39e5449e-75aa-11eb-0831-1986962d0bee
# ╠═662c766e-7582-11eb-3150-513857e0213f
# ╠═9c92e826-7582-11eb-34a2-979d09caac22
# ╠═925c225c-7580-11eb-1e20-85f296118996
# ╠═e435a728-7586-11eb-1f1c-e5ff17b67e31
# ╠═d5607b06-7586-11eb-313e-d5acfad97d7d

max_stars_repo_name: zenna/expect

max_issues_repo_name: zenna/expect

max_forks_repo_name: zenna/expect


text:
import ..UncertainDatasets.AbstractUncertainValueDataset
import ..UncertainDatasets.UncertainDataset
import ..UncertainValues.UncertainScalarKDE

abstract type SamplingConstraint end

"""
    NoConstraint

A (non)constraint indicating that the distribution furnishing an uncertain value
should be sampled its entire support.
"""
struct NoConstraint <: SamplingConstraint end

#########################################################################
# Sampling constraints for regular data (i.e. not age/depth/time index...,
# but the values associated to those indices).
#########################################################################

abstract type ValueSamplingConstraint <: SamplingConstraint end

"""
    TruncateLowerQuantile(lower_quantile::Float64)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated below at some quantile.
"""
struct TruncateLowerQuantile <: ValueSamplingConstraint
    lower_quantile::Float64
end

"""
    TruncateUpperQuantile(upper_quantile::Float64)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated above at some quantile.
"""
struct TruncateUpperQuantile <: ValueSamplingConstraint
    upper_quantile::Float64
end

"""
    TruncateQuantiles(lower_quantile::Float64, upper_quantile::Float64)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated at some quantile quantile
`(lower_quantile, upper_quantile)`.
"""
struct TruncateQuantiles{T1<:Real, T2<:Real} <: ValueSamplingConstraint
    lower_quantile::T1
    upper_quantile::T2

    function TruncateQuantiles(lower_quantile::T1, upper_quantile::T2) where {T1, T2}
        err_msg = "Need 0 <= lower_quantile < upper_quantile <= 1"

        if !(lower_quantile < upper_quantile && 0.0 <= lower_quantile < upper_quantile <= 1.0)
            throw(DomainError(err_msg * " (got lo = $lower_quantile, hi = $upper_quantile)"))
        else
            new{T1, T2}(lower_quantile, upper_quantile)
        end
    end
end

"""
    TruncateStd(nσ::Number)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated at the mean ± `nσ` (`n` standard deviations).

## Notes

- Beware when you apply the `TruncateStd` constraint to a (usually a numeric)
    population with a small value range. With `nσ` small, you might end up with
    a population mean *between* the actual values, so that the range
    `[mean(pop) - nσ*std(pop), mean(pop) + nσ*std(pop)]` returns `nothing`.
"""
struct TruncateStd{T<:Number} <: ValueSamplingConstraint
    nσ::T

    function TruncateStd(nσ::T) where T

        if nσ <= 0
            err_str = "TruncateStd must be initialised with nσ strictly positive"
            throw(DomainError(err_str *  " (got nσ = $nσ)"))
        else
            new{T}(nσ)
        end
    end
end

"""
    TruncateMinimum(min::Number)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated below at some specified minimum value.
"""
struct TruncateMinimum{T<:Number} <: ValueSamplingConstraint
    min::T
end

"""
    TruncateMaximum(max::Number)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated above at some specified maximum value.
"""
struct TruncateMaximum{T<:Number} <: ValueSamplingConstraint
    max::T
end

"""
    TruncateRange(min::Number, max::Number)

A constraint indicating that the distribution furnishing an uncertain value
should be truncated at some range `[min, max]`.
"""
struct TruncateRange{T1, T2} <: ValueSamplingConstraint
    min::T1
    max::T2

    function TruncateRange(min::T1, max::T2) where {T1, T2}
        if min < max
            return new{T1, T2}(min, max)
        else
            err_msg = "Cannot create TruncateRange instance. Need min < max"
            throw(DomainError(err_msg * " (got min = $min, max = $max)"))
        end
    end
end

export
SamplingConstraint,
NoConstraint,

ValueSamplingConstraint,
TruncateLowerQuantile,
TruncateUpperQuantile,
TruncateQuantiles,
TruncateMinimum,
TruncateMaximum,
TruncateRange,
TruncateStd

#########################################################################
# Sampling constraints for sample indices (time index, age, depth, etc...)
# Often, these need to be sampled to obey some physical criteria (i.e.,
# observations are from physical samples lying above each other, so the order
# of the observations cannot be mixed).
#########################################################################
include("ordered_sequences/ordered_sequence_algorithms.jl")

"""
    IndexSamplingConstraint

An abstract type for sampling constraints valid only for indices.
"""
abstract type IndexSamplingConstraint <: SamplingConstraint end

#########################################################################
# Sequential sampling constraints
#########################################################################

abstract type SequentialSamplingConstraint end

# Add the ordered sampling scheme to the seqential sampling constraints,
# because that's all they affect. Defaults to `StartToEnd`.
(::Type{SSC})() where SSC<:SequentialSamplingConstraint = SSC(StartToEnd())

"""
    StrictlyIncreasing

A sampling constraint indicating element-wise sampling of the uncertain values in a dataset,
such that the values of the draw are strictly increasing in magnitude.

Typically used when there are known, physical constraints on the measurements.
For example, geochemical measurements of sediments at different depths of a sediment core
are taken at physically separate depths in the core. Thus, the order of the indices cannot
be flipped, and must be strictly decreasing/increasing.
"""
struct StrictlyIncreasing{OA<:OrderedSamplingAlgorithm} <: SequentialSamplingConstraint
    ordered_sampling_algorithm::OA
end

"""
    StrictlyDecreasing

A sampling constraint indicating element-wise sampling of the uncertain values in a dataset,
such that the values of the draw are strictly decreasing in magnitude.

Typically used when there are known, physical constraints on the measurements.
For example, geochemical measurements of sediments at different depths of a sediment core
are taken at physically separate depths in the core. Thus, the order of the indices cannot
be flipped, and must be strictly decreasing/increasing.
"""
struct StrictlyDecreasing{OA<:OrderedSamplingAlgorithm} <: SequentialSamplingConstraint
    ordered_sampling_algorithm::OA
end

export
IndexSamplingConstraint,
SequentialSamplingConstraint,
StrictlyIncreasing,
StrictlyDecreasing


text:
@safetestset "Setting and getting headers" begin

  using Genie, HTTP
  using Genie.Router, Genie.Responses

  route("/headers") do
    setheaders("X-Foo-Bar" => "Baz")

    "OK"
  end

  route("/headers", method = OPTIONS) do
    setheaders(["X-Foo-Bar" => "Bazinga", "Access-Control-Allow-Methods" => "GET, POST, OPTIONS"])
    setstatus(200)

    "OOKK"
  end

  port = rand(8500:8900)

  up(port; open_browser = false, verbose = true)

  response = HTTP.request("GET", "http://localhost:$port/headers") # unhandled, should get default response
  @test response.status == 200
  @test String(response.body) == "OK"
  @test Dict(response.headers)["X-Foo-Bar"] == "Baz"
  @test get(Dict(response.headers), "Access-Control-Allow-Methods", nothing) == nothing

  response = HTTP.request("OPTIONS", "http://localhost:$port/headers") # handled
  @test response.status == 200
  @test String(response.body) == "OOKK"
  @test Dict(response.headers)["X-Foo-Bar"] == "Bazinga"
  @test get(Dict(response.headers), "Access-Control-Allow-Methods", nothing) == "GET, POST, OPTIONS"

  down()
  sleep(1)
  server = nothing

end


text:
const defdir = joinpath(dirname(@__FILE__), "..", "datasets")

function getmovielensdata(dir)
   	mkpath(dir)
   	path = download("http://files.grouplens.org/datasets/movielens/ml-100k.zip")
   	run(unpack_cmd(path, dir, ".zip", ""))
end

function getmovielensdata1m(dir)
   	mkpath(dir)
   	path = download("http://files.grouplens.org/datasets/movielens/ml-1m.zip")
   	run(unpack_cmd(path, dir, ".zip", ""))
end

"""
    MovieLens()::Persa.Dataset

Return MovieLens 100k dataset.
"""
function MovieLens()::Persa.Dataset
   	filename = "$(defdir)/ml-100k/u.data"

   	isfile(filename) || getmovielensdata(defdir)

   	file = CSV.read(filename, DataFrame, delim = '\t',
					header = [:user, :item, :rating, :timestamp],
					types = [Int, Int, Int, Int])

   	return Persa.Dataset(file)
end

"""
    MovieLens1M()::Persa.Dataset

Return MovieLens 1M dataset.
"""
function MovieLens1M()::Persa.Dataset
    filename = "$(defdir)/ml-1m/ratings.dat"

    isfile(filename) || getmovielensdata1m(defdir)

    file = CSV.read(filename, DataFrame, delim = "::",
						header = [:user, :item, :rating, :timestamp],
						types = [Int, Int, Int, Int])

    df = DataFrame()

   	df[!, :user] = convert(Array{Int}, file[!, :user])
   	df[!, :item] = convert(Array{Int}, file[!, :item])
   	df[!, :item] = labelencode(labelmap(df[!, :item]), df[!, :item])
   	df[!, :rating] = convert(Array{Int}, file[!, :rating])
   	df[!, :timestamp] = convert(Array{Int}, file[!, :timestamp])

    return Persa.Dataset(df)
end


text:
using CSV
using DataFrames
using Definitions

household_name = "model_households"
people_name = "model_people"

hh_dataset = CSV.File("$(MODEL_DATA_DIR)/$(household_name).tab", delim='\t' ) |> DataFrame
people_dataset = CSV.File("$(MODEL_DATA_DIR)/$(people_name).tab", delim='\t') |> DataFrame

scottish_hhlds = hh_dataset[(hh_dataset.region .== 299999999),:]
scottish_people = join(people_dataset, scottish_hhlds,on=[:hid,:data_year],kind = :semi)

CSV.write("$(MODEL_DATA_DIR)model_households_scotland.tab", scottish_hhlds, delim = "\t")
CSV.write("$(MODEL_DATA_DIR)model_people_scotland.tab", scottish_people, delim = "\t")


text:
##################################################################################
# This file is part of StateSpaceEcon.jl
# BSD 3-Clause License
# Copyright (c) 2020, Bank of Canada
# All rights reserved.
##################################################################################

"""
    1dsolvers.jl

This file contains a couple of solvers used in SteadyStateSolver.
The functions here solve a problem where a multivariate function is
solved in a single coordinate, keeping the other coordinates fixed.
We have 1d- Newton and a variant of the bisection method.

### Important note:
These functions are used in pre-solving the steady state.
They have a peculiar feature that they fail if the first derivative is zero.
Normally, if the residual is zero, that would be a solution regardless of
the first derivative. However, in the context of presolving the steady state
we have to consider that the first derivative might be zero because the variable
actually cancels out of the equation. In that case, any value would
result in zero residual, but we can't consider that to be a solution.
For this reason, the implementations in this file deliberately fail
if the derivative is zero, even if the residual is zero.
"""

# This line intentionally left blank

"""
    newton1!(F, x, i; <options>)

Solve the equation `F(x) = 0` for `x[i]` keeping the other values of `x` fixed.
The input value of `x[i]` is used as the initial guess and it is updated in place.
Other entries of `x` are not accessed at all.
Return `true` upon success, or `false` otherwise.

### Function `F`
The function `F` must accept a single argument `x`, which is an array, and must return a
tuple of two things: the value of `F` (numeric scalar) and the gradient of `F`
(an array of the same shape as x). Only the i-th index of the gradient array is used.

### Options
  * `maxiter = 5` - maximum number of iterations. The default is small (5) because
  the Newton method either converges very fast or doesn't converge at all.
  * `tol = 1e-8` - desired tolerance of the solution.

### Notes
The `tol` value is used for a stopping criterion and also for diagnosing problems.

!!! warning
    This is an internal function used by the steady state solver. In the future it might be
    removed or modified.
"""
function newton1!(F::Function, vals::AbstractVector{T}, ind::Integer; maxiter=5, tol=sqrt(eps(T)))::Bool where T <: AbstractFloat
    fval, Jval = F(vals)
    err = tol * abs(fval) + tol
    for iter = 1:maxiter
        if abs(Jval[ind]) < tol
            return false
        end
        if abs(fval) < err
            return true
        end
        dx = fval / Jval[ind]
        vals[ind] -= dx
        fval, Jval = F(vals)
    end
    return abs(fval) < err
end

"""
    bisect!(F, x, i, dF; <options>)

Solve the equation `F(x) = 0` for `x[i]` keeping the other values of `x` fixed.
The input value of `x[i]` is used as the initial guess and it is updated in place.
Other entries of `x` are not accessed at all. Return `true` upon success, or `false` otherwise.

### Arguments
  * `F` - A function that must accept a single argument `x`, which is an array, and must return
  the value of `F` (numeric scalar).
  * `x` - An array.
  * `i` - The index identifying the dimension in which we're solving the problem.
  * `dF` - A numeric value. This must equal the partial derivative of F with respect to `x[i]`
   at the input value of `x[i]`.

### Options
  * `maxiter = 500` - maximum number of iterations. The default is large (500) because
  this method sometimes converges slowly.
  * `tol = 1e-8` - desired tolerance of the solution.

!!! warning
    This is an internal function used by the steady state solver. In the future it might be
    removed or modified.
"""
function bisect!(F::Function, vals::AbstractVector{T}, ind::Int64, deriv::T; maxiter=500, tol=sqrt(eps(T)))::Bool where T <: AbstractFloat
    # This code is a mess. Someone please clean it up!

    # Convenience wrapper - evaluate F as if it were a univariate function
    # and trap any errors (e.g. inadmissible arguments) returning NaN.
    # With each call, the current value of vals[i] is updated in place.
    f(x) = (vals[ind] = x; try; F(vals); catch; NaN; end)

    """
        _do_bisect(x0, f0, x1, f1)

    Perform the iteration of the bisection method.

    The two initial points are assumed to bracket the solution, i.e. f0 and f1 have different signs.
    On each iteration we replace one of the endpoints with the midpoint, always maintaining
    that property.

    Return `true` if either the length of the interval shrinks to the machine accuracy
    of if the function value is with `tol` of zero. Return `false` otherwise.

    Note that here we call the function f(x) defined above. In particular, the value of
    x that solves the problem is written directly into `vals[i]`.
    """
    function _do_bisect(x0, f0, x1, f1)
        for it = 1:maxiter
            abs(x0 - x1) <= eps(x0) && return true
            xp = 0.5 * (x1 + x0)
            fp = f(xp)
            abs(fp) < tol && return true
            if fp * f0 < 0.0
                x1 = xp
                f1 = fp
            else
                x0 = xp
                f0 = fp
            end
        end
        return f(0.5 * (x0 + x1)) < tol
    end

    #######################################################################
    # The problem is to find two points that bracket the solution, i.e. such
    # that f(x0) and f(x1) have opposite signs.

    # With the sign of f0 and the known derivative at x0 we can search for x1
    # in the direction in which the function approaches zero.)
    # if the derivative is zero at the initial point, that's an argument error
    abs(deriv) < 1e-10 && return false
    isnan(deriv) && return false

    # First point - that's easy
    x0 = vals[ind]
    f0 = f(x0)
    # is x0 the solution?
    abs(f0) < tol && return true
    isnan(f0) && return false

    # Try a line search in the Newton direction
    step = -f0 / deriv
    x1 = x0 + step
    f1 = f(x1)
    while isnan(f1) || abs(f1) > 1e5 * abs(f0)
        # If x1 is inadmissible or too far off to infinity try a smaller step
        step *= 0.5
        step < eps(T) && return false
        x1 = x0 + step
        f1 = f(x1)
    end
    # is x1 the solution?
    abs(f1) < tol && return true
    # does (x0, x1) bracket the solution?
    f1 * f0 < 0.0 && return _do_bisect(x0, f0, x1, f1)

    # We have two points (x0, f0) and (x1, f1), but f0 and f1 are of the same sign.
    # It may be that there's a root between them, but we overshot, or that
    # the root is beyond x1 (from x0)

    # try the midpoint
    x2 = 0.5 * (x0 + x1)
    f2 = f(x2)
    # if x2 the solution?
    abs(f2) < tol && return true
    # does (x0, x2) bracket the solution?
    if f0 * f2 < 0.0
        # yes, then (x1, x2) also bracket the solution. Hmmm!
        return abs(f0) < abs(f1) ? _do_bisect(x0, f0, x2, f2) : _do_bisect(x1, f1, x2, f2)
    end

    # We have three points with the same sign of f.
    # Desperately try a few iterations of inverse quadratic interpolation.
    for i = 1:20
        # Approximate f-inverse with a quadratic through the three points we have and set x3 = f-inverse(0)
        x3 = f0 * f1 * x2 / (f2 - f0) / (f2 - f1) + f0 * x1 * f2 / (f1 - f0) / (f1 - f2) + x0 * f1 * f2 / (f0 - f1) / (f0 - f2)
        f3 = f(x3)
        # is it a bad point?
        (isnan(f3) || isinf(f3)) && break
        # is x3 a solution?
        abs(f3) < tol && return true
        # is x3 on the opposite side of the root?
        (f0 * f3 < 0.0) && return _do_bisect(x0, f0, x3, f3)
        f0, f1, f2 = f1, f2, f3
        x0, x1, x2 = x1, x2, x3
    end
    # all else failed, try brute-force interval search
    step = -sign(f0) * sign(deriv) * 0.01
    for it = 1:30
        step *= 2.0
        x1 = x0 + step
        f1 = f(x1)
        abs(f1) < tol && return true
        f0 * f1 < 0.0 && return _do_bisect(x0, f0, x1, f1)
    end
    # we failed miserably! :-(
    return false
end


text:
function bigibbs(T::Int64, rho::Float64)
    x = ones(T+1)
    y = ones(T+1)
    for t = 1:T
        x[t+1] = randn() * sqrt(1-rho^2) + rho*y[t]
        y[t+1] = randn() * sqrt(1-rho^2) + rho*x[t+1]
    end
    return x, y
end

## example
x, y = bigibbs(Int64(2e6), 0.5)

# ## plot
# using PyPlot
# plt[:subplot](211)
# plt[:hist](x)
# ylabel(L"$x$")
# plt[:subplot](212)
# plt[:hist](y)
# ylabel(L"$y$")
# plt[:tight_layout]()
# plt[:savefig]("hist-gibbs-julia.png")

max_stars_repo_name: szcf-weiya/MCMC

max_issues_repo_name: szcf-weiya/MCMC

max_forks_repo_name: szcf-weiya/MCMC


text:
mutable struct DynamicObstaclesDirected{T, R} <: AbstractGridWorld
    world::GridWorldBase{Tuple{Agent, Wall, Obstacle, Goal}}
    agent_pos::CartesianIndex{2}
    agent_dir::AbstractDirection
    reward::T
    rng::R
    terminal_reward::T
    goal_pos::CartesianIndex{2}
    num_obstacles::Int
    obstacle_pos::Vector{CartesianIndex{2}}
    terminal_penalty::T
    done::Bool
end

@generate_getters(DynamicObstaclesDirected)
@generate_setters(DynamicObstaclesDirected)

mutable struct DynamicObstaclesUndirected{T, R} <: AbstractGridWorld
    world::GridWorldBase{Tuple{Agent, Wall, Obstacle, Goal}}
    agent_pos::CartesianIndex{2}
    reward::T
    rng::R
    terminal_reward::T
    goal_pos::CartesianIndex{2}
    num_obstacles::Int
    obstacle_pos::Vector{CartesianIndex{2}}
    terminal_penalty::T
    done::Bool
end

@generate_getters(DynamicObstaclesUndirected)
@generate_setters(DynamicObstaclesUndirected)

#####
# Directed
#####

function DynamicObstaclesDirected(; T = Float32, height = 8, width = 8, num_obstacles = floor(Int, sqrt(height * width) / 2), rng = Random.GLOBAL_RNG)
    objects = (AGENT, WALL, OBSTACLE, GOAL)
    world = GridWorldBase(objects, height, width)

    room = Room(CartesianIndex(1, 1), height, width)
    place_room!(world, room)

    goal_pos = CartesianIndex(height - 1, width - 1)
    world[GOAL, goal_pos] = true

    agent_pos = CartesianIndex(2, 2)
    world[AGENT, agent_pos] = true

    agent_dir = RIGHT
    reward = zero(T)
    terminal_reward = one(T)
    obstacle_pos = CartesianIndex{2}[]
    terminal_penalty = -one(T)
    done = false

    env = DynamicObstaclesDirected(world, agent_pos, agent_dir, reward, rng, terminal_reward, goal_pos, num_obstacles, obstacle_pos, terminal_penalty, done)

    RLBase.reset!(env)

    return env
end

RLBase.state_space(env::DynamicObstaclesDirected, ::RLBase.Observation, ::RLBase.DefaultPlayer) = nothing
const DYNAMIC_OBSTACLES_DIRECTED_LAYERS = SA.SVector(2, 3, 4)
RLBase.state(env::DynamicObstaclesDirected, ::RLBase.Observation, ::RLBase.DefaultPlayer) = get_grid(get_world(env), get_agent_pos(env), get_agent_dir(env), get_half_size(env), DYNAMIC_OBSTACLES_DIRECTED_LAYERS)

RLBase.state_space(env::DynamicObstaclesDirected, ::RLBase.InternalState, ::RLBase.DefaultPlayer) = nothing
RLBase.state(env::DynamicObstaclesDirected, ::RLBase.InternalState, ::RLBase.DefaultPlayer) = (copy(get_grid(env)), get_agent_dir(env))

RLBase.action_space(env::DynamicObstaclesDirected, ::RLBase.DefaultPlayer) = (DIRECTED_NAVIGATION_ACTIONS..., NO_MOVE)
RLBase.reward(env::DynamicObstaclesDirected, ::RLBase.DefaultPlayer) = get_reward(env)
RLBase.is_terminated(env::DynamicObstaclesDirected) = get_done(env)

function RLBase.reset!(env::DynamicObstaclesDirected{T}) where {T}
    world = get_world(env)
    rng = get_rng(env)

    for pos in env.obstacle_pos
        world[OBSTACLE, pos] = false
    end

    world[AGENT, get_agent_pos(env)] = false
    world[GOAL, get_goal_pos(env)] = false

    new_goal_pos = rand(rng, pos -> !any(@view world[:, pos]), env)
    set_goal_pos!(env, new_goal_pos)
    world[GOAL, new_goal_pos] = true

    env.obstacle_pos = CartesianIndex{2}[]

    for i in 1:env.num_obstacles
        pos = rand(rng, pos -> !any(@view world[:, pos]), env)
        world[OBSTACLE, pos] = true
        push!(env.obstacle_pos, pos)
    end

    agent_start_pos = rand(rng, pos -> !any(@view world[:, pos]), env)
    set_agent_pos!(env, agent_start_pos)
    world[AGENT, agent_start_pos] = true

    set_agent_dir!(env, rand(rng, DIRECTIONS))

    set_reward!(env, zero(T))
    set_done!(env, false)

    return nothing
end

function (env::DynamicObstaclesDirected{T})(action::AbstractTurnAction) where {T}
    world = get_world(env)
    update_obstacles!(env)

    new_dir = turn(action, get_agent_dir(env))
    set_agent_dir!(env, new_dir)

    if world[GOAL, get_agent_pos(env)]
        set_done!(env, true)
        set_reward!(env, get_terminal_reward(env))
    elseif iscollision(env)
        set_done!(env, true)
        set_reward!(env, get_terminal_penalty(env))
    else
        set_done!(env, false)
        set_reward!(env, zero(T))
    end

    return nothing
end

function (env::DynamicObstaclesDirected{T})(action::AbstractMoveAction) where {T}
    world = get_world(env)
    update_obstacles!(env)

    agent_pos = get_agent_pos(env)
    dest = move(action, get_agent_dir(env), agent_pos)
    if !world[WALL, dest]
        world[AGENT, agent_pos] = false
        set_agent_pos!(env, dest)
        world[AGENT, dest] = true
    end

    if world[GOAL, get_agent_pos(env)]
        set_done!(env, true)
        set_reward!(env, get_terminal_reward(env))
    elseif iscollision(env)
        set_done!(env, true)
        set_reward!(env, get_terminal_penalty(env))
    else
        set_done!(env, false)
        set_reward!(env, zero(T))
    end

    return nothing
end

#####
# Undirected
#####

function DynamicObstaclesUndirected(; T = Float32, height = 8, width = 8, num_obstacles = floor(Int, sqrt(height * width) / 2), rng = Random.GLOBAL_RNG)
    objects = (AGENT, WALL, OBSTACLE, GOAL)
    world = GridWorldBase(objects, height, width)

    room = Room(CartesianIndex(1, 1), height, width)
    place_room!(world, room)

    goal_pos = CartesianIndex(height - 1, width - 1)
    world[GOAL, goal_pos] = true

    agent_pos = CartesianIndex(2, 2)
    world[AGENT, agent_pos] = true

    reward = zero(T)
    terminal_reward = one(T)
    obstacle_pos = CartesianIndex{2}[]
    terminal_penalty = -one(T)
    done = false

    env = DynamicObstaclesUndirected(world, agent_pos, reward, rng, terminal_reward, goal_pos, num_obstacles, obstacle_pos, terminal_penalty, done)

    RLBase.reset!(env)

    return env
end

RLBase.state_space(env::DynamicObstaclesUndirected, ::RLBase.Observation, ::RLBase.DefaultPlayer) = nothing
const DYNAMIC_OBSTACLES_UNDIRECTED_LAYERS = SA.SVector(2, 3, 4)
RLBase.state(env::DynamicObstaclesUndirected, ::RLBase.Observation, ::RLBase.DefaultPlayer) = get_grid(get_world(env), get_agent_pos(env), get_half_size(env), DYNAMIC_OBSTACLES_UNDIRECTED_LAYERS)

RLBase.state_space(env::DynamicObstaclesUndirected, ::RLBase.InternalState, ::RLBase.DefaultPlayer) = nothing
RLBase.state(env::DynamicObstaclesUndirected, ::RLBase.InternalState, ::RLBase.DefaultPlayer) = copy(get_grid(env))

RLBase.action_space(env::DynamicObstaclesUndirected, player::RLBase.DefaultPlayer) = (UNDIRECTED_NAVIGATION_ACTIONS..., NO_MOVE)
RLBase.reward(env::DynamicObstaclesUndirected, ::RLBase.DefaultPlayer) = get_reward(env)
RLBase.is_terminated(env::DynamicObstaclesUndirected) = get_done(env)

function RLBase.reset!(env::DynamicObstaclesUndirected{T}) where {T}
    world = get_world(env)
    rng = get_rng(env)

    for pos in env.obstacle_pos
        world[OBSTACLE, pos] = false
    end

    world[AGENT, get_agent_pos(env)] = false
    world[GOAL, get_goal_pos(env)] = false

    new_goal_pos = rand(rng, pos -> !any(@view world[:, pos]), env)
    set_goal_pos!(env, new_goal_pos)
    world[GOAL, new_goal_pos] = true

    env.obstacle_pos = CartesianIndex{2}[]

    for i in 1:env.num_obstacles
        pos = rand(rng, pos -> !any(@view world[:, pos]), env)
        world[OBSTACLE, pos] = true
        push!(env.obstacle_pos, pos)
    end

    agent_start_pos = rand(rng, pos -> !any(@view world[:, pos]), env)
    set_agent_pos!(env, agent_start_pos)
    world[AGENT, agent_start_pos] = true

    set_reward!(env, zero(T))
    set_done!(env, false)

    return nothing
end

function (env::DynamicObstaclesUndirected{T})(action::AbstractMoveAction) where {T}
    world = get_world(env)
    update_obstacles!(env)

    agent_pos = get_agent_pos(env)
    dest = move(action, agent_pos)
    if !world[WALL, dest]
        world[AGENT, agent_pos] = false
        set_agent_pos!(env, dest)
        world[AGENT, dest] = true
    end

    if world[GOAL, get_agent_pos(env)]
        set_done!(env, true)
        set_reward!(env, get_terminal_reward(env))
    elseif iscollision(env)
        set_done!(env, true)
        set_reward!(env, get_terminal_penalty(env))
    else
        set_done!(env, false)
        set_reward!(env, zero(T))
    end

    return nothing
end

#####
# Common
#####

iscollision(env::Union{DynamicObstaclesDirected, DynamicObstaclesUndirected}) = get_world(env)[OBSTACLE, get_agent_pos(env)]

function valid_obstacle_dest(env::Union{DynamicObstaclesDirected, DynamicObstaclesUndirected}, pos::CartesianIndex{2})
    world = get_world(env)
    candidate_pos = CartesianIndices((pos[1]-1:pos[1]+1, pos[2]-1:pos[2]+1))
    return filter(p -> (!any(@view world[:, p]) || p == pos), candidate_pos)
end

function update_obstacles!(env::Union{DynamicObstaclesDirected, DynamicObstaclesUndirected})
    world = get_world(env)
    rng = get_rng(env)
    for (i, pos) in enumerate(env.obstacle_pos)
        world[OBSTACLE, pos] = false
        new_pos = rand(rng, valid_obstacle_dest(env, pos))
        env.obstacle_pos[i] = new_pos
        world[OBSTACLE, new_pos] = true
    end

    return nothing
end