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

using Markdown
using InteractiveUtils

# ╔═╡ aa13f80d-87d5-4c88-af19-6ffe76d737bd
using PlutoUI; TableOfContents(title = "Negation Processing", aside = false)

# ╔═╡ b18f8835-dfb2-491b-b4f6-1cf885abdddd
begin
	using CSV, DataFrames
	import FreqTables: freqtable
	using Statistics # Statistics: mean
	using GLM        # 推论统计
	using CategoricalArrays
	using CairoMakie #GLMakie
		set_theme!(theme_minimal())
		update_theme!(
			backgroundcolor = RGBf(0.98, 0.98, 0.98),
			resolution = (1024, 768)
		 )
end

# ╔═╡ 214b6943-7672-47ce-99f8-f7c253d6490d
md"""
## Load packages and data
"""

# ╔═╡ f0b1a34d-9dc5-479b-b514-3493758e1377
cd(@__DIR__) # pwd()

# ╔═╡ 8820c2b2-c115-41a7-a206-2e8d04702064
md"""
## Experiments combined
"""

# ╔═╡ ccc5a309-3ae2-4a39-b08a-6af26e5702fe
md"""
### Box Transparency
"""

# ╔═╡ 7fe143be-ae8a-4cc7-9487-1e3cf4830385
md"""
### Agent Behavior
"""

# ╔═╡ d3b864ee-7991-401f-b1f7-7f692f605631
md"""
## Experiment 1
"""

# ╔═╡ b42f39c7-8e83-4604-9291-30115b8240e2
md"""
## Experiment 2
"""

# ╔═╡ 8f11b4fa-440b-4ec3-8bf7-d63b376ea1d0
md"""
## Experiment 3
"""

# ╔═╡ 5e47de4c-374a-4870-9fde-890e4237ebd9
md"""
## Appendixes
"""

# ╔═╡ f93407b7-ee46-46c3-ba01-69e8674aa931
md"""
### Object-test-image information
"""

# ╔═╡ fda7ab2f-1a46-4842-94b6-ed818fe53be7
Image_Object_Cor = CSV.read("Image_Object_Correspondance.csv",
	DataFrame, stringtype = String
);

# ╔═╡ 85782b61-69ce-410b-84ff-bfe8f7bb81ab
md"""
### Video-box-transparency information
"""

# ╔═╡ ce71136a-2d3d-44f4-8efc-6b69670759ac
begin
	Video_Object_Box = CSV.read(
		"Video_Object_Correspondance.csv", DataFrame, stringtype = String
	);

	Object_Box_Color = stack(Video_Object_Box,
		[:Box_Color_Ex1, :Box_Color_Ex2, :Box_Color_Ex3],
		variable_name = "Experiment", value_name = "Box_Color"
	);

	transform!(Object_Box_Color, :Experiment => ByRow(
		x -> replace(x, r"^Box_Color_Ex(\w+?)$" => s"Experiment_\1") ) => :Experiment
	);

	Object_Box_Transparency = stack(Video_Object_Box,
		[:Transparency_Ex1, :Transparency_Ex2, :Transparency_Ex3],
		variable_name = "Experiment", value_name = "Box_Transparency"
	);

	transform!(Object_Box_Transparency, :Experiment => ByRow(
		x -> replace(x, r"^Transparency_Ex(\w+?)$" => s"Experiment_\1") ) => :Experiment
	);

	Video_Box_Transparency = innerjoin(Object_Box_Color, Object_Box_Transparency,
		on = [:Trial_Number, :Chosed_Box, :Left_Box, :Right_Box, :Basket, :Experiment]
	);

	select!(Video_Box_Transparency,
		:Trial_Number, :Chosed_Box, :Left_Box, :Right_Box, :Basket,
		:Experiment, :Box_Color, :Box_Transparency
	);
end;

# ╔═╡ ebf2cf77-73c6-4f94-a505-efc50af40425
md"""
### Decode video name
"""

# ╔═╡ 4154ae38-899a-4999-8bc5-588eb0156bdf
# Create columns `Box_Color`, `Trial_Number`, and `Chosed_Box` from `Video_1`
function video_decode(Video)
	Video_Name = replace(Video, r"(\w+?)\\+?(\w*?).mp4" => s"\2")
	Box_Color    = String.(SubString.(Video_Name, 1, 2))
	Chosed_Box   =   SubString.(Video_Name, 3, 3) == "Z" ? "Left" : "Right"
	Trial_Number = "P" .*  SubString.(Video_Name, 4, 5)
	return Box_Color, Trial_Number, Chosed_Box
end

# ╔═╡ fa6344d6-86ed-48bb-bfb3-da3790a9a90f
md"""
### Load and preprocess data
"""

# ╔═╡ f2dc2797-c0f4-4f8e-8541-c71aa1a1358c
function read_combine_data(Experiment)

	# 00. Convert experiment to dir
	dir = "data/Experiment_" * string(Experiment)

	# 01. List CSV files
	csv_list = filter(endswith(".csv"), readdir(dir, join = true))

	# 02. Retrieve experiment name from file list
	Experiment = only(
		unique(replace.(csv_list, r"(\w*?)/(\w*?)/(\w*?).csv" => s"\2"))
	)

	# 03. Read CSV files into one DataFrame file
	df = mapreduce(vcat, csv_list) do csv
		CSV.read(csv, DataFrame, stringtype = String,
			drop = (i, name) -> startswith(string(name), "Column")
		)
	end

	# 04. Insert Experiment name into the DataFrame
	insertcols!(df, 1, :Experiment => Experiment)

	# 05. Remove rows when the value of `:Numb` is missing
	dropmissing!(df, :Numb)

	# 06. Decode column `:Video_1` into `Box_color`, `Trial_Number`, and `Chosed_Box`
	transform!(df,
		:Video_1 => ByRow(video_decode) => [:Box_Color, :Trial_Number, :Chosed_Box]
	)

	# 07. Rename columns
	rename!(df, "slider_left.response"  => "Object_Left",
				"slider_mid.response"   => "Object_Middle",
				"slider_right.response" => "Object_Right"
	)

	# 08. Convert Wide to Long format
	df = stack(df, [:Object_Left, :Object_Middle, :Object_Right],
			variable_name = "Object_Position", value_name = "Object_Rate"
	)

	# 09. Append Image-Object correspondence
	df = leftjoin(df, Image_Object_Cor, on = [:Trial_Number, :Object_Position])

	# 10. Append Video-Object correspondence
	df = leftjoin(df, Video_Box_Transparency,
		on = [:Experiment, :Trial_Number, :Box_Color, :Chosed_Box]
	)

	# 11. Convert `Object_Rate` from String to Float64
	subset!(df, :Object_Rate => ByRow(!=("None")))
	transform!(df, :Object_Rate =>
		ByRow(i -> isa(i, String) ? parse(Float64, i) : i) => :Object_Rate
	)

	# 12. Create column `Agent_Choice` from the `Chosed Box`
	transform!(df, [:Chosed_Box, :Left_Box, :Right_Box] =>
		ByRow((c, l, r) -> c == "Left" ? l : r) => :Agent_Choice
	)

	# 13. Rename columns
	rename!(df, "participant" => "Participant", "group" => "Group" )

	# 14. Convert column types
	transform!(df,
		:Left_Box         => ByRow(x -> String(x)) => :Left_Box,
		:Right_Box        => ByRow(x -> String(x)) => :Right_Box,
		:Basket           => ByRow(x -> String(x)) => :Basket,
		:Object_Number    => ByRow(x -> String(x)) => :Object_Number,
		:Box_Transparency => ByRow(x -> String(x)) => :Box_Transparency
	)

	# 15. Create a column to signify the conditions
		## a. define a function
	function AgentBehavior(x, y, z)
		if (x != y) & (x != z)    # :Object_Number, :Agent_Choice, :Basket
			return "UnChosen"
		elseif x == y             # :Object_Number == :Agent_Choice
			return "Chosen"
		elseif x == z             # :Object_Number == :Basket
			return "Basket"
		end
	end

		## b. do the conversion
	transform!(df,
		[:Object_Number, :Agent_Choice, :Basket] => ByRow(AgentBehavior) => :Agent_Behavior
	)

	# 18. Replace Transparency values to combine groups
	replace!(df.Box_Transparency,
		"OO-TT" => "TT-OO", # Experiment 1
		"TO-TT" => "TT-TO", # Experiment 2
		"OO-TO" => "TO-OO", # Experiment 3 ->
		"OO-TT" => "TT-OO",
		"OT-TT" => "TT-OT"
	)

	# 16. Create two columns: Agent perspective and Participant perspective
	transform!(df,
		:Box_Transparency =>
			ByRow(x -> SubString(x, 1, 1) * SubString(x, 4, 4)) =>
			:Participant_Perspective,
		:Box_Transparency =>
			ByRow(x -> SubString(x, 2, 2) * SubString(x, 5, 5)) =>
			:Agent_Perspective
	)

	# 17. Select columns
	select!(df, ["Experiment", "Participant", "Trial_Number",
		"Box_Transparency", "Participant_Perspective", "Agent_Perspective",
		 "Agent_Behavior", "Box_Color", "Object_Rate"]
	)

	return df

end

# ╔═╡ 0a9e79af-b016-4bbc-9070-f1c75b48571c
CombinedResults = mapreduce(read_combine_data, vcat, 1:3); # Experiment 1 - 3

# ╔═╡ 22952d34-eca9-4672-ac6c-801f5f711fdc
ExS = combine(
	groupby(CombinedResults,
		[:Experiment, :Participant, :Agent_Behavior, :Box_Transparency]),
	:Object_Rate => mean => :Object_Rate
);

# ╔═╡ 5cb6d10a-7e5f-4728-8b91-336b9f0fa549
Ex1 = subset(ExS, :Experiment => ByRow(==("Experiment_1")));

