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

using Markdown
using InteractiveUtils

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

# ╔═╡ 451ae3a0-8068-4747-95a7-d31955808f29
begin

	# external packages -
	using PlutoUI
	using Plots
	using PrettyTables
end

# ╔═╡ 8ba6a00a-7a53-4dcc-af4d-cb85aa9b4d68
md"""
### Simple and Complex Models of Enzyme Kinetics

The flux bounds are essential constraints in flux balance analysis calculations and the convex decomposition of the stoichiometric array. Beyond their role in the flux estimation problem, the flux bounds are _integrative_, i.e., these constraints integrate many types of genetic and biochemical information into the flux estimation problem.

Flux bounds constrain the values that each reaction in a metabolic network can take. A general model for these bounds is given by:

$$-\delta_{j}\left[{V_{max,j}^{\circ}}\left(\frac{e}{e^{\circ}}\right)\theta_{j}\left(\dots\right){f_{j}\left(\dots\right)}\right]\leq{v_{j}}\leq{V_{max,j}^{\circ}}\left(\frac{e}{e^{\circ}}\right)\theta_{j}\left(\dots\right){f_{j}\left(\dots\right)}$$

where $V_{max,j}^{\circ}$ denotes the maximum reaction velocity (units: flux) computed at some characteristic enzyme abundance (units: concentration), the ratio $e/e^{\circ}$ is a correction for enzyme abundance (units: dimensioness), $\theta_{j}\left(\dots\right)\in\left[0,1\right]$ is the fraction of maximial enzyme activity (a function or measurement producing units: dimensionless), and $f_{j}\left(\dots\right)$ is a function describing the substrate dependence of the reaction rate $j$ (units: dimensionless). Both $\theta_{j}\left(\dots\right)$ and $f_{j}\left(\dots\right)$ could have associated parameters, e.g., saturation or binding constants, etc.  Finally, the quanity $\delta_{j}\in\left\{0,1\right\}$ is a _binary_ variable:
* If reaction $j$ is __reversible__ $\delta_{j}=1$ or,
* If reaction $j$ is __irreversible__ $\delta_{j}=0$

Today, let's focus on approaches for computing the value of these bounds, i.e., the form and value of the terms in the brackets. In this lecture, we will:

1. Develop simple models of enzyme kinetics using the Michaelis–Menten approach
1. Introduce the fundamental concepts underlying more complex models of allosteric regulation (the fast control mechanisms that we mentioned previously)
1. Introduce effective discrete regulation models to capture allosteric regulation
"""

# ╔═╡ 8869f117-1fc6-4cc5-9803-b8ec72a109a6
md"""
### What is allosteric regulation?
Allosteric regulation modulates enzyme activity by binding effector molecules to sites other than the enzyme's active site. These events can activate (enhances rate) and inhibit (decreases rate). Allosteric regulation operates on a fast time scale compared to gene expression (synthesis of the enzyme).

Allosteric mechanisms in Central Carbon Metabolism:

* [Reznik E, Christodoulou D, Goldford JE, Briars E, Sauer U, Segrè D, Noor E. Genome-Scale Architecture of Small Molecule Regulatory Networks and the Fundamental Trade-Off between Regulation and Enzymatic Activity. Cell Rep. 2017 Sep 12;20(11):2666-2677. doi: 10.1016/j.celrep.2017.08.066. PMID: 28903046; PMCID: PMC5600504.](https://pubmed.ncbi.nlm.nih.gov/28903046/)

"""

# ╔═╡ 17724757-604e-4c77-a42b-238ba121e88f
md"""
### Simple: Michaelis–Menten kinetics
Let's assume we have a well-mixed test tube containing an enzyme $E$ (a protein that catalyzes chemical reactions), which converts substrate $S$ (the starting compound)
into product $P$ according to three elementary reactions:

$$\begin{eqnarray}
	E+S&\rightleftharpoons&{E:S}\\
	{E:S}&\longrightarrow&E+P
\end{eqnarray}$$

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

$$\begin{eqnarray}
	r_{1} & = & k_{1}\left[E\right]\left[S\right]\\
	r_{2} & = & k_{2}\left[E:S\right]\\
	r_{3} & = & k_{3}\left[E:S\right]
\end{eqnarray}$$

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

* The rate $r_{1}$ describes the _association_ rate between the enzyme and substrate,
* The rate $r_{2}$ represents the rate of _dissociation_ of the enzyme-substrate complex, and
* The $r_{3}$ denotes the rate of _chemical conversion_ of the bound substrate into the product (we assume the dissociation of the product from the enzyme is fast).

The enzyme must obey the relationship:

$$\left[E_{T}\right] = \left[E\right] + \left[E:S\right]$$

where $\left[E_{T}\right]$ denotes the total enzyme concentration in the tube,
$\left[E\right]$ denotes the free enzyme concentration (not bound to substrate) while
$\left[E:S\right]$ denotes the enzyme-substrate complex.

To estimate the _overall_ rate $v$, we stipulate a single rate-limiting step out of the set of elementary reactions. Let's assume that the rate of chemical conversion ($r_{3}$) is the slowest step, i.e., the substrate bounces on/off the enzyme quickly with only a tiny fraction of these binding events resulting in a successful chemical transformation. Thus, the overall rate is then given by:

$$v = k_{3}\left[E:S\right]$$

Let's also assume that we already know (or can estimate) the rate constants $k_{1},k_{2}$ and $k_{3}$. When this is true, the only unknown is $\left[E:S\right]$.
However, we can relate $\left[E:S\right]$ to variables we know ($E_{T}$ and at least initially $S$) through the enzyme balance, and the _pseudo-steady-state assumption_ for the reaction intermediate
$\left[E:S\right]$:

$$\frac{d\left[E:S\right]}{dt} = k_{1}\left[E\right]\left[S\right] - k_{2}\left[E:S\right] - k_{3}\left[E:S\right]\simeq{0}$$

Rearranging and solving for $\left[E:S\right]$ gives the relationship:

$$\left[E:S\right]\simeq\frac{k_{1}}{k_{2}+k_{3}}\left[E\right]\left[S\right]$$

where the ratio of constants is defined as the Michaelis-Menten saturation coefficient or $K_{M}$:

$$\frac{1}{K_{M}}\equiv\frac{k_{1}}{k_{2}+k_{3}}$$

Substituting the definition of $K_{M}$ into the overall rate yields:

$$v = k_{3}\frac{\left[E\right]\left[S\right]}{K_{M}}$$

However, we do not know the free enzyme concentration of $\left[E\right]$; to find $\left[E\right]$
we subsitute $\left[E:S\right]$ into the enzyme balance and solving for $\left[E\right]$:

$$\left[E\right] = \frac{\left[E_T\right]K_{M}}{K_{M}+\left[S\right]}$$

Lastly, we substitute $\left[E\right]$ into the overall rate to arrive at the final expression for $v$:

$$v = V_{max}\frac{\left[S\right]}{K_{M}+\left[S\right]}$$

where $V_{max}\equiv{k_{3}}\left[E_{T}\right]$.

__Limiting cases:__
* when $S\gg{K}_{M}$, the rate becomes close to $V_{max}$.
* when $S\ll{K}_{M}$ the rate appears to be linear with respect to substrate concentration.
* when $K_{M}\simeq S$ the reaction rate equals $v\simeq 1/2V_{max}$.
"""

# ╔═╡ 431ccdf0-93a9-4b3c-9576-8854ba2f1fad
@bind MM_parameters PlutoUI.combine() do Child
	md"""
	##### Michaelis–Menten Parameters

	\[E\] $(
		Child(Slider(1:5))
	) (μM) and Kₘ $(
		Child(Slider(5:100))
	) (mM)

	"""
end

# ╔═╡ 7efaf27c-8e0a-40f9-ac28-af90357450a3
begin

	# get MM parameter values -
	E = MM_parameters[1]
	Kₘ = MM_parameters[2]
	kcat = 13.7 # units: s^-1
	number_of_steps = 1000

	# substrate range -
	S_array = range(0.0,stop=100.0,length=number_of_steps) |> collect;

	# initialize space -
	v_array = Array{Float64,1}(undef,number_of_steps)

	# compute the rate -
	for (i,S) ∈ enumerate(S_array)

		# compute the rate -
		v_array[i] = (kcat*E)*(S/(S+Kₘ))
	end

	# plot -
	plot(S_array,v_array,xlims=(0.0,100.0),ylims=(0.0,14), label="v: E = $(E) μM and Kₘ = $(Kₘ) (mM)")
	xlabel!("Substrate S (mM)",fontsize=18)
	ylabel!("Rate v (μM/s)",fontsize=18)
end

