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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el)
        el
    end
end

# ╔═╡ a38a9620-6bea-11eb-2293-c5469f2d5bdc
begin
	#try
		using PlutoUI
		using Plots
		using LinearAlgebra
		using SparseArrays
		using DataFrames
		using Random
		md"""
		#### Packages

		All needed Packages available :) """
	#=
	catch
		using Pkg;
		Pkg.activate(mktempdir())
		Pkg.add("PlutoUI")
		Pkg.add("Plots")
		Pkg.add("Random")
		#Pkg.add("LinearAlgebra")
		#Pkg.add("SparseArrays")
		#Pkg.add("DataFrames")

		using PlutoUI
		using Plots
		using LinearAlgebra
		using SparseArrays
		using DataFrames
		using Random
		md"""
		#### Packages

		Some Package sources not added, this will take approx. 3 minutes"""
	end
	=#
end

# ╔═╡ 5f9b8270-79c4-11eb-0780-03bde90c8d2b
md"""
# Sailing deviations ⛵

## Explanation:

- We consider the motion of the ship in discrete time steps

- Initially you fix some parameters:

   1) direction of the random ocean current (N,E,S,W)  [fixed thoughout the sailing trip]

   2) probability $P_{oc}$ that the ocean current is present in one time step

   3) probability $P_{Pascal}$ that Pascal makes an error in one time step

- at each time step the following **random variables** are defined:

   	a) $X$ for the **sailing directions** (*North*, *East*, *South* and *West*). We use the assignment (1,2,3,4)

    b) $Y$ for the **sailing deviations** , with the following assignments:

   * *port deviation* $\,\,\rightarrow -1$,

   * *no deviation*   $\,\,\,\,\rightarrow 0$,

   * *starboard deviation* $\rightarrow +1$

   the probability for one of the two deviations is $P_{Pascal}/2$, for no deviation it is $1-P_{Pascal}$

  c) with probability $P_{oc}$ the occean current leads to a sailing deviation $\pm 1$ if the ocean current acts perpendicular to the actual sailing direction. The sign is chose according to the direction where the ocean current comes from.

"""

# ╔═╡ 7dafedbe-7aa3-11eb-2054-79fd4db63d4b
md"""
## Experimental setup
"""

# ╔═╡ c1d63b90-86b4-11eb-209d-8985ce0e2f82
md" Choose a random **seed** 👉 $(@bind seed Slider(1:1:200, default=1, show_value = true)) "

# ╔═╡ 05f72bc0-6c45-11eb-3602-c955811f9acf

md" Choose the **number of data points** Pascal is using in her statistics 👉 $(@bind n_data_points Slider(500:100:2000, default=1000, show_value = true)) "

# ╔═╡ 70049580-6bea-11eb-390b-d3013dd12235
md"Choose **probability** of the **ocean current** to lead to a deviation 👉 $(@bind ocean_current_prob Slider(0:0.05:0.3, default = 0.15, show_value = true)) "

# ╔═╡ deb2ef40-6bea-11eb-3a13-c9642d262b93
md"Choose **probability** of **Pascal to fail on keeping the course** 👉 $(@bind pascal_fail_prob Slider(0:0.05:0.3, default = 0.1, show_value = true)) "

# ╔═╡ 08bf49de-6bec-11eb-1b80-5f6e74cbb8d0
md"""
Choose **direction of ocean current** $(@bind direction_of_current Select([ "north" => "North ⬆", "east" => "East ➡", "south" => "South ⬇", "west" => "West ⬅"]))
"""

# ╔═╡ 6345d02e-7a69-11eb-0e07-a519c0d7b2d0
md"""
#### frequencies of pairs of random sailing direction and random sailing deviations
"""

# ╔═╡ 0a2a4d9c-7a89-11eb-23ce-dfd7d38b0ab8
md"""
## Various computational steps
"""

# ╔═╡ da7a4c84-7a77-11eb-3e98-ff115e06df23

begin
function myDataFrame(table_in)
		if typeof(table_in[1]) == Int64
			table = table_in
		else
			table = round.(table_in,digits=3)
		end
Markdown.parse("""
| direction    |  deviation starboard    | no deviation  |deviation port|
| :------------|:-------------| :-----| :--|
| North:      | $(table[1,1]) |  $(table[1,2])  | $(table[1,3]) |
| East:      | $(table[2,1])      |   $(table[2,2]) | $(table[2,3]) |
| South: | $(table[3,1])      |   $(table[3,2]) | $(table[3,3]) |
| West: | $(table[4,1])      |    $(table[4,2]) | $(table[4,3]) |
""")

end
	md"#### function defintion"
end

# ╔═╡ 0a0abad2-86b5-11eb-1d3f-4d7e79c32419
begin
	rng = MersenneTwister(seed);
	direction = rand(rng, 1:4, n_data_points)
	rr = rand(rng,n_data_points)
	ss = rand(rng,n_data_points)
	md"#### Random number generator, determine random sailing directions and deviations"
end

# ╔═╡ c4582980-6bef-11eb-18e9-0b1732c8d932
begin
	md"#### determine random sailing directions"
end

# ╔═╡ dc84d260-6bef-11eb-1e6c-23d28cf6b1d3
begin
	sail_deviation = zeros(1,n_data_points)
	sail_deviation = (-(rr .<= pascal_fail_prob/2)) + (rr.>= 1-pascal_fail_prob/2)
	# r<= p/2   => -1
	# r>= 1-p/2 => +1
	# p/2 <= r <= 1-p/2   => 0
	md"#### determine deviations due to Pascal's random errors"
end

# ╔═╡ 71561790-6bf1-11eb-1acf-a1a46a8eb3d8
begin
	if direction_of_current == "north"
		left_drift = 2;
		right_drift = 4;
	elseif direction_of_current == "east"
		left_drift = 3 ;
		right_drift = 1;
	elseif direction_of_current == "south"
		left_drift = 4 ;
		right_drift = 2;
	else
		left_drift = 1;
		right_drift = 3;
	end

	added_deviation = (ss .<= ocean_current_prob) .*((-(direction .== left_drift)) + (direction .== right_drift))
	# with prob. ocean_current_prob a random deviation +/- 1 is created
	# the sign depends on the direction of the current selected once and for all
	md"#### determine deviation due to random ocean currents"
end

# ╔═╡ 054eba90-6bf4-11eb-2214-ede88296a7b8
begin
	deviation = sail_deviation .+ added_deviation
	md"#### compute total deviation"
end

# ╔═╡ 4249bb68-7a66-11eb-1b12-e31916ad1504
begin
	table = [[sum(deviation[ direction .==i] .<= -1) for i=1:4] [sum(deviation[ 	direction .==i] .== 0) for i=1:4] [sum(deviation[ direction .==i] .>= 1) for i=1:4]]
	# Example from the episode:
	#table = [17 255 11; 62 178 10; 11 219 12; 11 169 45]
	md"#### compute joint frequencies for random sailing direction and sailing deviations"
end

# ╔═╡ 2a1a57c0-7ab9-11eb-0e60-115736d61684
begin
#df = DataFrame([["North: "; "East:  "; "South: "; "West:"] table], [:direction, :deviation_starboard, :no_deviation, :deviation_port])
df = DataFrame("Direction" => ["North: "; "East:  "; "South: "; "West:"], "Deviation starboard" => table[:,1], "no deviation" => table[:,2], "deviation port" => table[:,3])

myDataFrame(table)
#$(df)
end