# ╔═╡ 87389fe3-0c1d-40ec-863c-43e3189f64ed
Ex2 = subset(ExS, :Experiment => ByRow(==("Experiment_2")));

# ╔═╡ ca54d080-408e-4bcb-8810-fc8ca264def4
Ex3 = subset(ExS, :Experiment => ByRow(==("Experiment_3")));

# ╔═╡ cb471c5c-6bdf-422b-a9f4-3fc5b46df1d2
md"""
### Define statistical models
"""

# ╔═╡ 440449ee-c93d-4907-ae47-889ad42169fd
function FitBoxTransparency(data, behavior)
	DataSubset = subset(data, :Agent_Behavior => ByRow(==(behavior)) )
	formula = @formula(Object_Rate ~ Box_Transparency)
	Contr = Dict(:Box_Transparency => EffectsCoding())
	fm = fit(LinearModel, formula, DataSubset, contrasts = Contr)
	coeftable(fm)
end

# ╔═╡ 336298c5-f69c-4ffb-a1bb-828d23fa6421
FitBoxTransparency(ExS, "UnChosen")

# ╔═╡ dd113e74-42d9-48d0-a741-51b5e803b902
FitBoxTransparency(ExS, "Chosen")

# ╔═╡ c7e73376-020d-482a-9791-fc2da25f490e
FitBoxTransparency(ExS, "Basket")

# ╔═╡ 863b7bc9-7ff7-4814-8daf-050ca59ed87a
FitBoxTransparency(Ex1, "UnChosen")

# ╔═╡ 1aedbde2-4ed0-4879-88cd-84fef564e9e5
FitBoxTransparency(Ex1, "Chosen")

# ╔═╡ bbb052f7-9d0c-4d23-9226-17f6b9da6a39
FitBoxTransparency(Ex1, "Basket")

# ╔═╡ 4cc80b39-cb72-4fb8-8143-8c6f7c620bb1
FitBoxTransparency(Ex2, "UnChosen")

# ╔═╡ 66a9f995-e8fd-4adb-a89c-ffb52334f1a0
FitBoxTransparency(Ex2, "Chosen")

# ╔═╡ d29de449-f44c-4481-9033-1a8c8cf9e92c
FitBoxTransparency(Ex2, "Basket")

# ╔═╡ 478864a8-8d31-472e-a565-ef19ade9df98
FitBoxTransparency(Ex3, "UnChosen")

# ╔═╡ aad8ba23-11a9-4c5b-9e19-2df7303de72a
FitBoxTransparency(Ex3, "Chosen")

# ╔═╡ 1fe1b8f8-feec-4a19-9b75-71ff191bf2d9
FitBoxTransparency(Ex3, "Basket")

# ╔═╡ a248ffc1-ccc8-469a-b209-ccfe984ac25b
function FitAgentBehavior(data, BoxTransparency)
	DataSubset = subset(data, :Box_Transparency => ByRow(==(BoxTransparency)) )
	formula = @formula(Object_Rate ~ Agent_Behavior)
	Contr = Dict(:Agent_Behavior => EffectsCoding())
	fm = fit(LinearModel, formula, DataSubset, contrasts = Contr)
	coeftable(fm)
end

# ╔═╡ 1e8c6eca-1bf1-4c0b-b396-198be4c45590
FitAgentBehavior(ExS, "OO-OO")

# ╔═╡ 803bb2cb-58ba-47ae-90dd-229687e95532
FitAgentBehavior(ExS, "TO-OO")

# ╔═╡ 259c6c81-9a71-4aaa-afcb-0dbff9922090
FitAgentBehavior(ExS, "TO-TO")

# ╔═╡ eb6f158f-fdb9-40f9-89ca-e93a03492a2c
FitAgentBehavior(ExS, "TT-OO")

# ╔═╡ 2d4ca637-5794-4399-8b17-7c3558febc5f
FitAgentBehavior(ExS, "TT-OT")

# ╔═╡ 979b9318-da99-48e6-a7d8-8298caa2a2a8
FitAgentBehavior(ExS, "TT-TO")

# ╔═╡ 4a4cc155-ceeb-4195-92d8-2692e9b8d21a
FitAgentBehavior(ExS, "TT-TT")

# ╔═╡ 1f1d13f4-3422-49ae-98ff-1889bd673c8b
FitAgentBehavior(Ex1, "OO-OO")

# ╔═╡ 8ab0b603-888c-4de0-b1bb-2cddd2340346
FitAgentBehavior(Ex1, "TT-OO")

# ╔═╡ 29b7ba0c-380d-4102-9765-a8aa1ab5466f
FitAgentBehavior(Ex1, "TT-TT")

# ╔═╡ 9f28f81f-1441-424b-8a6a-a3993a874c58
FitAgentBehavior(Ex2, "TO-TO")

# ╔═╡ dc4060e7-b4bf-4ac5-9146-5e39012df40d
FitAgentBehavior(Ex2, "TT-TO")

# ╔═╡ 1ecd7ee8-63a3-4530-a2ee-2068ff28dfcf
FitAgentBehavior(Ex2, "TT-TT")

# ╔═╡ ff4ed2c1-1c3f-49e9-9a11-cea63aa00b66
FitAgentBehavior(Ex3, "TO-OO")

# ╔═╡ a628acc7-77ff-497b-9adf-eff1209ae62c
FitAgentBehavior(Ex3, "TT-OO")

# ╔═╡ 3901c060-91ea-411c-bb28-47fe076ea42b
FitAgentBehavior(Ex3, "TT-OT")

# ╔═╡ a3b610ff-0e32-47f6-bfa8-9adafed64745
md"""
### Define plot functions
"""

# ╔═╡ 572be4fa-93ca-4a90-83c0-13bca09147a0
function PlotAgentBehavior(data)
	gdata = groupby(data, [:Participant, :Box_Transparency, :Agent_Behavior])
	sdata = combine(gdata, :Object_Rate => mean => :Object_Rate)
	sort!(sdata, [:Box_Transparency, :Agent_Behavior], rev = [false, true])

	BoxTrans   = unique(sdata.Box_Transparency)
	AgentBehav = unique(sdata.Agent_Behavior)
	colors = Makie.default_palettes.patchcolor.val
	rt = (length(BoxTrans) <= 3) ? 0pi : pi / 5

	fig = Figure(resolution = (1000, 500))

	gl1 = fig[1, 1] = GridLayout()
	for (id1, val1) in enumerate(BoxTrans)
		bxtr = subset(sdata, :Box_Transparency => ByRow(==(val1)) )
		ax1 = Axis(gl1[1, id1], title = val1,
			xticks = (1:length(AgentBehav), AgentBehav),
			xlabel = "Agent Behavior", ylabel = "Preference Rating",
			xticklabelrotation = rt
		)

		for (id2, val2) in enumerate(AgentBehav)
			ab = subset(bxtr, :Agent_Behavior => ByRow(==(val2)))
			xx = repeat([id2], size(ab, 1))
			yy = ab.Object_Rate
			boxplot!(ax1, xx, yy,
				color = (colors[id2], 1),
				whiskercolor = (colors[id2], 1),
				whiskerwidth = 0.5,
				show_notch = false
			)
		end
		ylims!(ax1, 0, 8)
		id1 > 1 && hideydecorations!(ax1)
	end

	fig
end

# ╔═╡ 715f3064-d6c7-4d0e-8faa-e2565dcd6eec
PlotAgentBehavior(ExS)

# ╔═╡ 6d862bbc-b2a4-4cdd-b871-16d2d453faae
PlotAgentBehavior(Ex1)

# ╔═╡ 409d8ef4-2aec-47cd-a62f-fc78687391b7
PlotAgentBehavior(Ex2)

# ╔═╡ 39ffdc92-bbf7-4539-84c5-e72271a9d24f
PlotAgentBehavior(Ex3)

# ╔═╡ 377224cb-9d74-4e98-81de-34b062daf859
function PlotBoxTransparency(data)
	gdata = groupby(data, [:Participant, :Box_Transparency, :Agent_Behavior])
	sdata = combine(gdata, :Object_Rate => mean => :Object_Rate)
	sort!(sdata, [:Box_Transparency, :Agent_Behavior], rev = [false, true])

	BoxTrans   = unique(sdata.Box_Transparency)
	AgentBehav = unique(sdata.Agent_Behavior)
	colors = Makie.default_palettes.patchcolor.val
	rt = (length(BoxTrans) <= 3) ? 0pi : pi / 5

	fig = Figure(resolution = (1000, 500))

	gl2 = fig[1, 1] = GridLayout()
	for (id2, val2) in enumerate(AgentBehav)
		bxtr = subset(sdata, :Agent_Behavior => ByRow(==(val2)) )
		ax2 = Axis(gl2[1, id2], title = val2,
				xticks = (1:length(BoxTrans), BoxTrans),
				xlabel = "Box Transparency", ylabel = "Preference Rating",
				xticklabelrotation = rt
		)
		for (id1, val1) in enumerate(BoxTrans)
			ab = subset(bxtr, :Box_Transparency => ByRow(==(val1)))
			xx = repeat([id1], size(ab, 1))
			yy = ab.Object_Rate
			boxplot!(ax2, xx, yy,
				color = (colors[id2], 1),
				whiskercolor = (colors[id2], 1),
				whiskerwidth = 0.5,
				show_notch = false
			)
		end
		ylims!(ax2, 0, 8)
		id2 > 1 && hideydecorations!(ax2)
	end

	fig
end

# ╔═╡ 18b1d0f6-1a29-48ea-8930-132500af1a81
PlotBoxTransparency(ExS)

# ╔═╡ 946462c0-0c7f-4c28-968b-a2c43f97a287
PlotBoxTransparency(Ex1)

# ╔═╡ e664a623-af69-444f-9eac-845e7b2cc0e2
PlotBoxTransparency(Ex2)

# ╔═╡ 7d91e44c-f738-4bec-b909-5ed821424e88
PlotBoxTransparency(Ex3)