# ╔═╡ 55ea8324-f36d-40bd-99e3-92e7fcbafca9
md"""
### Complex: MWC and Sequential kinetic models
The Monod-Wyman-Changeux model (MWC model, also known as the symmetry model) describes allosteric transitions of proteins made up of identical subunits. Effector binding modulates the state of the entire protein.

* [MONOD J, WYMAN J, CHANGEUX JP. ON THE NATURE OF ALLOSTERIC TRANSITIONS: A PLAUSIBLE MODEL. J Mol Biol. 1965 May;12:88-118. doi: 10.1016/s0022-2836(65)80285-6. PMID: 14343300.](https://pubmed.ncbi.nlm.nih.gov/14343300/)

The sequential model (KNF model) of allosteric regulation posits that enzyme subunits are independent.
Thus, binding substrate (or effector) to a subunit results in only slight conformational changes to adjacent subunits. KNF model can do describe both positive and negative cooperativity:

* [Koshland D Jr, Némethy G, Filmer D. Comparison of experimental binding data and theoretical models in proteins containing subunits. Biochemistry. 1966 Jan;5(1):365-85. doi: 10.1021/bi00865a047. PMID: 5938952.](https://pubmed.ncbi.nlm.nih.gov/5938952/)

"""

# ╔═╡ 3502da52-7d2b-4c79-82ce-7424d756cd9b
md"""
### Effective discrete state kinetic models

Michaelis–Menten kinetics are easy to understand, but they neglect many factors, e.g., the influence of allosteric regulators. On the other hand, MWC/sequential models are detailed but case-specific (and too complex). It would be great if we could correct Michaelis–Menten kinetics to capture the influence of allosteric factors.

Suppose we model the rate $v_{j}$ as the product of a kinetic limit (a simple model of the rate) and a correction term that accounts for the missing regulation:

$$v_{j} = r_{j}\theta\left(...\right)_{j}$$

where $v_{j}$ denotes the overall rate (units: $\mu$M/time), $r_{j}$ denotes the kinetic limit i.e., the maximum rate of conversion (units: $\mu$M/time) and
$0\leq \theta\left(...\right)_{j}\leq 1$ (units: dimensionless) is a control function that describes the influence of effector molecules.
"""

# ╔═╡ c392c8a9-361d-47e4-933e-2e51b793e069
md"""
##### Discrete state control function model
There is a wide variety of different possible ways we can build the $\theta\left(...\right)_{j}$ control functions. Ultimately, it doesn't matter what we choose, as long as it gives a good performance. However, let's introduce an idea that we will revisit later, namely a discrete probabilistic approach.

###### Theory
Suppose an enzyme $E$ can exits in one of $s=1,2\dots,\mathcal{S}$ possible microstates, where each microstate $s$ has some pseudo energy $\epsilon_{s}$. Some microstates will lead to activity (the ability to carry out the chemical reactions, while others will not). For each microstate $s$, let's assign a pseudo energy $\epsilon_{s}$, where by definition $\epsilon_{1}=0$; we assume the base state has the lowest energy. Next, suppose the probability that enzyme $E$ is in microstate $s$ follows a [Boltzmann distribution](https://en.wikipedia.org/wiki/Boltzmann_distribution) which says:

$$p_{i} = \frac{1}{Z} \times f_{i}\exp\left(-\beta\epsilon_{i}\right)\qquad{i=1,2,\dots,\mathcal{S}}$$

where $p_{i}$ denotes the probability that enzyme $E$ is in microstate $i=1,2,\dots,\mathcal{S}$, $f_{i}$ denotes a state-specific factor $f_{i}\in\left[0,1\right]$, $\beta$ denotes the [thermodynamic beta](https://en.wikipedia.org/wiki/Thermodynamic_beta) and $Z$ denotes a normalization factor (called the [Partiton function](https://en.wikipedia.org/wiki/Partition_function_(statistical_mechanics)) in the statistical physics community). We can find $Z$ using the summation law of discrete probolity e.g.,  $\sum_{s}p_{s} = 1$ which gives:

$$Z = \sum_{s=1}^{\mathcal{S}}f_{i}\exp\left(-\beta\epsilon_{i}\right)$$

which gives:

$$p_{i} = \frac{f_{i}\exp\left(-\beta\epsilon_{i}\right)}{\displaystyle \sum_{s=1}^{\mathcal{S}}f_{i}\exp\left(-\beta\epsilon_{i}\right)}\qquad{i=1,2,\dots,\mathcal{S}}$$.

Finally, we relate the probability that enzyme $E$ is in microstate $s$ back to the $\theta$ control function by computing the overall probability that the desired event happens, e.g., enzyme $E$ catalyzes the reaction of interests. We know if $\Omega = \left\{1,2,\dots,\mathcal{S}\right\}$, then we can define the subset $\mathcal{A}\subseteq\Omega$ in which the desired event happens. Given $\mathcal{A}$, the $\theta$ function becomes:

$$\theta=\sum_{s\in{\mathcal{A}}}p_{s}$$

###### Conceptual exampleTo illustrate this idea, consider an enzyme inhibited by a downstream product (this is a common allosteric motif known as [feedback inhibition](Pedreño S, Pisco JP, Larrouy-Maumus G, Kelly G, de Carvalho LP. Mechanism of feedback allosteric inhibition of ATP phosphoribosyltransferase. Biochemistry. 2012;51(40):8027-8038. doi:10.1021/bi300808b)). In this case, suppose enzyme $E$, which is inhibited by compound $I$, can exist in one of three possible microstates:

* __State s = 1__: No substrate $S$ is bound, $E$ is floating around in solution minding its own business (base state, no reaction)
* __State s = 2__: Substrate $S$ is bound to enzyme $E$, but inhibitor $I$ is not bound (reaction possible)
* __State s = 3__: Both the substrate $S$ and inhibitor $I$ are bound to enzyme $E$ (no reaction possible)

Given these microstates (and their functional assignment) we know that enzyme $E$ can only catalyze its reaction in microstate $s=2$, thus:

$$\theta = \frac{f_{2}\exp\left(-\beta\epsilon_{i}\right)}{\displaystyle \sum_{s=1}^{\mathcal{3}}f_{s}\exp\left(-\beta\epsilon_{s}\right)}$$

###### What are the state-specific factors?
The state-specific factors $f_{i}\in\left[0,1\right]$ control the reachability of a microstate:

* if $f_{\star} = 0$, then microstate $\star$ can __never__ be obtained
* if $f_{\star} = 1$, then microstate $\star$ can __always__ be obtained

As a modeler, you can choose the form (or value) that $f_{\star}$ takes. These factors can
be set to a specific value by definition (depending upon the state) or can be used to describe events associated with state $i$, e.g., such as binding events. For example, suppose state $i$ involved binding an effector molecule $x$ to the enzyme $E$. In this case, we could model the state-specific factor $f_{i}$ as:

$$f_{i} = (x/K_{i})^{n_{i}}/(1+(x/K_{i})^{n_{i}})$$

where $x\geq{0}$ denotes effector abundance, $K_{i}\geq{0}$ denotes a binding constant and $n_{i}\geq{0}$ denotes a binding order parameter.
"""

# ╔═╡ 91345d04-f502-4e90-935e-a4dc250244db
@bind DSM_parameters PlutoUI.combine() do Child

	md"""
	\[I\] $(
		Child(Slider(0:100))
	) (μM)  K $(
		Child(Slider(1:1:100))
	) (mM)  ϵ₂ $(
		Child(Slider(0.001:0.1:100))
	) (J/mol) ϵ₃ $(
		Child(Slider(0.001:0.1:100))
	) (J/mol)
	"""
end

# ╔═╡ 719784fe-3ef6-4e53-ad52-82140e3d0b5e
begin

	# get I -
	Iₒ = DSM_parameters[1]
	Kd = DSM_parameters[2]
	ϵ₂ = (DSM_parameters[3])/100
	ϵ₃ = (DSM_parameters[4])/100

	# setup system -
	R = 8.314 			# units: J/mol-K
	T = 273.15 + 25.0 	# units: K
	β = 1/R*T

	# setup binding parameters for state 3 -
	n = 2.0

	# setup energy array -
	ϵ_array = [
		0.0 	; # state 1 (just E)
		-ϵ₂ 	; # state 2 (E bound to S, but no I)
		-ϵ₃ 	; # state 3 (E bound to I)
	];

	# compute W -
	W_array = exp.(-β*ϵ_array)

	# let's compute the state-specific factor array -
	f_array = [
		1.0 ; # state 1
		1.0 ; # state 2
		((Iₒ/Kd)^(n))/(1+(Iₒ/Kd)^(n))
	];

	# compute the θ variable -
	microstate_array = f_array.*W_array;
	Z = sum(microstate_array)
	p_array = (1/Z)*microstate_array
	θ = p_array[2]

	# show -
	with_terminal() do
		println("θ = $(θ)")
	end
