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

using Markdown
using InteractiveUtils

# ╔═╡ 2b2d7259-c670-4765-95d1-d33595729dc2
begin

	# load some packages -
	using PlutoUI
	using Distributions
	using Plots

	# setup paths -
	_PATH_TO_ROOT = pwd()
	_PATH_TO_DATA = joinpath(_PATH_TO_ROOT, "data")
	_PATH_TO_FIGS = joinpath(_PATH_TO_ROOT, "figs")
	_PATH_TO_SRC = joinpath(_PATH_TO_ROOT, "src")

	# show -
	nothing
end

# ╔═╡ 3024cd1a-61dd-4feb-bd21-2f6b38ee36b5
md"""
### Single cell gene expression dynamics

In this lecture we'll continue our discussion of gene expression dynamics. In particular:

* We'll derive a _starter_ model for the kinetic rate of transcription $r_{X,i}$
* We'll introduce the basics of the stochastic simulation algorithms developed by [Gillespie](https://en.wikipedia.org/wiki/Daniel_Gillespie), [Petzold](https://engineering.ucsb.edu/people/linda-petzold) and coworkers.
* We'll use the [τ leaping algorithm](https://en.wikipedia.org/wiki/Tau-leaping) to simulate the expresssion of a single gene in an _Escherichia coli_ cell.

"""

# ╔═╡ 1342bde2-37d7-4bef-beac-9303742e786b
PlutoUI.LocalResource(joinpath(_PATH_TO_FIGS,"Fig-TXTL-Starter.png"))

# ╔═╡ 922c72ec-aefd-46d6-a465-cbf72a2cc05f
md"""
### A simple model for transcription kinetics

##### Assumptions and derivation
The rate of transcription is the product between the _kinetic limit_ of transcription $r_{X,i}$ and the control variable $u_{i}\left(\dots\right)$, which describes the activity of promoter $i$. One simple model of $r_{X, i}$ can be developed by thinking about RNA polymerase (RNAP) as an enzyme that produces mRNA but does not consume its substrate, gene $i$ ($G_{i}$). Suppose we proposed the elementary steps:

$$\begin{eqnarray}
	RNAP+G_{i}&\rightleftharpoons&{RNAP:G_{i}}\\
	{RNAP:G_{i}}&\longrightarrow&RNAP+G_{i}+m_{i}
\end{eqnarray}$$

The kinetics of each elementary step can be written using mass-action kinetics, i.e.,

$$\begin{eqnarray}
	r_{1,i} & = & k_{1,i}\left[RNAP\right]\left[G_{i}\right]\\
	r_{2,i} & = & k_{2,i}\left[RNAP:G_{i}\right]\\
	r_{3,i} & = & k_{3,i}\left[RNAP:G_{i}\right]
\end{eqnarray}$$

where $\left[\cdot\right]$ denotes a species concentration, and $k_{\star,i}$ denotes the rate constant governing the $\star$ elementary reaction:

* The rate $r_{1,i}$ describes the _association_ rate between RNAP and the ith gene,
* The rate $r_{2,i}$ represents the rate of _dissociation_ of the RNAP-gene complex, and
* The $r_{3,i}$ denotes the rate of _transcription_ of gene $i$ forming mRNA $m_{i}$

RNAP must obey the relationship:

$$\left[RNAP\right]_{T} = \left[RNAP\right] + \left[RNAP:G_{i}\right]$$

where $\left[RNAP\right]_{T}$ denotes the total RNAP concentration in the system,
$\left[RNAP\right]$ denotes the free RNAP concentration (not bound to gene) while
$\left[RNAP:G_{i}\right]$ denotes the enzyme-substrate complex.

To estimate the _overall_ rate of transcription $r_{X, i}$, we stipulate a single rate-limiting step out of the set of elementary reactions. Let's assume that the rate of elongation ($r_{3,i}$) is the slowest step. Thus, the overall transcription rate is then given by:

$$v = k_{3,i}\left[RNAP:G_{i}\right]$$

Following the same procedure as the derivation of Michaelis-Menten enzyme kinetics gives the expression:

$$r_{X,i} = V_{max,i}\frac{\left[G_{i}\right]}{K_{X,i}+\left[G_{i}\right]}$$

where $V_{max,i}\equiv{k_{3,i}}\left[RNAP\right]_{T}$, and $K_{X,i}$ denotes the saturation constant governing the expression of gene $i$:

##### A model for the elongation rate constant
We can estimate a value for $V_{max,i}$, and in particular the rate of elongation $k_{3,i}$ (units: 1/s), from first principles. The elongation rate constant can modeled as an average elongation rate of the polymerase $\langle e_{X} \rangle$ (units: nt/s) times the inverse of the length of gene $i$ $L_{i}$:

$$k_{3,i} \sim \langle e_{X} \rangle L_{i}^{-1}$$

Experimental measurements of the elongation rate $\langle e_{X} \rangle$ for multiple organisms are availble on [bionumbers](https://bionumbers.hms.harvard.edu/search.aspx?trm=RNAP+elongation+rate).

##### What is the saturation constant of transcription?

The saturation constant of transcription $K_{X,i}$ (units: conc) is defined as the ratio of elementary rate constants:

$$K_{X,i}\equiv\frac{k_{2,i}+k_{3,i}}{k_{1,i}}$$

In the limit of small $k_{3,i}$, the saturation constant $K_{X,i}$ is the inverse of the affinity (and directly proportional to the dissociation constant) of the polymerase for the gene. In other words:

* High affinity: tight binding $k_{1,i}\gg k_{2,i}$ implies $K_{X,i}$ is small, conversely
* Low affinity: loose binding $k_{1,i}\ll k_{2,i}$ which implies $K_{X,i}$ is large.

We know that the RNAP dissociation constant $K_{D,i}$:

$$K_{D,i} = \frac{k_{2,i}}{k_{1,i}}$$

for the lac promoter in _E. coli_ is [$K_{D}\sim 550$ nM (units: nM or molecules/cell)](https://bionumbers.hms.harvard.edu/search.aspx?trm=KD+for+RNAP+to+lac+E.+coli).
"""

# ╔═╡ 2d47c9da-c182-4e7f-9f4d-bfff4b97e3a4
md"""
### A crash course in Stochastic Simulation Algorithms (SSAs)

__Key references__
* [Gillespie DT. Stochastic simulation of chemical kinetics. Annu Rev Phys Chem. 2007;58:35-55. doi: 10.1146/annurev.physchem.58.032806.104637. PMID: 17037977.](https://pubmed.ncbi.nlm.nih.gov/17037977/)
* [Gillespie, D. T. (2001). Approximate accelerated stochastic simulation of chemically reacting systems. J. Chem Phys. 115: 1716–1733. Bibcode:2001JChPh.115.1716G. doi:10.1063/1.1378322](https://aip.scitation.org/doi/10.1063/1.1378322)
"""

# ╔═╡ f9c5fea7-f713-403e-ad82-75c68ecfe81d
md"""
##### Example: Expression of a gene in a single _Escherichia coli_ cell
"""

# ╔═╡ c4cdac00-b344-4246-a445-23f710047a8c
begin

	# setup the parameters -
	parameters = Dict{String, Any}()

	# let's compute a literature value -
	k₁ = 100.0 	# units: 1/conc-t
	eₓ = 35.0 	# units: nt/s
	L = 1000.0 	# units: nt
	KD = 1000.0  # units: nM
	Kₓ = (eₓ*(1/L) + KD*k₁)/(k₁)

	# get parameters from bionumbers -
	parameters["RNAP_copy_number"] = 4600.0 					# units: copies/cell BNID 108601
	parameters["RNAP_elongation_rate"] = eₓ 					# units: nt/s BNID 111871
	parameters["gene_coding_length"] = L 						# units: nt BNID 111610
	parameters["mRNA_half_life"] = 0.5*(60)						# units: s BIND 104324
	parameters["gene_copy_number"] = 20.0 						# units: copies/cell problem
	parameters["saturation_constant_transcription"] = Kₓ 		# units: copies/cell problem

	# show -
	nothing
end

# ╔═╡ 782c6ddb-f5fa-46db-8a1e-5ae01285e3ef
Kₓ

# ╔═╡ 3c48cfd0-5403-4faf-a1f9-6460a18df49c
md"""
### Summary and conclusions
In this lecture we:

* Derived a _starter_ model for the kinetic rate of transcription $r_{X,i}$
* Introduced the basics of the stochastic simulation algorithms developed by [Gillespie](https://en.wikipedia.org/wiki/Daniel_Gillespie), [Petzold](https://engineering.ucsb.edu/people/linda-petzold) and coworkers.
* Used the [τ leaping algorithm](https://en.wikipedia.org/wiki/Tau-leaping) to simulate the expresssion of a single gene in an _Escherichia coli_ cell.
"""

# ╔═╡ 8eae03bc-f2f4-4546-81eb-112be811f5dd
md"""
### Next time

* We'll move back to the continuous world to simulate gene expression for cell-free synthetic circuits and
* We'll couple the rate of gene expression with the availability of metabolic resources.

__Reference__:

[Allen TE, Palsson BØ. Sequence-based analysis of metabolic demands for protein synthesis in prokaryotes. J Theor Biol. 2003 Jan 7;220(1):1-18. doi: 10.1006/jtbi.2003.3087. PMID: 12453446.](https://pubmed.ncbi.nlm.nih.gov/12453446/)
"""

# ╔═╡ c7949300-f103-424d-996e-907cc0f04d92
md"""
### Function library
"""

# ╔═╡ cc2e34c3-e86c-40ca-be7a-0ba1d6f92201
function generate_step_size(S,X,R)::Float64

	# setup -
	ϵ = 0.03
	τ_array = Vector{Float64}()

	# compute the auxilary variables -
	μ = S*R
	σ = (S.^2)*R

	# compute the highest order event, and then τ -
	(ℳ,ℛ) = size(S)
	for i ∈ 1:ℳ

		# find the rates in which this species is a reactant -
		idx_negative = findall(x->x<0.0, S[i,:])

		# get the values for these rates -
		gᵢ = maximum(R[idx_negative])

		# terms -
		term_1 = max(ϵ*X[i]/gᵢ, 1)/abs(μ[i])
		term_2 = (max(ϵ*X[i]/gᵢ, 1)^2)/σ[i]
		τᵢ = min(term_1, term_2)
		push!(τ_array, τᵢ)
	end

	return minimum(τ_array)