# ╔═╡ f15c3d1b-4d89-4ed7-81ea-4ee8ad6d76e5
function MyBoxPlot(data)
	gdata = groupby(data, [:Participant, :Box_Transparency, :Agent_Behavior])
	sdata = combine(gdata, :Object_Rate => mean => :Object_Rate)
	sort!(sdata, [:Box_Transparency, :Agent_Behavior], rev = [false, true])

	BoxTrans   = unique(sdata.Box_Transparency)
	AgentBehav = unique(sdata.Agent_Behavior)
	colors = Makie.default_palettes.patchcolor.val
	rt = (length(BoxTrans) <= 3) ? 0pi : pi / 5

	fig = Figure(resolution = (1000, 800))

	gl1 = fig[1, 1] = GridLayout()
	for (id1, val1) in enumerate(BoxTrans)
		bxtr = subset(sdata, :Box_Transparency => ByRow(==(val1)) )
		ax1 = Axis(gl1[1, id1], title = val1,
			xticks = (1:length(AgentBehav), AgentBehav),
			xlabel = "Agent Behavior", ylabel = "Preference Rating",
			xticklabelrotation = rt
		)

		for (id2, val2) in enumerate(AgentBehav)
			ab = subset(bxtr, :Agent_Behavior => ByRow(==(val2)))
			xx = repeat([id2], size(ab, 1))
			yy = ab.Object_Rate
			boxplot!(ax1, xx, yy,
				color = (colors[id2], 1),
				whiskercolor = (colors[id2], 1),
				whiskerwidth = 0.5,
				show_notch = false
			)
		end
		ylims!(ax1, 0, 8)
		id1 > 1 && hideydecorations!(ax1)
	end

	# Label(gl1[1, 1:length(BoxTrans), Top()], "Agent Behavior by Box Transparency",
	# 	valign = :bottom, padding = (0, 0, 40, 0))

	gl2 = fig[2, 1] = GridLayout()
	for (id2, val2) in enumerate(AgentBehav)
		bxtr = subset(sdata, :Agent_Behavior => ByRow(==(val2)) )
		ax2 = Axis(gl2[1, id2], title = val2,
				xticks = (1:length(BoxTrans), BoxTrans),
				xlabel = "Box Transparency", ylabel = "Preference Rating",
				xticklabelrotation = rt
		)
		for (id1, val1) in enumerate(BoxTrans)
			ab = subset(bxtr, :Box_Transparency => ByRow(==(val1)))
			xx = repeat([id1], size(ab, 1))
			yy = ab.Object_Rate
			boxplot!(ax2, xx, yy,
				color = (colors[id2], 1.1),
				whiskercolor = (colors[id2], 1.1),
				whiskerwidth = 0.5,
				show_notch = false
			)
		end
		ylims!(ax2, 0, 8)
		id2 > 1 && hideydecorations!(ax2)
	end

	# Label(gl2[1, 1:length(BoxTrans), Top()], "Box Transparency by Agent Behavior",
	# 	valign = :bottom, padding = (0, 0, 40, 0))

	fig
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
FreqTables = "da1fdf0e-e0ff-5433-a45f-9bb5ff651cb1"
GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[compat]
CSV = "~0.9.10"
CairoMakie = "~0.7.5"
CategoricalArrays = "~0.10.5"
DataFrames = "~1.2.2"
FreqTables = "~0.4.5"
GLM = "~1.5.1"
PlutoUI = "~0.7.17"
"""

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

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

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

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

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

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

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

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

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

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

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

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

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

[[CSV]]
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings"]
git-tree-sha1 = "74147e877531d7c172f70b492995bc2b5ca3a843"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.9.10"

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

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

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

[[CategoricalArrays]]
deps = ["DataAPI", "Future", "Missings", "Printf", "Requires", "Statistics", "Unicode"]
git-tree-sha1 = "109664d3a6f2202b1225478335ea8fea3cd8706b"
uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597"
version = "0.10.5"

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

[[CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

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

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

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

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

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

[[Combinatorics]]
git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
version = "1.0.2"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[FilePathsBase]]
deps = ["Dates", "Mmap", "Printf", "Test", "UUIDs"]
git-tree-sha1 = "d962b5a47b6d191dbcd8ae0db841bc70a05a3f5b"
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
version = "0.9.13"

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

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

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

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

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

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

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

[[FreqTables]]
deps = ["CategoricalArrays", "Missings", "NamedArrays", "Tables"]
git-tree-sha1 = "488ad2dab30fd2727ee65451f790c81ed454666d"
uuid = "da1fdf0e-e0ff-5433-a45f-9bb5ff651cb1"
version = "0.4.5"

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

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

[[GLM]]
deps = ["Distributions", "LinearAlgebra", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "StatsModels"]
git-tree-sha1 = "f564ce4af5e79bb88ff1f4488e64363487674278"
uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
version = "1.5.1"

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

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

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

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

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

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

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

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

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

[[HypertextLiteral]]
git-tree-sha1 = "5efcf53d798efede8fee5b2c8b09284be359bf24"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.2"

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

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

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

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

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

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

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

[[InlineStrings]]
deps = ["Parsers"]
git-tree-sha1 = "19cb49649f8c41de7fea32d089d37de917b553da"
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
version = "1.0.1"

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

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

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

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

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

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

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

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

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

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "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]]
deps = ["CEnum", "FileIO", "ImageCore", "JpegTurbo_jll", "TOML"]
git-tree-sha1 = "a77b273f1ddec645d1b7c4fd5fb98c8f90ad10a5"
uuid = "b835a17e-a41a-41e7-81f0-2f016b05efe0"
version = "0.1.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "e595b205efd49508358f7dc670a940c790204629"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2022.0.0+0"

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

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

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

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

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

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

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

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

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

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

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

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

[[NamedArrays]]
deps = ["Combinatorics", "DataStructures", "DelimitedFiles", "InvertedIndices", "LinearAlgebra", "Random", "Requires", "SparseArrays", "Statistics"]
git-tree-sha1 = "2fd5787125d1a93fbe30961bd841707b8a80d75b"
uuid = "86f7a689-2022-50b4-a561-43c23ac3c673"
version = "0.9.6"

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

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

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

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

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

[[OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "a193d6ad9c45ada72c14b731a318bedd3c2f00cf"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.3.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"

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

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

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

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

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

[[Ratios]]
deps = ["Requires"]
git-tree-sha1 = "dc84268fe0e3335a62e315a3a7cf2afa7178a734"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.3"

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

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

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

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

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

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

[[SIMD]]
git-tree-sha1 = "7dbc15af7ed5f751a82bf3ed37757adf76c32402"
uuid = "fdea26ae-647d-5447-a871-4b548cad5224"
version = "3.4.1"

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

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

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

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

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

[[ShiftedArrays]]
git-tree-sha1 = "22395afdcf37d6709a5a0766cc4a5ca52cb85ea0"
uuid = "1277b4bf-5013-50f5-be3d-901d8477a67a"
version = "1.0.0"

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

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

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

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

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

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

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

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

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

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

[[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", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "eb35dcc66558b2dda84079b9a1be17557d32091a"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.12"

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

[[StatsModels]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "REPL", "ShiftedArrays", "SparseArrays", "StatsBase", "StatsFuns", "Tables"]
git-tree-sha1 = "677488c295051568b0b79a77a8c44aa86e78b359"
uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
version = "0.6.28"

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

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

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

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

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "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"

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

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

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

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

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

[[WeakRefStrings]]
deps = ["DataAPI", "InlineStrings", "Parsers"]
git-tree-sha1 = "c69f9da3ff2f4f02e811c3323c22e5dfcb584cfa"
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
version = "1.4.1"

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

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

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

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

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

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

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

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

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

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

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

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

[[isoband_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51b5eeb3f98367157a7a12a1fb0aa5328946c03c"
uuid = "9a68df92-36a6-505f-a73e-abb412b6bfb4"
version = "0.2.3+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"

[[libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╟─aa13f80d-87d5-4c88-af19-6ffe76d737bd
# ╠═214b6943-7672-47ce-99f8-f7c253d6490d
# ╠═f0b1a34d-9dc5-479b-b514-3493758e1377
# ╠═b18f8835-dfb2-491b-b4f6-1cf885abdddd
# ╠═0a9e79af-b016-4bbc-9070-f1c75b48571c
# ╠═22952d34-eca9-4672-ac6c-801f5f711fdc
# ╟─8820c2b2-c115-41a7-a206-2e8d04702064
# ╟─ccc5a309-3ae2-4a39-b08a-6af26e5702fe
# ╠═18b1d0f6-1a29-48ea-8930-132500af1a81
# ╠═336298c5-f69c-4ffb-a1bb-828d23fa6421
# ╠═dd113e74-42d9-48d0-a741-51b5e803b902
# ╠═c7e73376-020d-482a-9791-fc2da25f490e
# ╟─7fe143be-ae8a-4cc7-9487-1e3cf4830385
# ╠═715f3064-d6c7-4d0e-8faa-e2565dcd6eec
# ╠═1e8c6eca-1bf1-4c0b-b396-198be4c45590
# ╠═803bb2cb-58ba-47ae-90dd-229687e95532
# ╠═259c6c81-9a71-4aaa-afcb-0dbff9922090
# ╠═eb6f158f-fdb9-40f9-89ca-e93a03492a2c
# ╠═2d4ca637-5794-4399-8b17-7c3558febc5f
# ╠═979b9318-da99-48e6-a7d8-8298caa2a2a8
# ╠═4a4cc155-ceeb-4195-92d8-2692e9b8d21a
# ╟─d3b864ee-7991-401f-b1f7-7f692f605631
# ╠═5cb6d10a-7e5f-4728-8b91-336b9f0fa549
# ╠═946462c0-0c7f-4c28-968b-a2c43f97a287
# ╠═863b7bc9-7ff7-4814-8daf-050ca59ed87a
# ╠═1aedbde2-4ed0-4879-88cd-84fef564e9e5
# ╠═bbb052f7-9d0c-4d23-9226-17f6b9da6a39
# ╠═6d862bbc-b2a4-4cdd-b871-16d2d453faae
# ╠═1f1d13f4-3422-49ae-98ff-1889bd673c8b
# ╠═8ab0b603-888c-4de0-b1bb-2cddd2340346
# ╠═29b7ba0c-380d-4102-9765-a8aa1ab5466f
# ╟─b42f39c7-8e83-4604-9291-30115b8240e2
# ╠═87389fe3-0c1d-40ec-863c-43e3189f64ed
# ╠═e664a623-af69-444f-9eac-845e7b2cc0e2
# ╠═4cc80b39-cb72-4fb8-8143-8c6f7c620bb1
# ╠═66a9f995-e8fd-4adb-a89c-ffb52334f1a0
# ╠═d29de449-f44c-4481-9033-1a8c8cf9e92c
# ╠═409d8ef4-2aec-47cd-a62f-fc78687391b7
# ╠═9f28f81f-1441-424b-8a6a-a3993a874c58
# ╠═dc4060e7-b4bf-4ac5-9146-5e39012df40d
# ╠═1ecd7ee8-63a3-4530-a2ee-2068ff28dfcf
# ╟─8f11b4fa-440b-4ec3-8bf7-d63b376ea1d0
# ╠═ca54d080-408e-4bcb-8810-fc8ca264def4
# ╠═7d91e44c-f738-4bec-b909-5ed821424e88
# ╠═478864a8-8d31-472e-a565-ef19ade9df98
# ╠═aad8ba23-11a9-4c5b-9e19-2df7303de72a
# ╠═1fe1b8f8-feec-4a19-9b75-71ff191bf2d9
# ╠═39ffdc92-bbf7-4539-84c5-e72271a9d24f
# ╠═ff4ed2c1-1c3f-49e9-9a11-cea63aa00b66
# ╠═a628acc7-77ff-497b-9adf-eff1209ae62c
# ╠═3901c060-91ea-411c-bb28-47fe076ea42b
# ╟─5e47de4c-374a-4870-9fde-890e4237ebd9
# ╟─f93407b7-ee46-46c3-ba01-69e8674aa931
# ╟─fda7ab2f-1a46-4842-94b6-ed818fe53be7
# ╟─85782b61-69ce-410b-84ff-bfe8f7bb81ab
# ╟─ce71136a-2d3d-44f4-8efc-6b69670759ac
# ╟─ebf2cf77-73c6-4f94-a505-efc50af40425
# ╟─4154ae38-899a-4999-8bc5-588eb0156bdf
# ╟─fa6344d6-86ed-48bb-bfb3-da3790a9a90f
# ╟─f2dc2797-c0f4-4f8e-8541-c71aa1a1358c
# ╟─cb471c5c-6bdf-422b-a9f4-3fc5b46df1d2
# ╟─440449ee-c93d-4907-ae47-889ad42169fd
# ╟─a248ffc1-ccc8-469a-b209-ccfe984ac25b
# ╟─a3b610ff-0e32-47f6-bfa8-9adafed64745
# ╟─572be4fa-93ca-4a90-83c0-13bca09147a0
# ╟─377224cb-9d74-4e98-81de-34b062daf859
# ╟─f15c3d1b-4d89-4ed7-81ea-4ee8ad6d76e5
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder, Pkg

name = "OpenCVQt"
version = v"0.7.1"

# Collection of sources required to complete build
sources = [
    GitSource(
      "https://github.com/opencv/opencv.git",
      "d5fd2f0155ffad366f9ac912dfd6d189a7a6a98e",
    ),
]
# Bash recipe for building across all platforms
script = raw"""