end

# ╔═╡ 1d4d6059-5b79-43cd-ac17-ef2aa057ecad
with_terminal() do

	# initialize -
	𝒮 = 3
	state_table = Array{Any,2}(undef,𝒮,4)

	# populate the state array -
	for s ∈ 1:𝒮

		state_table[s,1] = s
		state_table[s,2] = f_array[s]
		state_table[s,3] = W_array[s]
		state_table[s,4] = p_array[s]
	end

	# header -
	header_row = (["s","fₛ","Wₛ","pₛ"])
	pretty_table(state_table;header=header_row)

end

# ╔═╡ d46ced14-a5d3-45a9-9d43-38dc7879b0c7
let

	# get MM parameter values -
	E = 1.0 # units: μM
	Kₘ = 5 	# units: mM
	kcat = 13.7 # units: s^-1
	number_of_steps = 1000

	# substrate range -
	S_array = range(0.0,stop=100.0,length=number_of_steps) |> collect;

	# initialize space -
	v_array = Array{Float64,1}(undef,number_of_steps)

	# compute the rate -
	for (i,S) ∈ enumerate(S_array)

		# compute the rate -
		v_array[i] = (kcat*E)*(S/(S+Kₘ))*θ
	end

	# plot -
	plot(S_array,v_array,xlims=(0.0,100.0),ylims=(0.0,14), label="v: I = $(Iₒ) mM and Kd = $(Kd) (mM)")
	xlabel!("Substrate S (mM)",fontsize=18)
	ylabel!("Rate v (μM/s)",fontsize=18)

end

# ╔═╡ d3568c5d-16bf-4698-9891-0be65d62b36c
md"""
### Summary and Conclusions

In this lecture we:

1. Developed simple models of enzyme kinetics using the Michaelis–Menten approach
1. Introduced the fundamental concepts underlying more complex models of allosteric regulation (the fast control mechanisms that we mentioned previously)
1. Introduced effective discrete regulation models to simulate allosteric regulation

"""

# ╔═╡ 55d4ab48-9589-4fd9-ac06-3338fdb418c4
md"""
### Next Time

* What about multiple substrates?
* Does the discrete state model work?
* How do we implement these bounds models in a flux balance analysis calculation?

"""

# ╔═╡ 54370424-3add-4f93-91b0-e136166842ae
TableOfContents(title="📚 Lecture Outline", indent=true, depth=5, aside=true)

# ╔═╡ 06a90381-b4cb-4d32-af0d-2f084364129c
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>"""

# ╔═╡ b6890de0-8923-11ec-3552-3113bdd53f86
html"""
<style>
main {
    max-width: 860px;
    width: 70%;
    margin: auto;
    font-family: "Roboto, monospace";
}

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

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"

[compat]
Plots = "~1.25.8"
PlutoUI = "~0.7.34"
PrettyTables = "~1.3.1"
"""

# ╔═╡ 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]]
deps = ["Cairo_jll", "Colors", "Glib_jll", "Graphics", "Libdl", "Pango_jll"]
git-tree-sha1 = "d0b3f8b4ad16cb0a2988c6788646a5e6a17b6b1b"
uuid = "159f3aea-2a34-519c-b102-8c37f9878175"
version = "1.0.5"

[[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.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "f9982ef575e19b0e5c7a98c6e75ee496c0f73a93"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.12.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", "Luxor", "Random"]
git-tree-sha1 = "5b7d2a8b53c68dfdbce545e957a3b5cc4da80b01"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.17.0"

[[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 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.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.Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

[[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.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[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.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.FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "80ced645013a5dbdc52cf70329399c35ce007fae"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.13.0"

[[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 = "4a740db447aae0fbeb3ee730de1afbb14ac798a1"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.63.1"

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

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

[[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.Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "1c5a84319923bea76fa145d49e93aa4394c73fc2"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.1"

[[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.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]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

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

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

[[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 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

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

[[deps.Juno]]
deps = ["Base64", "Logging", "Media", "Profile"]
git-tree-sha1 = "07cb43290a840908a771552911a6274bc6c072c7"
uuid = "e5e0dc1b-0480-54bc-9374-aad01c23163d"
version = "0.8.4"

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

[[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 = "a8f4f279b6fa3c3c4f1adadd78a621b13a506bce"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.9"

[[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.Librsvg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pango_jll", "Pkg", "gdk_pixbuf_jll"]
git-tree-sha1 = "25d5e6b4eb3558613ace1c67d6a871420bfca527"
uuid = "925c91fb-5dd6-59dd-8e8c-345e74382d89"
version = "2.52.4+0"

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

[[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 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

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

[[deps.Luxor]]
deps = ["Base64", "Cairo", "Colors", "Dates", "FFMPEG", "FileIO", "Juno", "LaTeXStrings", "Random", "Requires", "Rsvg"]
git-tree-sha1 = "81a4fd2c618ba952feec85e4236f36c7a5660393"
uuid = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
version = "3.0.0"

[[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.Media]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "75a54abd10709c01f1b86b84ec225d26e840ed58"
uuid = "e89f7d12-3494-54d1-8411-f7d8b9ae1f27"
version = "0.5.0"

[[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 = "b086b7ea07f8e38cf122f5016af580881ac914fe"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.7"

[[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.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "648107615c15d4e09f7eca16307bc821c1f718d8"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.13+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.Pango_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3a121dfbba67c94a5bec9dde613c3d0cbcf3a12b"
uuid = "36c8627f-9965-5494-a995-c6b170f724f3"
version = "1.50.3+0"

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "0b5cfbb704034b5b4c1869e36634438a047df065"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.2.1"

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

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

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

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

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

[[deps.Profile]]
deps = ["Printf"]
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"

[[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.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 = "37c1631cb3cc36a535105e6d5557864c82cd8c2b"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.5.0"

[[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.Rsvg]]
deps = ["Cairo", "Glib_jll", "Librsvg_jll"]
git-tree-sha1 = "3d3dc66eb46568fb3a5259034bfc752a0eb0c686"
uuid = "c4c386cf-5103-5370-be45-f3a111cca3b8"
version = "1.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.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "a635a9333989a094bddc9f940c04c549cd66afcf"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.3.4"

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

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

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

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

[[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", "TableTraits", "Test"]
git-tree-sha1 = "bb1064c9a84c52e277f1096cf41434b675cd368b"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.6.1"

[[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 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.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.gdk_pixbuf_jll]]
deps = ["Artifacts", "Glib_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Xorg_libX11_jll", "libpng_jll"]
git-tree-sha1 = "c23323cd30d60941f8c68419a70905d9bdd92808"
uuid = "da03df04-f53b-5353-a52f-6a8b0620ced0"
version = "2.42.6+1"

[[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:
# ╟─8ba6a00a-7a53-4dcc-af4d-cb85aa9b4d68
# ╟─8869f117-1fc6-4cc5-9803-b8ec72a109a6
# ╟─17724757-604e-4c77-a42b-238ba121e88f
# ╟─431ccdf0-93a9-4b3c-9576-8854ba2f1fad
# ╟─7efaf27c-8e0a-40f9-ac28-af90357450a3
# ╟─55ea8324-f36d-40bd-99e3-92e7fcbafca9
# ╟─3502da52-7d2b-4c79-82ce-7424d756cd9b
# ╟─c392c8a9-361d-47e4-933e-2e51b793e069
# ╟─91345d04-f502-4e90-935e-a4dc250244db
# ╟─719784fe-3ef6-4e53-ad52-82140e3d0b5e
# ╟─1d4d6059-5b79-43cd-ac17-ef2aa057ecad
# ╟─d46ced14-a5d3-45a9-9d43-38dc7879b0c7
# ╟─d3568c5d-16bf-4698-9891-0be65d62b36c
# ╟─55d4ab48-9589-4fd9-ac06-3338fdb418c4
# ╟─54370424-3add-4f93-91b0-e136166842ae
# ╠═451ae3a0-8068-4747-95a7-d31955808f29
# ╠═06a90381-b4cb-4d32-af0d-2f084364129c
# ╠═b6890de0-8923-11ec-3552-3113bdd53f86
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using DrWatson
@quickactivate
using HierarchicalAD
using MLDatasets
using FileIO, BSON
using CSV
using DataFrames

#
y_tr = MLDatasets.MNIST.trainlabels();
y_tst = MLDatasets.MNIST.testlabels();
inpath = datadir("morpho_mnist/original")
f_tr = joinpath(inpath, "train-morpho.csv")
f_tst = joinpath(inpath, "t10k-morpho.csv")
label_df = vcat(CSV.read(f_tr, DataFrame), CSV.read(f_tst, DataFrame))
label_df[!,:digit] = vcat(y_tr, y_tst)
CSV.write(datadir("morpho_mnist/labels.csv"), label_df)

#
bwl = load(datadir("digits_bw/labels.bson"))[:labels]
bw_df = DataFrame(
		:digit => [l[3] for l in bwl],
		:font => [l[1] for l in bwl],
		:boldness => [l[2] for l in bwl],
		:rotation => [l[4] for l in bwl],
		:xshear => [l[5] for l in bwl],
		:yshear => [l[6] for l in bwl],
		:scale => [l[7] for l in bwl]
	)
CSV.write(datadir("digits_bw/labels.csv"), bw_df)

# RGB
rgbl = load(datadir("digits_rgb/labels.bson"))[:labels]
rgb_df = DataFrame(
		:digit => [l[3] for l in rgbl],
		:color => [l[4] for l in rgbl],
		:font => [l[1] for l in rgbl],
		:boldness => [l[2] for l in rgbl],
		:rotation => [l[5] for l in rgbl],
		:xshear => [l[6] for l in rgbl],
		:yshear => [l[7] for l in rgbl],
		:scale => [l[8] for l in rgbl]
	)
CSV.write(datadir("digits_rgb/labels.csv"), rgb_df)

ext: jl

max_stars_repo_name: vitskvara/HierarchicalAD

max_issues_repo_name: vitskvara/HierarchicalAD

max_forks_repo_name: vitskvara/HierarchicalAD


text:
import CurricularAnalyticsSimulationLibrary: Curriculum

mutable struct Simulation
    curriculum::Curriculum                  # The curriculum that is simulated
    duration::Int                           # The number of terms the simulation runs for

    predictionModel::Module                 # Module that implements the model for predicting student's performance in courses

    numStudents::Int                        # The number of students in the simulation
    enrolledStudents::Array{Student}        # Array of students that are enrolled
    graduatedStudents::Array{Student}       # Array of students that have graduated
    stopoutStudents::Array{Student}         # Array of students who stopped out

    studentProgress::Array{Int}             # Indicates wheter students have passed each course

    gradRate::Float64                       # Graduation rate at the end of the simulation
    termGradRates::Array{Float64}           # Array of graduation rates at the end of the simulation
    timeToDegree::Float64                   # Average number of semesters it takes to graduate students
    stopoutRate::Float64                    # Stopout rate at the end of the simulation
    termStopoutRates::Array{Float64}        # Array of stopout rates for each term

    function Simulation(curriculum)
        this = new()

        this.curriculum = curriculum

        this.enrolledStudents = Student[]
        this.graduatedStudents = Student[]
        this.stopoutStudents = Student[]

        # Set up courses
        for (id, course) in enumerate(curriculum.courses)
            course.id = id
        end

        return this
    end
end

max_stars_repo_name: M-S-H/CASL

max_issues_repo_name: M-S-H/CASL

max_forks_repo_name: M-S-H/CASL


text:
"""