# ╔═╡ f6ed4510-79d2-11eb-16b9-87007281ed31
begin

#df = DataFrame([["North: "; "East:  "; "South: "; "West:"] table], [:direction, :deviation_starboard, :no_deviation, :deviation_port])
df2 = DataFrame("Direction" => ["North: "; "East:  "; "South: "; "West:"], "Deviation starboard" => table[:,1]./n_data_points, "no deviation" => table[:,2]./n_data_points, "deviation port" => table[:,3]./n_data_points)

md"""
#### estimated joint probabilities for random sailing direction and random sailing deviations

$(df2)
"""
end

# ╔═╡ 628591be-79be-11eb-278e-954c42f8a638
begin
	joint_prob = table./n_data_points
	#marginal probabilities
	marg_prob_dir = sum(joint_prob, dims=2)
	marg_prob_dev = sum(joint_prob, dims=1)
	#random variables
	X_dir = [0,pi/2,pi,3*pi/2] #[1,2,3,4]#
	X_dev = [-1,0,1]
	#mean values
	Av_dir = sum(X_dir.*marg_prob_dir)
	Av_dev = sum(X_dev.*marg_prob_dev')    # wvl:  transpose
	#grid with local deviations (X-<X>)
	dir = (X_dir.-Av_dir).* ones(3)'
	dev = ones(4) .* (X_dev .- Av_dev)'
	#mean value of weighted product of local deviations: P(X,Y) * (X-<X>) * (Y-<Y>)
	covariance = n_data_points/(n_data_points-1)*[ sum(dir.*dir.*joint_prob) sum(dir.*dev.*joint_prob); sum(dir.*dev.*joint_prob) sum(dev.*dev.*joint_prob)]
	cov12 =round(covariance[1,2],digits=4)
	md"#### compute covariance"
end

# ╔═╡ b859d540-7cd7-11eb-29b5-95d538b7dc0a

md"""

#### Estimated covariance between sailing direction and sailing deviation $C(\textrm{dir},\textrm{dev}) \approx$ **$(cov12)**
"""

# ╔═╡ 1ae179d4-7a6a-11eb-317b-09994dba67d1

md"""

#### Estimated covariance between sailing direction and sailing deviation $C(\textrm{dir},\textrm{dev}) \approx$ **$(cov12)**

---

## Explanation:
Given the table above we want to investigate whether this data set allows to make statements about dependent variables.

$\textrm{CoV}(X,Y) = \sum_{ij} P(X_i,Y_j) \cdot (X_i - \langle X \rangle) \cdot (Y_j - \langle Y \rangle)$

with $\langle X \rangle $ resp. $\langle Y \rangle$ the mean value of the marginal probability distribution $P(X)$ resp. $P(Y)$.

Since the intrinsic probabilites and intrinsic marginal mean values are not given, we use the sample mean values and relative frequencies to estimate them.

In order to estimate the covariance of sailing deviations and sailing directions by  using Pascal's recorded sample we proceed in the following way:

- Use the relative frequencies $\boldsymbol{N}(X_i, Y_j)/N$ to estimate the probabilities $P(X_i,Y_j)$ in the table
- Use this estimated joint probability distribution to calculate the covariance using the formula above.
- Since the used marginal mean values are sample mean values $\overline{\boldsymbol{X}}$ and $\overline{\boldsymbol{Y}}$ obtained from the same sample set we get a bias. To correct for this bias we have to multiply by $\frac{N}{N-1}$.

$\textrm{CoV}(X, Y) \approx \frac{N}{N-1}\sum_{ij} \frac{\boldsymbol{N}_{ij}}{N} \cdot (X_i -  \overline{\boldsymbol{X}}) \cdot (Y_j - \overline{\boldsymbol{Y}} ))$

"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
DataFrames = "~1.2.2"
Plots = "~1.24.0"
PlutoUI = "~0.7.20"
"""

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

[[AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "0bc60e3006ad95b4bb7497698dd7c6d649b9bc06"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.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"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[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 = "0c603255764a1fa0b61752d2bec14cfbd18f7fe8"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+1"

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

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

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

[[Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

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

[[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 = "0fa77022fe4b511826b39c894c90daf5fce3334a"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.17"

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

[[Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[HypertextLiteral]]
git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.3"

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

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

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

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

[[InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[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", "UnicodeFun"]
git-tree-sha1 = "02a083caba3f73e42decb810b2e0740783022978"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.24.0"

[[PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "1e0cb51e0ccef0afc01aab41dc51a3e7f781e8cb"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.20"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "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 = "0f2aa8e32d511f758a2ce49208181f7733a0936a"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.1.0"

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

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

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

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

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

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

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

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

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

[[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"]
git-tree-sha1 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.0+0"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

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

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

# ╔═╡ Cell order:
# ╟─5f9b8270-79c4-11eb-0780-03bde90c8d2b
# ╟─7dafedbe-7aa3-11eb-2054-79fd4db63d4b
# ╟─c1d63b90-86b4-11eb-209d-8985ce0e2f82
# ╟─05f72bc0-6c45-11eb-3602-c955811f9acf
# ╟─70049580-6bea-11eb-390b-d3013dd12235
# ╟─deb2ef40-6bea-11eb-3a13-c9642d262b93
# ╟─08bf49de-6bec-11eb-1b80-5f6e74cbb8d0
# ╟─6345d02e-7a69-11eb-0e07-a519c0d7b2d0
# ╟─2a1a57c0-7ab9-11eb-0e60-115736d61684
# ╟─b859d540-7cd7-11eb-29b5-95d538b7dc0a
# ╟─f6ed4510-79d2-11eb-16b9-87007281ed31
# ╟─1ae179d4-7a6a-11eb-317b-09994dba67d1
# ╟─0a2a4d9c-7a89-11eb-23ce-dfd7d38b0ab8
# ╠═a38a9620-6bea-11eb-2293-c5469f2d5bdc
# ╟─da7a4c84-7a77-11eb-3e98-ff115e06df23
# ╟─0a0abad2-86b5-11eb-1d3f-4d7e79c32419
# ╟─c4582980-6bef-11eb-18e9-0b1732c8d932
# ╟─dc84d260-6bef-11eb-1e6c-23d28cf6b1d3
# ╟─71561790-6bf1-11eb-1acf-a1a46a8eb3d8
# ╟─054eba90-6bf4-11eb-2214-ede88296a7b8
# ╟─4249bb68-7a66-11eb-1b12-e31916ad1504
# ╟─628591be-79be-11eb-278e-954c42f8a638
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: moserjo/bayes-imoox

max_issues_repo_name: moserjo/bayes-imoox

max_forks_repo_name: moserjo/bayes-imoox


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

using Markdown
using InteractiveUtils

# ╔═╡ 4c2e0eae-3841-11eb-0d59-65813cee8451
using Plots, Calculus

# ╔═╡ 0a49708c-3858-11eb-0988-29a07064bace
linkURL = "https://www.desmos.com/calculator/38igphyb3r"

# ╔═╡ 78fe48b6-3841-11eb-2c0e-87abc273de4d
begin
	function f(x)
		sqrt(abs(sin(x)x^2))
	end
end

# ╔═╡ 6b582dc2-3852-11eb-0635-41b6b9ff3646
derivative(f,0)

# ╔═╡ 5311b818-3850-11eb-01b6-457d4866d0ee
begin

	function slope(xl,xr,yl,yr,x)
		m = (yr-yl)/(xr-xl)
		b = yl-m*xl
		m*x+b
	end
	function slope(m::Float64,y0,x0,x)
		b = y0-m*x0
		y0 + m*(x-x0)
	end
end

# ╔═╡ c7976676-3858-11eb-123d-4f645aa88c7e

# ╔═╡ 57b0a79a-384a-11eb-28e0-49ba5030094b
begin
	m = derivative(f,-5)
	f5 = f(5)
	plot(f,-5.5,-4.5,title="linear approximation at x=-5",lw=.5)
	xlabel!("x")
	ylabel!("f(x) ")
	plot!(x->slope(m,f(-5),-5,x),-5.5,-4.5)
	savefig("lin_approx1.png")
end

# ╔═╡ 23fd305a-3843-11eb-0d62-2bc677836fee
cd("/mnt/c/users/cheri/desktop/julia_Programs/Calculus/Derivatives")

# ╔═╡ 8e52f7ce-3856-11eb-0f43-a7090f42935e
show(f)

# ╔═╡ 49e94d4e-3843-11eb-37ae-6f8f0e0ef077
pwd()

# ╔═╡ Cell order:
# ╠═4c2e0eae-3841-11eb-0d59-65813cee8451
# ╠═0a49708c-3858-11eb-0988-29a07064bace
# ╠═6b582dc2-3852-11eb-0635-41b6b9ff3646
# ╠═78fe48b6-3841-11eb-2c0e-87abc273de4d
# ╠═5311b818-3850-11eb-01b6-457d4866d0ee
# ╠═c7976676-3858-11eb-123d-4f645aa88c7e
# ╠═57b0a79a-384a-11eb-28e0-49ba5030094b
# ╠═23fd305a-3843-11eb-0d62-2bc677836fee
# ╠═8e52f7ce-3856-11eb-0f43-a7090f42935e
# ╠═49e94d4e-3843-11eb-37ae-6f8f0e0ef077

ext: jl


text:
"""
Keypoint is a feature in the image used for tracking.

# Parameters:

- `id::Int64`: Id of the Keypoint.
- `pixel::Point2f`: Pixel coordinate in the image plane in `(y, x)` format.
- `undistorted_pixel::Point2f`: In presence of distortion in camera,
    this is the undistorted `pixel` coordinates.
- `position::Point3f`: Pre-divided (backprojected) keypoint in camera space.
    This is used in algorithms like 5Pt for Essential matrix calculation.
- `descriptor::BitVector`: Descriptor of a keypoint.
- `is_3d::Bool`: If `true`, then this keypoint was triangulated.
- `is_retracked::Bool`: If `true`, then this keypoint was lost
    and re-tracked back by `match_local_map!` method.
- `is_stereo::Bool`: If `true`, then this keypoint has left↔right
    correspondence for the stereo image.
- `right_pixel::Point2f`: Pixel coordinate in the right image plane
    in `(y, x)` format.
- `right_undistorted_pixel::Point2f`: In presence of distortion in camera,
    this is the undistorted `right_pixel` coordinates.
- `right_position::Point3f`: Pre-divided (backprojected) right keypoint
    in camera space. This is used in algorithms like 5Pt
    for Essential matrix calculation.
"""
mutable struct Keypoint
    id::Int64
    pixel::Point2f
    undistorted_pixel::Point2f

    position::Point3f
    descriptor::BitVector

    is_3d::Bool
    is_retracked::Bool
    is_stereo::Bool

    right_pixel::Point2f
    right_undistorted_pixel::Point2f
    right_position::Point3f
end

function Keypoint(id, pixel, undistorted_pixel, position, descriptor, is_3d)
    Keypoint(
        id, pixel, undistorted_pixel, position, descriptor,
        is_3d, false, false,
        pixel, undistorted_pixel, position)
end

"""
Frame that encapsulates information of a camera in space at a certain moment.

# Parameters:

- `id::Int64`: Id of the Frame.
- `kfid::Int64`: Id of the Frame in the global map, contained in MapManager.
    Frames that are in this map are called "Key-Frames".
- `time::Float64`: Time of the frame at which it was taken on the camera.
- `cw::SMatrix{4, 4, Float64, 16}`: Transformation matrix `[R|t]`
    that transforms from world to camera space.
- `wc::SMatrix{4, 4, Float64, 16}`: Transformation matrix `[R|t]`
    that transforms from camera to world space.
- `camera::Camera`: Camera associated with this frame.
- `right_camera::Camera`: In case of stereo, this is the camera
    associated with the right frame.
- `keypoints::Dict{Int64, Keypoint}`: Map of that this frames observes.
- `ketpoints_grid::Matrix{Set{Int64}}`: Grid, where each cell contains
    several keypoints. This is useful when want to retrieve neighbours
    for a certain Keypoint.
- `nb_occupied_cells::Int64`: Number of cells in `keypoints_grid` that have
    at least one Keypoint.
- `cell_size::Int64`: Cell size in pixels.
- `nb_keypoints::Int64`: Total number of keypoints in the Frame.
- `nb_2d_keypoints::Int64`: Total number of 2D keypoints in the Frame.
- `nb_3d_keypoints::Int64`: Total number of 3D keypoints in the Frame.
- `nb_3d_keypoints::Int64`: Total number of stereo keypoints in the Frame.
- `covisible_kf::OrderedDict{Int64, Int64}`: Dictionary with `kfid` => `score`
    of ids of Frames that observe the sub-set of size `score` of keypoints
    in Frame.
- `local_map_ids::Set{Int64}`: Set of ids of MapPoints that are not visible
    in this Frame, but are a potential candidates for remapping
    back into this Frame.
"""
mutable struct Frame
    id::Int64
    kfid::Int64

    time::Float64
    cw::SMatrix{4, 4, Float64, 16}
    wc::SMatrix{4, 4, Float64, 16}

    camera::Camera
    right_camera::Camera

    keypoints::Dict{Int64, Keypoint}
    keypoints_grid::Matrix{Set{Int64}}

    nb_occupied_cells::Int64
    cell_size::Int64

    nb_keypoints::Int64
    nb_2d_kpts::Int64
    nb_3d_kpts::Int64
    nb_stereo_kpts::Int64

    covisible_kf::OrderedDict{Int64, Int64}
    local_map_ids::Set{Int64}

    keypoints_lock::ReentrantLock
    pose_lock::ReentrantLock
    grid_lock::ReentrantLock
    covisibility_lock::ReentrantLock
end

function Frame(;
    camera, right_camera = nothing, cell_size,
    id = 0, kfid = 0, time = 0.0,
    cw = SMatrix{4, 4, Float64}(I),
    wc = SMatrix{4, 4, Float64}(I),
)
    if right_camera ≡ nothing
        @warn "[F] No right camera."
        right_camera = camera
    end

    nb_keypoints = 0
    nb_occupied_cells = 0
    keypoints = Dict{Int64, Keypoint}()

    image_resolution = (camera.height, camera.width)
    cells = ceil.(Int64, image_resolution ./ cell_size)
    grid = [Set{Int64}() for _=1:cells[1], _=1:cells[2]]

    keypoints_lock = ReentrantLock()
    pose_lock = ReentrantLock()
    grid_lock = ReentrantLock()
    covisibility_lock = ReentrantLock()

    Frame(
        id, kfid, time, cw, wc,
        camera, right_camera,
        keypoints, grid,
        nb_occupied_cells, cell_size,
        nb_keypoints, 0, 0, 0,
        OrderedDict{Int64, Int64}(), Set{Int64}(),
        keypoints_lock, pose_lock, grid_lock, covisibility_lock,
    )
end

function get_keypoints(f::Frame)
    lock(f.keypoints_lock) do
        [deepcopy(kp) for kp in values(f.keypoints)]
    end
end

function get_2d_keypoints(f::Frame)
    lock(f.keypoints_lock) do
        kps = Vector{Keypoint}(undef, f.nb_2d_kpts)
        i = 1
        for k in values(f.keypoints)
            k.is_3d || (kps[i] = deepcopy(k); i += 1;)
        end
        @assert (i - 1) == f.nb_2d_kpts
        kps
    end
end

function get_3d_keypoints(f::Frame)
    lock(f.keypoints_lock) do
        kps = Vector{Keypoint}(undef, f.nb_3d_kpts)
        i = 1
        for k in values(f.keypoints)
            k.is_3d && (kps[i] = deepcopy(k); i += 1;)
        end
        @assert (i - 1) == f.nb_3d_kpts
        kps
    end
end

function get_stereo_keypoints(f::Frame)
    lock(f.keypoints_lock) do
        kps = Vector{Keypoint}(undef, f.nb_stereo_kpts)
        i = 1
        for k in values(f.keypoints)
            k.is_stereo && (kps[i] = deepcopy(k); i += 1;)
        end
        @assert (i - 1) == f.nb_stereo_kpts
        kps
    end
end

function get_3d_keypoints_nb(f::Frame)
    lock(f.keypoints_lock) do
        return f.nb_3d_kpts
    end
end

function get_3d_keypoints_ids(f::Frame)
    lock(f.keypoints_lock) do
        ids = Vector{Int64}(undef, f.nb_3d_kpts)
        i = 1
        for k in values(f.keypoints)
            k.is_3d && (ids[i] = k.id; i += 1;)
        end
        @assert (i - 1) == f.nb_3d_kpts
        ids
    end
end

function get_keypoint(f::Frame, kpid)
    lock(f.keypoints_lock) do
        deepcopy(get(f.keypoints, kpid, nothing))
    end
end

function get_keypoint_unpx(f::Frame, kpid)
    lock(f.keypoints_lock) do
        kpid in keys(f.keypoints) ?
            f.keypoints[kpid].undistorted_pixel : nothing
    end
end

function add_keypoint!(
    f::Frame, point, id; descriptor::BitVector = BitVector(),
    is_3d::Bool = false,
)
    undistorted_point = undistort_point(f.camera, point)
    position = backproject(f.camera, undistorted_point)
    add_keypoint!(f, Keypoint(
        id, point, undistorted_point, position, descriptor, is_3d))
end

function add_keypoint!(f::Frame, keypoint::Keypoint)
    lock(f.keypoints_lock) do
        if keypoint.id in keys(f.keypoints)
            @warn "[Frame] $(f.id) already has keypoint $(keypoint.id)."
            return
        end

        f.keypoints[keypoint.id] = keypoint
        add_keypoint_to_grid!(f, keypoint)

        f.nb_keypoints += 1
        if keypoint.is_3d
            f.nb_3d_kpts += 1
        else
            f.nb_2d_kpts += 1
        end
    end
end

function update_keypoint!(f::Frame, kpid, point)
    lock(f.keypoints_lock) do
        ckp = get(f.keypoints, kpid, nothing)
        ckp ≡ nothing && return

        kp = ckp |> deepcopy
        kp.pixel = point
        kp.undistorted_pixel = undistort_point(f.camera, kp.pixel)
        kp.position = backproject(f.camera, kp.undistorted_pixel)

        if kp.is_stereo
            kp.is_stereo = false
            f.nb_stereo_kpts -= 1
        end

        update_keypoint_in_grid!(f, ckp, kp)
        f.keypoints[kpid] = kp
    end
end

function update_stereo_keypoint!(f::Frame, kpid, right_pixel)
    lock(f.keypoints_lock) do
        kp = get(f.keypoints, kpid, nothing)
        kp ≡ nothing && return

        kp.right_pixel = right_pixel
        kp.right_undistorted_pixel =
            undistort_point(f.right_camera, right_pixel)
        kp.right_position =
            backproject(f.right_camera, kp.right_undistorted_pixel)

        if !kp.is_stereo
            kp.is_stereo = true
            f.nb_stereo_kpts += 1
        end
    end
end

function update_keypoint!(f::Frame, prev_id, new_id, is_3d)
    has_new = false
    lock(f.keypoints_lock)
    has_new = new_id in keys(f.keypoints)
    unlock(f.keypoints_lock)
    has_new && return false

    prev_kp = get_keypoint(f, prev_id)
    prev_kp ≡ nothing && return false

    prev_kp.id = new_id
    prev_kp.is_retracked = true
    prev_kp.is_3d = is_3d

    remove_keypoint!(f, prev_id)
    add_keypoint!(f, prev_kp)
    true
end

function update_keypoint_in_grid!(
    f::Frame, previous_keypoint::Keypoint, new_keypoint::Keypoint,
)
    prev_kpi = to_cartesian(previous_keypoint.pixel, f.cell_size)
    new_kpi = to_cartesian(new_keypoint.pixel, f.cell_size)
    prev_kpi == new_kpi && return
    # Update grid, when new keypoint changes its position
    # so much as to move to the other grid cell.
    remove_keypoint_from_grid!(f, previous_keypoint)
    add_keypoint_to_grid!(f, new_keypoint)
end

function add_keypoint_to_grid!(f::Frame, keypoint::Keypoint)
    kpi = to_cartesian(keypoint.pixel, f.cell_size)
    lock(f.grid_lock) do
        isempty(f.keypoints_grid[kpi]) && (f.nb_occupied_cells += 1;)
        push!(f.keypoints_grid[kpi], keypoint.id)
    end
end

function remove_keypoint_from_grid!(f::Frame, keypoint::Keypoint)
    kpi = to_cartesian(keypoint.pixel, f.cell_size)
    lock(f.grid_lock) do
        if keypoint.id in f.keypoints_grid[kpi]
            pop!(f.keypoints_grid[kpi], keypoint.id)
            isempty(f.keypoints_grid[kpi]) && (f.nb_occupied_cells -= 1)
        end
    end
end

function remove_keypoint!(f::Frame, kpid)
    lock(f.keypoints_lock) do
        kp = get(f.keypoints, kpid, nothing)
        kp ≡ nothing && return

        pop!(f.keypoints, kpid)
        remove_keypoint_from_grid!(f, kp)

        f.nb_keypoints -= 1
        kp.is_stereo && (f.nb_stereo_kpts -= 1;)
        if kp.is_3d
            f.nb_3d_kpts -= 1
        else
            f.nb_2d_kpts -= 1
        end
    end
end

function remove_stereo_keypoint!(f::Frame, kpid)
    lock(f.keypoints_lock) do
        kp = get(f.keypoints, kpid, nothing)
        kp ≡ nothing && return
        kp.is_stereo || return

        kp.is_stereo = false
        f.nb_stereo_kpts -= 1
    end
end

function set_wc!(f::Frame, wc, visualizer = nothing)
    lock(f.pose_lock) do
        f.wc = wc
        f.cw = inv(SE3, wc)
        visualizer ≢ nothing && set_frame_wc!(visualizer, f.id, f.wc)
    end
end

function set_cw!(f::Frame, cw, visualizer = nothing)
    lock(f.pose_lock) do
        f.cw = cw
        f.wc = inv(SE3, cw)
        visualizer ≢ nothing && set_frame_wc!(visualizer, f.id, f.wc)
    end
end

function get_cw(f::Frame)
    lock(f.pose_lock) do
        f.cw
    end
end

function get_wc(f::Frame)
    lock(f.pose_lock) do
        f.wc
    end
end

function get_Rwc(f::Frame)
    lock(f.pose_lock) do
        f.wc[1:3, 1:3]
    end
end

function get_Rcw(f::Frame)
    lock(f.pose_lock) do
        f.cw[1:3, 1:3]
    end
end

function get_twc(f::Frame)
    lock(f.pose_lock) do
        f.wc[1:3, 4]
    end
end

function get_tcw(f::Frame)
    lock(f.pose_lock) do
        f.cw[1:3, 4]
    end
end

function get_cw_ba(f::Frame)::NTuple{6, Float64}
    lock(f.pose_lock) do
        r = RotZYX(f.cw[1:3, 1:3])
        (r.theta1, r.theta2, r.theta3, f.cw[1:3, 4]...)
    end
end

function get_wc_ba(f::Frame)::NTuple{6, Float64}
    lock(f.pose_lock) do
        r = RotXYZ(f.wc[1:3, 1:3])
        (r.theta1, r.theta2, r.theta3, f.wc[1:3, 4]...)
    end
end

function set_cw_ba!(f::Frame, θ)
    lock(f.pose_lock) do
        set_cw!(f, to_4x4(RotZYX(θ[1:3]...), θ[4:6]))
    end
end

function project_camera_to_world(f::Frame, point)
    lock(f.pose_lock) do
        f.wc * to_homogeneous(point)
    end
end

function project_world_to_camera(f::Frame, point)
    lock(f.pose_lock) do
        f.cw * to_homogeneous(point)
    end
end

function project_world_to_right_camera(f::Frame, point)
    lock(f.pose_lock) do
        f.right_camera.Ti0 * f.cw * to_homogeneous(point)
    end
end

function project_world_to_image(f::Frame, point)
    project(f.camera, project_world_to_camera(f, point))
end

function project_world_to_right_image(f::Frame, point)
    project(f.camera, f.right_camera.Ti0 * project_world_to_camera(f, point))
end

function project_world_to_image_distort(f::Frame, point)
    project_undistort(f.camera, project_world_to_camera(f, point))
end

function project_world_to_right_image_distort(f::Frame, point)
    project_undistort(f.camera, project_world_to_right_camera(f, point))
end

function turn_keypoint_3d!(f::Frame, id)
    lock(f.keypoints_lock) do
        kp = get(f.keypoints, id, nothing)
        kp ≡ nothing && return
        kp.is_3d && return

        kp.is_3d = true
        f.nb_2d_kpts -= 1
        f.nb_3d_kpts += 1
    end
end

function get_covisible_map(f::Frame)
    lock(f.covisibility_lock) do
        deepcopy(f.covisible_kf)
    end
end

function set_covisible_map!(f::Frame, covisible_map)
    lock(f.covisibility_lock) do
        f.covisible_kf = covisible_map
    end
end

function add_covisibility!(f::Frame, kfid, cov_score)
    kfid == f.kfid && return
    lock(f.covisibility_lock) do
        f.covisible_kf[kfid] = cov_score
    end
end

function add_covisibility!(f::Frame, kfid)
    kfid == f.kfid && return
    lock(f.covisibility_lock) do
        score = get(f.covisible_kf, kfid, 0)
        f.covisible_kf[kfid] = score + 1
    end
end

function decrease_covisible_kf!(f::Frame, kfid)
    lock(f.covisibility_lock) do
        kfid == f.kfid && return
        cov_score = get(f.covisible_kf, kfid, nothing)
        (cov_score ≡ nothing || cov_score == 0) && return

        cov_score -= 1
        f.covisible_kf[kfid] = cov_score
        cov_score == 0 && pop!(f.covisible_kf, kfid)
    end
end

function remove_covisible_kf!(f::Frame, kfid)
    kfid == f.kfid && return
    lock(f.covisibility_lock) do
        kfid in keys(f.covisible_kf) && pop!(f.covisible_kf, kfid)
    end
end

function is_observing_kp(f::Frame, kpid)
    lock(f.keypoints_lock) do
        kpid in keys(f.keypoints)
    end
end

function get_surrounding_keypoints(f::Frame, kp::Keypoint)
    keypoints = Vector{Keypoint}(undef, 0)
    sizehint!(keypoints, 20)
    kpi = to_cartesian(kp.pixel, f.cell_size)

    lock(f.keypoints_lock)
    lock(f.grid_lock)
    try
        for r in (kpi[1] - 1):(kpi[1] + 1), c in (kpi[2] - 1):(kpi[2] + 1)
            (r < 1 || c < 1 || r > size(f.keypoints_grid, 1)
                || c > size(f.keypoints_grid, 2)) && continue

            for cell_kpid in f.keypoints_grid[r, c]
                cell_kpid == kp.id && continue
                cell_kp = get(f, cell_kpid, nothing)
                cell_kp ≡ nothing || push!(keypoints, cell_kp)
            end
        end
    finally
        unlock(f.grid_lock)
        unlock(f.keypoints_lock)
    end

    keypoints
end

function get_surrounding_keypoints(f::Frame, pixel)
    keypoints = Vector{Keypoint}(undef, 0)
    sizehint!(keypoints, 20)
    kpi = to_cartesian(pixel, f.cell_size)

    lock(f.keypoints_lock)
    lock(f.grid_lock)
    try
        for r in (kpi[1] - 1):(kpi[1] + 1), c in (kpi[2] - 1):(kpi[2] + 1)
            (r < 1 || c < 1 || r > size(f.keypoints_grid, 1)
                || c > size(f.keypoints_grid, 2)) && continue

            for cell_kpid in f.keypoints_grid[r, c]
                cell_kp = get(f.keypoints, cell_kpid, nothing)
                cell_kp ≡ nothing || push!(keypoints, cell_kp)
            end
        end
    finally
        unlock(f.grid_lock)
        unlock(f.keypoints_lock)
    end

    keypoints
end

in_image(f::Frame, point) = in_image(f.camera, point)
in_right_image(f::Frame, point) = in_image(f.right_camera, point)

function reset!(f::Frame)
    lock(f.covisibility_lock)
    lock(f.keypoints_lock)
    lock(f.pose_lock)
    lock(f.grid_lock)

    f.nb_2d_kpts = 0
    f.nb_3d_kpts = 0
    f.nb_stereo_kpts = 0
    f.nb_keypoints = 0
    f.nb_occupied_cells = 0
    f.time = 0

    f.keypoints |> empty!
    f.keypoints_grid .|> empty!
    f.covisible_kf |> empty!

    f.wc = SMatrix{4, 4, Float64}(I)
    f.cw = SMatrix{4, 4, Float64}(I)

    unlock(f.grid_lock)
    unlock(f.pose_lock)
    unlock(f.keypoints_lock)
    unlock(f.covisibility_lock)
end


text:
module MPITests

using MPI
using Test

#Sysimage
sysimage=nothing
if length(ARGS)==1
   @assert isfile(ARGS[1]) "$(ARGS[1]) must be a valid Julia sysimage file"
   sysimage=ARGS[1]
end

mpidir = @__DIR__
testdir = mpidir #joinpath(mpidir,"..")
repodir = joinpath(mpidir,"../../")

function run_driver(procs,file,sysimage)
  mpiexec() do cmd
    if sysimage!=nothing
       extra_args="-J$(sysimage)"
       cmd=`$cmd -n $procs --allow-run-as-root --oversubscribe $(Base.julia_cmd()) --project=$repodir $(joinpath(mpidir,file))`
    else
       cmd=`$cmd -n $procs --allow-run-as-root --oversubscribe $(Base.julia_cmd()) --project=$repodir $(joinpath(mpidir,file))`
    end
    println(cmd)
    run(cmd)
    @test true
  end
end
run_driver(4,"CubedSphereDiscreteModelsTests.jl",sysimage)
run_driver(4,"DarcyCubedSphereTests.jl",sysimage)
run_driver(4,"LaplaceBeltramiCubedSphereTests.jl",sysimage)
run_driver(4,"WeakDivPerpTests.jl",sysimage)

end # module

max_stars_repo_name: santiagobadia/GridapGeosciences

max_issues_repo_name: santiagobadia/GridapGeosciences

max_forks_repo_name: santiagobadia/GridapGeosciences


text:
using NSDEBase
using Test

@testset "IVP and RHS" begin
    f(u, t) = @. u * (1.0 - u)
    problem = IVP(f, 0.5, (0.0, 1.0))
    @test problem isa InitialValueProblem
    @test showable(MIME("text/plain"), problem)
    @test problem.rhs isa RightHandSideFunction
    @test showable(MIME("text/plain"), problem.rhs)

    f!(du, u, t) = @. du = u * (1.0 - u)
    problem = IVP(f!, [0.5], 0.0, 1.0)
    @test problem isa InitialValueProblem
    @test problem.rhs isa RightHandSideFunction
end

@testset "ODEs" begin
    @test Dahlquist() isa InitialValueProblem
    @test Logistic() isa InitialValueProblem
    @test SimplePendulum() isa InitialValueProblem
    @test VanderPol() isa InitialValueProblem
    @test Rössler() isa InitialValueProblem
    @test Lorenz() isa InitialValueProblem
    @test Lorenz96() isa InitialValueProblem
end


text:
facts("Parameters") do

  context("When no parameters") do

    ps = Parameters()
    @fact ps[:NotThere] => nothing
    @fact ps["Neither there"] => nothing

    ps[:a] = 1
    @fact ps[:a] => 1

  end

  context("With one parameter in one set") do

    ps = Parameters({:a => 1})

    @fact ps[:a] => 1
    @fact ps["a"] => 1

    @fact ps[:A] => nothing
    @fact ps["A"] => nothing
    @fact ps[:B] => nothing
    @fact ps["B"] => nothing

  end

  context("With parameters in multiple sets") do

    ps = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3}, {:c => 5})

    @fact ps[:a] => 1
    @fact ps["a"] => 1

    @fact ps[:c] => 4
    @fact ps["c"] => 4

    @fact ps[:b] => 3
    @fact ps["b"] => 3

    @fact ps[:A] => nothing
    @fact ps["A"] => nothing
    @fact ps[:B] => nothing
    @fact ps["B"] => nothing

  end

  context("Updating parameters after construction") do

    ps = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3}, {:c => 5})

    ps[:c] = 6
    ps["b"] = 7

    @fact ps[:a] => 1
    @fact ps["a"] => 1

    @fact ps[:c] => 6
    @fact ps["c"] => 6

    @fact ps[:b] => 7
    @fact ps["b"] => 7

  end

  context("Constructing from another parameters object") do

    ps1 = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3})
    ps2 = Parameters({:a => 5}, ps1, {:c => 6})

    @fact ps2[:a] => 5
    @fact ps2[:c] => 4

  end

  context("Get key without default") do

    ps = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3})
    @fact get(ps, :a) => 1
    @fact get(ps, :b) => 3
    @fact get(ps, :d) => nothing

  end

  context("Get key without default") do

    ps = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3})
    @fact get(ps, :d, 10) => 10

  end

  context("Merge with Parameters or Dict") do

    ps = Parameters({:a => 1, "c" => 4}, {:a => 2, :b => 3})
    ps2 = merge(ps, {:d => 5, :a => 20})
    @fact ps2[:d] => 5
    @fact ps2[:b] => 3
    @fact ps2[:a] => 20

  end
end


text:
println("Loading packages and data, this may take some time...")
using MAT
cd(dirname(Base.source_path()))
include("../src/utils.jl")
include("../src/2d/cpab2dIntegration.jl")
include("../src/2d/imageWarp.jl")
include("../src/2d/2dInference.jl")

file = matopen("tri_R2toR2_MINS_0_0_MAXS_512_512_nc_4_4_Xbdr_0_0_ext_0.mat")
As = read(file, "As")
pts_src = read(file, "pts_src")
pts_fwd = read(file, "pts_fwd")
tw_args = read(file, "tw_args")
nCols = tw_args["nCols"]
nRows = tw_args["nRows"]
B = read(file, "B")
θ = vec(read(file, "theta"))
priorCov = read(file, "covariance_of_the_prior")
close(file)

nC1 = 4
nC2 = 4
incX = nCols/nC1
incY = nRows/nC2
nPts = size(pts_src,1)
t=0.001
nSteps = 100
Nsteps = 10
Δt = t/Nsteps
ΔtAs = Δt*As
bdryConstraints = true

function decreaseNumPts(A)
  reshape(reshape(A,512,512,2)[16:32:end,16:32:end,:],256,2)
end
pts_src1 = decreaseNumPts(pts_src)
pts_fwd1 = decreaseNumPts(pts_fwd)
solutionSingleThread1 = zeros(size(pts_src1,1), 2)
expT = Array(Float64, size(As,1), 3, 3)
Avees = Array(Float64, size(θ,1))

function leastSquaresTransformation(θ)
  computeAndEvaluateTransformationSingleThread(B,θ,As,pts_src1,pts_fwd1,solutionSingleThread1,t,nCols,nRows,incX,incY,Nsteps,Δt,nSteps,ΔtAs,expT,Avees,bdryConstraints)
end

iterations = 50000
using PyPlot
println("Running Metropolis")
@time optimizedθ, acceptanceTrace, llTrace, lpTrace, lpllTrace = metropolis(leastSquaresTransformation, rand(size(θ,1)), iterations, 10.0, priorCov, 0.00001*priorCov, true)
println("Done!")
optimizedθArray = convert(Array, optimizedθ)

PyPlot.figure("Metropolis",figsize=(18,6))
PyPlot.subplot(2,6,1)
PyPlot.title("Original Points")
xOriginal, yOriginal = separateAxis2D(pts_src1)
PyPlot.axis([0.0,512.0,0.0,512.0])
PyPlot.scatter(xOriginal, yOriginal, label="Original Points", color="blue")

PyPlot.subplot(2,6,2)
PyPlot.title("Destination Points")
PyPlot.axis([0.0,512.0,0.0,512.0])
xDst, yDst = separateAxis2D(pts_fwd1)
PyPlot.scatter(xDst, yDst, label="Destination Points", color="blue")

PyPlot.subplot(2,6,3)
PyPlot.title("Transformed Points")
PyPlot.axis([0.0,512.0,0.0,512.0])
xInferred, yInferred = separateAxis2D(solutionSingleThread1)
PyPlot.scatter(xInferred, yInferred, label="Transformed Points", color="blue")

PyPlot.subplot(2,6,7)
PyPlot.title("Original Image")
img = load("lena.jpg")
imr = reinterpret(UInt8, separate(img))
PyPlot.imshow(imr.data)

PyPlot.subplot(2,6,8)
PyPlot.title("Destination Image")
newimg1 = reinterpret(UInt8, separate(imwarp(pts_fwd, img, nCols, nRows)))
PyPlot.imshow(newimg1.data)

PyPlot.subplot(2,6,9)
PyPlot.title("Transformed Image")
transformedAs = similar(As)
solutionSingleThread = similar(pts_src)
computeAs(B,optimizedθArray,transformedAs)
solver2d(pts_src,solutionSingleThread,t,transformedAs,nCols,nRows,incX,incY,Nsteps,Δt,nSteps,ΔtAs)
newimg2 = reinterpret(UInt8, separate(imwarp(solutionSingleThread, img, nCols, nRows)))
PyPlot.imshow(newimg2.data)

PyPlot.subplot(1,2,2)
PyPlot.title("Log Probability vs Iterations")
PyPlot.plot(1:iterations, llTrace,label="log likelihood", color="blue")
PyPlot.plot(1:iterations, lpTrace,label="log prior", color="red")
PyPlot.plot(1:iterations, lpllTrace,label="log likelihood + log prior", color="green")
PyPlot.xlabel("Iterations")
PyPlot.ylabel("Log Probability")
PyPlot.legend(loc="lower right",fancybox="true")


text:
abstract type ABCtype end
abstract type Particle end

"""
    Prior(distributions)

    Create Prior type for ABC algorithm specifying priors for each parameters. This is an array of Distribution types from Distribution.jl, each element corresponding to a parameter.
"""
mutable struct Prior
  distribution
  Prior(distributionarray) = new(tuple(distributionarray...))
end

mutable struct ParticleRejection <: Particle
  params::Array{Float64, 1}
  distance::Float64
  other::Any
end

mutable struct ParticleRejectionModel <: Particle
  params::Array{Float64, 1}
  model::Int64
  distance::Float64
  other::Any
end

mutable struct ParticleSMC <: Particle
  params::Array{Float64, 1}
  weight::Float64
  distance::Float64
  other::Any
end

mutable struct ParticleSMCModel <: Particle
  params::Array{Float64, 1}
  weight::Float64
  model::Int64
  distance::Float64
  other::Any
end

"""
    ABCRejection(sim_func::Function, nparams::Int64, ϵ::Float64, prior::Prior; <keyword arguments>)

Create an ABCRejection type which will simulate data with sim_func. nparams is the number of parameters inputted into sim_func, ϵ is the target tolerance and prior sets the priors for the parameters. sim_func needs to take in 3 values, the parameters (in an array), constants (array) and target data in that order and needs to return 2 values, the first being the distance between the target data and simulated data and the second can be anything but is useful if for example you want to record some additional information about the simulations.
...
## Arguments
- `maxiterations = 10^5`: Maximum number of samples before the ABC algorithm terminates.
- `constants = []`: Any constants needed to simulate from sim_func
- `nparticles = 100`: Number of particles (ie samples) of ABC algorithm
...
"""
mutable struct ABCRejection <: ABCtype

  simfunc::Function
  nparams::Int64
  ϵ::Float64
  nparticles::Int64
  constants::Array{Any,1}
  maxiterations::Int64
  prior::Prior

  ABCRejection(sim_func::Function, nparams::Int64, ϵ::Float64, prior::Prior;
    maxiterations = 10000,
    constants = [],
    nparticles = 100,
    ) =
  new(sim_func, nparams, ϵ, nparticles, constants, maxiterations, prior)

end

"""
    ABCRejection(sim_func::Function, nparams::Int64, ϵT::Float64, prior::Prior; <keyword arguments>)

Create an ABCSMC type which will simulate data with sim_func. nparams is the number of parameters inputted into sim_func, ϵT is the target tolerance and prior sets the priors for the parameters. sim_func needs to take in 3 values, the parameters (in an array), constants (array) and target data in that order and needs to return 2 values, the first being the distance between the target data and simulated data and the second can be anything but is useful if for example you want to record some additional information about the simulations.
...
## Arguments
- `maxiterations = 10^5`: Maximum number of samples before the ABC algorithm terminates.
- `constants = []`: Any constants needed to simulate from sim_func
- `nparticles = 100`: Number of particles (ie samples) of ABC algorithm
- `α = 0.3`: The αth quantile of population i is chosen as the ϵ for population i + 1
- `ϵ1 = 10^5`: Starting ϵ for first ABC SMC populations
- `convergence = 0.05`: ABC SMC stops when ϵ in population i + 1 is within 0.05 of populations i
- `kernel = uniformkernel`: Parameter perturbation kernel, default is a uniform distribution. `gaussiankernel` is also an option that is already available in ApproxBayes.jl. Alternatively you can code up your own kernel function. See kernels.jl for examples.
...
"""
mutable struct ABCSMC <: ABCtype

  simfunc::Function
  nparams::Int64
  ϵ1::Float64
  ϵT::Float64
  nparticles::Int64
  constants::Array{Any,1}
  maxiterations::Int64
  prior::Prior
  α::Float64
  convergence::Float64
  kernel::Kernel

  ABCSMC(sim_func::Function, nparams::Int64, ϵT::Float64, prior::Prior;
    maxiterations = 10^5,
    constants = [],
    nparticles = 100,
    α = 0.3,
    ϵ1 = 10000.0,
    convergence = 0.05,
    kernel = ApproxBayes.uniformkernel
    ) =
  new(sim_func, nparams, ϵ1, ϵT, nparticles, constants, maxiterations, prior, α, convergence, kernel)

end

"""
    ABCRejectionModel(sim_func::Array{Function, 1}, nparams::Array{Int64, 1}, ϵ::Float64, prior::Array{Prior, 1}; <keyword arguments>)

Create an ABCRejectionModel type which will create a type to run ABC with model selection. Each model is specified with a function, first input is an array of functions. nparams and priors are arrays for the number of parameters and priors for each model. each sim_func needs to take in 3 values, the parameters (in an array), constants (array) and target data in that order and needs to return 2 values, the first being the distance between the target data and simulated data and the second can be anything but is useful if for example you want to record some additional information about the simulations.
...
## Arguments
- `maxiterations = 10^5`: Maximum number of samples before the ABC algorithm terminates.
- `constants = [[]]`: Any constants needed to simulate from sim_func, needs to be an array of arrays, each one corresponding to a model function.
- `nparticles = 100`: Number of particles (ie samples) of ABC algorithm
...
"""
mutable struct ABCRejectionModel <: ABCtype

  Models::Array{ABCRejection, 1}
  nmodels::Int64

  ABCRejectionModel(sim_func::Array{Function, 1}, nparams::Array{Int64, 1}, ϵ::Float64, prior::Array{Prior, 1};
    constants = repeat([[]], outer = length(sim_func)),
    maxiterations = 10000,
    nparticles = 100,
    ) =
  new([ABCRejection(sim_func[i], nparams[i], ϵ, prior[i],  maxiterations = maxiterations, constants = constants[i], nparticles = nparticles) for i in 1:length(sim_func)], length(sim_func))

end

"""
    ABCSMCModel(sim_func::Array{Function, 1}, nparams::Array{Int64, 1}, ϵT::Float64, prior::Array{Prior, 1}; <keyword arguments>)

Create an ABCSMCModel type which will create a type to run the ABC SMC with model selection algorithm. Each model is specified with a function, first input is an array of functions. nparams and priors are arrays for the number of parameters and priors for each model, ϵT is the target tolerance. Each sim_func needs to take in 3 values, the parameters (in an array), constants (array) and target data in that order and needs to return 2 values, the first being the distance between the target data and simulated data and the second can be anything but is useful if for example you want to record some additional information about the simulations.
...
## Arguments
- `maxiterations = 10^5`: Maximum number of samples before the ABC algorithm terminates.
- `constants = []`: Any constants needed to simulate from sim_func
- `nparticles = 100`: Number of particles (ie samples) of ABC algorithm
- `α = 0.3`: The αth quantile of population i is chosen as the ϵ for population i + 1
- `ϵ1 = 10^5`: Starting ϵ for first ABC SMC populations
- `convergence = 0.05`: ABC SMC stops when ϵ in population i + 1 is within 0.05 of populations i
- `modelkern = 0.7`: Probability model stays the same in model perturbation kernel, ie 70% of the time the model perturbation kernel will leave the model the same.
...
"""
mutable struct ABCSMCModel <: ABCtype

  Models::Array{ABCSMC, 1}
  nmodels::Int64
  modelkern::Float64
  nparticles::Int64
  α::Float64
  ϵT::Float64
  maxiterations::Int64
  convergence::Float64
  other::Any

  function ABCSMCModel(sim_func::Array{Function, 1}, nparams::Array{Int64, 1}, ϵT::Float64, prior::Array{Prior, 1};
    constants = repeat([[]], outer = length(sim_func)),
    maxiterations = 10^5,
    nparticles = 100,
    α = 0.3,
    ϵ1 = 10000.0,
    modelkern = 0.7,
    convergence = 0.05,
    other = [],
    kernels = [ApproxBayes.uniformkernel for i in 1:length(sim_func)]
    )
    smcarray = [ABCSMC(sim_func[i], nparams[i], ϵT, prior[i],  maxiterations = maxiterations, constants = constants[i], nparticles = nparticles, α = α, ϵ1 = ϵ1, convergence = convergence, kernel = deepcopy(kernels[i])) for i in 1:length(sim_func)]
    nmodels = length(sim_func)
    new(smcarray, nmodels, modelkern, nparticles, α, ϵT, maxiterations, convergence, other)
  end

end

mutable struct ABCrejectionresults

  parameters::Array{Float64,2}
  accratio::Float64
  numsims::Int64
  dist::Array{Float64,1}
  particles::Array{ParticleRejection, 1}
  setup::ABCRejection

   function ABCrejectionresults(particles, its, ABCsetup, dist)
      parameters = hcat(map(x -> x.params, particles)...)'
      accratio = ABCsetup.nparticles/its
      new(parameters, accratio, its, dist, particles, ABCsetup)
   end
end

mutable struct ABCrejectionmodelresults

   parameters
   accratio::Float64
   numsims::Int64
   dist::Array{Float64,1}
   particles::Array{ParticleRejectionModel, 1}
   modelfreq::Array{Float64, 1}
   setup::ABCRejectionModel

   function ABCrejectionmodelresults(particles, its, ABCsetup, dist)
     parameters = []
     modelfreq = []
     for i in 1:ABCsetup.nmodels
        push!(modelfreq, sum(map(x -> x.model, particles) .== i))
        models = map(x -> x.model, particles)
        parameters = push!(parameters,
        hcat(map(x -> x.params, particles[map(x -> x.model, particles) .== i])...)')
     end
     accratio = ABCsetup.Models[1].nparticles/its
     modelfreq = modelfreq ./ sum(modelfreq)

     new(parameters, accratio, its, dist, particles, modelfreq, ABCsetup)
   end
end

mutable struct ABCSMCresults

  parameters::Array{Float64,2}
  weights::Array{Float64, 1}
  accratio::Float64
  numsims::Array{Int64,1}
  ϵ::Array{Float64,1}
  particles::Array{ParticleSMC, 1}
  setup::ABCSMC

   function ABCSMCresults(particles, numsims, ABCsetup, epsvec)
      parameters = hcat(map(x -> x.params, particles)...)'
      weights = map(x -> x.weight, particles)
      accratio = ABCsetup.nparticles/sum(numsims)
      new(parameters, weights, accratio, numsims, epsvec, particles, ABCsetup)
   end
end

mutable struct ABCSMCmodelresults

   parameters
   weights
   accratio::Float64
   numsims::Array{Int64, 1}
   ϵ::Array{Float64,1}
   particles::Array{ParticleSMCModel, 1}
   modelfreq::Array{Float64, 1}
   modelprob::Array{Float64, 1}
   setup::ABCSMCModel

   function ABCSMCmodelresults(particles, its, ABCsetup, dist)

     parameters = []
     weights = []
     modelfreq = []
     modelweights = map(x -> x.weight, particles)
     models = map(x -> x.model, particles)
     modelprob = []
     for i in 1:ABCsetup.nmodels
        push!(modelfreq, sum(map(x -> x.model, particles) .== i))
        push!(modelprob, sum(modelweights[models .== i]))
        parameters = push!(parameters, hcat(map(x -> x.params, particles[map(x -> x.model, particles) .== i])...)')
        weights = push!(weights, map(x -> x.weight, particles[map(x -> x.model, particles) .== i]))
     end
     accratio = ABCsetup.nparticles ./ sum(its)
     modelfreq = modelfreq ./ sum(modelfreq)

     new(parameters, weights, accratio, its, dist, particles, modelfreq, modelprob, ABCsetup)
   end
end


text:
# Autogenerated wrapper script for ATK_jll for x86_64-linux-musl
export libatk

using Glib_jll
JLLWrappers.@generate_wrapper_header("ATK")
JLLWrappers.@declare_library_product(libatk, "libatk-1.0.so.0")
function __init__()
    JLLWrappers.@generate_init_header(Glib_jll)
    JLLWrappers.@init_library_product(
        libatk,
        "lib/libatk-1.0.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
#=
    Support for single variable functions i.e a <= b
=#

"""
    less_than(com::CS.CoM, constraint::SingleVariableConstraint; logs = true)

Support for constraints of the form a <= b where a and b are single variables.
This function removes values which aren't possible based on this constraint.
"""
function less_than(com::CS.CoM, constraint::CS.SingleVariableConstraint; logs = true)
    lhs = constraint.lhs
    rhs = constraint.rhs
    search_space = com.search_space
    !remove_above!(com, search_space[lhs], search_space[rhs].max) && return false
    !remove_below!(com, search_space[rhs], search_space[lhs].min) && return false
    return true
end

"""
    less_than(com::CoM, constraint::CS.SingleVariableConstraint, val::Int, index::Int)

Checks whether setting an `index` to `val` fulfills `constraint`
"""
function less_than(com::CoM, constraint::CS.SingleVariableConstraint, val::Int, index::Int)
    if constraint.lhs == index
        # if a > maximum possible value of rhs => Infeasible
        if val > com.search_space[constraint.rhs].max
            return false
        else
            return true
        end
    elseif constraint.rhs == index
        if val < com.search_space[constraint.lhs].min
            return false
        else
            return true
        end
    else
        error("This should not happen but if it does please open an issue with the information: SingleVariableConstraint index is neither lhs nor rhs and your model.")
    end
end