# Build with Qt for linux platform except i686
if [[ $target == "x86_64-linux-gnu" ]]; then
  linux_extra_flags="-DWITH_QT=ON"
fi

if [[ $target == "aarch64-linux-gnu" ]]; then
  linux_extra_flags="-DWITH_QT=ON"
fi

if [[ $target == "arm-linux-gnueabihf" ]]; then
  linux_extra_flags="-DWITH_QT=ON -DCMAKE_CXX_LINK_FLAGS=-latomic"
fi

mkdir build
cd build
cmake -DCMAKE_FIND_ROOT_PATH=$prefix \
      -DCMAKE_INSTALL_PREFIX=$prefix -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} \
      -DCMAKE_BUILD_TYPE=Release \
      $linux_extra_flags \
      ../opencv/
VERBOSE=ON cmake --build . --config Release --target install -- -j${nproc}
cd ..
install_license opencv/LICENSE
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = [
   Linux(:i686, libc=:glibc),
   Linux(:x86_64, libc=:glibc),
   Linux(:aarch64, libc=:glibc),
   Linux(:armv7l, libc=:glibc, call_abi=:eabihf),
   #Linux(:powerpc64le, libc=:glibc), <- build should pass, but it takes much time to build.
   Linux(:i686, libc=:musl),
   #Linux(:x86_64, libc=:musl), <- fails
   Linux(:aarch64, libc=:musl),
   Linux(:armv7l, libc=:musl, call_abi=:eabihf),
   MacOS(:x86_64),
   #FreeBSD(:x86_64), <- fails,
   Windows(:i686),
   Windows(:x86_64),
] |> expand_cxxstring_abis

# The products that we will ensure are always built
products = [
    LibraryProduct(["libopencv_calib3d", "libopencv_calib3d450"], :libopencv_calib3d),
    LibraryProduct(["libopencv_core", "libopencv_core450"], :libopencv_core),
    LibraryProduct(["libopencv_dnn", "libopencv_dnn450"], :libopencv_dnn),
    LibraryProduct(["libopencv_features2d", "libopencv_features2d450"], :libopencv_features2d),
    LibraryProduct(["libopencv_flann", "libopencv_flann450"], :libopencv_flann),
    LibraryProduct(["libopencv_gapi", "libopencv_gapi450"], :libopencv_gapi),
    LibraryProduct(["libopencv_highgui", "libopencv_highgui450"], :libopencv_highgui),
    LibraryProduct(["libopencv_imgcodecs", "libopencv_imgcodecs450"], :libopencv_imgcodecs),
    LibraryProduct(["libopencv_imgproc", "libopencv_imgproc450"], :libopencv_imgproc),
    LibraryProduct(["libopencv_ml", "libopencv_ml450"], :libopencv_ml),
    LibraryProduct(["libopencv_objdetect", "libopencv_objdetect450"], :libopencv_objdetect),
    LibraryProduct(["libopencv_photo", "libopencv_photo450"], :libopencv_photo),
    LibraryProduct(["libopencv_stitching", "libopencv_stitching450"], :libopencv_stitching),
    LibraryProduct(["libopencv_video", "libopencv_video450"], :libopencv_video),
    LibraryProduct(["libopencv_videoio", "libopencv_videoio450"], :libopencv_videoio),
]

# Dependencies that must be installed before this package can be built
dependencies = [
    Dependency(PackageSpec(name="Qt_jll", version="5.15.2")),
    Dependency(PackageSpec(name="Libglvnd_jll", version="1.3.0")),
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies; preferred_gcc_version = v"7")

ext: jl


text:
"""
    CG(j1,m1,j2,m2,j,m)

a shortcut for `clebschgordan`
"""
CG(j1,m1,j2,m2,j,m) = clebschgordan(j1,m1,j2,m2,j,m)

"""
    CG_doublearg(j1,m1,j2,m2,j,m)

a shortcut for `clebschgordan_doublearg`
"""
CG_doublearg(two_j1,two_m1,two_j2,two_m2,two_j,two_m) = clebschgordan_doublearg(two_j1,two_m1,two_j2,two_m2,two_j,two_m)

"""
    clebschgordan(j1,m1,j2,m2,j,m)

gives a numerical value of the Clebsch-Gordan coefficient
```
    ⟨ j₁ m₁ ; j₂ m₂ | j m ⟩
```
The input values are expected to be __integers__.
For a general case including half-integers see `clebschgordan_doublearg`.
"""
clebschgordan(j1,m1,j2,m2,j,m) = clebschgordan_doublearg(2j1,2m1,2j2,2m2,2j,2m)

"""
    clebschgordan_doublearg(two_j1,two_m1,two_j2,two_m2,two_j,two_m)

gives a numerical value of the Clebsch-Gordan coefficient
```
    ⟨ j₁ m₁ ; j₂ m₂ | j m ⟩
```
The function requires __doubled value of the momenta__ for the input.
"""
function clebschgordan_doublearg(two_j1,two_m1,two_j2,two_m2,two_j,two_m)
    ((abs(two_m1) > two_j1) || (abs(two_m2) > two_j2) || (abs(two_m ) > two_j )) && return 0.0
    ((two_m1+two_m2 != two_m) || !(abs(two_j1-two_j2) ≤ two_j ≤ two_j1+two_j2))  && return 0.0
     #
    prefactor = sqrt(two_j+1)*
        exp( ( f_logfact2(two_j1+two_j2-two_j) +
               f_logfact2(two_j1+two_j -two_j2) +
               f_logfact2(two_j2+two_j -two_j1) -
               f_logfact2(two_j1+two_j2+two_j+2) +
               #
               f_logfact2(two_j1+two_m1) +
               f_logfact2(two_j1-two_m1) +
               f_logfact2(two_j2+two_m2) +
               f_logfact2(two_j2-two_m2) +
               f_logfact2(two_j +two_m ) +
               f_logfact2(two_j -two_m ) ) / 2)
    res = 0.0
    two_t_min = max(0,
                    two_j2-two_m1-two_j,
                    two_j1+two_m2-two_j)
    two_t_max = min(two_j1+two_j2-two_j,
                    two_j1-two_m1,
                    two_j2+two_m2)
    #
    for two_t = two_t_min:2:two_t_max
        logs = f_logfact2(two_t) +
               f_logfact2(two_j-two_j2+two_m1+two_t) +
               f_logfact2(two_j-two_j1-two_m2+two_t) +
               f_logfact2(two_j1+two_j2-two_j-two_t) +
               f_logfact2(two_j1-two_m1-two_t) +
               f_logfact2(two_j2+two_m2-two_t);
        res += (abs(two_t) % 4 == 2 ? -1.0 : 1.0) * exp(-logs);
    end
    res *= prefactor
    return res;