# Available method diagnostics

Currently limited to Gradient().

"""
abstract type Diagnostics end

"""

# Gradient type and constructor

Settings for diagnostic=Gradient() in Diagnose().

### Method
```julia
Gradient(;epsilon=1e-6, error=1e-6)
```
### Optional arguments
```julia
* `epsilon::Float64`           : Finite difference step size
* `error::Float64`             : Error threshold
```

### Related help
```julia
?Diagnose                      : Diagnostic method
```
"""
mutable struct Gradient <: Diagnostics
  epsilon::Float64
  error::Float64
end
Gradient(;epsilon=1e-6, error=1e-6) = Gradient(epsilon, error)

"""

# Diagnose type and constructor

### Method
```julia
Diagnose(;d=Gradient())
```
### Optional arguments
```julia
* `d::Diagnostics`            : Finite difference step size
```

### Related help
```julia
?Diagnostics                  : Diagnostic methods
?Gradient                     : Currently sole diagnostic method
```
"""
mutable struct Diagnose
  diagnostic::Diagnostics
end
Diagnose(;d=Gradient()) = Diagnose(d)

function diagnose_show(io::IO, d::StanDiagnose.Diagnose, compact::Bool)
  if compact
    println(io, "Diagnose($(d.diagnostic))")
  else
    println(io, "  method =                  Diagnose()")
    if isa(d.diagnostic, Gradient)
      println(io, "    diagnostic =              Gradient()")
      println(io, "      epsilon =                 ", d.diagnostic.epsilon)
      println(io, "      error =                   ", d.diagnostic.error)
    end
  end
end

show(io::IO, d::StanDiagnose.Diagnose) = diagnose_show(io, d, false)


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: iotdeviceadvisor
using AWS.Compat
using AWS.UUIDs

"""
    create_suite_definition()
    create_suite_definition(params::Dict{String,<:Any})