end

# ╔═╡ de95690b-a564-471d-8597-0d9e6dcf2f1b
function propensity(X::Vector{Float64}, parameters::Dict{String, Any})

	# get values from the parameters dictionary -
	RNAP = parameters["RNAP_copy_number"]
	eₓ = parameters["RNAP_elongation_rate"]
	Kₓ = parameters["saturation_constant_transcription"]
	G = parameters["gene_copy_number"]
	t_half_life = parameters["mRNA_half_life"]
	L = parameters["gene_coding_length"]

	# compute Vmax and the degrdation constant -
	Vmax = RNAP*(eₓ)*(1/L)
	θₓ = -(log(0.5)/t_half_life)

	# compute the propensity -
	a = Array{Float64,1}(undef,2)
	a[1] = Vmax*(G/(Kₓ + G))
	a[2] = θₓ*X[1]

	# return -
	return a
end

# ╔═╡ ed06b789-ece0-4d4e-a9bc-4431806f3b43
function tau_leaping_solve(S::Matrix{Float64}, Xₒ::Array{Float64,1}, Tₒ::Float64, T₁::Float64,
	parameters::Dict{String,Any}; τ::Union{Nothing,Float64} = nothing, should_update_τ::Bool = false)

	# initialize some stuff -
	loop_counter = 1
	should_we_continue = true
	state_array = Array{Vector{Float64},1}()
	time_array = Vector{Float64}()
	T = Tₒ
	X = Xₒ
	K_array = Vector{Float64}()

	push!(time_array,Tₒ)
	push!(state_array,Xₒ)

	# generate an initial propensity function -
	R = propensity(Xₒ, parameters)

	# generate a step size -
	if (should_update_τ == true)
		τ = generate_step_size(S, X, R)
	elseif (isnothing(τ) == true)
		τ = 0.01
	end

	# main loop -
	while (should_we_continue)

		# K-array -
		for r ∈ R
			# for each channel / compute a random number of "firings" -
			λ = r*τ
			K = rand(Poisson(λ))
			push!(K_array, K)
		end

		# update the state -
		Δ = S*K_array
		X += Δ

		# correct for negative numbers if there are any -
		#X = max.(0.0, X)

		# recompute the propensity with the new state -
		R = propensity(X, parameters)

		# package into the state array -
		push!(state_array, X)

		# update time -
		T += τ
		push!(time_array, T)

		# clean up -
		empty!(K_array)

		# should we go around again?
		if (T>=T₁)
			should_we_continue = false
		else

			if (should_update_τ == true)
				τ = generate_step_size(S, X, R)
			elseif (isnothing(τ) == true)
				τ = 0.01
			end
		end
	end

	SA = vcat(state_array...)
	TA = time_array

	# return -
	return (TA, SA)
end

# ╔═╡ b8bed16f-e4b3-4ee8-8c73-a04d1df43205
begin

	# setup problem -
	Xₒ = ones(1) # suppose we start with a single mRNA molecule -
	number_of_cells = 3
	cell_dictionary = Dict()

	# we have 1 species (mRNA) and two reaction "channels" -
	S = Array{Float64,2}(undef, 1,2)
	S[1,1] = 1.0
	S[1,2] = -1.0

	# setup time -
	Tₒ = 0.0
	T₁ = 120.0 # simulate number of s

	# run solver -
	for i ∈ 1:number_of_cells
		cell_dictionary[i] = tau_leaping_solve(S, Xₒ, Tₒ, T₁, parameters; τ = 0.01)
	end

	# show -
	nothing
end

# ╔═╡ 5e3fb403-4f13-451b-a996-2466504971e7
begin

	for i ∈ 1:number_of_cells
		(T,X) = cell_dictionary[i]
		if (i == 1)
			plot(T,X, legend=false)
		else
			plot!(T,X)
		end
	end
	xlabel!("Time (s)", fontsize=18)
	ylabel!("Copies (mRNA/cell)", fontsize=18)
	current()
end

# ╔═╡ 8cfc75c7-5893-4505-8825-b2b351088aea
TableOfContents(title="📚 Lecture Outline", indent=true, depth=5, aside=true)

# ╔═╡ cdf5e092-499c-4010-a2a3-c050a9395fb4
html"""
<style>
main {
    max-width: 860px;
    width: 70%;
    margin: auto;
    font-family: "Roboto, monospace";
}

a {
    color: blue;
    text-decoration: none;
}
</style>"""

# ╔═╡ ea0020f6-a051-11ec-2fb6-ef39a663134b
html"""
<script>
	// initialize -
	var section = 0;
	var subsection = 0;
	var subsubsection = 0;
	var headers = document.querySelectorAll('h3, h5, h6');

	// main loop -
	for (var i=0; i < headers.length; i++) {

		var header = headers[i];
	    var text = header.innerText;
	    var original = header.getAttribute("text-original");
	    if (original === null) {

			// Save original header text
	        header.setAttribute("text-original", text);
	    } else {

			// Replace with original text before adding section number
	        text = header.getAttribute("text-original");
	    }

	    var numbering = "";
	    switch (header.tagName) {
	        case 'H3':
	            section += 1;
	            numbering = section + ".";
	            subsection = 0;
	            break;
	        case 'H5':
	            subsection += 1;
	            numbering = section + "." + subsection;
	            break;
			case 'H6':
	            subsubsection += 1;
	            numbering = section + "." + subsection + "." + subsubsection;
	            break;
	    }
		// update the header text
		header.innerText = numbering + " " + text;
	};
</script>"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"

[compat]
Distributions = "~0.25.49"
Plots = "~1.26.0"
PlutoUI = "~0.7.37"
"""

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

julia_version = "1.7.2"
manifest_format = "2.0"

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "8eaf9f1b4921132a4cff3f36a1d9ba923b14a481"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.4"

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

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

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

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

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

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