end


text:
# =========================================================================================
"""
    readstl{T}(
        stream::IOStream,
              ::Type{T}=Float64
    )

Reads a surface model from the given STL file.

!!! note
    This file type does not support charge models! Hence, the charge list of the returning `Model` object is empty and has to be set separately.

# Specification
<https://fabbers.com/tech/STL_Format>

# Return type
`Model{T, Triangle{T}}`

# Alias

    readstl{T}(
        fname::String,
             ::Type{T}=Float64
    )

Reads the model using a file name rather than an `IOStream` object.
"""
function readstl(
    stream::IOStream,
          ::Type{T}=Float64
    ) where T
    # skip header
    skip(stream, 80)
    # read number of triangles
    numelem = read(stream, UInt32)
    elements = Vector{Triangle{T}}(undef, numelem)

    for i in 1:numelem
        skip(stream, 12) # skip normal (will be computed by props)
        elements[i] = Triangle(
            map(T, [read(stream, Float32) for _ in 1:3]),
            map(T, [read(stream, Float32) for _ in 1:3]),
            map(T, [read(stream, Float32) for _ in 1:3])
        )
        skip(stream, 2)
    end

    nodes = collect(Set(unpack([[e.v1, e.v2, e.v3] for e in elements])))
    Model(nodes, elements)
end

function readstl(
    fname::String,
         ::Type{T}=Float64
) where T
    open(fh -> readstl(fh, T), fname)
end

# =========================================================================================
"""
    writestl{T}(
        stream::IOStream,
        model ::Model{T, Triangle{T}}
    )

Creates a binary STL file from a given surface model.

# Specification
<http://www.fabbers.com/tech/STL_Format>

# Return type
`Void`

# Alias

    writestl{T}(
        fname::String,
        model::Model{T, Triangle{T}}
    )

Creates the STL file by name rather than `IOStream` object.
"""
function writestl(
    stream::IOStream,
    model ::Model{T, Triangle{T}}
) where T
    # header (empty)
    write(stream, zeros(UInt8, 80))
    # number of triangles
    write(stream, UInt32(length(model.elements)))

    for elem in model.elements
        write(stream, map(Float32, elem.normal))
        write(stream, map(Float32, elem.v1))
        write(stream, map(Float32, elem.v2))
        write(stream, map(Float32, elem.v3))
        write(stream, zero(UInt16))
    end
    nothing
end

function writestl(fname::String, model::Model{T, Triangle{T}}) where T
    open(fh -> writestl(fh, model), fname, "w")
end


text:
# File used to create the test data

using BrainFlow
using DataFrames
using ProgressMeter
using CSV