Creates a Device Advisor test suite. Requires permission to access the
CreateSuiteDefinition action.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"suiteDefinitionConfiguration"`: Creates a Device Advisor test suite with suite
  definition configuration.
- `"tags"`: The tags to be attached to the suite definition.
"""
function create_suite_definition(; aws_config::AbstractAWSConfig=global_aws_config())
    return iotdeviceadvisor(
        "POST", "/suiteDefinitions"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function create_suite_definition(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "POST",
        "/suiteDefinitions",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_suite_definition(suite_definition_id)
    delete_suite_definition(suite_definition_id, params::Dict{String,<:Any})

Deletes a Device Advisor test suite. Requires permission to access the
DeleteSuiteDefinition action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite to be deleted.

"""
function delete_suite_definition(
    suiteDefinitionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "DELETE",
        "/suiteDefinitions/$(suiteDefinitionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_suite_definition(
    suiteDefinitionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "DELETE",
        "/suiteDefinitions/$(suiteDefinitionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_endpoint()
    get_endpoint(params::Dict{String,<:Any})

Gets information about an Device Advisor endpoint.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"certificateArn"`: The certificate ARN of the device. This is an optional parameter.
- `"thingArn"`: The thing ARN of the device. This is an optional parameter.
"""
function get_endpoint(; aws_config::AbstractAWSConfig=global_aws_config())
    return iotdeviceadvisor(
        "GET", "/endpoint"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function get_endpoint(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET", "/endpoint", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    get_suite_definition(suite_definition_id)
    get_suite_definition(suite_definition_id, params::Dict{String,<:Any})

Gets information about a Device Advisor test suite. Requires permission to access the
GetSuiteDefinition action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite to get.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"suiteDefinitionVersion"`: Suite definition version of the test suite to get.
"""
function get_suite_definition(
    suiteDefinitionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_suite_definition(
    suiteDefinitionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_suite_run(suite_definition_id, suite_run_id)
    get_suite_run(suite_definition_id, suite_run_id, params::Dict{String,<:Any})

Gets information about a Device Advisor test suite run. Requires permission to access the
GetSuiteRun action.

# Arguments
- `suite_definition_id`: Suite definition ID for the test suite run.
- `suite_run_id`: Suite run ID for the test suite run.

"""
function get_suite_run(
    suiteDefinitionId, suiteRunId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_suite_run(
    suiteDefinitionId,
    suiteRunId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_suite_run_report(suite_definition_id, suite_run_id)
    get_suite_run_report(suite_definition_id, suite_run_id, params::Dict{String,<:Any})

Gets a report download link for a successful Device Advisor qualifying test suite run.
Requires permission to access the GetSuiteRunReport action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite.
- `suite_run_id`: Suite run ID of the test suite run.

"""
function get_suite_run_report(
    suiteDefinitionId, suiteRunId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)/report";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_suite_run_report(
    suiteDefinitionId,
    suiteRunId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)/report",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_suite_definitions()
    list_suite_definitions(params::Dict{String,<:Any})

Lists the Device Advisor test suites you have created. Requires permission to access the
ListSuiteDefinitions action.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return at once.
- `"nextToken"`: A token used to get the next set of results.
"""
function list_suite_definitions(; aws_config::AbstractAWSConfig=global_aws_config())
    return iotdeviceadvisor(
        "GET", "/suiteDefinitions"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_suite_definitions(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET",
        "/suiteDefinitions",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_suite_runs()
    list_suite_runs(params::Dict{String,<:Any})

Lists runs of the specified Device Advisor test suite. You can list all runs of the test
suite, or the runs of a specific version of the test suite. Requires permission to access
the ListSuiteRuns action.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return at once.
- `"nextToken"`: A token to retrieve the next set of results.
- `"suiteDefinitionId"`: Lists the test suite runs of the specified test suite based on
  suite definition ID.
- `"suiteDefinitionVersion"`: Must be passed along with suiteDefinitionId. Lists the test
  suite runs of the specified test suite based on suite definition version.
"""
function list_suite_runs(; aws_config::AbstractAWSConfig=global_aws_config())
    return iotdeviceadvisor(
        "GET", "/suiteRuns"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_suite_runs(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET", "/suiteRuns", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

Lists the tags attached to an IoT Device Advisor resource. Requires permission to access
the ListTagsForResource action.

# Arguments
- `resource_arn`: The ARN of the IoT Device Advisor resource.

"""
function list_tags_for_resource(
    resourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "GET",
        "/tags/$(resourceArn)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    resourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "GET",
        "/tags/$(resourceArn)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_suite_run(suite_definition_id)
    start_suite_run(suite_definition_id, params::Dict{String,<:Any})

Starts a Device Advisor test suite run. Requires permission to access the StartSuiteRun
action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"suiteDefinitionVersion"`: Suite definition version of the test suite.
- `"suiteRunConfiguration"`: Suite run configuration.
- `"tags"`: The tags to be attached to the suite run.
"""
function start_suite_run(
    suiteDefinitionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "POST",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_suite_run(
    suiteDefinitionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "POST",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    stop_suite_run(suite_definition_id, suite_run_id)
    stop_suite_run(suite_definition_id, suite_run_id, params::Dict{String,<:Any})

Stops a Device Advisor test suite run that is currently running. Requires permission to
access the StopSuiteRun action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite run to be stopped.
- `suite_run_id`: Suite run ID of the test suite run to be stopped.

"""
function stop_suite_run(
    suiteDefinitionId, suiteRunId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "POST",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)/stop";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function stop_suite_run(
    suiteDefinitionId,
    suiteRunId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "POST",
        "/suiteDefinitions/$(suiteDefinitionId)/suiteRuns/$(suiteRunId)/stop",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Adds to and modifies existing tags of an IoT Device Advisor resource. Requires permission
to access the TagResource action.

# Arguments
- `resource_arn`: The resource ARN of an IoT Device Advisor resource.
- `tags`: The tags to be attached to the IoT Device Advisor resource.

"""
function tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config())
    return iotdeviceadvisor(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tags" => tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    resourceArn,
    tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tags" => tags), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Removes tags from an IoT Device Advisor resource. Requires permission to access the
UntagResource action.

# Arguments
- `resource_arn`: The resource ARN of an IoT Device Advisor resource.
- `tag_keys`: List of tag keys to remove from the IoT Device Advisor resource.

"""
function untag_resource(
    resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    resourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tagKeys" => tagKeys), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_suite_definition(suite_definition_id)
    update_suite_definition(suite_definition_id, params::Dict{String,<:Any})

Updates a Device Advisor test suite. Requires permission to access the
UpdateSuiteDefinition action.

# Arguments
- `suite_definition_id`: Suite definition ID of the test suite to be updated.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"suiteDefinitionConfiguration"`: Updates a Device Advisor test suite with suite
  definition configuration.
"""
function update_suite_definition(
    suiteDefinitionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return iotdeviceadvisor(
        "PATCH",
        "/suiteDefinitions/$(suiteDefinitionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_suite_definition(
    suiteDefinitionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return iotdeviceadvisor(
        "PATCH",
        "/suiteDefinitions/$(suiteDefinitionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
using MiniFastai
using Test

@testset "MiniFastai.jl" begin
    # Write your tests here.
    include("test_data.jl")
    include("test_callback.jl")
    include("test_cnn.jl")
    #include("test_learner.jl")
    include("test_training.jl")
end


text:
abstract SDPSolver

verbose(solver::SDPSolver) = solver.verbose

abstract SDPAGEN <: SDPSolver

executable(solver::SDPAGEN) = solver.executable

immutable SDPA <: SDPAGEN
    speed::Int
    executable::ASCIIString
    verbose::Bool
end

SDPA(; speed::Integer=0,
       executable::ASCIIString="sdpa",
       verbose::Bool=false) = SDPA(speed, executable, verbose)

immutable SDPAQD <: SDPAGEN
    speed::Int
    executable::ASCIIString
    verbose::Bool
end

SDPAQD(; speed::Integer=0,
         executable::ASCIIString="sdpa_qd",
         verbose::Bool=false) = SDPAQD(speed, executable, verbose)

immutable SDPAGMP <: SDPAGEN
    speed::Int
    executable::ASCIIString
    verbose::Bool
end

SDPAGMP(; speed::Integer=0,
          executable::ASCIIString="sdpa_gmp",
          verbose::Bool=false) = SDPAGMP(speed, executable, verbose)

immutable CSDP <: SDPSolver
    executable::ASCIIString
    verbose::Bool
end

CSDP(; executable="csdp", verbose=false) = CSDP(executable, verbose)

executable(solver::CSDP) = solver.executable

function solve{T<:Real}(sdp::SparseSDP{T}, solver::SDPAGEN; io::IO=STDOUT, outputfname="output.temp")
    datafname, dataio = mktemp()
    if verbose(solver)
        println(io, "Data filename: $datafname")
    end
    writesdpasparse(dataio, sdp)
    flush(dataio)
    primalobjective = NaN
    dualobjective = NaN

    for l in eachline(`$(executable(solver)) -ds $datafname -o $outputfname`)
        if verbose(solver)
            print(io, l)
        end
        if startswith(l, "objValPrimal = ")
            f = float(strip(split(l, " = ")[2]))
            primalobjective = ismaximizationproblem(sdp) ? f : -f
        end
        if startswith(l, "objValDual ")
            f = float(strip(split(l, " = ")[2]))
            dualobjective = ismaximizationproblem(sdp) ? f : -f
         end
    end
    close(dataio)
    SparseSDPSolution(primalobjective, dualobjective)
end

function solve(sdp::SparseSDP, solver::CSDP; io::IO=STDOUT, extraio=nothing, outputfname=nothing)
    sdp, cm, bm, ems = normalize(sdp)

    datafname, dataio = mktemp()
    removeoutputfname = false
    if outputfname == nothing
        outputfname, outputio = mktemp()
        removeoutputfname = true
    else
        outputio = open(outputfname, "w")
    end
    if verbose(solver)
        println(io, "Data filename: $datafname")
        println(io, "Output filename: $outputfname")
    end
    writesdpasparse(dataio, sdp)
    close(dataio)

    primalobjective = NaN
    dualobjective = NaN
    for l in eachline(`$(executable(solver)) $datafname $outputfname`)
        if extraio != nothing
            print(extraio, l)
            flush(extraio)
        end
        if verbose(solver)
            print(io, l)
        end
        if startswith(l, "Primal objective value: ")
            f = float(strip(split(l, ": ")[2]))
            primalobjective = ismaximizationproblem(sdp) ? f : -f
        end
        if startswith(l, "Dual objective value: ")
            f = float(strip(split(l, ": ")[2]))
            dualobjective = ismaximizationproblem(sdp) ? f : -f
        end
    end
    sol = SparseSDPSolution(primalobjective, dualobjective)
    readcsdpoutput!(outputio, sol, cm, bm, ems)
    close(outputio)
    if removeoutputfname
        rm(outputfname)
    end
    rm(datafname)
    sol
end


text:
module Exp
using StatsBase
using Statistics
include("./observable.jl")

const t = [i*60.0 for i in [0, 5, 15, 30, 45, 60, 90, 120]]  # sec.

function norm01(;egf1::Vector{Int}, hrg1::Vector{Int}, egf2::Vector{Int},
                hrg2::Vector{Int}, egf3::Vector{Int}, hrg3::Vector{Int})
    data1::Matrix{Float64} = hcat(egf1, hrg1)
    data2::Matrix{Float64} = hcat(egf2, hrg2)
    data3::Matrix{Float64} = hcat(egf3, hrg3)

    data1 .= data1 ./ maximum(data1)
    data2 .= data2 ./ maximum(data2)
    data3 .= data3 ./ maximum(data3)

    egf_ave::Vector{Float64} = zeros(length(t))
    hrg_ave::Vector{Float64} = zeros(length(t))
    egf_sem::Vector{Float64} = zeros(length(t))
    hrg_sem::Vector{Float64} = zeros(length(t))

    for i in eachindex(t)
        egf_ave[i] = mean([data1[i,1], data2[i,1], data3[i,1]])
        hrg_ave[i] = mean([data1[i,2], data2[i,2], data3[i,2]])
    end

    ave_vec::Vector{Float64} = vcat(egf_ave, hrg_ave)
    ave_min::Float64 = minimum(ave_vec)
    ave_max::Float64 = maximum(ave_vec)

    data1 .= (data1 .- ave_min) ./ (ave_max .- ave_min)
    data2 .= (data2 .- ave_min) ./ (ave_max .- ave_min)
    data3 .= (data3 .- ave_min) ./ (ave_max .- ave_min)

    for i in eachindex(t)
        egf_ave[i] = mean([data1[i,1], data2[i,1], data3[i,1]])
        hrg_ave[i] = mean([data1[i,2], data2[i,2], data3[i,2]])
        egf_sem[i] = std([data1[i,2], data2[i,2], data3[i,2]]) ./ sqrt(3)
        hrg_sem[i] = std([data1[i,2], data2[i,2], data3[i,2]]) ./ sqrt(3)
    end

    return egf_ave, hrg_ave, egf_sem, hrg_sem
end

experiments = Array{Dict{String,Array{Float64,1}},1}(undef, length(observables))
error_bars = Array{Dict{String,Array{Float64,1}},1}(undef, length(observables))

mcf7_data_pAkt = norm01(
    egf1=[32101, 156970, 90301, 76709, 63640, 52536, 46414, 57329],
    hrg1=[32101, 565508, 551901, 560064, 489678, 408802, 425323, 451502],
    egf2=[11612, 96189, 43622, 43238, 41007, 29902, 19255, 35079],
    hrg2=[11612, 397931, 432609, 417622, 434519, 509919, 361041, 292523],
    egf3=[66038, 208525, 102689, 117308, 125158, 92086, 68587, 78252],
    hrg3=[66038, 563079, 573540, 521062, 447462, 383774, 434807, 409615],
)
bt474_data_pAkt = norm01(
    egf1=[405198, 356865, 321475, 383445, 346872, 328052, 299123, 316633],
    hrg1=[405198, 357121, 419948, 488508, 495214, 443710, 402765, 451831],
    egf2=[432524, 619289, 581376, 481899, 429541, 399922, 376170, 334923],
    hrg2=[432524, 410919, 413878, 390581, 405359, 408471, 373108, 515120],
    egf3=[150446, 435897, 466378, 443105, 415827, 381441, 398841, 413906],
    hrg3=[150446, 556176, 560385, 539165, 589297, 552227, 540005, 539010],
)
mdamb231_data_pAkt = norm01(
    egf1=[86491, 826975, 575400, 354446, 143728, 107326, 88082, 108892],
    hrg1=[86491, 85990, 114224, 94636, 66139, 92359, 89540, 126099],
    egf2=[56004, 816102, 296684, 165282, 92711, 83090, 55002, 50605],
    hrg2=[56004, 50640, 64646, 55814, 70627, 66657, 68994, 46922],
    egf3=[36061, 729961, 218315, 166109, 68746, 53331, 45191, 21852],
    hrg3=[36061, 75029, 174050, 89546, 88262, 99161, 78673, 58412],
)
experiments[observables_index("Phosphorylated_Akt")] = Dict(
    "MCF7_EGF" => mcf7_data_pAkt[1],
    "MCF7_HRG" => mcf7_data_pAkt[2],
    "BT474_EGF" => bt474_data_pAkt[1],
    "BT474_HRG" => bt474_data_pAkt[2],
    "MDAMB231_EGF" => mdamb231_data_pAkt[1],
    "MDAMB231_HRG" => mdamb231_data_pAkt[2],
)
error_bars[observables_index("Phosphorylated_Akt")] = Dict(
    "MCF7_EGF" => mcf7_data_pAkt[3],
    "MCF7_HRG" => mcf7_data_pAkt[4],
    "BT474_EGF" => bt474_data_pAkt[3],
    "BT474_HRG" => bt474_data_pAkt[4],
    "MDAMB231_EGF" => mdamb231_data_pAkt[3],
    "MDAMB231_HRG" => mdamb231_data_pAkt[4],
)

mcf7_data_pERK = norm01(
    egf1=[65481, 446949, 221435, 283171, 265152, 266056, 204912, 188972],
    hrg1=[65481, 698717, 766252, 710005, 693622, 691856, 522173, 334410],
    egf2=[41927, 507623, 169918, 193671, 164088, 145916, 110844, 130362],
    hrg2=[41927, 605118, 699511, 654697, 579863, 490649, 299946, 229297],
    egf3=[118995, 807929, 338665, 267160, 253820, 230200, 157620, 153112],
    hrg3=[118995, 710436, 673318, 615206, 612686, 523198, 390301, 257664],
)
bt474_data_pERK = norm01(
    egf1=[358203, 550378, 633802, 632047, 500267, 394009, 339650, 221411],
    hrg1=[358203, 531893, 703437, 663640, 629213, 612525, 613871, 643056],
    egf2=[355065, 1421536, 1307969, 1101679, 939944, 689539, 507787, 468836],
    hrg2=[355065, 929915, 897601, 924274, 865529, 820386, 673456, 788623],
    egf3=[61593, 631017, 754722, 652440, 575812, 432406, 315961, 259708],
    hrg3=[61593, 480140, 487770, 463604, 438917, 452289, 470624, 531531],
)
mdamb231_data_pERK = norm01(
    egf1=[314472, 504819, 607786, 618492, 475195, 376035, 293988, 324600],
    hrg1=[314472, 156705, 183456, 277862, 141450, 199719, 253331, 407923],
    egf2=[458693, 1001334, 875594, 834259, 782639, 815888, 629576, 539187],
    hrg2=[458693, 322542, 403985, 331734, 263578, 262142, 276371, 313541],
    egf3=[365691, 747932, 937413, 945635, 870059, 706306, 510590, 451927],
    hrg3=[365691, 340876, 428510, 303543, 269653, 195660, 215972, 388050],
)
experiments[observables_index("Phosphorylated_ERK")] = Dict(
    "MCF7_EGF" => mcf7_data_pERK[1],
    "MCF7_HRG" => mcf7_data_pERK[2],
    "BT474_EGF" => bt474_data_pERK[1],
    "BT474_HRG" => bt474_data_pERK[2],
    "MDAMB231_EGF" => mdamb231_data_pERK[1],
    "MDAMB231_HRG" => mdamb231_data_pERK[2],
)
error_bars[observables_index("Phosphorylated_ERK")] = Dict(
    "MCF7_EGF" => mcf7_data_pERK[3],
    "MCF7_HRG" => mcf7_data_pERK[4],
    "BT474_EGF" => bt474_data_pERK[3],
    "BT474_HRG" => bt474_data_pERK[4],
    "MDAMB231_EGF" => mdamb231_data_pERK[3],
    "MDAMB231_HRG" => mdamb231_data_pERK[4],
)

mcf7_data_pcFos = norm01(
    egf1=[43200, 101848, 134050, 187681, 274701, 188891, 186912, 147868],
    hrg1=[43200, 243299, 340259, 537344, 583257, 527613, 551327, 630883],
    egf2=[36344, 99849, 173325, 179897, 207943, 155466, 154118, 138196],
    hrg2=[36344, 139813, 245333, 389460, 402734, 556006, 513591, 432916],
    egf3=[43604, 83374, 108733, 116103, 113879, 95504, 94969, 94662],
    hrg3=[43604, 111136, 343365, 464180, 453578, 440094, 404483, 589354],
)
bt474_data_pcFos = norm01(
    egf1=[30474, 28409, 41129, 149499, 202734, 209115, 228033, 191176],
    hrg1=[30474, 37651, 86813, 196100, 343675, 393495, 381987, 424195],
    egf2=[29037, 67984, 102222, 193780, 284045, 268596, 257846, 173705],
    hrg2=[29037, 54659, 170148, 312924, 332799, 416213, 509015, 479438],
    egf3=[41306, 106705, 223130, 255095, 311870, 301535, 296093, 274372],
    hrg3=[41306, 81420, 176053, 264250, 400465, 424547, 522829, 609155],
)
mdamb231_data_pcFos = norm01(
    egf1=[124104, 175391, 230831, 210449, 337825, 317246, 375420, 311936],
    hrg1=[124104, 124400, 102863, 125643, 124228, 144544, 156551, 163124],
    egf2=[60197, 45929, 63355, 77438, 115070, 122509, 166049, 129227],
    hrg2=[60197, 56254, 57765, 67667, 60445, 66214, 33948, 32766],
    egf3=[47449, 63064, 67735, 183991, 275103, 183211, 552227, 362380],
    hrg3=[47449, 88082, 93539, 73279, 44637, 55030, 56284, 35506],
)
experiments[observables_index("Phosphorylated_cFos")] = Dict(
    "MCF7_EGF" => mcf7_data_pcFos[1],
    "MCF7_HRG" => mcf7_data_pcFos[2],
    "BT474_EGF" => bt474_data_pcFos[1],
    "BT474_HRG" => bt474_data_pcFos[2],
    "MDAMB231_EGF" => mdamb231_data_pcFos[1],
    "MDAMB231_HRG" => mdamb231_data_pcFos[2],
)
error_bars[observables_index("Phosphorylated_cFos")] = Dict(
    "MCF7_EGF" => mcf7_data_pcFos[3],
    "MCF7_HRG" => mcf7_data_pcFos[4],
    "BT474_EGF" => bt474_data_pcFos[3],
    "BT474_HRG" => bt474_data_pcFos[4],
    "MDAMB231_EGF" => mdamb231_data_pcFos[3],
    "MDAMB231_HRG" => mdamb231_data_pcFos[4],
)

function get_timepoint(obs_name::String)::Vector{Float64}
    if obs_name in ["Phosphorylated_ErbB1", "Phosphorylated_ErbB2",
                    "Phosphorylated_ErbB3", "Phosphorylated_ErbB4",
                    "Phosphorylated_Akt", "Phosphorylated_ERK",
                    "Phosphorylated_cFos"]
        return t
    end
end
end # module


text:
# Test the 3-input 1-output case of Hu (2020)
# To run:  from evotech/CGP.jl/src:
# julia -L CGP.jl -L LinChromosome.jl ../test/testLinChromosome.jl
using Random
using Test
using Main.CGP
@testset "Testing functions of LinChromosome.jl in the 3-input 1-output 2-registers 6-instructions case." begin

numinputs=3
numregisters=2
lfuncs = lin_funcs(numinputs)
ni = num_instructions( numregisters, numinputs, lfuncs )
# Testing that instruction_vect_to_instruction_int() is the inverse of instruction_int_to_instruction_vect()
for i = 0:ni-1
  @test i == instruction_vect_to_instruction_int(instruction_int_to_instruction_vect( i, numregisters, numinputs, lfuncs ), numregisters, numinputs, lfuncs )
end

# Test of the circuit of Hu (2012, 309)
# See testComposition.jl for another version of this example.
numinputs=2
numinstructions=4
numregisters=2
p = Parameters(numinputs,1,numinstructions,numregisters)
lfuncs = lin_funcs(numinputs)  # Note that lin_funcs() needs to be set to the Hu gate set
@test num_instructions(numregisters,numinputs,lfuncs) == 128
# array of circuit vects corresponding to the circuit of Hu (2012, 309)
# An instruction is specified either by a 4-tuple of MyInts or by an integer of OutputType.
# The elements of the 4-tuple are:
#  1.  The index of the logical operation (such as AND, OR) in the funcs array.
#  2.  The index of the element of R where the output is stored
#  3.  The index of the element of R which is the first operand of the logical operation
#  4.  The index of the element of R which is the second operand of the logical operation
# Note that these indices are 1-based instead of 0-based
lc = [
  MyInt[2, 2, 3, 4],
  MyInt[1, 1, 2, 3],
  MyInt[3, 2, 1, 2],
  MyInt[4, 1, 4, 2]
]
i_ints=map( x->instruction_vect_to_instruction_int( x, numregisters,numinputs,lfuncs), lc )
@test i_ints == [60, 7, 82, 110]
@test MyInt[ 0x4, 0x3, 0xc, 0xa ] == execute_lcircuit( i_ints, numregisters,numinputs,lfuncs)
cint = instruction_ints_to_circuit_int( i_ints, p, lfuncs )
@test i_ints == circuit_int_to_instruction_ints( instruction_ints_to_circuit_int( i_ints, p, lfuncs), p, lfuncs )

# Test of the circuit of Hu (2020, 378)
numinputs=3
numinstructions=6
numregisters=2
p = Parameters(numinputs,1,numinstructions,numregisters)
lfuncs = lin_funcs(numinputs)  # Note that lin_funcs() needs to be set to the Hu gate set
@test num_instructions(numregisters,numinputs,lfuncs) == 200
# array of circuit vects corresponding to the circuit of Hu (2020, 378)
# Note that these indices are 1-based instead of 0-based
# for the registers, our index 1 corresponds to R0
# our index 1 corresponds to R0  # calculation register
# our index 2 corresponds to R4  # calculation register
# our index 3 corresponds to R1  # input register
# our index 4 corresponds to R2  # input register
# our index 5 corresponds to R3  # input register
lcv = [
  MyInt[1, 2, 4, 5],
  MyInt[2, 1, 3, 2],
  MyInt[3, 2, 2, 1],
  MyInt[1, 2, 5, 4],
  MyInt[4, 1, 3, 3],
  MyInt[1, 1, 5, 1]
]
lc = LinCircuit( lcv, p )
i_ints=map( x->instruction_vect_to_instruction_int( x, numregisters,numinputs,lfuncs), lcv )
@test i_ints == [45, 62, 131, 49, 163, 21]
@test MyInt[ 0x000a, 0x0088, 0x00f0, 0x00cc, 0x00aa ] == execute_lcircuit( i_ints, numregisters,numinputs,lfuncs)
c_int = Int128(14178641952420)
@test c_int == instruction_ints_to_circuit_int( i_ints, p, lfuncs )
@test i_ints == circuit_int_to_instruction_ints( instruction_ints_to_circuit_int( i_ints, p, lfuncs), p, lfuncs )
@test circuit_int_to_circuit( circuit_to_circuit_int( lc, lfuncs ), p, lfuncs ).circuit_vects == lcv
@test circuit_to_circuit_int( circuit_int_to_circuit( c_int, p, lfuncs ), lfuncs ) == c_int

ctx = construct_context(3)
# Execute circuit one step at a time as specified in the Hu (2020) paper
R0=0x0000; R1=ctx[1]; R2=ctx[2]; R3=ctx[3]; R4=0x0000;
R4 = R2 & R3
R0 = R1 | R4
R4 = Nand( R4, R0 )
R4 = R3 & R2
R0 = Nor( R1, R1 )
R0 = R3 & R0
@test [R0,R4,R1,R2,R3] == execute_lcircuit( i_ints, numregisters, numinputs, lfuncs )

# Test of functions with parameter arguments.
p = Parameters(numinputs,1,length(lcv),numregisters)
@test execute_lcircuit( lcv, numregisters, numinputs, lfuncs ) ==  execute_lcircuit( LinCircuit(lcv,p), lfuncs )
@test num_instructions( p.numlevelsback, p.numinputs, lfuncs ) == num_instructions( p, lfuncs )
Random.seed!(1); riv0 = rand_ivect( p.numlevelsback, p.numinputs, lfuncs )
Random.seed!(1); riv1 = rand_ivect( p, lfuncs )
@test riv0 == riv1
Random.seed!(1); rii0 = rand_lcircuit( p.numinteriors, p.numlevelsback, p.numinputs, lfuncs )
Random.seed!(1); rii1 = rand_lcircuit( p, lfuncs )
#println("rii0.params: ",rii0.params,"  rii1.params: ",rii1.params)
#println("rii0.circuit_vects: ",rii0.circuit_vects)
#println("rii1.circuit_vects: ",rii1.circuit_vects)
#@test rii0.params == rii1.params && rii0.circuit_vects == rii1.circuit_vects  # 6/30/21: test rii0.params == rii1.params failed even though they are equal
@test rii0.circuit_vects == rii1.circuit_vects
llfuncs = length(lfuncs)
num_mutate_locations = ((llfuncs>1) ? (llfuncs-1) : 0) + (p.numlevelsback-1) + p.nodearity*(p.numlevelsback+p.numinputs-1)
nml0=map(ml->instruction_vect_to_instruction_int(Main.CGP.mutate_instruction(lcv[1],p.numlevelsback,p.numinputs,lfuncs,ml),p.numlevelsback,p.numinputs,lfuncs),1:num_mutate_locations)
nml1=map(ml->instruction_vect_to_instruction_int(Main.CGP.mutate_instruction(lcv[1],p,lfuncs,ml),p.numlevelsback,p.numinputs,lfuncs),1:num_mutate_locations)
@test nml0 == nml1
@test length(unique(nml0)) == length(nml0)   # Check that all mutations are unique
Random.seed!(1); mc0 = Main.CGP.mutate_instruction( lcv[1], p.numlevelsback, p.numinputs, lfuncs )
Random.seed!(1); mc1 = Main.CGP.mutate_instruction( lcv[1], p, lfuncs )
@test mc0 == mc1
Random.seed!(1); mc0=Main.CGP.mutate_circuit!(deepcopy(lcv),p,lfuncs)
Random.seed!(1); mc1=Main.CGP.mutate_circuit!(deepcopy(lcv),p.numlevelsback,p.numinputs,lfuncs)
@test mc0 == mc1
Random.seed!(1); mc0 = Main.CGP.mutate_circuit!( deepcopy(lcv), p.numlevelsback, p.numinputs, lfuncs )
Random.seed!(1); mc1 = Main.CGP.mutate_circuit!( deepcopy(lcv), p, lfuncs )
@test mc0 == mc1
@test Main.CGP.mutate_circuit_all( lcv, p.numlevelsback, p.numinputs, lfuncs ) == Main.CGP.mutate_circuit_all( lcv, p, lfuncs )

# Iterate through all of genotype space in the special case of 3-instruction circuits
# Return all circuits that are circuit_distance 1 from circuit rlc.
nr =  numregisters
function test_mutate(rlc::LinCircuit, numinputs::Int64, nr::Int64, funcs::Vector{Func} )
  n_instructions = num_instructions( nr, numinputs, funcs )
  nbrs = []
  for i = 1:n_instructions
    for j = 1:n_instructions
      for k = 1:n_instructions
        rcirc =[
            instruction_int_to_instruction_vect( i, nr, numinputs, funcs ),
            instruction_int_to_instruction_vect( j, nr, numinputs, funcs ),
            instruction_int_to_instruction_vect( k, nr, numinputs, funcs )];
        if circuit_distance(rcirc, rlc.circuit_vects) == 1
          push!(nbrs,rcirc)
       end
      end
    end
  end
  nbrs
end
p = Parameters(2,1,3,nr)
funcs = lin_funcs(p.numinputs)
rlc=rand_lcircuit(p)
@test sort(CGP.mutate_circuit_all( rlc.circuit_vects, p, funcs )) == sort(test_mutate(rlc,p.numinputs,nr,funcs))

end #testset


text:
# AUTO GENERATED FILE - DO NOT EDIT

export ''_antdcolumn

"""
    ''_antdcolumn(;kwargs...)

An AntdColumn component.

Keyword arguments:
- `id` (String; optional)
- `annotations` (optional)
- `appendPadding` (Real | Array of Reals | String; optional)
- `autoFit` (Bool; optional)
- `className` (String; optional)
- `color` (optional): . color has the following type: String | Array of Strings | lists containing elements 'func'.
Those elements have the following types:
  - `func` (String; optional)
- `columnBackground` (optional): . columnBackground has the following type: lists containing elements 'style'.
Those elements have the following types:
  - `style` (optional)
- `columnStyle` (optional): . columnStyle has the following type: lists containing elements 'func'.
Those elements have the following types:
  - `func` (String; optional)
- `columnWidthRatio` (Real; optional)
- `connectedArea` (optional): . connectedArea has the following type: lists containing elements 'trigger'.
Those elements have the following types:
  - `trigger` (Bool | String; optional) | Bool
- `conversionTag` (optional): . conversionTag has the following type: lists containing elements 'size', 'spacing', 'offset', 'arrow', 'text'.
Those elements have the following types:
  - `size` (Real; optional)
  - `spacing` (Real; optional)
  - `offset` (Real; optional)
  - `arrow` (optional): . arrow has the following type: Bool | lists containing elements 'headSize'.
Those elements have the following types:
  - `headSize` (Real; optional)
  - `text` (optional): . text has the following type: Bool | lists containing elements 'formatter', 'style'.
Those elements have the following types:
  - `formatter` (optional): . formatter has the following type: lists containing elements 'func'.
Those elements have the following types:
  - `func` (String; optional)
  - `style` (optional)
- `data` (Array of Dicts; required)
- `dodgePadding` (Real; optional)
- `groupField` (String; optional)
- `height` (Real; optional)
- `intervalPadding` (Real; optional)
- `isGroup` (Bool; optional)
- `isPercent` (Bool; optional)
- `isRange` (Bool; optional)
- `isStack` (Bool; optional)
- `label` (optional)
- `legend` (optional)
- `loading_state` (optional): . loading_state has the following type: lists containing elements 'is_loading', 'prop_name', 'component_name'.
Those elements have the following types:
  - `is_loading` (Bool; optional): Determines if the component is loading or not
  - `prop_name` (String; optional): Holds which property is loading
  - `component_name` (String; optional): Holds the name of the component that is loading
- `locale` (String; optional)
- `marginRatio` (Real; optional)
- `maxColumnWidth` (Real; optional)
- `meta` (optional)
- `minColumnWidth` (Real; optional)
- `padding` (Real | Array of Reals | String; optional)
- `renderer` (String; optional)
- `scrollbar` (optional)
- `seriesField` (String; optional)
- `slider` (optional)
- `style` (Dict; optional)
- `tooltip` (optional)
- `width` (Real; optional)
- `xAxis` (optional)
- `xField` (String; required)
- `yAxis` (optional)
- `yField` (String; required)
"""
function ''_antdcolumn(; kwargs...)
        available_props = Symbol[:id, :annotations, :appendPadding, :autoFit, :className, :color, :columnBackground, :columnStyle, :columnWidthRatio, :connectedArea, :conversionTag, :data, :dodgePadding, :groupField, :height, :intervalPadding, :isGroup, :isPercent, :isRange, :isStack, :label, :legend, :loading_state, :locale, :marginRatio, :maxColumnWidth, :meta, :minColumnWidth, :padding, :renderer, :scrollbar, :seriesField, :slider, :style, :tooltip, :width, :xAxis, :xField, :yAxis, :yField]
        wild_props = Symbol[]
        return Component("''_antdcolumn", "AntdColumn", "feffery_antd_charts", available_props, wild_props; kwargs...)
end

max_stars_repo_name: CNFeffery/feffery-antd-charts

max_issues_repo_name: CNFeffery/feffery-antd-charts

max_forks_repo_name: CNFeffery/feffery-antd-charts


text:
module KuramotoSivashinsky

export
  InitialValueProblem,
  updatevars!,
  set_u!

using
  FFTW,
  Reexport

@reexport using FourierFlows

using LinearAlgebra: mul!, ldiv!

"""
    Problem(; parameters...)

Construct a Kuramoto-Sivashinky problem that solves the equation

∂t u + ∂ₓ⁴u + ∂ₓ²u + u ∂ₓu = 0.
"""
function Problem(;
       nx = 256,
       Lx = 2π,
       dt = 0.01,
  stepper = "RK4")

  g  = OneDGrid(nx, Lx)
  pr = Params()
  vs = Vars(g)
  eq = Equation(pr, g)
  ts = TimeStepper(stepper, dt, eq.LC, g)

  FourierFlows.Problem(g, vs, pr, eq, ts)
end

# Placeholder Params type
struct Params <: AbstractParams; end

"Returns the Equation type for Kuramoto-Sivashinsky."
function Equation(p, g)
  LC = @. g.kr^2 - g.kr^4
  FourierFlows.Equation(LC, calcN!)
end

# Construct Vars type
physicalvars = [:u, :ux, :uux]
transformvars = [:uh, :uxh, :uuxh]
eval(FourierFlows.structvarsexpr(:Vars, physicalvars, transformvars; vardims=1))

"Returns the Vars object for Kuramoto-Sivashinsky."
function Vars(g)
  @createarrays Float64 (g.nx,) u ux uux
  @createarrays Complex{Float64} (g.nkr,) uh uxh uuxh
  Vars(u, ux, uux, uh, uxh, uuxh)
end

"Calculates N = - u uₓ, the nonlinear term for the Kuramoto-Sivashinsky equation."
function calcN!(N, sol, t, s, v, p, g)
  @. v.uh = sol
  @. v.uxh = im*g.kr*sol
  ldiv!(v.u, g.rfftplan, v.uh)
  ldiv!(v.ux, g.rfftplan, v.uxh)
  @. v.uux = v.u*v.ux
  mul!(v.uuxh, g.rfftplan, v.uux)
  @. N = -v.uuxh
  dealias!(N, g)
  nothing
end

# Helper functions
"""
    updatevars!(v, s, g)

Update the vars in v on the grid g with the solution in s.sol.
"""
function updatevars!(v, s, g)
  v.uh .= s.sol
  ldiv!(v.u, g.rfftplan, v.uh)
  nothing
end

updatevars!(prob::AbstractProblem) = updatevars!(prob.vars, prob.state, prob.grid)

"""
    set_u!(prob, u)
    set_u!(s, v, g, u)

Set the solution prob.state.sol as the transform of u and update variables.
"""
function set_u!(s, v, g, u)
  mul!(s.sol, g.rfftplan, u)
  updatevars!(v, s, g)
  nothing
end

set_u!(prob::AbstractProblem, u) = set_u!(prob.state, prob.vars, prob.grid, u)

end # module