[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"

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

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

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

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

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

[[deps.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 = "96b0bc6c52df76506efc8a441c6cf1adcb1babc4"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.42.0"

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

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

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

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

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

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

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

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

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

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

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

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

[[deps.DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "90b158083179a6ccbce2c7eb1446d5bf9d7ae571"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.7"

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

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

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

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

[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "0dbc5b9683245f905993b51d2814202d75b34f1a"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.13.1"

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

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

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

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

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

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

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

[[deps.GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "a6c850d77ad5118ad3be4bd188919ce97fffac47"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.64.0+0"

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

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

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

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

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

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

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

[[deps.HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "SpecialFunctions", "Test"]
git-tree-sha1 = "65e4589030ef3c44d3b90bdc5aac462b4bb05567"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.8"

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

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

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

[[deps.IniFile]]
git-tree-sha1 = "f550e6e32074c939295eb5ea6de31849ac2c9625"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.1"

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

[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "91b5dcf362c5add98049e6c29ee756910b03051d"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.3"

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

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

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

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

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.3"

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

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

[[deps.LERC_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434"
uuid = "88015f11-f218-50d7-93a8-a6af411a945d"
version = "3.0.0+1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[deps.NaNMath]]
git-tree-sha1 = "737a5957f387b17e74d4ad2f440eb330b39a62c5"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.0"

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

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

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

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

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

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

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

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

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

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

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "85b5da0fa43588c75bb1ff986493443f821c70b7"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.2.3"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[deps.RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "995a812c6f7edea7527bb570f0ac39d0fb15663c"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.5.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "74fb527333e72ada2dd9ef77d98e4991fb185f04"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.4.1"

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

[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "c3d8ba7f3fa0625b062b82853a7d5229cb728b6b"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[deps.Unzip]]
git-tree-sha1 = "34db80951901073501137bdbc3d5a8e7bbd06670"
uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d"
version = "0.1.2"

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

[[deps.Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4528479aa01ee1b3b4cd0e6faef0e04cf16466da"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.25.0+0"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╟─3024cd1a-61dd-4feb-bd21-2f6b38ee36b5
# ╠═1342bde2-37d7-4bef-beac-9303742e786b
# ╟─922c72ec-aefd-46d6-a465-cbf72a2cc05f
# ╟─2d47c9da-c182-4e7f-9f4d-bfff4b97e3a4
# ╟─f9c5fea7-f713-403e-ad82-75c68ecfe81d
# ╠═c4cdac00-b344-4246-a445-23f710047a8c
# ╠═782c6ddb-f5fa-46db-8a1e-5ae01285e3ef
# ╠═b8bed16f-e4b3-4ee8-8c73-a04d1df43205
# ╠═5e3fb403-4f13-451b-a996-2466504971e7
# ╟─3c48cfd0-5403-4faf-a1f9-6460a18df49c
# ╟─8eae03bc-f2f4-4546-81eb-112be811f5dd
# ╟─c7949300-f103-424d-996e-907cc0f04d92
# ╟─ed06b789-ece0-4d4e-a9bc-4431806f3b43
# ╟─cc2e34c3-e86c-40ca-be7a-0ba1d6f92201
# ╟─de95690b-a564-471d-8597-0d9e6dcf2f1b
# ╠═2b2d7259-c670-4765-95d1-d33595729dc2
# ╠═8cfc75c7-5893-4505-8825-b2b351088aea
# ╟─cdf5e092-499c-4010-a2a3-c050a9395fb4
# ╟─ea0020f6-a051-11ec-2fb6-ef39a663134b
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
module Ekztazy

using Dates
using Distributed
using HTTP
using InteractiveUtils
using JSON3
using StructTypes
using OpenTrick
using Setfield
using TimeToLive

const D1ZKORD_JL_VERSION = v"0.6.1"
const API_VERSION = 9
const DISCORD_API = "https://discordapp.com/api"

# Shortcuts for common unions.
const Optional{T} = Union{T, Missing}
const Nullable{T} = Union{T, Nothing}
const OptionalNullable{T} = Union{T, Missing, Nothing}
const StringOrChar = Union{AbstractString, AbstractChar}

# Shortcut functions .
jsonify(x) = JSON3.write(x)

# Constant functions.
donothing(args...; kwargs...) = nothing
alwaystrue(args...; kwargs...) = true
alwaysfalse(args...; kwargs...) = false

# Run a function with an acquired semaphore.
function withsem(f::Function, s::Base.Semaphore)
    Base.acquire(s)
    try f() finally Base.release(s) end
end

# Precompile all methods of a function, running it if force is set.
function compile(f::Function, force::Bool; kwargs...)
    for m in methods(f)
        types = Tuple(m.sig.types[2:end])
        precompile(f, types)
        force && try f(mock.(types; kwargs...)...) catch end
    end
end

function method_argnames(m::Method)
    argnames = ccall(:jl_uncompress_argnames, Vector{Symbol}, (Any,), m.slot_syms)
    isempty(argnames) && return argnames
    return argnames[2:m.nargs]
end

function method_argtypes(m::Method)
    return m.sig.types[2:end]
end

"""
    method_args(m::Method) -> Vector{Tuple{Symbol, Type}}
"""
function method_args(m::Method)
    n, t, v = method_argnames(m), method_argtypes(m), []
    for x = 1:length(n)
        push!(v, (n[x], t[x]))
    end
    v
end

include(joinpath("utils", "consts.jl"))
include(joinpath("types", "types.jl"))
include(joinpath("client", "client.jl"))
include(joinpath("client", "handlers.jl"))
include(joinpath("gateway", "gateway.jl"))
include(joinpath("rest", "rest.jl"))
include(joinpath("utils", "helpers.jl"))

end

ext: jl


text:
@testset "model" begin
    m = q2args_sqth_fno()

    n = 6
    points, 𝛒s, args, σs = gen_data_sqth(n_data=n)
    jldsave(joinpath(SqState.training_data_path(), "test.jld2"); points, 𝛒s, args, σs)

    loader = SqState.preprocess_q2args(joinpath(SqState.training_data_path(), "test.jld2"), batch_size=2)
    x, y = first(loader)

    ŷ = m(x)
    @test size(ŷ) == (3, 2)

    rm(joinpath(SqState.training_data_path(), "test.jld2"))
end


text:
## modules.j. Modules used in ROCAnalysis
## (c) 2015 David A. van Leeuwen.
##
## Licensed under the MIT software license, see LICENSE.md

using Compat
using Requires
using DataFrames: AbstractDataFrame, DataFrame, DataArray, NA
using NumericFuns


text:
import NMRDataSetup
import NMRSpectraSimulator
import NMRSpecifyRegions

include("../src/NMRCalibrate.jl")
import .NMRCalibrate

using LinearAlgebra
using FFTW
import PyPlot
import BSON
import JLD

#import Clustering
import Statistics
import Random

include("./helpers/final_helpers.jl")
include("./helpers/solute_calibrate.jl")
include("./helpers/loop_entries1.jl")

PyPlot.close("all")
fig_num = 1

Random.seed!(25)
PyPlot.matplotlib["rcParams"][:update](["font.size" => 22, "font.family" => "serif"])

p_set = Vector{String}(undef, 0)
m_set = Vector{Vector{String}}(undef, 0)
w_set = Vector{Vector{Float64}}(undef, 0)

#setupcalibrateserine!(p_set, m_set, w_set)
setupcalibrateentries1!(p_set, m_set, w_set)
#setupcalibrateentriesNamJan2022!(p_set, m_set, w_set)

projects_dir = "/home/roy/MEGAsync/outputs/NMR/calibrate/final"
base_path_JLD = "/home/roy/Documents/repo/NMRData//src/input/molecules"
cs_config_path = "/home/roy/Documents/repo/NMRData/src/input/reduced_cs_config.txt"

function loopscript(p_name_set, m_names_set, w_set,
    max_iters, projects_dir, base_path_JLD, cs_config_path)

    for i = 1:length(p_name_set)
        project_name = p_name_set[i]
        molecule_names = m_names_set[i]
        w = w_set[i]

        calibratesolute(project_name, molecule_names, w;
            max_iters = max_iters,
            projects_dir = projects_dir,
            base_path_JLD = base_path_JLD,
            cs_config_path = cs_config_path)

        println()
    end

end

### batch.
max_iters = 50000
loopscript(p_set, m_set, w_set, max_iters, projects_dir, base_path_JLD, cs_config_path)
### end batch.

# #### singular.
# # project_name = "Nam2022_Serine"
# # molecule_names = ["D-(+)-Glucose"; "L-Serine";]
# # w = [1.0; 1.0] #
#
# println("Now on $(project_name)")
# max_iters = 50000
# #max_iters = 5
# include("solute_calibrate.jl")
# println()
# ### end singular.


text:
export AbstractFeatureConstructor, create_features, feature_size

"""
    AbstractFeatureCreator
An abstract feature creator, for feature transformation from the states.
"""
abstract type AbstractFeatureConstructor end

"""
    create_features(fc::AbstractFeatureCreator, s)
Actually create the features
"""
function create_features(fc::AbstractFeatureConstructor, s; kwargs...)
    throw("Implement create features for $(typof(fc))")
end

"""
    feature_size(fc::AbstractFeatureCreator)
Get size of feature vector the features assume exists.
"""
function feature_size(fc::AbstractFeatureConstructor)
    throw("Implement feature size for $(typof(fc))")
end

# export TileCoder
# include("FeatureCreators/TileCoder.jl")

# export KenervaCoder
# include("FeatureCreators/KenervaCoder.jl")

max_stars_repo_name: mkschleg/JuliaRL

max_issues_repo_name: mkschleg/JuliaRL

max_forks_repo_name: mkschleg/JuliaRL


text:
using Pkg, DrWatson

@quickactivate "StatisticalRethinkingTuring"
using Turing
using StatisticalRethinking
Turing.setprogress!(false);

using DataFrames, Turing

N = 200
df = DataFrame()
df.weight = rand(Uniform(20, 90), N)
f(x) = mean(df.weight) + 1.6x + rand(Normal(0, 10))
df.height = f.(df.weight)

@model function m4_3(weights, heights)
    a ~ Normal(178, 20)
    b ~ LogNormal(0, 1)
    σ ~ Uniform(0, 50)
    μ = a .+ b .* weights
    for i in eachindex(heights)
        heights[i] ~ Normal(μ[i], σ)
    end
end

m4_3t = m4_3(df.weight, df.height)
chns4_3t = sample(m4_3t, NUTS(100, 0.65), N);
chns4_3t |> display

# Use DataFrame for easy handling

#= From README docs MCMCChains
Similarly, for DataFrames:

DataFrame(chns)                                 <- Iteration, chain index added
DataFrame(chns[:s])                             <- Still true?
DataFrame(chns, [:parameters])                  <- Still true?
...
=#

Array(chns4_3t, [:parameters]) |> display
DataFrame(Chains(chns4_3t, [:parameters]) |> display


text:
using DistributedStwdLDA
using Test, Statistics, StatsBase, Random, Distributions, CSV, DataFrames
using Distributed, SharedArrays

nwork = 4
while length(workers()) < nwork
    addprocs(1)
end

@everywhere using DistributedStwdLDA

function fillpb(scMeta,scReads,trueP;ncells=100,celltypes=["alpha","beta","gamma","delta"])
  pbulk = zeros(Int,size(trueP)[1],size(scReads)[2]-1)
  for i in 1:size(trueP)[1]
    for j in 1:size(trueP)[2]
      # @infiltrate
      allids = scMeta[scMeta.cellType.==celltypes[j],:].cellID
      inds = StatsBase.sample(1:length(allids),Int(ncells*trueP[i,j]),replace=true)
      ids = allids[inds]
      pbulk[i,:] .= vec(sum(Matrix(filter(x -> x.cellID in ids,scReads)[:,2:end]),dims=1))
    end
  end
  pbulk
end

@testset "deconvolution: baron" begin
  data_dir = joinpath(@__DIR__,"data","baron")

  C_fn = joinpath(data_dir,"BaronSC.DM.isletVST_C.csv")
  pDataC_fn = joinpath(data_dir,"BaronSC.DM.isletVST_pDataC.csv")
  thetabenchmark=nothing

  # sc metadata
  scMeta = DataFrame(CSV.File(pDataC_fn))[:,["cellID","cellType","sampleID"]]
  scMeta = filter(x -> x.cellType in ["alpha","beta","gamma","delta"],scMeta)

  # sc reads
  scReads = DataFrame(CSV.File(C_fn,transpose=true)) # this is an R data frame with "row names"
  rename!(scReads,Symbol.(["cellID",names(scReads)[2:end]...]))
  scReads = filter(x -> x.cellID in scMeta.cellID,scReads)

  # true proportions
  trueP = [
    0.1 0.3 0.5 0.1;
    0.5 0.1 0.3 0.1;
    0.3 0.1 0.1 0.5]

  # bulk reads
  pbulk = fillpb(scMeta,scReads,trueP,ncells=50,celltypes=["alpha","beta","gamma","delta"])
  bulkReads = DataFrame(pbulk,:auto)
  rename!(bulkReads,names(scReads[:,2:end]))
  insertcols!(bulkReads, 1, :bulkID => ["Bulk1","Bulk2","Bulk3"] )

  trueP = DataFrame(trueP,:auto)
  rename!(trueP,["alpha","beta","gamma","delta"])
  insertcols!(trueP, 1, :bulkID => ["Bulk1","Bulk2","Bulk3"] )

  jl_output = dsLDA_E_step(
      Matrix(scReads[:,2:end]),
      names(scReads[:,2:end]),
      scReads.cellID,
      scMeta,
      Matrix(bulkReads[:,2:end]),
      names(bulkReads[:,2:end]),
      bulkReads.bulkID,
      "",
      nparts=3,
      runqc=true,
      ldagenethresh=0.1,
          minCellsTopicCorp=1,
      scalebulk="log1p",
      bulkfactor=1000,
      scalesc="ident",
      betapseudo=0.0,
      scfactor=1.0,
      betaeps=0.01,
      nchains=2,
      alpha=0.1,
      philatent=2,
      blocksize=5,
      niter=1000,
      initflavor="unif",
      verbose=false,
      burn=0.5,
      thinning=5,
      rmchains=true
    )
  print(sqrt(mean((jl_output[1].-Matrix(trueP[:,2:end])).^2)))
  @test size(jl_output[1]) == size(trueP[:,2:end])
end


text:
# "Packages"
using Revise # reduce need for recompile
using Plots
using Documenter
using LinearAlgebra
using SparseArrays
using UnPack

# "User defined modules"
push!(LOAD_PATH, "./src")
using CommonUtils
using Basis1D
using Basis2DQuad # face trace space
using Basis3DHex
using UniformHexMesh

push!(LOAD_PATH, "./examples/EntropyStableEuler")
using EntropyStableEuler

using SetupDG

N = 2
K1D = 8
T = 2/3 # endtime
CFL = .75

VX,VY,VZ,EToV = uniform_hex_mesh(K1D,K1D,K1D)

rd = init_reference_hex(N,gauss_lobatto_quad(0,0,N))
md = init_mesh((VX,VY,VZ),EToV,rd)

# Make hybridized SBP operators
@unpack M,Dr,Ds,Dt,Pq,Vq,Vf,nrJ,nsJ,ntJ,wf = rd
Qr = Pq'*M*Dr*Pq
Qs = Pq'*M*Ds*Pq
Qt = Pq'*M*Dt*Pq
Ef = Vf*Pq
Br = diagm(wf.*nrJ)
Bs = diagm(wf.*nsJ)
Bt = diagm(wf.*ntJ)
Qrh = .5*[Qr-Qr' Ef'*Br;
        -Br*Ef Br]
Qsh = .5*[Qs-Qs' Ef'*Bs;
        -Bs*Ef Bs]
Qth = .5*[Qt-Qt' Ef'*Bt;
        -Bt*Ef Bt]

"sparse skew symmetric versions of the operators"
Qrhskew = .5*(Qrh-transpose(Qrh))
Qshskew = .5*(Qsh-transpose(Qsh))
Qthskew = .5*(Qth-transpose(Qth))
Qrhskew_sparse = droptol!(sparse(Qrhskew),1e-12)
Qshskew_sparse = droptol!(sparse(Qshskew),1e-12)
Qthskew_sparse = droptol!(sparse(Qthskew),1e-12)

# precompute union of sparse ids for Qr, Qs
Qnzids = [unique([Qrhskew_sparse[i,:].nzind; Qshskew_sparse[i,:].nzind; Qthskew_sparse[i,:].nzind]) for i = 1:size(Qrhskew,1)]

# make periodic
@unpack Nfaces = rd
@unpack xf,yf,zf,K,mapM,mapP,mapB = md
LX = 2; LY = 2; LZ = 2
mapPB = build_periodic_boundary_maps(xf,yf,zf,LX,LY,LZ,Nfaces*K,mapM,mapP,mapB)
mapP[mapB] = mapPB
@pack! md = mapP

# add curved mapping
@unpack x,y,z = md
a = .05
dx = @. (x-1)*(x+1)*(y-1)*(y+1)*(z-1)*(z+1)
x = x + a.*dx
y = y + a.*dx
z = z + a.*dx

# recompute phys nodes, geofacs, etc for a curved mesh
@unpack xq,yq,zq = md
xq,yq,zq = (x->Vq*x).((x,y,z))
@pack! md = xq,yq,zq

vgeo = geometric_factors(x,y,z,Dr,Ds,Dt)
rxJ,sxJ,txJ,ryJ,syJ,tyJ,rzJ,szJ,tzJ,J = vgeo
nxJ = nrJ.*(Vf*rxJ) + nsJ.*(Vf*sxJ) + ntJ.*(Vf*txJ)
nyJ = nrJ.*(Vf*ryJ) + nsJ.*(Vf*syJ) + ntJ.*(Vf*tyJ)
nzJ = nrJ.*(Vf*rzJ) + nsJ.*(Vf*szJ) + ntJ.*(Vf*tzJ)
sJ = @. sqrt(nxJ.^2 + nyJ.^2 + nzJ.^2)
@pack! md = nxJ,nyJ,nzJ,sJ

# interp geofacs to both vol/surface quadrature points
rxJ,sxJ,txJ,ryJ,syJ,tyJ,rzJ,szJ,tzJ = (x->[Vq;Vf]*x).(vgeo)
@pack! md = rxJ,sxJ,txJ,ryJ,syJ,tyJ,rzJ,szJ,tzJ

# convert to quadrature node basis
@unpack wq=rd
Vh = droptol!(sparse(vcat(diagm(ones(length(wq))), Ef)),1e-12)
Ph = droptol!(sparse(2*diagm(@. 1/wq)*transpose(Vh)),1e-12)
Lf = droptol!(sparse(diagm(@. 1/wq)*(transpose(Ef)*diagm(wf))),1e-12)
ops = (Qrhskew_sparse,Qshskew_sparse,Qthskew_sparse,Qnzids,Ph,Lf)
J = Vq*J
wJq = diagm(wq)*J # recompute for curved
@pack! md = J,wJq

# initial conditions
rhoex(x,y,z,t) = @. 2 + .5*sin(pi*(x-t))
rho = rhoex(xq,yq,zq,0)
u = ones(size(x))
v = zeros(size(x))
w = zeros(size(x))
p = ones(size(x))
Q = primitive_to_conservative(rho,u,v,w,p)

"timestepping"
rk4a,rk4b,rk4c = rk45_coeffs()
CN = (N+1)*(N+2)*3/2  # estimated trace constant
dt = CFL * 2 / (CN*K1D)
Nsteps = convert(Int,ceil(T/dt))
dt = T/Nsteps

"sparse version - precompute sparse row ids for speed"
function sparse_hadamard_sum(Qhe,ops,vgeo,flux_fun)

    (Qr,Qs,Qt,Qnzids) = ops
    nrows = size(Qr,1)
    nfields = length(Qhe)

    # precompute logs for logmean
    (rho,u,v,w,beta) = Qhe
    Qlog = (log.(rho), log.(beta))

    rhsQe = ntuple(x->zeros(nrows),nfields)
    rhsi = zeros(nfields) # prealloc a small array for accumulation
    for i = 1:nrows
        Qi = (x->x[i]).(Qhe)
        Qlogi = (x->x[i]).(Qlog)
        vgeo_i = (x->x[i]).(vgeo)

        fill!(rhsi,0) # reset rhsi before accumulation
        for j = Qnzids[i] # nonzero row entries
            Qj = (x->x[j]).(Qhe)
            Qlogj = (x->x[j]).(Qlog)
            vgeo_j = (x->x[j]).(vgeo)

            avg(uL,uR) = .5*(uL+uR)
            rxJa,sxJa,txJa,ryJa,syJa,tyJa,rzJa,szJa,tzJa = avg.(vgeo_i,vgeo_j)

            Fx,Fy,Fz = flux_fun(Qi,Qj,Qlogi,Qlogj)
            Fr = @. rxJa*Fx + ryJa*Fy + rzJa*Fz
            Fs = @. sxJa*Fx + syJa*Fy + szJa*Fz
            Ft = @. txJa*Fx + tyJa*Fy + tzJa*Fz

            # sum(Qx.*Fx + Qy.*Fy,2) = sum(Qr*rxJ*Fx + Qs*sxJ*Fx + Qr*ryJ*Fy ...)
            @. rhsi += Qr[i,j]*Fr + Qs[i,j]*Fs + Qt[i,j]*Ft
        end

        # faster than one-line fixes (no return args)
        for fld in eachindex(rhsQe)
            rhsQe[fld][i] = rhsi[fld]
        end
    end

    return rhsQe
end

function rhs(Q,md::MeshData,ops,flux_fun,compute_rhstest=false)

    # unpack args
    (Qrh_sparse,Qsh_sparse,Qth_sparse,Qnzids,Ph,Lf)=ops
    @unpack rxJ,sxJ,txJ,ryJ,syJ,tyJ,rzJ,szJ,tzJ=md
    @unpack J,wJq,nxJ,nyJ,nzJ,sJ,mapP,mapB,K = md
    Nq,Nh = size(Ph)

    # entropy projection
    VU = v_ufun(Q...)
    Uf = u_vfun((x->Ef*x).(VU)...) # conservative vars
    Uh = vcat.(Q,Uf)

    # convert to rho,u,v,beta vars
    (rho,rhou,rhov,rhow,E) = Uh
    beta = betafun(rho,rhou,rhov,rhow,E)
    Qh = (rho,rhou./rho,rhov./rho,rhow./rho,beta) # redefine Q = (rho,U,β)

    QM = (x->x[Nq+1:end,:]).(Qh)
    QP = (x->x[mapP]).(QM)

    # lax friedrichs dissipation
    (rho,rhou,rhov,rhow,E) = Uf
    rhoU_n = @. (rhou*nxJ + rhov*nyJ + rhow*nzJ)/sJ
    lam = abs.(wavespeed(rho,rhoU_n,E))
    LFc = .5*max.(lam,lam[mapP]).*sJ

    fSx,fSy,fSz = flux_fun(QM,QP)
    normal_flux(fx,fy,fz,uM) = fx.*nxJ + fy.*nyJ + fz.*nzJ - LFc.*(uM[mapP]-uM)
    flux = normal_flux.(fSx,fSy,fSz,Uf)
    # flux = ntuple(x->zeros(size(mapP)),length(QM))
    # for i = 1:length(mapP)
    #     QMi = (x->x[i]).(QM)
    #     QPi = (x->x[i]).(QP)
    #     fSx,fSy,fSz = flux_fun(QMi,QPi)
    #     normal_flux!(f,fx,fy,fz,u) = f[i] = fx*nxJ[i] + fy*nyJ[i] + fz*nzJ[i] - LFc[i]*(u[mapP[i]]-u[i])
    #     normal_flux!.(flux,fSx,fSy,fSz,Uf)
    # end
    rhsQ = (x->Lf*x).(flux)

    # compute volume contributions using flux differencing
    for e = 1:K
        Qhe = tuple((x->x[:,e]).(Qh)...)
        vgeo_elem = (x->x[:,e]).((rxJ,sxJ,txJ,ryJ,syJ,tyJ,rzJ,szJ,tzJ)) # assumes curved elements

        Qops = (Qrh_sparse,Qsh_sparse,Qth_sparse,Qnzids)
        QFe = sparse_hadamard_sum(Qhe,Qops,vgeo_elem,flux_fun) # sum(Q.*F,dims=2)

        mxm_accum!(X,x) = X[:,e] += Ph*x
        mxm_accum!.(rhsQ,QFe)
    end

    rhsQ = (x -> -x./J).(rhsQ)

    rhstest = 0
    if compute_rhstest
        for fld in eachindex(rhsQ)
            rhstest += sum(wJq.*VU[fld].*rhsQ[fld])
        end
    end

    return rhsQ,rhstest # scale by Jacobian
end

# force Q to be an array of arrays for mutability
Q = collect(Q)
resQ = [zeros(size(x)) for i in eachindex(Q)]
for i = 1:Nsteps

    rhstest = 0
    for INTRK = 1:5
        compute_rhstest = INTRK==5
        rhsQ,rhstest = rhs(Q,md,ops,euler_fluxes,compute_rhstest)

        @. resQ = rk4a[INTRK]*resQ + dt*rhsQ
        @. Q += rk4b[INTRK]*resQ
    end

    if i%10==0 || i==Nsteps
        println("Time step: $i out of $Nsteps with rhstest = $rhstest")
    end
end

(rho,rhou,rhov,rhow,E) = (x->Pq*x).(Q) # project back to Lobatto nodes

@unpack VDM=rd
rq2,sq2,tq2,wq2 = quad_nodes_3D(N+2)
Vq2 = vandermonde_3D(N,rq2,sq2,tq2)/VDM
(xq2,yq2,zq2) = (x->Vq2*x).((x,y,z))
wJq2 = abs.(diagm(wq2)*(Vq2*Pq*J)) # recall J = converted to quad node basis
L2err = sqrt(sum(wJq2.*(Vq2*rho - rhoex(xq2,yq2,zq2,T)).^2))
# L2err = sqrt(sum(wJq.*(Vq*rho - rhoex(xq,yq,zq,T)).^2))
@show L2err

# gr(aspect_ratio=1,legend=false,
#    markerstrokewidth=0,markersize=2)
#
# @unpack Vp = rd
# (xp,yp,zp,vv) = (x->Vp*x).((x,y,z,rho))
#
# ids = map(x->x[1],findall(@. abs(zp[:])<1e-10))
# (xp,yp,zp,vv) = (x->x[ids]).((xp,yp,zp,vv))
# scatter(xp,yp,vv,zcolor=vv,camera=(0,90))

max_stars_repo_name: yiminllin/ESDG-Fourier

max_issues_repo_name: yiminllin/ESDG-Fourier

max_forks_repo_name: yiminllin/ESDG-Fourier


text:
# accepted types of non-deterministic inputs (non-canonical form)
const UNCF{N} = Union{<:LazySet{N}, Vector{<:LazySet{N}}, <:AbstractInput} where {N}

# accepted types for the state constraints (non-canonical form)
const XNCF{N} = Union{<:LazySet{N}, Nothing} where {N}

"""
    normalize(system::AbstractSystem)

Transform a mathematical system to a normalized (or canonical) form.

### Input

- `system` -- system; it can be discrete or continuous

### Output

Either the same system if it already conforms to a canonical form, or a new
system otherwise.

### Notes

The normalization procedure consists of transforming a given system type into a
"canonical" format that is used internally. More details are given below.

### Algorithm

The implementation of `normalize` exploits `MathematicalSystems`'s' types, which
carry information about the problem as a type parameter.

Homogeneous ODEs of the form ``x' = Ax, x ∈ \\mathcal{X}`` are canonical if the
associated problem is a `ConstrainedLinearContinuousSystem` and `A` is a matrix.
This type does not handle non-deterministic inputs.

Note that a `LinearContinuousSystem` does not consider constraints on the
state-space (such as an invariant); to specify state constraints, use a
`ConstrainedLinearContinuousSystem`. If the passed system is a `LinearContinuousSystem`
(i.e. no constraints) then the normalization fixes a universal set (`Universe`)
as the constraint set.

The generalization to canonical systems with constraints and possibly time-varying
non-deterministic inputs is considered next. These systems are of the form
``x' = Ax + u, u ∈ \\mathcal{U}, x ∈ \\mathcal{X}``. The system type is
`ConstrainedLinearControlContinuousSystem`, where `A` is a matrix, `X` is a set
and `U` is an input, that is, any concrete subtype of `AbstractInput`.

If `U` is not given as an input, normalization accepts either a `LazySet`, or
a vector of `LazySet`s. In these cases, the sets are wrapped around an appropriate
concrete input type.

If the system does not conform to a canonical form, the implementation tries
to make the transformation; otherwise an error is thrown. In particular, ODEs
of the form ``x' = Ax + Bu`` are mapped into ``x' = Ax + u, u ∈ B\\mathcal{U}``,
where now ``u`` has the same dimensions as ``x``.

The transformations described above are analogous in the discrete case, i.e.
``x_{k+1} = A x_k`` and ``x_{k+1} = Ax_{k} + u_k, u_k ∈ \\mathcal{U}, x_k ∈ \\mathcal{X}``
for the linear and affine cases respectively.
"""
function normalize(system::AbstractSystem)
    throw(ArgumentError("the system type $(typeof(system)) is currently not supported"))
end

# "black-box" like systems are not normalized; algorithms should handle this
normalize(S::Union{BBCS, CBBCS, CBBCCS}) = S

# x' = Ax, in the continuous case
# x+ = Ax, in the discrete case
for (L_S, CL_S) in ((:LCS, :CLCS), (:LDS, :CLDS))
    @eval begin
        function normalize(system::$L_S{N, AN}) where {N, AN<:AbstractMatrix{N}}
            n = statedim(system)
            X = Universe(n)
            return $CL_S(system.A, X)
        end
    end
end

# x' = Ax, x ∈ X in the continuous case
# x+ = Ax, x ∈ X in the discrete case
for CL_S in (:CLCS, :CLDS)
    @eval begin
        function normalize(system::$CL_S{N, AN, XT}) where {N, AN<:AbstractMatrix{N}, XT<:XNCF{N}}
            n = statedim(system)
            X = _wrap_invariant(stateset(system), n)
            return $CL_S(system.A, X)
        end
    end
end

# x' = Ax + Bu, x ∈ X, u ∈ U in the continuous case
# x+ = Ax + Bu, x ∈ X, u ∈ U in the discrete case
for CLC_S in (:CLCCS, :CLCDS)
    @eval begin
        function normalize(system::$CLC_S{N, AN, BN, XT, UT}) where {N, AN<:AbstractMatrix{N}, BN<:AbstractMatrix{N}, XT<:XNCF{N}, UT<:UNCF{N}}
            n = statedim(system)
            X = _wrap_invariant(stateset(system), n)
            U = _wrap_inputs(system.U, system.B)
            $CLC_S(system.A, I(n, N), X, U)
        end
    end
end

# x' = Ax + b, x ∈ X, u ∈ U in the continuous case
# x+ = Ax + b, x ∈ X, u ∈ U in the discrete case
for (CA_S, CLC_S) in ((:CACS, :CLCCS), (:CADS, :CLCDS))
    @eval begin
        function normalize(system::$CA_S{N, AN, VN, XT}) where {N, AN<:AbstractMatrix{N}, VN<:AbstractVector{N}, XT<:XNCF{N}}
            n = statedim(system)
            X = _wrap_invariant(system.X, n)
            U = _wrap_inputs(system.b)
            $CLC_S(system.A, I(n, N), X, U)
        end
    end
end

# x' = Ax + b in the continuous case
# x+ = Ax + b in the discrete case
for (A_S, CLC_S) in ((:ACS, :CLCCS), (:ADS, :CLCDS))
    @eval begin
        function normalize(system::$A_S{N, AN, VN}) where {N, AN<:AbstractMatrix{N}, VN<:AbstractVector{N}}
            n = statedim(system)
            X = Universe(n)
            U = _wrap_inputs(system.b)
            $CLC_S(system.A, I(n, N), X, U)
        end
    end
end

# x' = Ax + Bu + c, x ∈ X, u ∈ U in the continuous case
# x+ = Ax + Bu + c, x ∈ X, u ∈ U in the discrete case
for (CAC_S, CLC_S) in ((:CACCS, :CLCCS), (:CACDS, :CLCDS))
    @eval begin
        function normalize(system::$CAC_S{N, AN, BN, VN, XT, UT}) where {N, AN<:AbstractMatrix{N}, BN<:AbstractMatrix{N}, VN<:AbstractVector{N}, XT<:XNCF{N}, UT<:UNCF{N}}
            n = statedim(system)
            X = _wrap_invariant(system.X, n)
            U = _wrap_inputs(system.U, system.B, system.c)
            $CLC_S(system.A, I(n, N), X, U)
        end
    end
end

@inline isidentity(B::IdentityMultiple) = B.M.λ == oneunit(B.M.λ)

_wrap_invariant(X::LazySet, n::Int) = X
_wrap_invariant(X::Nothing, n::Int) = Universe(n)

_wrap_inputs(U::AbstractInput, B::IdentityMultiple) = isidentity(B) ? U : map(u -> B*u, U)
_wrap_inputs(U::AbstractInput, B::AbstractMatrix) = map(u -> B*u, U)

_wrap_inputs(U::LazySet, B::IdentityMultiple) = isidentity(B) ? ConstantInput(U) : ConstantInput(B*U)
_wrap_inputs(U::LazySet, B::AbstractMatrix) = ConstantInput(B*U)

_wrap_inputs(U::Vector{<:LazySet}, B::IdentityMultiple) = isidentity(B) ? VaryingInput(U) : VaryingInput(map(u -> B*u, U))
_wrap_inputs(U::Vector{<:LazySet}, B::AbstractMatrix) = VaryingInput(map(u -> B*u, U))

_wrap_inputs(U::AbstractInput, B::IdentityMultiple, c::AbstractVector) = isidentity(B) ? map(u -> u ⊕ c, U) : map(u -> B*u ⊕ c, U)
_wrap_inputs(U::AbstractInput, B::AbstractMatrix, c::AbstractVector) = map(u -> B*u ⊕ c, U)

_wrap_inputs(U::LazySet, B::IdentityMultiple, c::AbstractVector) = isidentity(B) ? ConstantInput(U ⊕ c) : ConstantInput(B*U ⊕ c)
_wrap_inputs(U::LazySet, B::AbstractMatrix, c::AbstractVector) = ConstantInput(B*U ⊕ c)

_wrap_inputs(U::Vector{<:LazySet}, B::IdentityMultiple, c::AbstractVector) = isidentity(B) ? VaryingInput(map(u -> u ⊕ c, U)) : VaryingInput(map(u -> B*u ⊕ c, U))
_wrap_inputs(U::Vector{<:LazySet}, B::AbstractMatrix, c::AbstractVector) = VaryingInput(map(u -> B*u ⊕ c, U))

_wrap_inputs(c::AbstractVector) = ConstantInput(Singleton(c))

"""
    distribute_initial_set(system::InitialValueProblem{<:HybridSystem, <:LazySet)

Distribute the set of initial states to each mode of a hybrid system.

### Input

- `system` -- an initial value problem wrapping a mathematical system (hybrid)
              and a set of initial states

### Output

A new initial value problem with the same hybrid system but where the set of initial
states is the list of tuples `(state, X0)`, for each state in the hybrid system.
"""
function distribute_initial_set(system::InitialValueProblem{<:HybridSystem, <:LazySet})
    HS, X0 = system.s, system.x0
    initial_states = [(loc, X0) for loc in states(HS)]
    return InitialValueProblem(HS, initial_states)
end


text:
using MCIntegration
using Test

@testset "MCIntegration.jl" begin
    # Write your tests here.
    include("montecarlo.jl")
end


text:
using Main.FAM: fa, coincidence
using Main.ComparisonM: iocComparison

while true

    # Get info in
    println("\nText [leave blank to break]:")
    human_input = readline()
    human_input == "" ? break :
    println("\nAlphabet [leave blank for default]:")
    human_alphabet = readline()
    human_alphabet == "" ? human_alphabet = "abcdefghijklmnopqrstuvwxyz" :
    println()
    println("\nFrequency Analysis: ")

    # Anaylse: Frequency analysis
    counted = fa(uppercase(human_input), uppercase(human_alphabet))
    for i in sort!(collect(counted), by = x->x[2], rev = true)
        println(i)
    end

    # Analyse: Index of coincidence
    println("\nIndex of Coincidence: ")
    println(coincidence(human_input, human_alphabet))

    # Sort IoC
    iocComparison(coincidence(human_input, human_alphabet))

end

max_stars_repo_name: Squalm/Cipher-Tools

max_issues_repo_name: Squalm/Cipher-Tools

max_forks_repo_name: Squalm/Cipher-Tools


text:
#Mixture of t Factor Analyzers
 function mtfa_esteps(model, Mquantities, Squantities, index)
  #p = size(data)[2]
  Mquantities.sigma = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
  Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
  #delta = mahalanobis(data, mu_i, real(B_i%*%t(B_i) + D_i), inverted = FALSE)
  #xi_ij =
  #zeta_ij =
  model.w_esteps[:,:,index] = hcat((model.Ψ[index] + Squantities.p) ./ (model.Ψ[index] .+ Mquantities.delta), digamma((model.Ψ[index] + Squantities.p)/2) .- log.((model.Ψ[index] .+ Mquantities.delta)/2))
 end

#Need to tacking the slash... why does it have to be so annoying :<

#Mixture of Slash Factor Analyzers
function mslfa_esteps(model, Mquantities, Squantities, index)
  #p = ncol(data); n = nrow(data)
    #n,p = size(data)
    #sig_i = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
    Mquantities.sigma = real(model.B[:,:,index]*model.B[:,:,index]') + model.D[:,:,index]
    Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
    Mquantities.mq.c = cdf.(Gamma.(model.Ψ[index]+Squantities.p/2, 1 ./(0.5*Mquantities.delta) ), 1)
    #xi_ij = 2*(model.Ψ[index]+Squantities.p/2).* cdf.(Gamma.(model.Ψ[index]+Squantities.p/2 + 1, 1 ./(0.5*Mquantities.delta) ), 1) ./ (Mquantities.delta.* c) #Need to fix this
    #int_res = zeros(n,1)
    @inbounds for i in 1:Squantities.n
        Mquantities.mq.integrand_estep = function integrand(u)
            u^(model.Ψ[index] + Squantities.p/2 - 1)*exp(-0.5*Mquantities.delta[i]*u)*log(u)
        end
        Mquantities.mq.int_res_estep[i] = quadgk(Mquantities.mq.integrand_estep,0,1,rtol = 1e-10)[1]
    end
    #zeta_ij = int_res.*((0.5*delta).^(model.Ψ[index]+p/2))./(gamma(model.Ψ[index]+p/2) .* c)
  model.w_esteps[:,:,index] = hcat(2*(model.Ψ[index]+Squantities.p/2).* cdf.(Gamma.(model.Ψ[index]+Squantities.p/2 + 1, 1 ./(0.5*Mquantities.delta) ), 1) ./ (Mquantities.delta.* Mquantities.mq.c),
  Mquantities.mq.int_res_estep.*((0.5*Mquantities.delta).^(model.Ψ[index]+Squantities.p/2))./(gamma(model.Ψ[index]+Squantities.p/2) .* Mquantities.mq.c)) #shape scale cdf(Gamma(model.Ψ[index]+p/2 + 1, 1./(0.5*delta) ), 1)
end

#Mixture of Contaminated Normal Factor Analyzers
function mcnfa_esteps(model, Mquantities, Squantities, index)
    #n,p = size(data)
    #sig_i = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
    Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
    Mquantities.mq.d1 = pdf(MvNormal(Vector(model.mu[:,index]), Matrix(Mquantities.sigma) ), Squantities.Y' )
    Mquantities.mq.d2 = pdf(MvNormal(Vector(model.mu[:,index]), Matrix(Mquantities.sigma)/model.Ψ[2,index] ), Squantities.Y' )
    Mquantities.mq.kappa_ij = 1 .- ((1-model.Ψ[1,index])*Mquantities.mq.d1) ./ ((1-model.Ψ[1,index])*Mquantities.mq.d1 + model.Ψ[1,index]*Mquantities.mq.d2)
  #kappa_ij = 1 .- rho_ij
    #xi_ij = (1 .- kappa_ij) .+ model.Ψ[2,index]*kappa_ij
    model.w_esteps[:,:,index] = hcat((1 .- Mquantities.mq.kappa_ij) .+ model.Ψ[2,index]*Mquantities.mq.kappa_ij, Mquantities.mq.kappa_ij,
    Mquantities.delta, repeat([Squantities.p],Squantities.n))
end

#Mixture of GH Factor Analyzers
function mghfa_esteps(model, Mquantities, Squantities, index)
  #c() wrappers needed here
    #n,p = size(data)
    Mquantities.sigma = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
    Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
    Mquantities.mq.delta_b = model.beta[:,index]'*inv(Mquantities.sigma)*model.beta[:,index]
    Mquantities.mq.omega = model.Ψ[1,index]
    Mquantities.mq.lambda = model.Ψ[2,index]
    Mquantities.mq.t1 = (Mquantities.mq.omega .+ Mquantities.delta)/(Mquantities.mq.omega + Mquantities.mq.delta_b)
    Mquantities.mq.t2 = besselk.(Mquantities.mq.lambda- 0.5*Squantities.p + 1, sqrt.((Mquantities.mq.omega + Mquantities.mq.delta_b)*(Mquantities.mq.omega .+ Mquantities.delta)))./
    besselk.(Mquantities.mq.lambda - 0.5*Squantities.p, sqrt.((Mquantities.mq.omega + Mquantities.mq.delta_b)*(Mquantities.mq.omega .+ Mquantities.delta)))
    #t3 = ones(n,1)
    @inbounds for j in 1:Squantities.n
      Mquantities.mq.integrand = function t2point5(t)
            log(besselk(t, sqrt((Mquantities.mq.omega + Mquantities.mq.delta_b)*(Mquantities.mq.omega + Mquantities.delta[j]))))
        end
        #Mquantities.init_para_error = false
        try
          Mquantities.mq.t3[j] = central_fdm(8, 1)(Mquantities.mq.integrand, Mquantities.mq.lambda - 0.5*Squantities.p) #(, lambda - 0.5*p),silent=TRUE) #derivative term here. derivative effectively zero if other terms are bad...!
        catch
          #Mquantities.init_para_error = true
          model.status = "failedE"
        end
    #if(class(temp)=="try-error"){t3[j]<- 0}else{t3[j] <- temp_deriv}
    end
    #xi_ij <- c(sqrt(t1))*c(t2) # -(2*lambda - p)./(omega .+ delta) + sqrt.(1./t1) .* t2
    #rho_ij <- -1*rep(2*lambda - p,n)/(rep(omega,n) + delta) + sqrt(1/t1)*t2
    #zeta_ij <- log(sqrt(t1)) + t3
    model.w_esteps[:,:,index] = hcat(sqrt.(Mquantities.mq.t1) .* Mquantities.mq.t2, -(2*Mquantities.mq.lambda - Squantities.p)./(Mquantities.mq.omega .+ Mquantities.delta) .+ sqrt.(1 ./Mquantities.mq.t1) .* Mquantities.mq.t2 , log.(sqrt.(Mquantities.mq.t1)) .+ Mquantities.mq.t3, repeat([Mquantities.mq.omega],Squantities.n), repeat([Mquantities.mq.lambda],Squantities.n) )
end

#Mixture of BS Factor Analyzers
function mbsfa_esteps(model, Mquantities, Squantities, index)

    #n,p = size(data) # <- nrow(data); p <- ncol(data)
    Mquantities.sigma = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
    Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
    Mquantities.mq.delta_b = model.beta[:,index]'*inv(Mquantities.sigma)*model.beta[:,index]
    Mquantities.mq.a = model.Ψ[index]
    Mquantities.mq.Theta = Mquantities.delta .+ Mquantities.mq.a^-2
    Mquantities.mq.Lambda = Mquantities.mq.delta_b + Mquantities.mq.a^-2

    Mquantities.mq.b1 = besselk.((1-Squantities.p)/2, sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))
    Mquantities.mq.b2 = besselk.((1+Squantities.p)/2, sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))

    #xi_ij = 0.5*(Theta./Lambda)^(0.5) .* (besselk(1 + (1-p)/2, sqrt.(Theta.*Lambda))./b1 + besselk(1 - (1+p)/2, sqrt.(Theta.*Lambda))./b2  )

    #rho_ij = 0.5*(Theta./Lambda)^(-0.5) .* (besselk(-1 + (1-p)/2,sqrt.(Theta.*Lambda))./b1 + besselk(-1 - (1+p)/2, sqrt.(Theta.*Lambda))./b2  )

    model.w_esteps[:,:,index] = hcat(0.5*(Mquantities.mq.Theta/Mquantities.mq.Lambda).^(0.5) .* (besselk.(1 + (1-Squantities.p)/2, sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))./Mquantities.mq.b1 + besselk.(1 - (1+Squantities.p)/2, sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))./Mquantities.mq.b2  ),
                0.5*(Mquantities.mq.Theta/Mquantities.mq.Lambda).^(-0.5) .* (besselk.(-1 + (1-Squantities.p)/2,sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))./Mquantities.mq.b1 + besselk.(-1 - (1+Squantities.p)/2, sqrt.(Mquantities.mq.Theta*Mquantities.mq.Lambda))./Mquantities.mq.b2  ))
end

#Mixture of Lindley Factor Analyzers
function mlfa_esteps(model, Mquantities, Squantities, index)
#  #c() wrappers needed here
  #n,p = size(data)
  #sig_i = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
  #delta = Distances.colwise(SqMahalanobis(inv(sig_i)), Array(data'), model.mu[:,index])
  Mquantities.sigma = real(model.B[:,:,index]*model.B[:,:,index]')+model.D[:,:,index]
  Mquantities.delta = Distances.colwise(SqMahalanobis(inv(Mquantities.sigma)), Array(Squantities.Y'), model.mu[:,index])
  #Mquantities.mq.delta_b = model.beta[:,index]'*inv(Mquantities.sigma)*model.beta[:,index]
  Mquantities.mq.a = model.Ψ[index]
  Mquantities.mq.delta_b = model.beta[:,index]'*inv(Mquantities.sigma)*model.beta[:,index] + 2*Mquantities.mq.a

  Mquantities.mq.numerator = Mquantities.mq.a*exp.(logd_GH(Squantities.Y,0,2*Mquantities.mq.a,1,model.B[:,:,index], model.mu[:,index], model.D[:,:,index], model.beta[:,index]))
  Mquantities.mq.py = Mquantities.mq.numerator./(Mquantities.mq.numerator .+ exp.(logd_GH(Squantities.Y,0,2*Mquantities.mq.a,2,model.B[:,:,index], model.mu[:,index], model.D[:,:,index], model.beta[:,index])))
  Mquantities.mq.rat = Mquantities.delta./Mquantities.mq.delta_b

  Mquantities.mq.b1 = besselk.(1 - Squantities.p/2, sqrt.(Mquantities.delta.*Mquantities.mq.delta_b))
  Mquantities.mq.b2 = besselk.(2 - Squantities.p/2, sqrt.(Mquantities.delta.*Mquantities.mq.delta_b))
  Mquantities.mq.b3 = besselk.(3 - Squantities.p/2, sqrt.(Mquantities.delta.*Mquantities.mq.delta_b))

  #xi_ij = rat.^(1/2).*(py.*b2./b1 + (1 .- py).*b3./b2)
  #rho_ij = rat.^(-1/2).*(py*besselk(- p/2, sqrt.(delta*delta_b))./b1 + (1 .- py).*b1./b2)

  model.w_esteps[:,:,index] = hcat(Mquantities.mq.rat.^(1/2).*(Mquantities.mq.py .* Mquantities.mq.b2 ./ Mquantities.mq.b1 + (1 .- Mquantities.mq.py).*Mquantities.mq.b3 ./Mquantities.mq.b2),
  Mquantities.mq.rat .^(-1/2).*(Mquantities.mq.py.*besselk.(-Squantities.p/2, sqrt.(Mquantities.delta*Mquantities.mq.delta_b))./Mquantities.mq.b1 + (1 .- Mquantities.mq.py).*Mquantities.mq.b1./Mquantities.mq.b2))
end

max_stars_repo_name: john-c-davey/FactorMixtures

max_issues_repo_name: john-c-davey/FactorMixtures

max_forks_repo_name: john-c-davey/FactorMixtures


text:
Base.size(d :: PenaltyDeviation) = Base.size(get_model_values(d));

get_data_values(d :: PenaltyDeviation) = nothing;
set_model_values(d :: PenaltyDeviation, modelV) = (d.modelV = modelV);

"""
    $(SIGNATURES)

Scalar deviation from one Deviation object.

Optionally includes `scalarWt` factor.
"""
function scalar_dev(d :: PenaltyDeviation{F1}; inclScalarWt :: Bool = true) where F1
    scalarDev = d.scalarDevFct(d.modelV);
    if inclScalarWt
        scalarDev *= d.scalarWt;
    end
    scalarStr = sprintf1("%.2f", scalarDev);

    return scalarDev, scalarStr
end

"""
	$(SIGNATURES)

Show a bounds deviation. As a table.
"""
function penalty_show_fct(d :: PenaltyDeviation; showModel :: Bool = true, fPath :: String = "")
    io = open_show_path(d, fPath = fPath);

    println(io, "$(d.name): ")
    println(io, get_model_values(d));

    close_show_path(d, io);
    return nothing
end

Base.show(io :: IO, p :: PenaltyDeviation) = Base.print(io, "Penalty deviation")

# ----------------


text:
using Erdos
using Test
using Random
using SparseArrays
using LinearAlgebra
using Arpack
using Statistics

testdir = dirname(@__FILE__)

tests = [
    "factory/graph",
    "factory/net",
    "core/edge",
    "core/interface_graph",
    "core/interface_network",
    "core/core",
    "core/edgeiter",
    "maps/vertexmap",
    "maps/edgemap",
    "maps/property_store",
    "operators/operators",
    "distances/distance",
    "distances/edit_distance",
    "linalg/spectral",
    "persistence/persistence",
    "persistence/datasets",
    "persistence/gt",
    "persistence/gexf",
    "persistence/graphml",
    "persistence/gml",
    "generators/randgraphs",
    "generators/staticgraphs",
    "generators/smallgraphs",
    "generators/euclideangraphs",
    "shortestpaths/astar",
    "shortestpaths/bellman-ford",
    "shortestpaths/dijkstra",
    "shortestpaths/floyd-warshall",
    "traversals/bfs",
    "traversals/dfs",
    "traversals/maxadjvisit",
    "traversals/graphvisit",
    "traversals/randomwalks",
    "traversals/connectivity",
    "community/core-periphery",
    "community/cliques",
    "community/modularity",
    "community/clustering",
    "community/detection",
    "centrality/betweenness",
    "centrality/closeness",
    "centrality/degree",
    "centrality/katz",
    "centrality/pagerank",
    "centrality/kcore",
    "flow/edmonds_karp",
    "flow/dinic",
    "flow/boykov_kolmogorov",
    "flow/push_relabel",
    "flow/maximum_flow",
    "flow/multiroute_flow",
    "spanningtrees/spanningtrees",
    "spanningtrees/kruskal",
    "dismantling/dismantling",
    "drawing/layout",
    "utils"
]

include("common.jl")

GLIST =    [
            (Network, DiNetwork),
            (Graph{Int64}, DiGraph{Int64}),
            (Graph{UInt32}, DiGraph{UInt32}),
            ]

for GDG in GLIST, t in tests
    global G = GDG[1]
    global DG = GDG[2]
    global TEST = t
    global E = edgetype(G)
    global V = vertextype(G)

    include(joinpath(testdir,"$(t).jl"))
end

println("Finished testing Erdos")


text:
using ExistingProcessManagers
using Test
using Distributed

import Documenter

@testset "Doctests" begin
    Documenter.doctest(ExistingProcessManagers)
end


text:
module Fingerprints
export fingerprint

function namestub(T::Type)::Symbol
   T.name.name
end

function namestub(T::UnionAll)::Symbol
    namestub(T.body)
end

abstract type Kind end
struct KindStruct <: Kind end
struct KindMutable <: Kind end
struct KindAbstract <: Kind end
struct KindPrimitive <: Kind end
struct KindBuiltin <: Kind end
struct KindUnionAll <: Kind end
struct KindUnion <: Kind end

@generated function Kind(::Type{T}) where {T}
    K = if T isa UnionAll
        KindUnionAll
    elseif T isa Union
        KindUnion
    elseif T.abstract
        KindAbstract
    elseif T <: Array
        KindBuiltin
    elseif T <: Symbol
        KindBuiltin
    elseif T <: String
        KindBuiltin
    elseif T <: Tuple
        KindBuiltin
    elseif isempty(fieldnames(T)) && (sizeof(T) > 0)
        KindPrimitive
    elseif T.mutable
        KindMutable
    else
        KindStruct
    end
    :($K())
end

function fingerprint(::Type{O}, h=zero(UInt64))::UInt64 where {O}
    hash(namestub(O), h)
end

function fingerprint(o, h=zero(UInt64))::UInt64
    _fingerprint(o, h, Kind(typeof(o)))
end

function _fingerprint(o, h, ::Union{KindPrimitive})
    hash(o, h)
end

function _fingerprint(o::Union{Symbol, String}, h, ::KindBuiltin)
    h = fingerprint(typeof(o), h)
    hash(o, h)
end

function _fingerprint(o::Union{Tuple,Array}, h, ::KindBuiltin)
    h = fingerprint(typeof(o), h)
    for x in o
        h = fingerprint(x, h)
    end
    h
end

function _fingerprint_fieldnames_impl(T)
    ret = quote
        salt = one(UInt64)
        h = fingerprint(salt, h)
        h = fingerprint($T, h)
    end
    for s in fieldnames(T)
        ex = :(
            h = fingerprint($(QuoteNode(s)), h);
            h = fingerprint(o.$s, h))
        push!(ret.args, ex)
    end
    push!(ret.args, :h)
    ret
end

@generated function _fingerprint(o, h, ::Union{KindStruct, KindMutable})
    _fingerprint_fieldnames_impl(o)
end

end # module


text:
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
# Since these FMAs can increase the performance of many numerical algorithms,
# we need to opt-in explicitly.
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
@muladd begin

"""
    DGMultiMesh{NDIMS, ...}

`DGMultiMesh` describes a mesh type which wraps `StartUpDG.MeshData` and `boundary_faces` in a
dispatchable type. This is intended to store geometric data and connectivities for any type of
mesh (Cartesian, affine, curved, structured/unstructured).
"""
struct DGMultiMesh{NDIMS, MeshType, MeshDataT <: MeshData{NDIMS}, BoundaryFaceT}
  md::MeshDataT
  boundary_faces::BoundaryFaceT
end

# enable use of @set and setproperties(...) for DGMultiMesh
ConstructionBase.constructorof(::Type{DGMultiMesh{T1, T2, T3, T4}}) where {T1, T2, T3, T4} = DGMultiMesh{T1, T2, T3, T4}

Base.ndims(::DGMultiMesh{NDIMS}) where {NDIMS} = NDIMS

function Base.show(io::IO, mesh::DGMultiMesh{NDIMS, MeshType}) where {NDIMS, MeshType}
  @nospecialize mesh # reduce precompilation time
  print(io, "$MeshType DGMultiMesh with NDIMS = $NDIMS.")
end

function Base.show(io::IO, ::MIME"text/plain", mesh::DGMultiMesh{NDIMS, MeshType}) where {NDIMS, MeshType}
  @nospecialize mesh # reduce precompilation time
  if get(io, :compact, false)
    show(io, mesh)
  else
    summary_header(io, "DGMultiMesh{$NDIMS, $MeshType}, ")
    summary_line(io, "number of elements", mesh.md.num_elements)
    summary_line(io, "number of boundaries", length(mesh.boundary_faces))
    for (boundary_name, faces) in mesh.boundary_faces
      summary_line(increment_indent(io), "nfaces on $boundary_name", length(faces))
    end
    summary_footer(io)
  end
end

end # @muladd


text:
function loss(model, data; average=true)
    sum = cnt = 0
    for args in data
        (loss,count) = model(args...; average=false)
        sum += loss
        cnt += count
    end
    average ? sum / cnt : (sum,cnt)
end

max_stars_repo_name: denizyuret/research

max_issues_repo_name: denizyuret/research

max_forks_repo_name: denizyuret/research


text:
isinteractive() && include("common.jl")

#####
##### Test building blocks of MCMC
#####

@testset "printing" begin
    ℓ = multivariate_normal(ones(1))
    κ = GaussianKineticEnergy(1)
    Q = evaluate_ℓ(ℓ, [1.0])
    @test repr(WarmupState(Q, κ, 1.0)) isa String
    @test repr(WarmupState(Q, κ, nothing)) isa String
end

@testset "mcmc" begin
    ℓ = multivariate_normal(ones(5))

    @testset "default warmup" begin
        results = mcmc_with_warmup(RNG, ℓ, 10000)
        Z = DynamicHMC.position_matrix(results.chain)
        @test norm(mean(Z; dims = 2) .- ones(5), Inf) < 0.02
        @test norm(std(Z; dims = 2) .- ones(5), Inf) < 0.025
        @test mean(x -> x.acceptance_rate, results.tree_statistics) ≥ 0.8
        @test 0.5 ≤ results.ϵ ≤ 2
    end

    @testset "fixed stepsize" begin
        results = mcmc_with_warmup(RNG, ℓ, 10000;
                                   initialization = (ϵ = 1.0, ),
                                   warmup_stages = fixed_stepsize_warmup_stages())
        Z = DynamicHMC.position_matrix(results.chain)
        @test norm(mean(Z; dims = 2) .- ones(5), Inf) < 0.03
        @test norm(std(Z; dims = 2) .- ones(5), Inf) < 0.03
        @test mean(x -> x.acceptance_rate, results.tree_statistics) ≥ 0.7
    end

    @testset "explicitly provided initial stepsize" begin
        results = mcmc_with_warmup(RNG, ℓ, 10000;
                                   initialization = (ϵ = 1.0, ),
                                   warmup_stages = default_warmup_stages(; stepsize_search = nothing))
        Z = DynamicHMC.position_matrix(results.chain)
        @test norm(mean(Z; dims = 2) .- ones(5), Inf) < 0.03
        @test norm(std(Z; dims = 2) .- ones(5), Inf) < 0.03
        @test mean(x -> x.acceptance_rate, results.tree_statistics) ≥ 0.7
    end

    @testset "stepwise" begin
        results = mcmc_keep_warmup(RNG, ℓ, 0; reporter = NoProgressReport())
        steps = mcmc_steps(results.sampling_logdensity, results.final_warmup_state)
        qs = let Q = results.final_warmup_state.Q
            [(Q = first(mcmc_next_step(steps, Q)); Q.q) for _ in 1:1000]
        end
        @test norm(mean(reduce(hcat, qs); dims = 2) .- ones(5), Inf) ≤ 0.1
    end
end

# @testset "tuner framework" begin
#     s = StepsizeTuner(10)
#     @test length(s) == 10
#     @test repr(s) == "Stepsize tuner, 10 samples"
#     c = StepsizeCovTuner(19, 7.0)
#     @test length(c) == 19
#     @test repr(c) ==
#         "Stepsize and covariance tuner, 19 samples, regularization 7.0"
#     b = bracketed_doubling_tuner() # testing the defaults
#     @test b isa TunerSequence
#     @test b.tuners == (StepsizeTuner(75), # init
#                        StepsizeCovTuner(25, 5.0), # doubling each step
#                        StepsizeCovTuner(50, 5.0),
#                        StepsizeCovTuner(100, 5.0),
#                        StepsizeCovTuner(200, 5.0),
#                        StepsizeCovTuner(400, 5.0),
#                        StepsizeTuner(50)) # terminate
#     @test repr(b) ==
#         """
# Sequence of 7 tuners, 900 total samples
#   Stepsize tuner, 75 samples
#   Stepsize and covariance tuner, 25 samples, regularization 5.0
#   Stepsize and covariance tuner, 50 samples, regularization 5.0
#   Stepsize and covariance tuner, 100 samples, regularization 5.0
#   Stepsize and covariance tuner, 200 samples, regularization 5.0
#   Stepsize and covariance tuner, 400 samples, regularization 5.0
#   Stepsize tuner, 50 samples"""
# end


text:
using Neet, Test

@testset "BooleanSpace" begin
    @testset "Construction" begin
        @test_throws DomainError BooleanSpace(-1)
        @test_throws DomainError BooleanSpace(0)

        let space = BooleanSpace(1)
            @test space.ndim == 1
            @test space.volume == 2
            @test space.isuniform == true
        end

        let space = BooleanSpace(2)
            @test space.ndim == 2
            @test space.volume == 4
            @test space.isuniform == true
        end
    end

    @testset "size" begin
        @test size(BooleanSpace(1)) == (2,)
        @test size(BooleanSpace(2)) == (2,2)
        @test size(BooleanSpace(3)) == (2,2,2)
    end

    @testset "volume" begin
        @test volume(BooleanSpace(1)) == 2
        @test volume(BooleanSpace(2)) == 4
        @test volume(BooleanSpace(3)) == 8
    end

    @testset "encode" begin
        let space = BooleanSpace(1)
            @test encode(space, [0]) == 0
            @test encode(space, [1]) == 1
        end
        let space = BooleanSpace(2)
            @test encode(space, [0,0]) == 0
            @test encode(space, [0,1]) == 1
            @test encode(space, [1,0]) == 2
            @test encode(space, [1,1]) == 3
        end
        let space = BooleanSpace(3)
            @test encode(space, [0,0,0]) == 0
            @test encode(space, [0,0,1]) == 1
            @test encode(space, [0,1,0]) == 2
            @test encode(space, [0,1,1]) == 3
            @test encode(space, [1,0,0]) == 4
            @test encode(space, [1,0,1]) == 5
            @test encode(space, [1,1,0]) == 6
            @test encode(space, [1,1,1]) == 7
        end
    end

    @testset "decode" for ndim in 1:3
        let space = BooleanSpace(ndim)
            @testset "$(ndim)D Space" for d in 0:volume(space)-1
                @test encode(space, decode(space, d)) == d
            end
        end
    end

    @testset "iterate" for ndim in 1:3
        let space = BooleanSpace(ndim)
            @testset "$(ndim)D Space" for (i, state) in enumerate(space)
                @test encode(space, state) == i-1
            end
        end
    end
end


text:
using Rocket

# Broken functionaliy

# struct PriorActor{D, P} <: Actor{D}
#     name  :: Symbol
#     prior :: P
# end

# prioractor(::Type{D}, name::Symbol, prior::P) where { D, P } = PriorActor{D, P}(name, prior)

# function Rocket.on_next!(actor::PriorActor{D}, data::D) where D
#     update!(actor.prior, as_message(data))
# end

# function Rocket.on_error!(actor::PriorActor, err)
#     println(stderr, "Error in prior actor $(actor.name): $err")
# end

# function Rocket.on_complete!(::PriorActor)
#     return nothing
# end

# link(datavar::DataVariable, source::S) where S = check_link(datavar, as_subscribable(S), source)

# check_link(datavar::DataVariable, ::InvalidSubscribableTrait, source)              = throw(InvalidSubscribableTraitUsageError(source))
# check_link(datavar::DataVariable, ::SimpleSubscribableTrait{D}, source)    where D = _link(datavar, D, source)
# check_link(datavar::DataVariable, ::ScheduledSubscribableTrait{D}, source) where D = _link(datavar, D, source)

# _link(datavar::DataVariable, ::Type{D}, source) where D = subscribe!(source |> discontinue(), prioractor(D, name(datavar), datavar))