function emg_data_to_dataframe(data, board_id::BrainFlow.BoardIds = BrainFlow.GFORCE_PRO_BOARD)
    emg_channels = BrainFlow.get_emg_channels(board_id)
    emg_data = data[emg_channels,:]
    emg_names = Symbol.(["emg$x" for x in 1:length(emg_channels)])
    df = DataFrame(emg_data')
    DataFrames.rename!(df, emg_names)

    # add time column
    nrows = size(df, 1)
    sample_rate = BrainFlow.get_sampling_rate(board_id)
    df.time = (1:nrows)/sample_rate

    return df
end

# Run this once for each gesture for a specified interval in seconds
function record_gesture(board_shim::BrainFlow.BoardShim, interval::Int = 30)
    sleep(0.5)
    BrainFlow.start_stream(board_shim)
    @showprogress 1 "Recording..." for n = 1:interval
        sleep(1)
    end
    BrainFlow.stop_stream(board_shim)
    data = BrainFlow.get_board_data(board_shim)
    return data
end

# prepare the session
board_id = BrainFlow.GFORCE_PRO_BOARD
BrainFlow.enable_dev_logger(BrainFlow.BOARD_CONTROLLER)
params = BrainFlowInputParams()
board_shim = BrainFlow.BoardShim(board_id, params)
BrainFlow.prepare_session(board_shim)

so_many_gestures = 4
for n = 1:so_many_gestures
    println("Press enter to start recording gesture $(n)")
    readline()

    data = record_gesture(board_shim)
    df = emg_data_to_dataframe(data, board_id)
    CSV.write("gesture_$(n)_data.csv", df)
end

## finally:
BrainFlow.release_session(board_shim)


text:
using Test, JSON3, StructTypes, UUIDs, Dates

struct data
    t :: Tuple{Symbol, String}
end

@enum Fruit apple banana

struct XInt
    x::Int64
end

struct A
    a::Int
    b::Int
    c::Int
    d::Int
end

mutable struct B
    a::Int
    b::Int
    c::Int
    d::Int
    B() = new()
end

struct C
end

struct D
    a::Int
    b::Float64
    c::String
end

abstract type Vehicle end

struct Car <: Vehicle
    type::String
    make::String
    model::String
    seatingCapacity::Int
    topSpeed::Float64
end

struct Truck <: Vehicle
    type::String
    make::String
    model::String
    payloadCapacity::Float64
end

abstract type Vehicle2 end

mutable struct Car2 <: Vehicle2
    make::String
    model::String
    seatingCapacity::Int
    topSpeed::Float64
    Car2() = new()
end

abstract type Expression end

abstract type Literal <: Expression end

abstract type BinaryFunction <: Expression end

struct LiteralValue <: Literal
    exprType::String
    value::Any
end

struct AndFunction <: BinaryFunction
    exprType::String
    lhs::Expression
    rhs::Expression
end

struct LotsOfFields
    x1::String
    x2::String
    x3::String
    x4::String
    x5::String
    x6::String
    x7::String
    x8::String
    x9::String
    x10::String
    x11::String
    x12::String
    x13::String
    x14::String
    x15::String
    x16::String
    x17::String
    x18::String
    x19::String
    x20::String
    x21::String
    x22::String
    x23::String
    x24::String
    x25::String
    x26::String
    x27::String
    x28::String
    x29::String
    x30::String
    x31::String
    x32::String
    x33::String
    x34::String
    x35::String
end

mutable struct DateStruct
    date::Date
    datetime::DateTime
    time::Time
end
DateStruct() = DateStruct(Date(0), DateTime(0), Time(0))

struct DictWithoutLength end

@testset "JSON3" begin

@testset "read.jl" begin

@test_throws ArgumentError JSON3.read("")
@test JSON3.read("{\"hey\":1}").hey == 1
@test JSON3.read("[\"hey\",1]") == ["hey",1]
@test JSON3.read("1.0") === Int64(1)
@test JSON3.read("1") === Int64(1)
@test JSON3.read("1.1") === 1.1
@test JSON3.read("+1.1") === 1.1
@test JSON3.read("-1.1") === -1.1
@test JSON3.read("\"hey\"") == "hey"
@test JSON3.read("null") === nothing
@test JSON3.read("true") === true
@test JSON3.read("false") === false

# more robust Int vs. Float detection: https://github.com/quinnj/JSON3.jl/issues/124
@test JSON3.read("9223372036854775807") == 9223372036854775807
@test JSON3.read("9223372036854775808") == 9.223372036854776e18 # overflowed Int64 promotes to Float64 (though slightly lossy)
@test JSON3.read("-9223372036854775808") == -9223372036854775808
@test JSON3.read("-9223372036854775809") == -9.223372036854776e18
# 2^53 boundaries
@test JSON3.read("9007199254740991") == 9007199254740991
@test JSON3.read("9007199254740992") == 9007199254740992
@test JSON3.read("9007199254740993") == 9007199254740993
@test JSON3.read("9007199254740994") == 9007199254740994
@test JSON3.read("1e17") == Int64(1e17)

@test_throws ArgumentError JSON3.read("{")
@test JSON3.read("{}") == JSON3.Object()
@test_throws ArgumentError JSON3.read("{a")
@test JSON3.read("{\"a\": 1}").a == 1
@test JSON3.read("{\"\\\"hey\\\"\": 1}")["\"hey\""] == 1
@test_throws ArgumentError JSON3.read("{\"a\"}")
@test JSON3.read("{\"a\": {\"a\": {\"a\": 1}}}").a.a.a == 1
@test JSON3.read("[3.14, 1]") == [3.14, 1]
@test JSON3.read("[1, 3.14]") == [1, 3.14]
@test JSON3.read("[null, 1]") == [nothing, 1]
@test JSON3.read("[1, null]") == [1, nothing]
@test JSON3.read("[null, null]") == [nothing, nothing]
@test JSON3.read("[null, \"hey\"]") == [nothing, "hey"]
@test_throws ArgumentError JSON3.read("{\"a\": 1\"")
@test_throws ArgumentError JSON3.read("{\"a\": 1, a")
@test JSON3.read("[]") == []
@test JSON3.read("[1]") == [1]
@test JSON3.read("[1,2,3]") == [1,2,3]
@test_throws ArgumentError JSON3.read("[1 a")
@test_throws ArgumentError JSON3.read("nulL")
@test_throws ArgumentError JSON3.read("\"\b\"")

obj = JSON3.read("""
{
    "int": 1,
    "float": 2.1,
    "bool1": true,
    "bool2": false,
    "none": null,
    "str": "\\"hey there sailor\\"",
    "obj": {
                "a": 1,
                "b": null,
                "c": [null, 1, "hey"],
                "d": [1.2, 3.4, 5.6]
            },
    "arr": [null, 1, "hey"],
    "arr2": [1.2, 3.4, 5.6]
}
""")
@test obj.int === Int64(1)
@test obj.float === 2.1
@test obj.bool1 === true
@test obj.bool2 === false
@test obj.none === nothing
@test obj.str == "\"hey there sailor\""
@test obj.obj.a === Int64(1)
@test obj.obj.b === nothing
@test obj.obj.c == [nothing, 1, "hey"]
@test obj.obj.d == [1.2, 3.4, 5.6]
@test obj.arr == [nothing, 1, "hey"]
@test obj.arr2 == [1.2, 3.4, 5.6]

@test_throws ArgumentError JSON3.read("trua")
@test_throws ArgumentError JSON3.read("tru")
@test_throws ArgumentError JSON3.read("fals")
@test_throws ArgumentError JSON3.read("falst")
@test_throws ArgumentError JSON3.read("f")

@test JSON3.read("\"\\u003e\\u003d\$1B\"") == ">=\$1B"

obj = JSON3.read("""
{ "a": 1,
  "b": 2,
  "c": 3,
  "d": 4
}""")

@test length(obj) == 4
for (i, (k, v)) in enumerate(obj)
    @test i == v
end

@test get(obj, :a) == 1
@test get(obj, Int, :a) == 1
@test_throws KeyError get(obj, :e)
@test_throws KeyError get(obj, Int, :e)
@test get(obj, :a, 2) == 1
@test get(obj, :e, 5) == 5
@test get(()->5, obj, :e) == 5
@test propertynames(obj) == [:a, :b, :c, :d]
@test obj["a"] == 1
@test get(obj, "a") == 1
@test get(obj, Int, "a") == 1
@test_throws KeyError get(obj, "e") == 1
@test_throws KeyError get(obj, Int, "e") == 1
@test get(obj, "a", 2) == 1
@test get(obj, Int, "a", 2) == 1
@test get(obj, "e", 5) == 5
@test get(obj, Int, "e", 5) == 5

arr = JSON3.read("""
[ 1,
  2,
  3,
  4
]""")

@test length(arr) == 4
@test size(arr) == (4,)

for (i, v) in enumerate(arr)
    @test i == v
end

@test arr[1] == 1
@test arr[end] == 4

arr = JSON3.read(SubString("""
[ 1,
  2,
  3,
  4
]""", 1, 20))

@test length(arr) == 4
@test size(arr) == (4,)

for (i, v) in enumerate(arr)
    @test i == v
end

@test arr[1] == 1
@test arr[end] == 4

end # @testset "read.jl"

@testset "structs.jl" begin

arr = JSON3.read(SubString("""
[ 1,
  2,
  3,
  4
]""", 1, 20), Vector{Int})

@test length(arr) == 4
@test size(arr) == (4,)

for (i, v) in enumerate(arr)
    @test i == v
end

@test arr[1] == 1
@test arr[end] == 4

@test JSON3.write(arr) == "[1,2,3,4]"

x = JSON3.read("1", Union{Int, Missing})
@test x == 1

x = JSON3.read("null", Union{Int, Missing})
@test x === missing

x = JSON3.read("1", Union{Int, Float64})
@test x === 1.0

StructTypes.construct(::Type{JSON3.PointerString}, ptr::Ptr{UInt8}, len::Int) = JSON3.PointerString(ptr, len)
str = "\"hey\""
x = JSON3.read(str, JSON3.PointerString);
@test x == "hey"
@test typeof(x) == JSON3.PointerString
@test JSON3.write(x) == str

@test JSON3.read("\"apple\"", Fruit) == apple
@test_throws Union{UndefVarError, ArgumentError} JSON3.read("\"watermelon\"", Fruit)
@test JSON3.write(apple) == "\"apple\""

@test JSON3.read("\"apple\"", Symbol) == :apple
@test JSON3.write(:apple) == "\"apple\""

@test JSON3.read("true", Bool)
@test JSON3.read("false", Bool) === false
@test JSON3.write(true) == "true"
@test JSON3.write(false) == "false"

StructTypes.StructType(::Type{XInt}) = StructTypes.NumberType()
StructTypes.numbertype(::Type{XInt}) = Int64
StructTypes.construct(::Type{Int64}, x::XInt) = x.x
x = XInt(10)
@test JSON3.read("10", XInt) == x
@test JSON3.write(x) == "10"

@test JSON3.read("[1,2,3]", Array) == Any[1,2,3]
@test JSON3.write(Any[1,2,3]) == "[1,2,3]"
@test JSON3.read("[1,2,3]", Tuple) == (1,2,3)
@test JSON3.write((1,2,3)) == "[1,2,3]"
@test JSON3.read("[1,2,3]", Set) == Set([1,2,3])
@test JSON3.write(Set([1,2])) in ("[1,2]", "[2,1]")

@test JSON3.read("{\"a\": 1, \"b\": 2}", Dict) == Dict("a"=>1, "b"=>2)
@test JSON3.write(Dict("a"=>1, "b"=>2)) in ("{\"a\":1,\"b\":2}", "{\"b\":2,\"a\":1}")
@test JSON3.read("{\"a\": 1, \"b\": 2}", Dict{String, Any}) == Dict("a"=>1, "b"=>2)
@test JSON3.read("{\"a\": 1, \"b\": 2}", Dict{Symbol, Int}) == Dict(:a=>1, :b=>2)
@test JSON3.write(Dict(:a=>1, :b=>2)) in ("{\"a\":1,\"b\":2}", "{\"b\":2,\"a\":1}")
@test JSON3.read("{\"a\": 1, \"b\": 2}", NamedTuple) == (a=1, b=2)
@test JSON3.write((a=1, b=2)) == "{\"a\":1,\"b\":2}"
@test JSON3.read("{\"a\": 1, \"b\": 2}", NamedTuple{(:a, :b)}) == (a=1, b=2)
@test JSON3.read("{\"a\": 1, \"b\": 2}", NamedTuple{(:a,)}) == (a=1,)
@test JSON3.write((a=1,)) == "{\"a\":1}"
@test JSON3.read("{\"a\": 1, \"b\": 2}", NamedTuple{(:a, :b), Tuple{Int, Int}}) == (a=1, b=2)
@test JSON3.read("{\"a\": 1, \"b\": 2}", NamedTuple{(:a, :b), Tuple{Float64, Float64}}) == (a=1.0, b=2.0)
@test JSON3.write((a=1.0, b=2.0)) == "{\"a\":1.0,\"b\":2.0}"

# Test that writing DictType works even when length(pairs(dict_type)) isn't
# available. Issue #37.
StructTypes.StructType(::Type{DictWithoutLength}) = StructTypes.DictType()
Base.pairs(x::DictWithoutLength) =
    Iterators.filter(x -> last(x) !== nothing, ("a" => 1, "b" => nothing))
@test JSON3.write(DictWithoutLength()) == "{\"a\":1}"

StructTypes.StructType(::Type{A}) = StructTypes.Struct()

obj = JSON3.read("""
{ "a": 1,
  "b": 2,
  "c": 3,
  "d": 4
}
""", A)

@test obj.a == 1
@test obj.d == 4

# test order doesn't matter
obj2 = JSON3.read("""
{ "d": 1,
  "b": 2,
  "c": 3,
  "a": 4
}
""", A)

@test obj2.d == 1
@test obj2.a == 4

@test_throws ArgumentError JSON3.read("", A)
@test_throws ArgumentError JSON3.read("a", A)
@test_throws ArgumentError JSON3.read("{a", A)
@test_throws ArgumentError JSON3.read("{\"a\"a", A)
@test_throws ArgumentError JSON3.read("{\"a\": 1a", A)
@test_throws ArgumentError JSON3.read("{\"a\": 1, a", A)
@test_throws ArgumentError JSON3.read("}", A)

# `JSON3.read!` should not work for immutable structs
@test_throws ArgumentError JSON3.read!("", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("a", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("{a", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("{\"a\"a", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("{\"a\": 1a", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("{\"a\": 1, a", A(1, 2, 3, 4))
@test_throws ArgumentError JSON3.read!("}", A(1, 2, 3, 4))

@test_throws ArgumentError JSON3.read("{}", C)
@test_throws ArgumentError JSON3.write(C())

StructTypes.StructType(::Type{C}) = StructTypes.Struct()

@test JSON3.read("{}", C) == C()
@test JSON3.write(obj) == "{\"a\":1,\"b\":2,\"c\":3,\"d\":4}"

StructTypes.StructType(::Type{D}) = StructTypes.OrderedStruct()
obj = JSON3.read("""
{ "a": 1,
  "b": 3.14,
  "c": "hey"
}
""", D)

@test obj.a == 1
@test obj.b == 3.14
@test obj.c == "hey"

# if order of fields is switched, error is thrown
@test_throws ArgumentError JSON3.read("""
{ "c": "hey",
  "b": 3.14,
  "a": 1
}
""", D)

@test JSON3.read("1", Union{String, Int}) == 1
@test JSON3.read("\"1\"", Union{String, Int}) == "1"
@test JSON3.read("null", Union{Int, String, Nothing}) === nothing
@test JSON3.read("1.0", Union{Float64, Int}) === 1.0

@test JSON3.read("1", Any) == 1
@test JSON3.read("3.14", Any) == 3.14
@test JSON3.read("\"a\"", Any) == "a"
@test JSON3.read("true", Any) === true
@test JSON3.read("false", Any) === false
@test JSON3.read("null", Any) === nothing
@test JSON3.read("[1,2,3]", Any) == [1,2,3]
@test JSON3.read("\"a\"", String) == "a"
@test JSON3.read("1", Int64) === Int64(1)
@test JSON3.read("3.14", Float64) === 3.14
@test JSON3.read("true", Bool) === true
@test JSON3.read("false", Bool) === false
@test JSON3.read("null", Nothing) === nothing
@test JSON3.read("null", Missing) === missing
@test JSON3.read("\"a\"", Char) == 'a'
@test JSON3.read("{\"a\": 1}", Any)["a"] == 1
@test JSON3.read("{\"a\": 1}", Dict{Symbol, Any})[:a] == 1
@test JSON3.read("[1,2,3]", Base.Array{Any}) == [1,2,3]
@test JSON3.read("[]", Vector{Any}) == []
@test JSON3.read("{}", Dict{Symbol, Any}) == Dict{Symbol, Any}()
@test JSON3.read("{\"a\":\"b\\/c\"}").a == "b/c"

@test_throws ArgumentError JSON3.read("hey", Any)
@test_throws ArgumentError JSON3.read("hey", String)
@test_throws ArgumentError JSON3.read("\"hey", String)
@test_throws ArgumentError JSON3.read("\"hey\\", String)
@test_throws ArgumentError JSON3.read("\"hey\\\\", String)
@test_throws ArgumentError JSON3.read("\"a", Char)
@test_throws ArgumentError JSON3.read("\"ab\"", Char)
@test_throws ArgumentError JSON3.read("trua", Bool)
@test_throws ArgumentError JSON3.read("tru", Bool)
@test_throws ArgumentError JSON3.read("fals", Bool)
@test_throws ArgumentError JSON3.read("falst", Bool)
@test_throws ArgumentError JSON3.read("f", Bool)
@test_throws ArgumentError JSON3.read("a1bc", Int)
@test_throws ArgumentError JSON3.read("a1.0b", Float64)
@test_throws ArgumentError JSON3.read("a1bc", Vector{Any})
@test_throws ArgumentError JSON3.read("[1,2n", Vector{Any})
@test_throws ArgumentError JSON3.read("a1bc", Dict{Symbol, Any})
@test_throws ArgumentError JSON3.read("{a1bc", Dict{Symbol, Any})
@test_throws ArgumentError JSON3.read("{\"a\"1bc", Dict{Symbol, Any})
@test_throws ArgumentError JSON3.read("{\"a\": 1bc", Dict{Symbol, Any})
@test_throws ArgumentError JSON3.read("{\"a\": 1, bc", Dict{Symbol, Any})

StructTypes.StructType(::Type{B}) = StructTypes.Mutable()

b = JSON3.read("""
{
    "d": 4,
    "b": 2,
    "a": 1,
    "c": 3
}""", B)

@test b.a == 1
@test b.b == 2
@test b.c == 3
@test b.d == 4

b = B()
JSON3.read!("""
{
    "d": 4,
    "b": 2,
    "a": 1,
    "c": 3
}""", b)

@test b.a == 1
@test b.b == 2
@test b.c == 3
@test b.d == 4

@test_throws ArgumentError JSON3.read("", B)
@test_throws ArgumentError JSON3.read("a", B)
@test_throws ArgumentError JSON3.read("{a", B)
@test_throws ArgumentError JSON3.read("{\"a\": 1b", B)
@test_throws ArgumentError JSON3.read("{\"a\": 1, b", B)
@test_throws ArgumentError JSON3.read("}", B)
b = JSON3.read("{}", B)
@test typeof(b) == B

@test_throws ArgumentError JSON3.read!("", B())
@test_throws ArgumentError JSON3.read!("a", B())
@test_throws ArgumentError JSON3.read!("{a", B())
@test_throws ArgumentError JSON3.read!("{\"a\": 1b", B())
@test_throws ArgumentError JSON3.read!("{\"a\": 1, b", B())
@test_throws ArgumentError JSON3.read!("}", B())
b = JSON3.read("{}", B)
@test typeof(b) == B

b = JSON3.read("""
{
    "d": 4,
    "b": 2,
    "a": 1,
    "c": 3,
    "e": 5
}""", B)

@test b.a == 1
@test JSON3.write(b) == "{\"a\":1,\"b\":2,\"c\":3,\"d\":4}"

b = B()
JSON3.read!("""
{
    "d": 4,
    "b": 2,
    "a": 1,
    "c": 3,
    "e": 5
}""", b)

@test b.a == 1
@test JSON3.write(b) == "{\"a\":1,\"b\":2,\"c\":3,\"d\":4}"

# Incremental updating of mutable structs with `JSON3.read!`
@testset "Incremental updating of mutable structs with `JSON3.read!`" begin
    b = B()
    b.a = 0
    b.b = 0
    b.c = 0
    b.d = 0

    @test b.a == 0
    @test b.b == 0
    @test b.c == 0
    @test b.d == 0

    foo = JSON3.read!("""
    {
        "b": 1
    }""", b)
    @test b.a == 0
    @test b.b == 1
    @test b.c == 0
    @test b.d == 0
    @test foo == b
    @test foo === b

    bar = JSON3.read!("""
    {
        "d": 30,
        "b": 20,
        "a": 10,
        "e": 40
    }""", b)
    @test b.a == 10
    @test b.b == 20
    @test b.c == 0
    @test b.d == 30
    @test bar == b
    @test bar === b

    baz = JSON3.read!("""
    {
        "d": 400,
        "b": 200,
        "a": 100,
        "c": 300,
        "e": 500
    }""", b)
    @test b.a == 100
    @test b.b == 200
    @test b.c == 300
    @test b.d == 400
    @test baz == b
    @test baz === b
end

StructTypes.names(::Type{B}) = ((:a, :z),)
b = JSON3.read("""
{
    "d": 4,
    "b": 2,
    "z": 1,
    "c": 3,
    "e": 5
}""", B)

@test b.a == 1
@test JSON3.write(b) == "{\"z\":1,\"b\":2,\"c\":3,\"d\":4}"

StructTypes.excludes(::Type{B}) = (:c, :d)
b = JSON3.read("""
{
    "d": 4,
    "b": 2,
    "z": 1,
    "c": 3,
    "e": 5
}""", B)
@test JSON3.write(b) == "{\"z\":1,\"b\":2}"

StructTypes.StructType(::Type{Vehicle}) = StructTypes.AbstractType()
StructTypes.subtypes(::Type{Vehicle}) = (car=Car, truck=Truck)

StructTypes.StructType(::Type{Car}) = StructTypes.Struct()
StructTypes.StructType(::Type{Truck}) = StructTypes.Struct()

car = JSON3.read("""
{
    "type": "car",
    "make": "Mercedes-Benz",
    "model": "S500",
    "seatingCapacity": 5,
    "topSpeed": 250.1
}""", Vehicle)

@test typeof(car) == Car
@test car.make == "Mercedes-Benz"
@test car.topSpeed === 250.1
@test JSON3.write(car) == "{\"type\":\"car\",\"make\":\"Mercedes-Benz\",\"model\":\"S500\",\"seatingCapacity\":5,\"topSpeed\":250.1}"

truck = JSON3.read("""
{
    "type": "truck",
    "make": "Isuzu",
    "model": "NQR",
    "payloadCapacity": 7500.5
}""", Vehicle)

@test typeof(truck) == Truck
@test truck.make == "Isuzu"
@test truck.payloadCapacity == 7500.5
@test JSON3.write(truck) == "{\"type\":\"truck\",\"make\":\"Isuzu\",\"model\":\"NQR\",\"payloadCapacity\":7500.5}"

@test_throws ArgumentError JSON3.read("", Vehicle)
@test_throws ArgumentError JSON3.read("a", Vehicle)
@test_throws ArgumentError JSON3.read("{a", Vehicle)
@test_throws ArgumentError JSON3.read("{}", Vehicle)
@test_throws ArgumentError JSON3.read("{\"a\"a", Vehicle)
@test_throws ArgumentError JSON3.read("{\"a\": 1a", Vehicle)
@test_throws ArgumentError JSON3.read("{\"a\": 1, a", Vehicle)
@test_throws ArgumentError JSON3.read("{\"a\": 1}", Vehicle)

StructTypes.StructType(::Type{Vehicle2}) = StructTypes.AbstractType()
StructTypes.subtypes(::Type{Vehicle2}) = (Car2=Car2,)
StructTypes.StructType(::Type{Car2}) = StructTypes.Mutable()
car2 = JSON3.read("""
{
    "topSpeed": 250.1,
    "model": "S500",
    "make": "Mercedes-Benz",
    "seatingCapacity": 5
}""", Vehicle2)

@test typeof(car2) == Car2
@test car2.make == "Mercedes-Benz"
@test car2.topSpeed === 250.1
@test JSON3.write(car2) == "{\"make\":\"Mercedes-Benz\",\"model\":\"S500\",\"seatingCapacity\":5,\"topSpeed\":250.1}"

StructTypes.StructType(::Type{Expression}) = StructTypes.AbstractType()
StructTypes.subtypes(::Type{Expression}) = (AND=AndFunction, LITERAL=LiteralValue)
StructTypes.subtypekey(::Type{Expression}) = :exprType

StructTypes.StructType(::Type{AndFunction}) = StructTypes.Struct()
StructTypes.StructType(::Type{LiteralValue}) = StructTypes.Struct()

expr = JSON3.read("""
{
    "exprType": "AND",
    "lhs": {
        "exprType": "LITERAL",
        "value": 3.14
    },
    "rhs": {
        "exprType": "AND",
        "lhs": {
            "exprType": "LITERAL",
            "value": null
        },
        "rhs": {
            "exprType": "LITERAL",
            "value": "hey"
        }
    }
}
""", Expression)
@test expr.exprType == "AND"
@test JSON3.write(expr) == "{\"exprType\":\"AND\",\"lhs\":{\"exprType\":\"LITERAL\",\"value\":3.14},\"rhs\":{\"exprType\":\"AND\",\"lhs\":{\"exprType\":\"LITERAL\",\"value\":null},\"rhs\":{\"exprType\":\"LITERAL\",\"value\":\"hey\"}}}"

@test JSON3.write(Int64) == "\"Int64\""
@test JSON3.write(Float64) == "\"Float64\""
@test JSON3.write(String) == "\"String\""
@test startswith(JSON3.write(NamedTuple{(:a, :b), Tuple{Int64, String}}), "\"NamedTuple{(:a, :b),")
@test startswith(JSON3.write(Dict{Symbol, Any}), "\"Dict{Symbol,")
@test JSON3.write(Bool) == "\"Bool\""
@test JSON3.write(Nothing) == "\"Nothing\""
@test JSON3.write(Missing) == "\"Missing\""
@test JSON3.write(A) == "\"A\""
@test JSON3.write(B) == "\"B\""
@test JSON3.write(Vehicle) == "\"Vehicle\""

StructTypes.StructType(::Type{LotsOfFields}) = StructTypes.Struct()
lotsoffields = LotsOfFields(fill("hey", 35)...)
jlots = JSON3.write(lotsoffields)
@test jlots == "{\"x1\":\"hey\",\"x2\":\"hey\",\"x3\":\"hey\",\"x4\":\"hey\",\"x5\":\"hey\",\"x6\":\"hey\",\"x7\":\"hey\",\"x8\":\"hey\",\"x9\":\"hey\",\"x10\":\"hey\",\"x11\":\"hey\",\"x12\":\"hey\",\"x13\":\"hey\",\"x14\":\"hey\",\"x15\":\"hey\",\"x16\":\"hey\",\"x17\":\"hey\",\"x18\":\"hey\",\"x19\":\"hey\",\"x20\":\"hey\",\"x21\":\"hey\",\"x22\":\"hey\",\"x23\":\"hey\",\"x24\":\"hey\",\"x25\":\"hey\",\"x26\":\"hey\",\"x27\":\"hey\",\"x28\":\"hey\",\"x29\":\"hey\",\"x30\":\"hey\",\"x31\":\"hey\",\"x32\":\"hey\",\"x33\":\"hey\",\"x34\":\"hey\",\"x35\":\"hey\"}"
@test JSON3.read(jlots, LotsOfFields) == lotsoffields

end # @testset "structs.jl"

@testset "show.jl" begin

@test repr(JSON3.read("{}")) == "{}"
@test repr(JSON3.read("{\"a\": 1}")) == "{\n   \"a\": 1\n}"
@test repr(JSON3.read("{\"a\": {\"b\": 2}}")) == "{\n   \"a\": {\n           \"b\": 2\n        }\n}"
# @test repr(JSON3.read("[]")) == "[]"
# @test repr(JSON3.read("[1,2,3]")) == "[\n  1,\n  2,\n  3\n]"
# @test repr(JSON3.read("[1,[2.1,2.2,2.3],3]")) == "[\n  1,\n  [\n    2.1,\n    2.2,\n    2.3\n  ],\n  3\n]"

end # @testset "show.jl"

include("json.jl")

# more tests for coverage
obj = JSON3.read("{\"hey\":1}")
@test get(obj, Int, :hey) == 1
@test get(obj, Int, :ho, 2) == 2

@test JSON3.read("{\"hey\":1}") == JSON3.read(b"{\"hey\":1}") == JSON3.read(IOBuffer("{\"hey\":1}"))

arr = JSON3.read("[\"hey\",1, null, false, \"ho\", {\"a\": 1}, 2]")
@test Base.IndexStyle(arr) == Base.IndexLinear()
@test arr[7] == 2

str = "hey"
ptr = JSON3.PointerString(pointer(str), 3)
@test hash(str) == hash(ptr)
@test codeunit(ptr) == UInt8
@test StructTypes.names(1) == ()
@test StructTypes.names(Any) == ()
@test StructTypes.excludes(1) == ()
@test StructTypes.excludes(Any) == ()
@test StructTypes.omitempties(1) == ()
@test StructTypes.omitempties(Any) == ()

@test StructTypes.subtypekey(1) == :type
@test StructTypes.subtypekey(Any) == :type
@test StructTypes.subtypes(1) == NamedTuple()
@test StructTypes.subtypes(Any) == NamedTuple()

@test JSON3.read(b"\"a\"", String) == "a"
@test JSON3.read(IOBuffer("\"a\""), String) == "a"
@test StructTypes.StructType(Char) == StructTypes.StringType()
@test StructTypes.construct(String, "hey") == "hey"
@test StructTypes.StructType(Bool) == StructTypes.BoolType()
@test StructTypes.construct(Bool, true) === true
@test StructTypes.StructType(UInt8) == StructTypes.NumberType()
@test StructTypes.numbertype(UInt8) == UInt8
@test StructTypes.numbertype(1) == Float64
@test StructTypes.construct(String, "hey") == "hey"
@test StructTypes.StructType(typeof((1,2))) == StructTypes.ArrayType()
x = Dict(:hey=>1)
@test StructTypes.construct(Dict{Symbol, Any}, x) == x

@test JSON3.gettapelen(Int64) == 2
@test JSON3.regularstride(Missing) == false
@test JSON3.regularstride(Int64) == true
@test JSON3.regularstride(Union{Int64, Float64}) == true
@test JSON3.getvalue(Nothing, [], [], 1, 2) === nothing
@test JSON3.defaultminimum(nothing) == 4
@test JSON3.defaultminimum(Int64) == 16
@test JSON3.defaultminimum('1') == 3

# https://github.com/quinnj/JSON3.jl/issues/1
txt = """
{ "a" : { "b" : [ 1, 2 ],
          "c" : [ 3, 4 ] } }
"""

@test JSON3.read(txt).a.b == [1,2]

# https://github.com/quinnj/JSON3.jl/issues/8
@test eltype(JSON3.read("[1.2, 2.0]")) === Float64
@test eltype(JSON3.read("[1.2, 2.0, 3.3]")) === Float64
@test eltype(JSON3.read("[1.2, null, 3.3]")) === Union{Float64, Nothing}
@test eltype(JSON3.read("[1.2, null, 3.0]")) === Union{Float64, Nothing}

# https://github.com/quinnj/JSON3.jl/issues/9
d = Dict(uuid1() => i for i in 1:3)
t = JSON3.write(d)
@test JSON3.read(t, Dict{UUID, Int}) == d
u = uuid1()
@test JSON3.read(JSON3.write(u), UUID) == u

d = Date(2019, 11, 16)
@test JSON3.read(JSON3.write(d), Date) == d
df = dateformat"dd-mm-yyyy"
@test JSON3.read(JSON3.write(d; dateformat=df), Date; dateformat=df) == d

# get issue
obj = JSON3.read("{\"hey\":1}")
@test get(obj, :hey) == get(obj, "hey") == get(obj, "hey", "") == get(()->"", obj, "hey")

# copy issue
obj = JSON3.read("{\"a\":\"b\", \"b\":null, \"c\":[null,null]}")
@test copy(obj) == Dict(:a => "b", :b => nothing, :c => [nothing, nothing])

# better Tuple reading support
@test JSON3.read("[\"car\",\"Mercedes\"]", Tuple{Symbol, String}) == (:car, "Mercedes")
@test JSON3.read("[\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\",\"hey\"]", NTuple{35, String}) ==
    ("hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey", "hey")

StructTypes.StructType(::Type{data}) = StructTypes.Struct()
@test JSON3.read("{\"t\":[\"car\",\"Mercedes\"]}", data) == data((:car, "Mercedes"))

# new StructTypes.keywordargs option
StructTypes.StructType(::Type{DateStruct}) = StructTypes.Mutable()
StructTypes.keywordargs(::Type{DateStruct}) = (date=(dateformat=dateformat"dd-mm-yyyy",), datetime=(dateformat=dateformat"dd-mm-yyyy HH:MM:SS",), time=(dateformat=dateformat"HH MM SS",))
ds = DateStruct(Date(2019, 11, 16), DateTime(2019, 11, 16, 1, 25), Time(1, 26))
@test JSON3.write(ds) == "{\"date\":\"16-11-2019\",\"datetime\":\"16-11-2019 01:25:00\",\"time\":\"01 26 00\"}"
ds2 = JSON3.read(JSON3.write(ds), DateStruct)
@test ds.date == ds2.date && ds.datetime == ds2.datetime && ds.time == ds2.time

# 63
@test JSON3.read(JSON3.write([Symbol("before \" after")])) == ["before \" after"]

# @pretty
io = IOBuffer()
JSON3.pretty(io, 3.14)
@test String(take!(io)) == "3.14"
JSON3.pretty(io, "hey")
@test String(take!(io)) == "hey"
JSON3.pretty(io, (a=1, b=true, c=3.14, d="hey", e=(abcdefghijklmnopqrstuvwxyz=1000, aa=1e8, dd=[nothing, nothing, nothing, 3.14])))

# 77
io = IOBuffer()
JSON3.pretty(io,  JSON3.write(Dict( "x" => Inf64), allow_inf=true), allow_inf=true )
@test String(take!(io)) == "{\n   \"x\": Infinity\n}"

# parsequoted
@test JSON3.read("{\"a\":\"10\",\"b\":\"1\",\"c\":\"45\",\"d\":\"100\"}", A; parsequoted=true) == A(10, 1, 45, 100)

json = "{\"a\": 1, \"b\": 2}\n{\"a\": 3, \"b\": 4}"
x = JSON3.read(json; jsonlines=true)
@test length(x) == 2
@test all(values(x[1]) .== (1, 2))

json = "1\r\n2\r\n3\r\n4\r\n5\r\n"
x = JSON3.read(json; jsonlines=true)
@test length(x) == 5
@test x == [1, 2, 3, 4, 5]

json = "1"
x = JSON3.read(json; jsonlines=true)
@test length(x) == 1
@test x == [1]

json = "  1\r\n\t2"
x = JSON3.read(json; jsonlines=true)
@test length(x) == 2
@test x == [1, 2]

# allow_inf consistency
@test_throws ArgumentError JSON3.read("-Infinity")

end # @testset "JSON3"

include("stringnumber.jl")